Adjust a text frame to fit its content

From Scribus Wiki
Jump to navigation Jump to search
This article is part of the Scripts series.

The scripts on this page work (better or only) with a recent 1.3.5svn and with "pt" as a measurement unit for the document.

I will try to fix the second issue soon, but i'm not sure that i want to use much resources to test them in 1.3.3.x myself (i don't have it installed on my computers).


Vertically adjust the size of existing text frames

"""
this script adjust the height of a text frame to exactly fit its content,
but not be longer than the page margin
@author: ale rimoldi
@version: 1.0 / 20090131
@copyright (c) 2009 aleo rimoldi under the mit license
           http://www.opensource.org/licenses/mit-license.html
"""
import sys
try:
   import scribus
except ImportError:
   print "This script only works from within Scribus"
   sys.exit(1)

# check that the selection is one text frame and get that frame
frame_n = scribus.selectionCount()
if frame_n == 0 :
    scribus.messageBox('Error:', 'No frame selected');
    sys.exit(1)
elif frame_n > 1 :
    scribus.messageBox('Error:', 'You may select only one frame');
    sys.exit(1)

frame = scribus.getSelectedObject(0)
try:
    char_n = scribus.getTextLength(frame)
except scribus.WrongFrameTypeError:
    scribus.messageBox('Error:', 'You may only adjust text frames');
    sys.exit(1)

if char_n == 0 :
    scribus.messageBox('Error:', 'You can\'t adjust an empty frame');
    sys.exit(1)

# get some page and frame measure
(x, ph) = scribus.getPageSize();
(x, x, x, pm) = scribus.getPageMargins(); # warning: gets the margins from document setup not for the current page

(x, y) = scribus.getPosition(frame)

bottom = (ph - pm) - y

(w, h) = scribus.getSize(frame)

# if the frame doesn't overflow, shorten it to make it overflow
while (((scribus.textOverflows(frame) == 0) or (h > bottom)) and (h > 0)) :
    h -= 10
    scribus.sizeObject(w, h, frame)

# resize the frame in 10pt steps
while ((scribus.textOverflows(frame) > 0) and (h < bottom)) :
    h += 10
    scribus.sizeObject(w, h, frame)

# undo the latest 10pt step and fine adjust in 1pt steps
h -= 10
scribus.sizeObject(w, h, frame)

while ((scribus.textOverflows(frame) > 0) and (h < bottom)) :
    h += 1
    scribus.sizeObject(w, h, frame)

Comments

Adjusting the frame horizontally

It's easy to do for a one-line frame. But what use cases do *you* see for an horizontal automatic correction?

"ein Text hat, anders als ein Bild keine Dimensionen. Wenn man ihn automatisch anpassen will, muß man die Schrift, die Schriftgröße, ggf. andere Einstellungen wie Silbentrennung, Kerning, Randausgleich berücksichtigen. Das mindeste,was man tun muß, ist, dem Anwender die Wahl zu lassen, in welche Richtung der Textrahmen angepaßt werden soll"

import a text with the right frame height

  • read a text file
  • filter it line by line
  • put it in a frame
  • fit the height of the frame to the length of its content

this script is thought as a prove of concept for automatic import of text files into a scribus file. you will have to build a loop to replace the 'abc.txt' (and if you want just to test the script, you will have to create a 'abc.txt' file with some text in it) and create a filter to modify the text you are importing.

#!/usr/bin/env python
"""
this script reads a text file, filters it line by line, puts in a
text fram and fits the height of the frame to fit the length of
its content
@author: alessandro rimoldi
@version: 1.0 / 20090131
@copyright (c) 2009 alessandro rimoldi under the mit license
           http://www.opensource.org/licenses/mit-license.html
"""

import sys
try:
   import scribus
except ImportError:
   print "This script only works from within Scribus"
   sys.exit(1)


# read the content of the file line by line into the text frame
file_name = 'mytext.txt'
file_name = 'abc.txt'
file = open(file_name, 'r')

text = "";

for line in open(file_name, 'r') :
    if line != '\n':
        # put here some text handling/filtering
        text += unicode(line, 'iso-8859-2')

# create a text frame and put the text into it
x = 60
y = 100
w = 300
h = 10

frame = scribus.createText(x, y, w, h)
scribus.setText(text, frame)

# resize the frame in 10pt steps
while (scribus.textOverflows(frame) > 0) :
    h += 10
    scribus.sizeObject(w, h, frame)

# undo the latest 10pt step and fine adjust in 1pt steps
h -= 10
scribus.sizeObject(w, h, frame)

while (scribus.textOverflows(frame) > 0) :
    h += 1
    scribus.sizeObject(w, h, frame)

center (vertical) align the content of a text frame

#!/usr/bin/python
"""
this script adjust the top and bottom distance of a text frame
to exactly put its content in the middle of the frame
@author: alessandro rimoldi
@version: 1.0 / 20090209
@copyright (c) 2009 alessandro rimoldi under the mit license
           http://www.opensource.org/licenses/mit-license.html
"""
import sys
try:
   import scribus
except ImportError:
   print "This script only works from within Scribus"
   sys.exit(1)

# check that the selection is one text frame and get that frame
frame_n = scribus.selectionCount()
if frame_n == 0 :
    scribus.messageBox('Error:', 'No frame selected');
    sys.exit(1)
elif frame_n > 1 :
    scribus.messageBox('Error:', 'You may select only one frame');
    sys.exit(1)

frame = scribus.getSelectedObject(0)
try:
    char_n = scribus.getTextLength(frame)
