# [reportlab-users] Font size, baseline and typography stuff

Robin Becker robin at reportlab.com
Fri Aug 5 08:40:12 EDT 2011

On 05/08/2011 13:18, Andy Robinson wrote:
..........

>

> (As a corollary, all complaints about any particular font need to be

> directed to the author of the font in question ;-) )

>

> Robin's technique of actually converting the text to a series of

> curves and asking for the boundaries is about as good as we will ever

> be able to get in ReportLab-land, and hopefully it is feasible for

> titles and 'word art'. It's certainly better than trusting the metrics

> supplied with the font.

>

> - Andy

with the caveat that our current getBounds for paths is using an extremely dodgy
approximation for the curveTo bounds. I've been through the analysis now and it
is possible to find the extrema properly so that will likely appear soon.

For those who want to check my (rather maxima's) analysis the code for the y
(ditto for x) points is

> def _getBezierExtrema(y0,y1,y2,y3):

> '''

> this is used to find if a curveTo path operator has extrema in its range

> The curveTo operator is defined by the points y0, y1, y2, y3

>

> B(t):=(1-t)^3*y0+3*(1-t)^2*t*y1+3*(1-t)*t^2*y2+t^3*y3

> :=t^3*(y3-3*y2+3*y1-y0)+t^2*(3*y2-6*y1+3*y0)+t*(3*y1-3*y0)+y0

> and is a cubic bezier curve.

>

> The differential is a quadratic

> t^2*(3*y3-9*y2+9*y1-3*y0)+t*(6*y2-12*y1+6*y0)+3*y1-3*y0

>

> The extrema must be at real roots, r, of the above which lie in 0<=r<=1

>

> a=3*y3-9*y2+9*y1-3*y0 b=6*y2-12*y1+6*y0 c=3*y1-3*y0

> or

> a=y3-3*y2+3*y1-y0 b=2*y2-4*y1+2*y0 c=y1-y0 (remove common factor of 3)

> or

> a=y3-3*(y2-y1)-y0 b=2*(y2-2*y1+y0) c=y1-y0

>

> The returned value is [y0,x1,x2,y3] where if found x1, x2 are any extremals that were found;

> there can be 0, 1 or 2 extremals

> '''

> a=y3-3*(y2-y1)-y0

> b=2*(y2-2*y1+y0)

> c=y1-y0

> Y = [y0] #the set of points

>

> #standard method to find roots of quadratic

> d = b*b - 4*a*c

> if d>=0:

> d = sqrt(d)

> if b<0: d = -d

> q = -0.5*(b+d)

> R = []

> try:

> R.append(q/a)

> except:

> pass

> try:

> R.append(c/q)

> except:

> pass

> for t in R:

> if 0<=t<=1:

> #real root in range evaluate spline there and add to X

> t2 = t*t

> t3 = t*t2

> Y.append(t3*a+1.5*t2*b+3*c*t+y0)

> Y.append(y3)

> return Y

anyone who knows a better technique for the extreme values (x/y) for a cubic
bezier curve is welcome to comment
--
Robin Becker