Text and font metrics

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Text and font metrics

JordanBrown

I was making From/To cards for Christmas, and there was no way to make them automatically size to fit the text.  What the heck, I'm off work for the next week and this seems like a more or less straightforward project.

I have it mostly working, give or take the halign/valign issues I discussed in a separate message.

tm = textmetrics(text=s, size=size, valign=valign, halign=halign, font=f, direction=dir);

yields

[
    [ minx, miny ],            // bounding box lower left corner
    [ width, height ],         // bounding box size
    [ advance_x, advance_y],   // translation for next text block
    [ ascent, descent ]        // Distance above/below baseline
]

I'm debating whether I need to add a width result, for vertical layouts, that would be the maximum character width.  This is distinct from bounding box; as noted in another message, some glyphs have ink outside the box that's used for spacing.  The bounding box above is intended to enclose all ink, while this width would be based on the spacing box.

Similarly,

fm = fontmetrics(font=f, size=size);

returns font-global information:

[
    [ ascent, descent ],	// Typographic ascent and descent
    [ max-ascent, max-descent],	// actual maximums
    leading			// inter-line spacing
]

These allow you to do things like this:

s = "Hello World!";
valign = "baseline";
halign = "left";
f = "Freestyle Script";
dir = "ltr";
size = 20;

tm = textmetrics(s, size=size, valign=valign, halign=halign, font=f, direction=dir);
translate(tm[0]) cube(concat(tm[1],1));
color("lightgreen") linear_extrude(height=2) text(s, size=size, valign=valign, halign=halign, font=f, direction=dir);

Note that that yellow cube will track whatever text you put in, with whatever layout parameters you give.

Any additional ideas?  Any additional parameters to return?  Bikeshedding names or return values?

