Discussion:
[reportlab-users] vertically centered text
Aaron Spike
2008-01-28 20:53:10 UTC
Permalink
I am able to center text horizontally with the drawCenteredString()
function that the api provides. I haven't been able to find any way to
center text vertically (or both vertically and horizontally at the same
time). Is there any font metric I can access to adjust the vertical
placement of text so that I can center it on a point?

Aaron Spike
Robin Becker
2008-01-28 22:05:41 UTC
Permalink
Post by Aaron Spike
I am able to center text horizontally with the drawCenteredString()
function that the api provides. I haven't been able to find any way to
center text vertically (or both vertically and horizontally at the same
time). Is there any font metric I can access to adjust the vertical
placement of text so that I can center it on a point?
Aaron Spike
.......
The y coordinate of a drawString type operation ends up as being the
baseline of the text. Typically text is not vertically symmetric so is
not visually centered. A good rule of thumb is that the part below the
base line is 20% of the point size ie the vertical middle of the text is
40% of the pointsize above the normal base line. However, these
assumptions are clearly dependent on exactly which glyphs are being
used. I know this is not a decent answer, but you can obtain the curves
being used for a particular string using
reportlab.graphics.charts.textlabels._text2path

def _text2Path(text, x=0, y=0, fontName='Times-Roman', fontSize=1000,
anchor='start', truncate=1, pathReverse=0):


the returned path can then be used to obtain a bounding box ie
Post by Aaron Spike
from reportlab.graphics.charts.textlabels import _text2Path
p=_text2Path('a min')
p.getBounds()
(34, -14, 2246, 694)
Post by Aaron Spike
p=_text2Path('A min')
p.getBounds()
(10, 0, 2524, 694)
so you can see that A is taller than a
--
Robin Becker
Aaron Spike
2008-01-28 23:16:07 UTC
Permalink
Post by Robin Becker
The y coordinate of a drawString type operation ends up as being the
baseline of the text. Typically text is not vertically symmetric so is
not visually centered.
Yes, and this works great because it is the natural visual anchor point
for most uses of text. But if you want to center text in a tightly
containing shape it is difficult. In my particular application I want to
center text in a circle. If it isn't close to exactly centered it
distracts the eye.
Post by Robin Becker
A good rule of thumb is that the part below the
base line is 20% of the point size ie the vertical middle of the text is
40% of the pointsize above the normal base line.
I tried using some magic numbers like these and found the results
unsatisfactory.
Post by Robin Becker
However, these
assumptions are clearly dependent on exactly which glyphs are being
used. I know this is not a decent answer, but you can obtain the curves
being used for a particular string using
reportlab.graphics.charts.textlabels._text2path
def _text2Path(text, x=0, y=0, fontName='Times-Roman', fontSize=1000,
the returned path can then be used to obtain a bounding box ie
from reportlab.graphics.charts.textlabels import _text2Path
p=_text2Path('a min')
p.getBounds()
(34, -14, 2246, 694)
p=_text2Path('A min')
p.getBounds()
(10, 0, 2524, 694)
so you can see that A is taller than a
_text2path looks like exactly what I need. When I'm working with Cairo I
use text_extents to find the bounds of a particular piece of text:

http://cairographics.org/manual/cairo-Scaled-Fonts.html#cairo-text-extents-t



My output with Cairo looks like:

http://www.ekips.org/misc/arpeggio/all.pdf

I'd like to make my diagrams flowable and use reportlab's layout
features for titles and annotations.

Should I be afraid that _text2path looks like a private part of the API?
or am I free to use that? Is there no public way to get this info? Maybe
something which can look into the current text rendering context?

Aaron Spike
Aaron Spike
2008-01-29 02:41:47 UTC
Permalink
Post by Aaron Spike
http://www.ekips.org/misc/arpeggio/all.pdf
Here is my new output using reportlab and the technique described in
this thread:

http://www.ekips.org/misc/arpeggio/reportlab_arps.pdf

As you can see it works. Thanks. But I'm still open to a more
presentable means.

Aaron Spike
Aaron Spike
2008-01-29 02:17:16 UTC
Permalink
Post by Robin Becker
from reportlab.graphics.charts.textlabels import _text2Path
p=_text2Path('a min')
p.getBounds()
(34, -14, 2246, 694)
p=_text2Path('A min')
p.getBounds()
(10, 0, 2524, 694)
Trying this.

I do:

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.graphics.charts.textlabels import _text2Path

FACE = 'Helvetica'
SIZE = 12

def t(text):
p = _text2Path(text, 0, 0, FACE, SIZE)
return text, p.getBounds()

c = canvas.Canvas('_text2Path_test.pdf', pagesize=letter)
print c.getAvailableFonts()
c.setFont(FACE, SIZE)

print t('test')
print t('tegt')
print t('a min')
print t('A min')

I get:

C:\Documents and Settings\Aaron\Desktop\arpeggio\arpeggio>text2Path.py
['Courier', 'Courier-Bold', 'Courier-BoldOblique', 'Courier-Oblique',
'Helvetica
', 'Helvetica-Bold', 'Helvetica-BoldOblique', 'Helvetica-Oblique',
'Symbol', 'Ti
mes-Bold', 'Times-BoldItalic', 'Times-Italic', 'Times-Roman',
'ZapfDingbats']
Warn: Can't find .pfb for face 'Helvetica'
Traceback (most recent call last):
File "C:\Documents and
Settings\Aaron\Desktop\arpeggio\arpeggio\text2Path.py",
line 16, in <module>
print t('test')
File "C:\Documents and
Settings\Aaron\Desktop\arpeggio\arpeggio\text2Path.py",
line 9, in t
p = _text2Path(text, 0, 0, FACE, SIZE)
File
"C:\Python25\lib\site-packages\reportlab\graphics\charts\textlabels.py",
line 80, in _text2Path

fontSize=fontSize,anchor=anchor,truncate=truncate,pathReverse=pathReverse))
File
"C:\Python25\lib\site-packages\reportlab\graphics\charts\textlabels.py",
line 65, in _text2PathDescription
renderPM._setFont(_gs,fontName,fontSize)
File "C:\Python25\lib\site-packages\reportlab\graphics\renderPM.py",
line 212,
in _setFont
raise RenderPMError, "Can't setFont(%s) missing the T1
files?\nOriginally %s
: %s" % (fontName,s1,s2)
reportlab.graphics.renderPM.RenderPMError: Can't setFont(Helvetica)
missing the
T1 files?
Originally <type 'exceptions.TypeError'>: makeT1Font() argument 2 must
be string
, not None