except scribus.WrongFrameTypeError:
    scribus.messageBox('Error:', 'You may only adjust text frames');
    sys.exit(1)

if char_n == 0 :
    scribus.messageBox('Error:', 'You can\'t adjust an empty frame');
    sys.exit(1)

if (scribus.textOverflows(frame) == 1) :
    scribus.messageBox('Error:', 'You can\' center a text which is overflowing');
    sys.exit(1)

# get some page and frame measure

(x, y) = scribus.getPosition(frame)

(w, h) = scribus.getSize(frame)

original_height = h

(dl, dr, dt, db) = scribus.getTextDistances();

scribus.setTextDistances(dl, dr, 0, 0);

# if the frame doesn't overflow, shorten it to make it overflow
while ((scribus.textOverflows(frame) == 0) and (h > 0)) :
    h -= 10
    scribus.sizeObject(w, h, frame)

# resize the frame in 10pt steps
while (scribus.textOverflows(frame) > 0) :
    h += 10
    scribus.sizeObject(w, h, frame)

# undo the latest 10pt step and fine adjust in 1pt steps
h -= 10
scribus.sizeObject(w, h, frame)

while (scribus.textOverflows(frame) > 0) :
    h += 1
    scribus.sizeObject(w, h, frame)


scribus.sizeObject(w, original_height, frame)

dt = (original_height - h) / 2

scribus.setTextDistances(dl, dr, dt, dt);

bottom align the content of a text frame

#!/usr/bin/python
"""
this script adjust the top and bottom distance of a text frame
to exactly put its content in the middle of the frame
@author: alessandro rimoldi
@version: 1.0 / 20090209
@copyright (c) 2009 alessandro rimoldi under the mit license
           http://www.opensource.org/licenses/mit-license.html
"""
import sys
try:
   import scribus
except ImportError:
   print "This script only works from within Scribus"
   sys.exit(1)

# check that the selection is one text frame and get that frame
frame_n = scribus.selectionCount()
if frame_n == 0 :
    scribus.messageBox('Error:', 'No frame selected');
    sys.exit(1)
elif frame_n > 1 :
    scribus.messageBox('Error:', 'You may select only one frame');
    sys.exit(1)

frame = scribus.getSelectedObject(0)
try:
    char_n = scribus.getTextLength(frame)
except scribus.WrongFrameTypeError:
    scribus.messageBox('Error:', 'You may only bottom aling text frames');
    sys.exit(1)

if char_n == 0 :
    scribus.messageBox('Error:', 'You can\'t bottom align an empty frame');
    sys.exit(1)

# get some page and frame measure

(x, y) = scribus.getPosition(frame)

(w, h) = scribus.getSize(frame)

(dl, dr, dt, db) = scribus.getTextDistances();

scribus.setTextDistances(dl, dr, 0, db);

if (scribus.textOverflows(frame) == 1) :
    scribus.setTextDistances(dl, dr, dt, db);
    scribus.messageBox('Error:', 'You can\' bottom align a text which is overflowing');
    sys.exit(1)

scribus.setTextDistances(dl, dr, 0, db);

top = 0

# grow the top margin in 10pt steps until it overflows
while ((scribus.textOverflows(frame) == 0) and (top < h)) :
    top += 10
    scribus.setTextDistances(dl, dr, top, db)


# reduce the top margin in 1pt steps until it doesn't overflow anymore
while (scribus.textOverflows(frame) > 0) and (top > 0) :
    top -= 1
    scribus.setTextDistances(dl, dr, top, db)

Horizontally adjust a text frame to fit its content

#!/usr/bin/python

"""
this script adjust the width of a text frame to exactly fit its content,
but not be wider than the page margin
@author: alessandro rimoldi
@version: 1.0 / 20090209
@copyright (c) 2009 alessandro rimoldi under the mit license
           http://www.opensource.org/licenses/mit-license.html
"""
import sys
try:
   import scribus
except ImportError:
   print "This script only works from within Scribus"
   sys.exit(1)

# check that the selection is one text frame and get that frame
frame_n = scribus.selectionCount()
if frame_n == 0 :
    scribus.messageBox('Error:', 'No frame selected');
    sys.exit(1)
elif frame_n > 1 :
    scribus.messageBox('Error:', 'You may select only one frame');
    sys.exit(1)

frame = scribus.getSelectedObject(0)
try:
    char_n = scribus.getTextLength(frame)
except scribus.WrongFrameTypeError:
    scribus.messageBox('Error:', 'You may only adjust text frames');
    sys.exit(1)

if char_n == 0 :
    scribus.messageBox('Error:', 'You can\'t adjust an empty frame');
    sys.exit(1)

# get some page and frame measure
(pw, x) = scribus.getPageSize();
(x, pm, x, x) = scribus.getPageMargins(); # warning: gets the margins from document setup not for the current page

(x, y) = scribus.getPosition(frame)

right = (pw - pm) - x

(w, h) = scribus.getSize(frame)

# if the frame doesn't overflow, shorten it to make it overflow
while (((scribus.textOverflows(frame) == 0) or (w > right)) and (w > 0)) :
    w -= 10
    scribus.sizeObject(w, h, frame)

# resize the frame in 10pt steps
while ((scribus.textOverflows(frame) > 0) and (w < right)) :
    w += 10
    scribus.sizeObject(w, h, frame)

# undo the latest 10pt step and fine adjust in 1pt steps
w -= 10
scribus.sizeObject(w, h, frame)

while ((scribus.textOverflows(frame) > 0) and (w < right)) :
    w += 1
    scribus.sizeObject(w, h, frame)