Issues:

  • Cleanup, error handling
  • Commonize measurement functionality with render function.
  • ttb/btt layout issues as described in another thread.
  • There's a 2.4% error between the size you give and the size you get.  I *think* I've compensated for it correctly, but need to analyze it more.  (Ref issue #2436.)
  • There appears to be a *very small* error somewhere that causes the very edges of glyphs to go outside the bounding box, or maybe to not quite make it to the edge of the bounding box.  This might be an error that the FreeType documentation mentions associated with font hinting that makes the actual points not quite match the bounding box.  They describe it as up to a one-pixel error, whatever that means for a vector environment.

(That 2.4% error is a real nuisance.  Font metrics are already complex, and there are something like four or five different scales used for the various values.  Adding another makes things just that much more complicated.)



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

JordanBrown

In IRC, Torsten asked about whether my font metrics stuff could handle حرف‌باز, HarfBuzz in Persian.  Yes, it can.


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

MichaelAtOz'
In reply to this post by JordanBrown

As mentioned elsewhere, space= & alignment has peculiarities.

 

I raise it here as it seems to be bounding box (BB) related, it would be interesting to know what the textmetrics produce.

 

The following shows "XX" with, top down, space=2, space=1, space=0.5.

 

The easy one is halign="left", looks normal:

 

The red blocks show the advance with space=2.

The dark blue, the 0.5 advance, ie goes back, the second X starts at the left edge, the light blue the (back) advance of the second X.

Should BB include the right red space, or exclude the light blue. Because...

 

halign="right":

Again the red block shows the advance, and why 'X X' is not butted-up to the axis.

Similarly the (back) advance light blue shows why it is in-effect butted up, but not actually.

 

halign="center":

Again centred including the forward/back advance.

i.e BB with red block included is centred, BB from left of 1st X to left of light blue is centred.

 

Given backward compatibility, we should not change this behaviour (??), so to be useful the output from textmetrics() should

present enough information to be able to correct this to get actual alignment.

 

That was all with direction="ltr", I need to look at "rtl" and also ttb/btt.

 

The three .scad files are attached if anyone wants to play.

 

 


From: Discuss [mailto:[hidden email]] On Behalf Of Jordan Brown
Sent: Mon, 28 Dec 2020 15:55
To: OpenSCAD general discussion
Subject: [OpenSCAD] Text and font metrics

 

I was making From/To cards for Christmas, and there was no way to make them automatically size to fit the text.  What the heck, I'm off work for the next week and this seems like a more or less straightforward project.

I have it mostly working, give or take the halign/valign issues I discussed in a separate message.

tm = textmetrics(text=s, size=size, valign=valign, halign=halign, font=f, direction=dir);

yields

[
    [ minx, miny ],            // bounding box lower left corner
    [ width, height ],         // bounding box size
    [ advance_x, advance_y],   // translation for next text block
    [ ascent, descent ]        // Distance above/below baseline
]

I'm debating whether I need to add a width result, for vertical layouts, that would be the maximum character width.  This is distinct from bounding box; as noted in another message, some glyphs have ink outside the box that's used for spacing.  The bounding box above is intended to enclose all ink, while this width would be based on the spacing box.

Similarly,

fm = fontmetrics(font=f, size=size);

returns font-global information:

[
    [ ascent, descent ],       // Typographic ascent and descent
    [ max-ascent, max-descent], // actual maximums
    leading                    // inter-line spacing
]

These allow you to do things like this:

s = "Hello World!";
valign = "baseline";
halign = "left";
f = "Freestyle Script";
dir = "ltr";
size = 20;
 
tm = textmetrics(s, size=size, valign=valign, halign=halign, font=f, direction=dir);
translate(tm[0]) cube(concat(tm[1],1));
color("lightgreen") linear_extrude(height=2) text(s, size=size, valign=valign, halign=halign, font=f, direction=dir);

Note that that yellow cube will track whatever text you put in, with whatever layout parameters you give.

Any additional ideas?  Any additional parameters to return?  Bikeshedding names or return values?

Issues:

  • Cleanup, error handling
  • Commonize measurement functionality with render function.
  • ttb/btt layout issues as described in another thread.
  • There's a 2.4% error between the size you give and the size you get.  I *think* I've compensated for it correctly, but need to analyze it more.  (Ref issue #2436.)
  • There appears to be a *very small* error somewhere that causes the very edges of glyphs to go outside the bounding box, or maybe to not quite make it to the edge of the bounding box.  This might be an error that the FreeType documentation mentions associated with font hinting that makes the actual points not quite match the bounding box.  They describe it as up to a one-pixel error, whatever that means for a vector environment.

(That 2.4% error is a real nuisance.  Font metrics are already complex, and there are something like four or five different scales used for the various values.  Adding another makes things just that much more complicated.)

 


Virus-free. www.avg.com

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

text left.scad (835 bytes) Download Attachment
text right.scad (814 bytes) Download Attachment
text center.scad (777 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

MichaelAtOz
Administrator

direction="rtl" is also broken, as like the ttb/btt broken, I'll post pictures, but they are effectively the same.

 


From: Discuss [mailto:[hidden email]] On Behalf Of Michael Marx
Sent: Wed, 30 Dec 2020 12:30
To: 'OpenSCAD general discussion'
Subject: Re: [OpenSCAD] Text and font metrics

 

As mentioned elsewhere, space= & alignment has peculiarities.

 

I raise it here as it seems to be bounding box (BB) related, it would be interesting to know what the textmetrics produce.

 

The following shows "XX" with, top down, space=2, space=1, space=0.5.

 

The easy one is halign="left", looks normal:

 

The red blocks show the advance with space=2.

The dark blue, the 0.5 advance, ie goes back, the second X starts at the left edge, the light blue the (back) advance of the second X.

Should BB include the right red space, or exclude the light blue. Because...

 

halign="right":

Again the red block shows the advance, and why 'X X' is not butted-up to the axis.

Similarly the (back) advance light blue shows why it is in-effect butted up, but not actually.

 

halign="center":

Again centred including the forward/back advance.

i.e BB with red block included is centred, BB from left of 1st X to left of light blue is centred.

 

Given backward compatibility, we should not change this behaviour (??), so to be useful the output from textmetrics() should

present enough information to be able to correct this to get actual alignment.

 

That was all with direction="ltr", I need to look at "rtl" and also ttb/btt.

 

The three .scad files are attached if anyone wants to play.

 

 


From: Discuss [mailto:[hidden email]] On Behalf Of Jordan Brown
Sent: Mon, 28 Dec 2020 15:55
To: OpenSCAD general discussion
Subject: [OpenSCAD] Text and font metrics

 

I was making From/To cards for Christmas, and there was no way to make them automatically size to fit the text.  What the heck, I'm off work for the next week and this seems like a more or less straightforward project.

I have it mostly working, give or take the halign/valign issues I discussed in a separate message.

tm = textmetrics(text=s, size=size, valign=valign, halign=halign, font=f, direction=dir);

yields

[
    [ minx, miny ],            // bounding box lower left corner
    [ width, height ],         // bounding box size
    [ advance_x, advance_y],   // translation for next text block
    [ ascent, descent ]        // Distance above/below baseline
]

I'm debating whether I need to add a width result, for vertical layouts, that would be the maximum character width.  This is distinct from bounding box; as noted in another message, some glyphs have ink outside the box that's used for spacing.  The bounding box above is intended to enclose all ink, while this width would be based on the spacing box.

Similarly,

fm = fontmetrics(font=f, size=size);

returns font-global information:

[
    [ ascent, descent ],       // Typographic ascent and descent
    [ max-ascent, max-descent], // actual maximums
    leading                    // inter-line spacing
]

These allow you to do things like this:

s = "Hello World!";
valign = "baseline";
halign = "left";
f = "Freestyle Script";
dir = "ltr";
size = 20;
 
tm = textmetrics(s, size=size, valign=valign, halign=halign, font=f, direction=dir);
translate(tm[0]) cube(concat(tm[1],1));
color("lightgreen") linear_extrude(height=2) text(s, size=size, valign=valign, halign=halign, font=f, direction=dir);

Note that that yellow cube will track whatever text you put in, with whatever layout parameters you give.

Any additional ideas?  Any additional parameters to return?  Bikeshedding names or return values?

Issues:

  • Cleanup, error handling
  • Commonize measurement functionality with render function.
  • ttb/btt layout issues as described in another thread.
  • There's a 2.4% error between the size you give and the size you get.  I *think* I've compensated for it correctly, but need to analyze it more.  (Ref issue #2436.)
  • There appears to be a *very small* error somewhere that causes the very edges of glyphs to go outside the bounding box, or maybe to not quite make it to the edge of the bounding box.  This might be an error that the FreeType documentation mentions associated with font hinting that makes the actual points not quite match the bounding box.  They describe it as up to a one-pixel error, whatever that means for a vector environment.

(That 2.4% error is a real nuisance.  Font metrics are already complex, and there are something like four or five different scales used for the various values.  Adding another makes things just that much more complicated.)

 

 

Virus-free. www.avg.com


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
OpenSCAD Admin - email* me if you need anything, or if I've done something stupid...
* on the Forum, click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain;
to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work.
Obviously inclusion of works of previous authors is not included in the above.
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

MichaelAtOz'

direction="rtl" - appears to me to be wrong, in the way ttb/btt is wrong.

 

Changed to "XY" to show the direction.

Note I did not change the position of the red blocks, but added green for rtl advance, I moved the blue. (I think correctly)

If it goes rtl the space=2 Y should have the advance on the left, and

if behaving similarly the Y should be positioned more to the right with an advance space to its left,

ie axis|<advance gap>Y<advance gap>X, like a mirror of the ltr/halign-right in previous post.

Basically it should be shifted right so the light green is on the right of the axis. Dark green is the X advance.

Similarly the space=0.5 should have ½ Y to the left of the axis.

The right side of light blue is the Y (back) advance, should be on the axis.

 

Basically the bounding box should be looked at backwards, trailing advance (or back) on the left.

 

The space=2 should have the X butted-up to the axis. Green shows the advances.

Ditto space=0.5 butted-up to X

 

The space=2 BB should be right side of X to left side of light green advance,

i.e. a mirror of the non-centred 'X X' of ltr.

space=0.5 should actually look centred on 'YX' (visually).

Again rtl advance should nudge the BB to the right.

 

Given this is probably broken, rather than an interpretation of glyph v's advance, maybe this

reverse direction should be fixed. ??

 

I'll think about ttb/btt tomorrow.

 

 


From: Discuss [mailto:[hidden email]] On Behalf Of MichaelAtOz
Sent: Wed, 30 Dec 2020 12:39
To: 'OpenSCAD general discussion'
Subject: Re: [OpenSCAD] Text and font metrics

 

direction="rtl" is also broken, as like the ttb/btt broken, I'll post pictures, but they are effectively the same.

 


From: Discuss [mailto:[hidden email]] On Behalf Of Michael Marx
Sent: Wed, 30 Dec 2020 12:30
To: 'OpenSCAD general discussion'
Subject: Re: [OpenSCAD] Text and font metrics

 

As mentioned elsewhere, space= & alignment has peculiarities.

 

I raise it here as it seems to be bounding box (BB) related, it would be interesting to know what the textmetrics produce.

 

The following shows "XX" with, top down, space=2, space=1, space=0.5.

 

The easy one is halign="left", looks normal:

 

The red blocks show the advance with space=2.

The dark blue, the 0.5 advance, ie goes back, the second X starts at the left edge, the light blue the (back) advance of the second X.

Should BB include the right red space, or exclude the light blue. Because...

 

halign="right":

Again the red block shows the advance, and why 'X X' is not butted-up to the axis.

Similarly the (back) advance light blue shows why it is in-effect butted up, but not actually.

 

halign="center":

Again centred including the forward/back advance.

i.e BB with red block included is centred, BB from left of 1st X to left of light blue is centred.

 

Given backward compatibility, we should not change this behaviour (??), so to be useful the output from textmetrics() should

present enough information to be able to correct this to get actual alignment.

 

That was all with direction="ltr", I need to look at "rtl" and also ttb/btt.

 

The three .scad files are attached if anyone wants to play.

 

 


From: Discuss [mailto:[hidden email]] On Behalf Of Jordan Brown
Sent: Mon, 28 Dec 2020 15:55
To: OpenSCAD general discussion
Subject: [OpenSCAD] Text and font metrics

 

I was making From/To cards for Christmas, and there was no way to make them automatically size to fit the text.  What the heck, I'm off work for the next week and this seems like a more or less straightforward project.

I have it mostly working, give or take the halign/valign issues I discussed in a separate message.

tm = textmetrics(text=s, size=size, valign=valign, halign=halign, font=f, direction=dir);

yields

[
    [ minx, miny ],            // bounding box lower left corner
    [ width, height ],         // bounding box size
    [ advance_x, advance_y],   // translation for next text block
    [ ascent, descent ]        // Distance above/below baseline
]

I'm debating whether I need to add a width result, for vertical layouts, that would be the maximum character width.  This is distinct from bounding box; as noted in another message, some glyphs have ink outside the box that's used for spacing.  The bounding box above is intended to enclose all ink, while this width would be based on the spacing box.

Similarly,

fm = fontmetrics(font=f, size=size);

returns font-global information:

[
    [ ascent, descent ],       // Typographic ascent and descent
    [ max-ascent, max-descent], // actual maximums
    leading                    // inter-line spacing
]

These allow you to do things like this:

s = "Hello World!";
valign = "baseline";
halign = "left";
f = "Freestyle Script";
dir = "ltr";
size = 20;
 
tm = textmetrics(s, size=size, valign=valign, halign=halign, font=f, direction=dir);
translate(tm[0]) cube(concat(tm[1],1));
color("lightgreen") linear_extrude(height=2) text(s, size=size, valign=valign, halign=halign, font=f, direction=dir);

Note that that yellow cube will track whatever text you put in, with whatever layout parameters you give.

Any additional ideas?  Any additional parameters to return?  Bikeshedding names or return values?

Issues:

  • Cleanup, error handling
  • Commonize measurement functionality with render function.
  • ttb/btt layout issues as described in another thread.
  • There's a 2.4% error between the size you give and the size you get.  I *think* I've compensated for it correctly, but need to analyze it more.  (Ref issue #2436.)
  • There appears to be a *very small* error somewhere that causes the very edges of glyphs to go outside the bounding box, or maybe to not quite make it to the edge of the bounding box.  This might be an error that the FreeType documentation mentions associated with font hinting that makes the actual points not quite match the bounding box.  They describe it as up to a one-pixel error, whatever that means for a vector environment.

(That 2.4% error is a real nuisance.  Font metrics are already complex, and there are something like four or five different scales used for the various values.  Adding another makes things just that much more complicated.)

 

 

Virus-free. www.avg.com


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

lar3ry
In reply to this post by JordanBrown
Talkative, you are!



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

MichaelAtOz
Administrator
In reply to this post by MichaelAtOz'

direction= ttb/btt has similar alignment issues with space!=0

 

Given the abnormal behaviour of ttb/bbt with valign that Jordan first raised,

the valign="center" is the only one I could test.

 

 

ttb has the same relative behaviour as ltr, ie the 'incorrect' centre due to the trailing advance.

Hence textmetrics() likewise could provide info to allow manually 'correctly' centring.

 

 

Likewise btt & space=2 does not correctly handle the reverse direction advance,

'X Y ' is in the same position.

It should handle the advance being 'after' Y in btt direction, and

produce the 'incorrect' centre, ie the above should be shifted down by one red block.

And space=0.5 likewise, to behave the same as ltr, to do the 'incorrect' centre,

the middle of X should be on the axis.

That would be consistent with the ttb behaviour.

 

So to summarise for space!=0 alignment if off, but really off in the other direction.

 

In 'forward'* processing the valign/halign# appropriate to 'forward' uses the position of

the last advance (which will be different to the edge of the last glyph) to do the BB which

is used to apply the alignment offset. Resulting in misalignment. [current behaviour]

 

*'forward' ie intrinsic direction, ltr or ttb

# halign for ltr/rtl, valign for ttb/btt

 

But with 'reverse' processing it doesn't consider the advance should apply to the 'other' end.

BB is the same as 'forward' so the misalignment is not in the correct direction to be consistent.

 

Well that is how it appears from the output, I have yet to look at the code, but that may be beyond me.

 

So the 'forward' misalignment is an unfortunate choice at the time, and unless

we choose to break backward compatibility, it should stay that way, but textmetrics() could

provide something like the advance, so text() could be manually positioned correctly.

 

However, I believe the 'reverse' processing is a bug and should be fixed.

Doing so will still have a misalignment, but it will be in the consistent place relative to the direction.

So again textmetrics() could provide the info to manually correct it.

 

That concludes my investigation.

 

 


From: Discuss [mailto:[hidden email]] On Behalf Of Michael Marx
Sent: Wed, 30 Dec 2020 13:42
To: 'OpenSCAD general discussion'
Subject: Re: [OpenSCAD] Text and font metrics

 

direction="rtl" - appears to me to be wrong, in the way ttb/btt is wrong.

 

Changed to "XY" to show the direction.

Note I did not change the position of the red blocks, but added green for rtl advance, I moved the blue. (I think correctly)

If it goes rtl the space=2 Y should have the advance on the left, and

if behaving similarly the Y should be positioned more to the right with an advance space to its left,

ie axis|<advance gap>Y<advance gap>X, like a mirror of the ltr/halign-right in previous post.

Basically it should be shifted right so the light green is on the right of the axis. Dark green is the X advance.

Similarly the space=0.5 should have ½ Y to the left of the axis.

The right side of light blue is the Y (back) advance, should be on the axis.

 

Basically the bounding box should be looked at backwards, trailing advance (or back) on the left.

 

The space=2 should have the X butted-up to the axis. Green shows the advances.

Ditto space=0.5 butted-up to X

 

The space=2 BB should be right side of X to left side of light green advance,

i.e. a mirror of the non-centred 'X X' of ltr.

space=0.5 should actually look centred on 'YX' (visually).

Again rtl advance should nudge the BB to the right.

 

Given this is probably broken, rather than an interpretation of glyph v's advance, maybe this

reverse direction should be fixed. ??

 

I'll think about ttb/btt tomorrow.

 

 


From: Discuss [mailto:[hidden email]] On Behalf Of MichaelAtOz
Sent: Wed, 30 Dec 2020 12:39
To: 'OpenSCAD general discussion'
Subject: Re: [OpenSCAD] Text and font metrics

 

direction="rtl" is also broken, as like the ttb/btt broken, I'll post pictures, but they are effectively the same.

 


From: Discuss [mailto:[hidden email]] On Behalf Of Michael Marx
Sent: Wed, 30 Dec 2020 12:30
To: 'OpenSCAD general discussion'
Subject: Re: [OpenSCAD] Text and font metrics

 

As mentioned elsewhere, space= & alignment has peculiarities.

 

I raise it here as it seems to be bounding box (BB) related, it would be interesting to know what the textmetrics produce.

 

The following shows "XX" with, top down, space=2, space=1, space=0.5.

 

The easy one is halign="left", looks normal:

 

The red blocks show the advance with space=2.

The dark blue, the 0.5 advance, ie goes back, the second X starts at the left edge, the light blue the (back) advance of the second X.

Should BB include the right red space, or exclude the light blue. Because...

 

halign="right":

Again the red block shows the advance, and why 'X X' is not butted-up to the axis.

Similarly the (back) advance light blue shows why it is in-effect butted up, but not actually.

 

halign="center":

Again centred including the forward/back advance.

i.e BB with red block included is centred, BB from left of 1st X to left of light blue is centred.

 

Given backward compatibility, we should not change this behaviour (??), so to be useful the output from textmetrics() should

present enough information to be able to correct this to get actual alignment.

 

That was all with direction="ltr", I need to look at "rtl" and also ttb/btt.

 

The three .scad files are attached if anyone wants to play.

 

 


From: Discuss [mailto:[hidden email]] On Behalf Of Jordan Brown
Sent: Mon, 28 Dec 2020 15:55
To: OpenSCAD general discussion
Subject: [OpenSCAD] Text and font metrics

 

I was making From/To cards for Christmas, and there was no way to make them automatically size to fit the text.  What the heck, I'm off work for the next week and this seems like a more or less straightforward project.

I have it mostly working, give or take the halign/valign issues I discussed in a separate message.

tm = textmetrics(text=s, size=size, valign=valign, halign=halign, font=f, direction=dir);

yields

[
    [ minx, miny ],            // bounding box lower left corner
    [ width, height ],         // bounding box size
    [ advance_x, advance_y],   // translation for next text block
    [ ascent, descent ]        // Distance above/below baseline
]

I'm debating whether I need to add a width result, for vertical layouts, that would be the maximum character width.  This is distinct from bounding box; as noted in another message, some glyphs have ink outside the box that's used for spacing.  The bounding box above is intended to enclose all ink, while this width would be based on the spacing box.

Similarly,

fm = fontmetrics(font=f, size=size);

returns font-global information:

[
    [ ascent, descent ],       // Typographic ascent and descent
    [ max-ascent, max-descent], // actual maximums
    leading                    // inter-line spacing
]

These allow you to do things like this:

s = "Hello World!";
valign = "baseline";
halign = "left";
f = "Freestyle Script";
dir = "ltr";
size = 20;
 
tm = textmetrics(s, size=size, valign=valign, halign=halign, font=f, direction=dir);
translate(tm[0]) cube(concat(tm[1],1));
color("lightgreen") linear_extrude(height=2) text(s, size=size, valign=valign, halign=halign, font=f, direction=dir);

Note that that yellow cube will track whatever text you put in, with whatever layout parameters you give.

Any additional ideas?  Any additional parameters to return?  Bikeshedding names or return values?

Issues:

  • Cleanup, error handling
  • Commonize measurement functionality with render function.
  • ttb/btt layout issues as described in another thread.
  • There's a 2.4% error between the size you give and the size you get.  I *think* I've compensated for it correctly, but need to analyze it more.  (Ref issue #2436.)
  • There appears to be a *very small* error somewhere that causes the very edges of glyphs to go outside the bounding box, or maybe to not quite make it to the edge of the bounding box.  This might be an error that the FreeType documentation mentions associated with font hinting that makes the actual points not quite match the bounding box.  They describe it as up to a one-pixel error, whatever that means for a vector environment.

(That 2.4% error is a real nuisance.  Font metrics are already complex, and there are something like four or five different scales used for the various values.  Adding another makes things just that much more complicated.)

 

 

Virus-free. www.avg.com


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
OpenSCAD Admin - email* me if you need anything, or if I've done something stupid...
* on the Forum, click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain;
to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work.
Obviously inclusion of works of previous authors is not included in the above.
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

JordanBrown
In reply to this post by lar3ry
On 12/29/2020 7:42 PM, lar3ry wrote:
Talkative, you are! 

Indeed.

However, there's a lot of subtlety in text layout, and even more once you introduce some of the slightly-to-very strange behavior that OpenSCAD introduces.

If we're going to add new features to the language, and especially if we tweak the existing behavior of the language, it's important that the stakeholders understand all of the issues.  If you don't care about exactly how text is placed, and you're happy with your existing ability to place it, and you're not doing anything particularly exotic with it, you can probably ignore the whole discussion.  You won't be using the new functions, and any (as yet hypothetical) changes will either be small or will be in exotic cases.  If, on the other hand, you *do* care about these things, if it's really important that your text fit *exactly* where you want it to, if you've had to work around OpenSCAD's ...interesting... behaviors, then you should probably follow the conversation and chime in when you see something that you think might cause you trouble.


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

JordanBrown
In reply to this post by MichaelAtOz'
[ Combined a couple of replies. ]

On 12/29/2020 5:29 PM, Michael Marx wrote:

As mentioned elsewhere, space= & alignment has peculiarities.


Yes, that's all pretty well aligned with my understanding of what's going on.  Plus there are some related and more subtle effects.

The "spacing" issues are related to the fact that halign is with respect to the difference between the origin and the total advance of the string, and the total advance is scaled up by the value of "spacing".
Definition:  "advance" is the amount that the origin is moved before the next glyph is drawn.
Suppose that we have an M that has eight units of ink in a ten-unit box:
.MMMMMMMM.
With just that, you'll get some subtle effects.  When you align it, it's the total width of the box that's used, *not* the size of the ink.  Thus, with | as the Y axis:
          |.MMMMMMMM.
.MMMMMMMM.|
     .MMMM|MMMM.
with halign=right, the ink starts slightly right of the origin, and with halign=left it stops slightly left of the origin - for this hypothetical glyph, one unit left/right.  This is easy to see:



When we add in "spacing", the behavior changes.  "spacing" scales up the advance value.  If we set spacing to 2, the advance for our M becomes 20:
.MMMMMMMM...........
and *that* is what halign uses for its alignment:
                    |.MMMMMMMM...........
.MMMMMMMM...........|
          .MMMMMMMM.|..........

The rightest answer to this sub-problem is to apply "spacing" on all but the last glyph in the string, so that the "extra" spacing on the end isn't counted in alignment.

However, there are other issues that also need to be considered:
  • Note that even without "spacing", the alignment isn't quite what you might expect, because it's based on a character box and the ink is generally inset from the box.  (Note, though, that in some fonts the ink extends *outside* the box and so there are the opposite results, with ink extending on the "wrong" side of the origin.)
  • I'll discuss it in more detail in a standalone message, but a few of the metrics (advance, offset, ascent, descent, but *not* the glyphs themselves) are scaled down by 2.4%, further confusing the issue.

While we're talking about halign and I have the images handy, there's a difference that I'm pretty sure is that 2.4% scaling effect.  Consider these images of the top-left corner of a left-aligned W and the top-right corner of a right-aligned W:


---

With respect to RTL:  the big question there is whether the effect should be to mirror the LTR behavior, or if it should be roughly as if the order of the characters was reversed.  Spacing introduces a relevant asymmetry, which is (I think) what you're describing:  in LTR, there's "extra" space on the right; in RTL should that "extra" space remain on the right or move to the left?  (Mostly I think the answer is that it doesn't matter, because the "extra" space is wrong no matter where you put it.)  Another relevant asymmetry can come from font design:  for instance, the "a" in Freestyle Script protrudes to the left of its nominal box, but has space to its right in the box.  With halign=left, it protrudes slightly left of the Y axis; with halign=right there is space between the Y axis and the ink.  What should happen in RTL?  Should that asymmetry be mirrored?  Current behavior is that the spacing is *not* mirrored; an RTL presentation of a single letter appears to be exactly the same as the LTR presentation of that letter, no matter how it's aligned.

BTW, the reversal associated with RTL happens before ligature processing, so you don't end up with silliness when you lay out a word like "Official".  If it was just reordering the glyphs, that would end up as "l a i c ffi O", and that would be silly.  Instead, it ends up as "l a i c i ff O".  Ligature processing is still done, so "different" rendered RTL is rendered as "t n e r e ffi d", with the reversed "iff" being rendered as an "ffi" ligature.  (In fonts with ligature support.  I'm using Calibri for most of those tests.)

---

With respect to TTB/BTT:  I think the issues there are basically similar to the LTR/RTL issues, with the added confusion of the other problems with TTB/BTT.

---
[ And back to the original message for the bottom line... ]

I raise it here as it seems to be bounding box (BB) related, it would be interesting to know what the textmetrics produce.


Indeed.  As the old joke goes, what do you want it to produce?

I have been thinking about it more in the context of the 2.4% scaling mismatch, but there is a question of what textmetrics() should return:  should it return values that are compatible with existing OpenSCAD behavior, or should it return values that match the font design and ink placement?

Matching OpenSCAD behavior lets you better understand what halign and valign are doing.  Matching the font design lets you do things that are perhaps artistically correct.  Matching the actual ink placement lets you control *exactly* where the ink goes.

Part of that is easy:  it should report both the font design metrics and the ink placement.  Beyond that, perhaps it should additionally report what OpenSCAD does.

As an example of the difference, in the M example above what is the width of the string?  Is it eight (the width of the ink), ten (the width of the character box), or twenty (the value OpenSCAD uses for alignment)?

Or maybe we should (optionally?) break backward compatibility and try to iron out these issues as much as is possible, so as to have a future that is as consistent and correct as possible.  (I am not optimistic about fixing all of the "spacing" issues.  Some of them are too hard.)

BTW, setting spacing=1024/1000 should cancel out the 2.4% scaling mismatch, at least with respect to horizontal alignment.


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

MichaelAtOz
Administrator

> and *that* is what halign uses for its alignment:

 

Yes, I know.

 

> Note that even without "spacing", the alignment isn't quite what you might expect,

> because it's based on a character box and the ink is generally inset from the box. 

 

This is a good picture:

bearingX is the left-inset, advance - bearingX - width = the right-inset (of import with space!=0).

 

So this is the font designers intent discussion (with space=1),

things may look like crap or alter meaning if the ink started at the origin,

particularly fancy or very-foreign fonts, or symbol fonts.

(I tried inserting some of my Cuneiform & Hieroglyphs* in this email - didn’t work)

 

This is where it is typographically correct, but often graphically awkward.

 

[* no I'm not a language specialist, I use them for esoteric graphics]

 

> (Note, though, that in some fonts the ink extends *outside* the box

> and so there are the opposite results, with ink extending on the "wrong" side of the origin.)

 

Again font designer intent, and alignment of multiple text() calls.

If the text() is jiggled to the 'correct' side you remove the fonts intent,

that information is lost, whereas having something in textmetrics telling you

how much 'wrongness' is there allows it to be compensated for if desired,

including adjusting subsequent text() calls to compensate the jiggle.

 

ie if you manually move your 'A',

 

you could apply that offset to a text() line below making 'a' inset to match the font intent.

 

This may seem trivial, but if you wanted to replicate some real world object which

uses typographic layout, having text() auto-jiggle means you can't match the real layout.

 

Perhaps an option in text() for those who don't care?

galign=true (glyph-align), purely uses the BB of the set-of-glyphs, moved to OpenSCAD origin,

(origin appropriate to ltr/rtl/ttb/btt).

 

> The rightest answer to this sub-problem [extra advance] is to apply "spacing" on all but the last glyph in the string

 

> Spacing introduces a relevant asymmetry, which is (I think) what you're describing: 

> in LTR, there's "extra" space on the right;

> in RTL should that "extra" space remain on the right or move to the left? 

> (Mostly I think the answer is that it doesn't matter, because the "extra" space is wrong no matter where you put it.)

 

Yes that is what I'm describing, and its effect on alignment to origin etc.

 

The point is backward compatibility.

 

We could say

a.         heck fix it all

b.         The LTR 'extra' is a technically correct in a typesetting sense*, but

            unsuited to graphic layout, but is locked-in behaviour

c.         The RTL is just wrong, fix it (as proposed for TTB/BTT)

            to match the locked-in LTR behaviour, ie 'extra' on the proper-end (left)

 

* on reflection, allowing 'extra' to cause valign to fail is not technically typeset correct.

 

So for b. & c. allow concerned people to correct it with textmetrics(),

or another text() option, trimtail=true??

 

The backward compatibility Force is Strong...

 

> a few of the metrics (advance, offset, ascent, descent, but *not* the glyphs themselves) are scaled down by 2.4%

 

I had presumed it was opposite (the glyphs were bigger) but that explains my observations.

valign=top, bottom of red boxes is the OpenSCAD origin. Eyeball says 2.4% could be it.

 

 

Perhaps we should ask the community (in a separate thread) what damage

the various fixes would do to their designs?

 

 

 


From: Discuss [mailto:[hidden email]] On Behalf Of Jordan Brown
Sent: Fri, 1 Jan 2021 06:57
To: OpenSCAD general discussion; Michael Marx
Subject: Re: [OpenSCAD] Text and font metrics

 

[ Combined a couple of replies. ]

On 12/29/2020 5:29 PM, Michael Marx wrote:

As mentioned elsewhere, space= & alignment has peculiarities.


Yes, that's all pretty well aligned with my understanding of what's going on.  Plus there are some related and more subtle effects.

The "spacing" issues are related to the fact that halign is with respect to the difference between the origin and the total advance of the string, and the total advance is scaled up by the value of "spacing".

Definition:  "advance" is the amount that the origin is moved before the next glyph is drawn.

Suppose that we have an M that has eight units of ink in a ten-unit box:

.MMMMMMMM.

With just that, you'll get some subtle effects.  When you align it, it's the total width of the box that's used, *not* the size of the ink.  Thus, with | as the Y axis:

          |.MMMMMMMM.
.MMMMMMMM.|
     .MMMM|MMMM.

with halign=right, the ink starts slightly right of the origin, and with halign=left it stops slightly left of the origin - for this hypothetical glyph, one unit left/right.  This is easy to see:



When we add in "spacing", the behavior changes.  "spacing" scales up the advance value.  If we set spacing to 2, the advance for our M becomes 20:

.MMMMMMMM...........

and *that* is what halign uses for its alignment:

                    |.MMMMMMMM...........
.MMMMMMMM...........|
          .MMMMMMMM.|..........


The rightest answer to this sub-problem is to apply "spacing" on all but the last glyph in the string, so that the "extra" spacing on the end isn't counted in alignment.

However, there are other issues that also need to be considered:

  • Note that even without "spacing", the alignment isn't quite what you might expect, because it's based on a character box and the ink is generally inset from the box.  (Note, though, that in some fonts the ink extends *outside* the box and so there are the opposite results, with ink extending on the "wrong" side of the origin.)
  • I'll discuss it in more detail in a standalone message, but a few of the metrics (advance, offset, ascent, descent, but *not* the glyphs themselves) are scaled down by 2.4%, further confusing the issue.

While we're talking about halign and I have the images handy, there's a difference that I'm pretty sure is that 2.4% scaling effect.  Consider these images of the top-left corner of a left-aligned W and the top-right corner of a right-aligned W:

---

With respect to RTL:  the big question there is whether the effect should be to mirror the LTR behavior, or if it should be roughly as if the order of the characters was reversed.  Spacing introduces a relevant asymmetry, which is (I think) what you're describing:  in LTR, there's "extra" space on the right; in RTL should that "extra" space remain on the right or move to the left?  (Mostly I think the answer is that it doesn't matter, because the "extra" space is wrong no matter where you put it.)  Another relevant asymmetry can come from font design:  for instance, the "a" in Freestyle Script protrudes to the left of its nominal box, but has space to its right in the box.  With halign=left, it protrudes slightly left of the Y axis; with halign=right there is space between the Y axis and the ink.  What should happen in RTL?  Should that asymmetry be mirrored?  Current behavior is that the spacing is *not* mirrored; an RTL presentation of a single letter appears to be exactly the same as the LTR presentation of that letter, no matter how it's aligned.

BTW, the reversal associated with RTL happens before ligature processing, so you don't end up with silliness when you lay out a word like "Official".  If it was just reordering the glyphs, that would end up as "l a i c ffi O", and that would be silly.  Instead, it ends up as "l a i c i ff O".  Ligature processing is still done, so "different" rendered RTL is rendered as "t n e r e ffi d", with the reversed "iff" being rendered as an "ffi" ligature.  (In fonts with ligature support.  I'm using Calibri for most of those tests.)

---

With respect to TTB/BTT:  I think the issues there are basically similar to the LTR/RTL issues, with the added confusion of the other problems with TTB/BTT.

---
[ And back to the original message for the bottom line... ]


I raise it here as it seems to be bounding box (BB) related, it would be interesting to know what the textmetrics produce.


Indeed.  As the old joke goes, what do you want it to produce?

I have been thinking about it more in the context of the 2.4% scaling mismatch, but there is a question of what textmetrics() should return:  should it return values that are compatible with existing OpenSCAD behavior, or should it return values that match the font design and ink placement?

Matching OpenSCAD behavior lets you better understand what halign and valign are doing.  Matching the font design lets you do things that are perhaps artistically correct.  Matching the actual ink placement lets you control *exactly* where the ink goes.

Part of that is easy:  it should report both the font design metrics and the ink placement.  Beyond that, perhaps it should additionally report what OpenSCAD does.

As an example of the difference, in the M example above what is the width of the string?  Is it eight (the width of the ink), ten (the width of the character box), or twenty (the value OpenSCAD uses for alignment)?

Or maybe we should (optionally?) break backward compatibility and try to iron out these issues as much as is possible, so as to have a future that is as consistent and correct as possible.  (I am not optimistic about fixing all of the "spacing" issues.  Some of them are too hard.)

BTW, setting spacing=1024/1000 should cancel out the 2.4% scaling mismatch, at least with respect to horizontal alignment.


Virus-free. www.avg.com

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
OpenSCAD Admin - email* me if you need anything, or if I've done something stupid...
* on the Forum, click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain;
to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work.
Obviously inclusion of works of previous authors is not included in the above.
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

MichaelAtOz'

bearingX is the left-inset, advance - bearingX - width = the right-inset (of import with space!=0).

 

bearingX is the left-inset, advance - bearingX - width = the right-inset (of import with space!=1).

 

 


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Text and font metrics

JordanBrown
In reply to this post by MichaelAtOz
I think we both understand the concepts and largely agree on how they should work in OpenSCAD.

On 12/31/2020 11:24 PM, MichaelAtOz wrote:
Perhaps an option in text() for those who don't care?

galign=true (glyph-align), purely uses the BB of the set-of-glyphs, moved to OpenSCAD origin,

(origin appropriate to ltr/rtl/ttb/btt).


Perhaps.  I'm a bit more inclined to say "query the metrics and use them to adjust as desired".

With respect to "spacing", I'm increasingly convinced that it isn't meaningful in the general case and so not worth worrying about.  What killed it for me was the ligature issue.  If you want some particular spacing behavior, crack your string up into characters on your own and translate them as you like.

The backward compatibility Force is Strong...


Yeah.  Mixed feelings.  Breaking something that was working before, even something that was only arguably right, is usually bad.  Fixing something that was clearly wrong, even if people might have come to implicitly depend on it, doesn't seem nearly as wrong - especially if it's subtle.

Remember that a backward compatibility break is a one-time pain, while leaving a bug in place is pain forever.

Mucking with "spacing" probably isn't worth it.  Without major changes to semantics (e.g. making it an addition rather than a multiplication, and doing something about ligatures), it's arguably right.  For better or worse, it's doing what it's designed to do, and it's hard to come up with answers that are more clearly right.

The 2.4% problem, in the other hand, is small and clearly wrong.  Backward compatibility is the *only* rationale for preserving it.  I'd fix it.

> a few of the metrics (advance, offset, ascent, descent, but *not* the glyphs themselves) are scaled down by 2.4%

 

I had presumed it was opposite (the glyphs were bigger) but that explains my observations.


The glyphs have the same internal scaling factor (100,000) on both "sides".  The metrics are scaled up by 100,000 and down by 102,400.  Although you could make them match by changing the glyph scaling, that would expand the weirdness.

Perhaps we should ask the community (in a separate thread) what damage

the various fixes would do to their designs?


Yes - after we think we understand the issues, I was thinking of making some concrete proposals for commentary.

A capsule summary of what I'm thinking of is:
  • Just fix the 2.4% problem.  (Or *maybe* make it an option, probably a $ variable.)
  • Just fix the TTB/BTT alignment issues for explicit halign and valign values.  Retain backward compatibility for cases where halign and valign are not specified by making the defaults for TTB/BTT be halign=center and valign=top.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org