I turned up an old thread on google:

http://osdir.com/ml/python.reportlab.user/2005-05/msg00088.html
http://osdir.com/ml/python.reportlab.user/2005-05/msg00092.html
http://bioinf.scri.ac.uk/lp/downloads/programs/genomediagram/renderPM_help.txt

I don't happen to have Acrobat Reader <=5 installed here, so I placed
the Type1 fonts in the fonts directory of the reportlab package. Is
there anything better I can do? I'm wondering, what was the "ready
answer" that Andy had for me?

Aaron Spike
Robin Becker
2008-01-29 10:00:55 UTC
Permalink
................
Post by Aaron Spike
T1 files?
Originally <type 'exceptions.TypeError'>: makeT1Font() argument 2 must
be string
, not None
http://osdir.com/ml/python.reportlab.user/2005-05/msg00088.html
http://osdir.com/ml/python.reportlab.user/2005-05/msg00092.html
http://bioinf.scri.ac.uk/lp/downloads/programs/genomediagram/renderPM_help.txt
I don't happen to have Acrobat Reader <=5 installed here, so I placed
the Type1 fonts in the fonts directory of the reportlab package. Is
there anything better I can do? I'm wondering, what was the "ready
answer" that Andy had for me?
.......
normally speaking the t1 fonts should be found if placed in that folder. It
might be the case that the names are wrong. The ones I have there (on my winxp
box) look like

_ab_____.pfb
_abi____.pfb
_ai_____.pfb
_eb_____.pfb
_ebi____.pfb
_ei_____.pfb
_er_____.pfb
aebl____.afm
aebl____.pfb
ael_____.afm
ael_____.inf
ael_____.pfb
aelo____.afm
aelo____.inf
aelo____.pfb
cob_____.pfb
cobo____.pfb
com_____.pfb
coo_____.pfb
sy______.pfb
zd______.pfb
zx______.pfb
zy______.pfb
--
Robin Becker
Andy Robinson
2008-01-29 10:34:01 UTC
Permalink
Post by Aaron Spike
I don't happen to have Acrobat Reader <=5 installed here, so I placed
the Type1 fonts in the fonts directory of the reportlab package. Is
there anything better I can do? I'm wondering, what was the "ready
answer" that Andy had for me?
I don't know either, it was 2 years back, but here's the problem.

We do not feel comfortable redistributing Adobe's metrics or font
files within our own open source distribution, as we haven't a clue
what permissions or license text would be needed. (They are available
in a separate file)

We also don't feel comfortable including non-Adobe files, as they are
supposed to be the 'Standard 14' files and it would be equally wrong
to include some other fonts which look roughly like
Helvetica/Times/Courier but may have subtly different shapes and
metrics.

PDF is now moving towards always embedding font files, rather than
just assuming they are present in the reader. This is part of the
PDF/A specification to make sure they can still be opened in 50 years
time and look the same. So, the answer will be for us to include a
standard set of open source fonts in our distro, use only those in our
test cases (thus ensuring you have the same fonts for bitmaps and
PDFs), and tell people clearly they are not 'genuine Adobe Helvetica'
or whatever. This is likely to happen in a release later this year.

Best Regards,


Andy Robinson

Rich Shepard
2008-01-28 22:08:25 UTC
Permalink
Post by Aaron Spike
I am able to center text horizontally with the drawCenteredString()
function that the api provides. I haven't been able to find any way to
center text vertically (or both vertically and horizontally at the same
time). Is there any font metric I can access to adjust the vertical
placement of text so that I can center it on a point?
Aaron,

Trial-and-error while manually tweaking the cursor's position is the way
to go. Not very automated, but you get exceptionally fine control of text
placement this way.

Rich
--
Richard B. Shepard, Ph.D. | Integrity Credibility
Applied Ecosystem Services, Inc. | Innovation
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863
Continue reading on narkive:
Loading...