Measuring width string
Hi I'm sending it here so that it doesn't get lost. There are multiple ways to measure string width. In the following examples performance will be tested measuring 10`000 times the width of the following string: *string := 'abcdefghijklmnopqrstuvwxyz 0123456789!@#$%^&*()_+'.* 1) The most straightforward way is to send #widthOfString: to the font. Time to run gives around 250ms. http://ws.stfx.eu/2Q5YA9DFTRDR Resulting value is rounded to integer and seems to be not absolutely correct and precise. 2) More complex way is to go deeper on the level of glyphs and manually summarise the width of each character in the string sending #getGlyphWidth: character to the font. Time to run gives around 750ms. http://ws.stfx.eu/ETBEW1EHAAZ8 Resulting value is float and looks like correct and precise value. 3) Even more complex is to use CairoFontMetricsProvider instead of font's methods. The same as in 2nd case we measure each character. Time to run around 350ms. http://ws.stfx.eu/7I89DMD0ZLM3 Resulting value is exactly the same as in the 2nd case. With almost equal performance to 1st it is nice alternative. 4) One more way is to let native cairo to calculate everything for us. Calls happen through nativeboost. Time to run around 120ms. http://ws.stfx.eu/HYD76OMIOM7L <http://ws.stfx.eu/HYD76OMIOM7L> As result it returns *CairoTextExtents* which allows to calculate width and height with one call. Cheers, Alex
Hi Alex, This is indeed a very useful information. You can also put it on StackOverflow, then it will be Googlable. Cheers. Uko
On 27 Oct 2015, at 12:02, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
Hi
I'm sending it here so that it doesn't get lost.
There are multiple ways to measure string width. In the following examples performance will be tested measuring 10`000 times the width of the following string:
string := 'abcdefghijklmnopqrstuvwxyz 0123456789!@#$%^&*()_+'.
1) The most straightforward way is to send #widthOfString: to the font. Time to run gives around 250ms. http://ws.stfx.eu/2Q5YA9DFTRDR <http://ws.stfx.eu/2Q5YA9DFTRDR> Resulting value is rounded to integer and seems to be not absolutely correct and precise.
2) More complex way is to go deeper on the level of glyphs and manually summarise the width of each character in the string sending #getGlyphWidth: character to the font. Time to run gives around 750ms. http://ws.stfx.eu/ETBEW1EHAAZ8 <http://ws.stfx.eu/ETBEW1EHAAZ8> Resulting value is float and looks like correct and precise value.
3) Even more complex is to use CairoFontMetricsProvider instead of font's methods. The same as in 2nd case we measure each character. Time to run around 350ms. http://ws.stfx.eu/7I89DMD0ZLM3 <http://ws.stfx.eu/7I89DMD0ZLM3> Resulting value is exactly the same as in the 2nd case. With almost equal performance to 1st it is nice alternative.
4) One more way is to let native cairo to calculate everything for us. Calls happen through nativeboost. Time to run around 120ms. http://ws.stfx.eu/HYD76OMIOM7LÂ <http://ws.stfx.eu/HYD76OMIOM7L> As result it returns CairoTextExtents which allows to calculate width and height with one call.
Cheers, Alex
Note that you shouldn't use 2) or 3) for non-monospace fonts because of kerning. font := StandardFonts defaultFont. font widthOfString: 'eT'. "16" font widthOfString: 'Te'. "15" 'eT' inject: 0 into: [ :width :c | width + (font getGlyphWidth: c) ]. "13.416015625" 'Te' inject: 0 into: [ :width :c | width + (font getGlyphWidth: c) ]. "13.416015625" 4) seems fine font := StandardFonts defaultFont. provider := CairoScaledFont fromFreetypeFont: font realFont. width := [ :string | converter := CairoUTF8Converter new. converter convert: string from: 1 to: string size. stringExtents := CairoTextExtents new. provider getExtentsOf: converter buffer into: stringExtents. stringExtents width ]. width value: 'eT'. "12.463638305664063" width value: 'Te'. "12.561752319335938" On Tue, Oct 27, 2015 at 12:27 PM, Yuriy Tymchuk <yuriy.tymchuk@me.com> wrote:
Hi Alex,
This is indeed a very useful information. You can also put it on StackOverflow, then it will be Googlable.
Cheers. Uko
On 27 Oct 2015, at 12:02, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
Hi
I'm sending it here so that it doesn't get lost.
There are multiple ways to measure string width. In the following examples performance will be tested measuring 10`000 times the width of the following string:
*string := 'abcdefghijklmnopqrstuvwxyz 0123456789!@#$%^&*()_+'.*
1) The most straightforward way is to send #widthOfString: to the font. Time to run gives around 250ms. http://ws.stfx.eu/2Q5YA9DFTRDR Resulting value is rounded to integer and seems to be not absolutely correct and precise.
2) More complex way is to go deeper on the level of glyphs and manually summarise the width of each character in the string sending #getGlyphWidth: character to the font. Time to run gives around 750ms. http://ws.stfx.eu/ETBEW1EHAAZ8 Resulting value is float and looks like correct and precise value.
3) Even more complex is to use CairoFontMetricsProvider instead of font's methods. The same as in 2nd case we measure each character. Time to run around 350ms. http://ws.stfx.eu/7I89DMD0ZLM3 Resulting value is exactly the same as in the 2nd case. With almost equal performance to 1st it is nice alternative.
4) One more way is to let native cairo to calculate everything for us. Calls happen through nativeboost. Time to run around 120ms. http://ws.stfx.eu/HYD76OMIOM7L <http://ws.stfx.eu/HYD76OMIOM7L> As result it returns *CairoTextExtents* which allows to calculate width and height with one call.
Cheers, Alex
But #widthOfString: is definitely weird... like it's adding some extra space on the sides or something. On Tue, Oct 27, 2015 at 12:50 PM, Peter Uhnák <i.uhnak@gmail.com> wrote:
Note that you shouldn't use 2) or 3) for non-monospace fonts because of kerning.
font := StandardFonts defaultFont. font widthOfString: 'eT'. "16" font widthOfString: 'Te'. "15"
'eT' inject: 0 into: [ :width :c | width + (font getGlyphWidth: c) ]. "13.416015625" 'Te' inject: 0 into: [ :width :c | width + (font getGlyphWidth: c) ]. "13.416015625"
4) seems fine
font := StandardFonts defaultFont. provider := CairoScaledFont fromFreetypeFont: font realFont. width := [ :string | converter := CairoUTF8Converter new. converter convert: string from: 1 to: string size. stringExtents := CairoTextExtents new. provider getExtentsOf: converter buffer into: stringExtents. stringExtents width ].
width value: 'eT'. "12.463638305664063" width value: 'Te'. "12.561752319335938"
On Tue, Oct 27, 2015 at 12:27 PM, Yuriy Tymchuk <yuriy.tymchuk@me.com> wrote:
Hi Alex,
This is indeed a very useful information. You can also put it on StackOverflow, then it will be Googlable.
Cheers. Uko
On 27 Oct 2015, at 12:02, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
Hi
I'm sending it here so that it doesn't get lost.
There are multiple ways to measure string width. In the following examples performance will be tested measuring 10`000 times the width of the following string:
*string := 'abcdefghijklmnopqrstuvwxyz 0123456789!@#$%^&*()_+'.*
1) The most straightforward way is to send #widthOfString: to the font. Time to run gives around 250ms. http://ws.stfx.eu/2Q5YA9DFTRDR Resulting value is rounded to integer and seems to be not absolutely correct and precise.
2) More complex way is to go deeper on the level of glyphs and manually summarise the width of each character in the string sending #getGlyphWidth: character to the font. Time to run gives around 750ms. http://ws.stfx.eu/ETBEW1EHAAZ8 Resulting value is float and looks like correct and precise value.
3) Even more complex is to use CairoFontMetricsProvider instead of font's methods. The same as in 2nd case we measure each character. Time to run around 350ms. http://ws.stfx.eu/7I89DMD0ZLM3 Resulting value is exactly the same as in the 2nd case. With almost equal performance to 1st it is nice alternative.
4) One more way is to let native cairo to calculate everything for us. Calls happen through nativeboost. Time to run around 120ms. http://ws.stfx.eu/HYD76OMIOM7L <http://ws.stfx.eu/HYD76OMIOM7L> As result it returns *CairoTextExtents* which allows to calculate width and height with one call.
Cheers, Alex
Hi Alex, thanks, this is very usefull. Can you tell which one of these measures is the closest to the effective length of a string morph? Number 4? Thierry 2015-10-27 12:02 GMT+01:00 Aliaksei Syrel <alex.syrel@gmail.com>:
Hi
I'm sending it here so that it doesn't get lost.
There are multiple ways to measure string width. In the following examples performance will be tested measuring 10`000 times the width of the following string:
*string := 'abcdefghijklmnopqrstuvwxyz 0123456789!@#$%^&*()_+'.*
1) The most straightforward way is to send #widthOfString: to the font. Time to run gives around 250ms. http://ws.stfx.eu/2Q5YA9DFTRDR Resulting value is rounded to integer and seems to be not absolutely correct and precise.
2) More complex way is to go deeper on the level of glyphs and manually summarise the width of each character in the string sending #getGlyphWidth: character to the font. Time to run gives around 750ms. http://ws.stfx.eu/ETBEW1EHAAZ8 Resulting value is float and looks like correct and precise value.
3) Even more complex is to use CairoFontMetricsProvider instead of font's methods. The same as in 2nd case we measure each character. Time to run around 350ms. http://ws.stfx.eu/7I89DMD0ZLM3 Resulting value is exactly the same as in the 2nd case. With almost equal performance to 1st it is nice alternative.
4) One more way is to let native cairo to calculate everything for us. Calls happen through nativeboost. Time to run around 120ms. http://ws.stfx.eu/HYD76OMIOM7L <http://ws.stfx.eu/HYD76OMIOM7L> As result it returns *CairoTextExtents* which allows to calculate width and height with one call.
Cheers, Alex
Yes, this is an important insight, I've made a visual comparison of #4 (red) compared to #1 (blue) âhttp://ws.stfx.eu/LWMJN1SY7VXT plus compared to the other ones it can even tell the height... now to teach Roassal how to use it... Peter On Tue, Oct 27, 2015 at 4:11 PM, Thierry Goubier <thierry.goubier@gmail.com> wrote:
Hi Alex,
thanks, this is very usefull. Can you tell which one of these measures is the closest to the effective length of a string morph? Number 4?
Thierry
2015-10-27 12:02 GMT+01:00 Aliaksei Syrel <alex.syrel@gmail.com>:
Hi
I'm sending it here so that it doesn't get lost.
There are multiple ways to measure string width. In the following examples performance will be tested measuring 10`000 times the width of the following string:
*string := 'abcdefghijklmnopqrstuvwxyz 0123456789!@#$%^&*()_+'.*
1) The most straightforward way is to send #widthOfString: to the font. Time to run gives around 250ms. http://ws.stfx.eu/2Q5YA9DFTRDR Resulting value is rounded to integer and seems to be not absolutely correct and precise.
2) More complex way is to go deeper on the level of glyphs and manually summarise the width of each character in the string sending #getGlyphWidth: character to the font. Time to run gives around 750ms. http://ws.stfx.eu/ETBEW1EHAAZ8 Resulting value is float and looks like correct and precise value.
3) Even more complex is to use CairoFontMetricsProvider instead of font's methods. The same as in 2nd case we measure each character. Time to run around 350ms. http://ws.stfx.eu/7I89DMD0ZLM3 Resulting value is exactly the same as in the 2nd case. With almost equal performance to 1st it is nice alternative.
4) One more way is to let native cairo to calculate everything for us. Calls happen through nativeboost. Time to run around 120ms. http://ws.stfx.eu/HYD76OMIOM7L <http://ws.stfx.eu/HYD76OMIOM7L> As result it returns *CairoTextExtents* which allows to calculate width and height with one call.
Cheers, Alex
On 04 Nov 2015, at 01:15, Peter Uhnák <i.uhnak@gmail.com> wrote:
Yes, this is an important insight, I've made a visual comparison of #4 (red) compared to #1 (blue) <dimensions.png> âhttp://ws.stfx.eu/LWMJN1SY7VXT
Peter, this script is soo cool, really great work !
plus compared to the other ones it can even tell the height... now to teach Roassal how to use it...
Peter
On Tue, Oct 27, 2015 at 4:11 PM, Thierry Goubier <thierry.goubier@gmail.com> wrote: Hi Alex,
thanks, this is very usefull. Can you tell which one of these measures is the closest to the effective length of a string morph? Number 4?
Thierry
2015-10-27 12:02 GMT+01:00 Aliaksei Syrel <alex.syrel@gmail.com>: Hi
I'm sending it here so that it doesn't get lost.
There are multiple ways to measure string width. In the following examples performance will be tested measuring 10`000 times the width of the following string:
string := 'abcdefghijklmnopqrstuvwxyz 0123456789!@#$%^&*()_+'.
1) The most straightforward way is to send #widthOfString: to the font. Time to run gives around 250ms. http://ws.stfx.eu/2Q5YA9DFTRDR Resulting value is rounded to integer and seems to be not absolutely correct and precise.
2) More complex way is to go deeper on the level of glyphs and manually summarise the width of each character in the string sending #getGlyphWidth: character to the font. Time to run gives around 750ms. http://ws.stfx.eu/ETBEW1EHAAZ8 Resulting value is float and looks like correct and precise value.
3) Even more complex is to use CairoFontMetricsProvider instead of font's methods. The same as in 2nd case we measure each character. Time to run around 350ms. http://ws.stfx.eu/7I89DMD0ZLM3 Resulting value is exactly the same as in the 2nd case. With almost equal performance to 1st it is nice alternative.
4) One more way is to let native cairo to calculate everything for us. Calls happen through nativeboost. Time to run around 120ms. http://ws.stfx.eu/HYD76OMIOM7L As result it returns CairoTextExtents which allows to calculate width and height with one call.
Cheers, Alex
2015-11-04 8:34 GMT+01:00 Sven Van Caekenberghe <sven@stfx.eu>:
On 04 Nov 2015, at 01:15, Peter Uhnák <i.uhnak@gmail.com> wrote:
Yes, this is an important insight, I've made a visual comparison of #4 (red) compared to #1 (blue) <dimensions.png> âhttp://ws.stfx.eu/LWMJN1SY7VXT
Peter, this script is soo cool, really great work !
I like the 'whatever' :)
Thierry
plus compared to the other ones it can even tell the height... now to teach Roassal how to use it...
Peter
On Tue, Oct 27, 2015 at 4:11 PM, Thierry Goubier < thierry.goubier@gmail.com> wrote: Hi Alex,
thanks, this is very usefull. Can you tell which one of these measures is the closest to the effective length of a string morph? Number 4?
Thierry
2015-10-27 12:02 GMT+01:00 Aliaksei Syrel <alex.syrel@gmail.com>: Hi
I'm sending it here so that it doesn't get lost.
There are multiple ways to measure string width. In the following examples performance will be tested measuring 10`000 times the width of the following string:
string := 'abcdefghijklmnopqrstuvwxyz 0123456789!@#$%^&*()_+'.
1) The most straightforward way is to send #widthOfString: to the font. Time to run gives around 250ms. http://ws.stfx.eu/2Q5YA9DFTRDR Resulting value is rounded to integer and seems to be not absolutely correct and precise.
2) More complex way is to go deeper on the level of glyphs and manually summarise the width of each character in the string sending #getGlyphWidth: character to the font. Time to run gives around 750ms. http://ws.stfx.eu/ETBEW1EHAAZ8 Resulting value is float and looks like correct and precise value.
3) Even more complex is to use CairoFontMetricsProvider instead of font's methods. The same as in 2nd case we measure each character. Time to run around 350ms. http://ws.stfx.eu/7I89DMD0ZLM3 Resulting value is exactly the same as in the 2nd case. With almost equal performance to 1st it is nice alternative.
4) One more way is to let native cairo to calculate everything for us. Calls happen through nativeboost. Time to run around 120ms. http://ws.stfx.eu/HYD76OMIOM7L As result it returns CairoTextExtents which allows to calculate width and height with one call.
Cheers, Alex
Nice. So trying with #Ta and #ffl I noticed that there is no kerning (at least not correct) but there are ligatures. Stephan
StandardFonts defaultFont
"a LogicalFont familyName: Source Sans Pro emphasis: nil pointSize: 10 realFont: FreeTypeFont('Source Sans Pro' 'Regular' 10) weight: 400 stretch: 5 slant: 0" StandardFonts defaultFont realFont "FreeTypeFont('Source Sans Pro' 'Regular' 10)" StandardFonts defaultFont realFont face hasKerning "false" Free type source sans pro in Pharo just *does not* support kerning.
However, Helvetica Neue on mac has kerning. Will check Cheers, Alex On Wed, Nov 4, 2015 at 1:59 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
StandardFonts defaultFont
"a LogicalFont familyName: Source Sans Pro emphasis: nil pointSize: 10 realFont: FreeTypeFont('Source Sans Pro' 'Regular' 10) weight: 400 stretch: 5 slant: 0"
StandardFonts defaultFont realFont
"FreeTypeFont('Source Sans Pro' 'Regular' 10)"
StandardFonts defaultFont realFont face hasKerning
"false"
Free type source sans pro in Pharo just *does not* support kerning.
Ok, answer is quite simple. Current string rendering on athens does not support kerning. Because it is not cairo's job. Kerning should be took into account *after* creating glyphs with cairo but *before* extent measurement and obviously rendering. It can be done with FreeType. I made small refactoring of text measurement and added kerning support. So, *in the latest version of Athens-Cairo* you can get extents easily: extents := CairoFontMetricsProvider new
font: StandardFonts defaultFont; extentsOf: 'Ta ffl'.
extent is an instance of CairoTextExtents. Rendering on athens with Times New Roman size 200 gives: (Mac OSX Yosemite) [image: Inline image 1] And here is what I get in Keynote with the same font [image: Inline image 2] Close enough :D Cheers, Alex On Wed, Nov 4, 2015 at 2:04 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
However, Helvetica Neue on mac has kerning. Will check
Cheers, Alex
On Wed, Nov 4, 2015 at 1:59 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
StandardFonts defaultFont
"a LogicalFont familyName: Source Sans Pro emphasis: nil pointSize: 10 realFont: FreeTypeFont('Source Sans Pro' 'Regular' 10) weight: 400 stretch: 5 slant: 0"
StandardFonts defaultFont realFont
"FreeTypeFont('Source Sans Pro' 'Regular' 10)"
StandardFonts defaultFont realFont face hasKerning
"false"
Free type source sans pro in Pharo just *does not* support kerning.
This is one beautiful piece of work! Doru On Wed, Nov 4, 2015 at 3:51 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
Ok, answer is quite simple. Current string rendering on athens does not support kerning. Because it is not cairo's job. Kerning should be took into account *after* creating glyphs with cairo but *before* extent measurement and obviously rendering. It can be done with FreeType. I made small refactoring of text measurement and added kerning support.
So, *in the latest version of Athens-Cairo* you can get extents easily:
extents := CairoFontMetricsProvider new
font: StandardFonts defaultFont; extentsOf: 'Ta ffl'.
extent is an instance of CairoTextExtents.
Rendering on athens with Times New Roman size 200 gives: (Mac OSX Yosemite)
[image: Inline image 1]
And here is what I get in Keynote with the same font
[image: Inline image 2]
Close enough :D
Cheers, Alex
On Wed, Nov 4, 2015 at 2:04 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
However, Helvetica Neue on mac has kerning. Will check
Cheers, Alex
On Wed, Nov 4, 2015 at 1:59 PM, Aliaksei Syrel <alex.syrel@gmail.com> wrote:
StandardFonts defaultFont
"a LogicalFont familyName: Source Sans Pro emphasis: nil pointSize: 10 realFont: FreeTypeFont('Source Sans Pro' 'Regular' 10) weight: 400 stretch: 5 slant: 0"
StandardFonts defaultFont realFont
"FreeTypeFont('Source Sans Pro' 'Regular' 10)"
StandardFonts defaultFont realFont face hasKerning
"false"
Free type source sans pro in Pharo just *does not* support kerning.
-- www.tudorgirba.com "Every thing has its own flow"
yes I want beautiful fonts in Pharo :) Le 4/11/15 18:14, Tudor Girba a écrit :
This is one beautiful piece of work!
Doru
On Wed, Nov 4, 2015 at 3:51 PM, Aliaksei Syrel <alex.syrel@gmail.com <mailto:alex.syrel@gmail.com>> wrote:
Ok, answer is quite simple. Current string rendering on athens does not support kerning. Because it is not cairo's job. Kerning should be took into account _after_ creating glyphs with cairo but _before_ extent measurement and obviously rendering. It can be done with FreeType. I made small refactoring of text measurement and added kerning support.
So, *in the latest version of Athens-Cairo* you can get extents easily:
extents := CairoFontMetricsProvider new font: StandardFonts defaultFont; extentsOf: 'Ta ffl'.
extent is an instance of CairoTextExtents.
Rendering on athens with Times New Roman size 200 gives: (Mac OSX Yosemite)
Inline image 1
And here is what I get in Keynote with the same font
Inline image 2
Close enough :D
Cheers, Alex
On Wed, Nov 4, 2015 at 2:04 PM, Aliaksei Syrel <alex.syrel@gmail.com <mailto:alex.syrel@gmail.com>> wrote:
However, Helvetica Neue on mac has kerning. Will check
Cheers, Alex
On Wed, Nov 4, 2015 at 1:59 PM, Aliaksei Syrel <alex.syrel@gmail.com <mailto:alex.syrel@gmail.com>> wrote:
StandardFonts defaultFont
"a LogicalFont familyName: Source Sans Pro emphasis: nil pointSize: 10 realFont: FreeTypeFont('Source Sans Pro' 'Regular' 10) weight: 400 stretch: 5 slant: 0"
StandardFonts defaultFont realFont
"FreeTypeFont('Source Sans Pro' 'Regular' 10)"
StandardFonts defaultFont realFont face hasKerning
"false"
Free type source sans pro in Pharo just _does not_ support kerning.
-- www.tudorgirba.com <http://www.tudorgirba.com>
"Every thing has its own flow"
On 04/11/15 15:51, Aliaksei Syrel wrote:
Ok, answer is quite simple. Current string rendering on athens does not support kerning. Because it is not cairo's job. Kerning should be took into account _after_ creating glyphs with cairo but _before_ extent measurement and obviously rendering. It can be done with FreeType. I made small refactoring of text measurement and added kerning support.
Really nice. Stephan
participants (8)
-
Aliaksei Syrel -
Peter Uhnák -
Stephan Eggermont -
stepharo -
Sven Van Caekenberghe -
Thierry Goubier -
Tudor Girba -
Yuriy Tymchuk