MDN may have intermittent access issues April 18 13:00 - April 19 01:00 UTC. See whistlepig.mozilla.org for all notifications.

mozilla

Revision 136754 of Gfx

  • Revision slug: Gfx2
  • Revision title: Gfx
  • Revision id: 136754
  • Created:
  • Creator: ryoqun
  • Is current revision? Yes
  • Comment 641 words added

Revision Content

As I study the code, I'm going to fill this page. Every sentence is of uncertainy. So, I don't use "maybe" or "perphaps". But that doesn't mean I'm sure that is correct. I just don't want to mess up readability with those unnessesary words. If you find errors, correct them.

Text rendering on Linux

Of cource, gfx takes text, and it breaks down to textruns. Then, what exactly happening under the hood? Basically, there is two dives into gfx to render the page. One is for making gfx do glyph-level layout, and auquiring the result of textruns, in turn, using that information, gecko do css-box-level layout with frames (a.k.a. reflow). The other is for actually making gfx draw graphics using the combined glyph-level- and css-box-level- geometric information.

Cairo

This is lying under gfx, with wearing thebes. ;) Cairo interacts with gfx's text rendering in some way. One is by becoming by proxy of gfx and Freetype. Because Freetype's glyph data is destined to Cairo, gfx instructs Freetype only via Cairo. Thus, actual glyph vector data are stop at Cairo, in the form which Cairo likes(cairo_scaled_font_t). To complicate this, mozilla-central contains cairo. What's happening here? Is it modified and/or used on Linux? Also, Cairo is used even on Windows and Mac OS X. So, gfxFont is associated with Cairo to some extent.

tree cairo

This cairo is the one residing in the system.

moz cairo

This cairo is the one shipped with Firefox. By default, this is used by most of time. False gdb, memory maps. This really dismayed me.......

Pango

Pango is for doing layout of glyphs. But, gfx doesn't use the high level PangoLayout. Instead, it interacts it deeply. First of all, Pango doesn't render at all. Pango is only used for calculating positions of glyphs. Then evenry resultant information are passed back to gfx. How gfx communicate with Pango?

Fontconfig

This enables font selection. Various CSS values are passed as FC_Pattern. Genelly FC_Pattern is used passing around information between gfx, pango, freetype. Because of modular neture, pango uses callbacks. Thus this kind of method is neccesary.

To understand its function, it's crucial to understand what's "Pattern" and many verbs applied to them.
Pattern is a set of various information which can represent a single particular font or a set of fonts. If it represent actual fonts, it contains really many information related to it, which is aquired from actual fonts files such *.ttc, *.ttf. On the other hand, when it represent a set of fonts, it merely contains such as font-style=sans-serif. If you can guess, it contains famous "font family", "style", "size", etc... And it also contains very specific little-known information such as weight, the language of the rendered text, the producer of the font. Turning to the developer's view, it can also contain the file path of the font, hinting, bitmap or vector font, RGB, BGR, RGBV, BGRV. Basically, it can contain virtually any information related font. And more importantly it can contain custom ones(gfx uses this feature). This object very important and powerful. That's why in gfxPangoFonts.cpp, we pass around them.
OK. Patterns are great. Then how do we use them to render a simple text with style using 'proper' font such as this:

<p style="font-family: New Times Roman">Sample Text</p>

Be careful, it's possible the font doesn't exist on Linux. What'd happen in such case? Keep in mind the possibility while reading next paragraphs.

Firstly, the style information is passed down to gfxPangoFonts.cpp from the gecko's CSS style system. I'll omit this. It's irrelevant to this discussion, so just take granted that somehow we get the style information of "font-family: New Times Roman".

Next, we make a pattern from that information like this way:
FcPattern p = FcPatternCreate();
p->FcPatternAdd("font-family","New Times Roman");

Next, we add computed values implied from CSS to it, by inheriting or cascading:
p->FcPatternAdd("font-size","12pt");
//...

Assume we've put every information into the pattern as much as possible into the newly-created pattern from the CSS style system.
Currently, this pattern is very abstract. It doesn't specify no actual font installed on the linux system. Thus we can't use them for rendering. Before that, we must make it refer to a particular font(in other words, a mega-pieces of bytes inside *.ttc). Only after that, cairo and freetype grok the bits of bytes, and do their job. That means somehow we must modify the pattern to make it specify an existing font. Then, the complete pattern is passed to cairo to make cairo_scaled_font_t, with that I can draw glyphs of the text. Also we accsess Freetype via Cairo. we don't directly use freetype at all except few cases.

FcPatternMatch
FcPatternSort
FcDefaultSubstitute
FcConfigSubstitute

I'll explain another important aspect of FcPattern which I intentionally omitted until now to simplify discussion. Patterns can have multiple values for each property.

FcPattern p = FcPatternCreate()
p->FcPatternAdd("font-family","New Times Roman");
p->FcPatternAdd("font-family","DejaVu Serif");

Freetype

This extracts glyphs from actual font files residing in the system. At this level, RTL glyphs are exactly same as LTR glyphs. This means. glyph's coordinate is tied to screen coordinate, not the text coordinate in which the glyph may belong to. So, while we render glyphs, we must do x-=width.

The files

gfxFont.cpp gfxFont.h: this is for platform-independent header related Fonts.

gfxPangoFont.cpp

Various caches:

textrun, glyph metrics, extents.

The flowchart.

1st: Glyph Layout part.

How extents are retreaved??? And cached??

gfx_pango_fc_font_get_glyph_extents() is called every time glyph extents is needed by Pango's shapers.

2nd: Glyph Rendering part.

nsSVGGlyphFrame::FillCharacters -> gfxTextRun::Draw -> gfxFont::Draw()

gfxFont.cpp:333 gfxFont::Draw() does final rendering of all glyphs rendered on Firefox, even including UI.

The types

gfxFontEntry

gfxFontStyle

gfxFcFont

gfxPangoFontGroup gfxPangoFontset

gfxTextRun: this is almost always treated as a collection. How about the assumption? next text run's x must be larger than the previous one's x? If I were do vertical layout directly, it'll break everything?

https://bugzilla.mozilla.org/show_bu...?id=385263#c15

  gfxFontGroup has
    PangoFont has
      gfxFont has
        cairo_scaled_font

Case Studies

Justification. -> CSS style text-align and text-justify -> NS_STYLE_TEXT_ALIGN_JUSTIFY, mTextAlign hmm text-align doesn't reach to gfx???

 

 

        /**
         * When set, the text string pointer used to create the text run
         * is guaranteed to be available during the lifetime of the text run.
         */
        TEXT_IS_PERSISTENT           = 0x0001,
        /**
         * When set, the text is known to be all-ASCII (< 128).
         */
        TEXT_IS_ASCII                = 0x0002,
        /**
         * When set, the text is RTL.
         */
        TEXT_IS_RTL                  = 0x0004,
        /**
         * When set, spacing is enabled and the textrun needs to call GetSpacing
         * on the spacing provider.
         */
        TEXT_ENABLE_SPACING          = 0x0008,
        /**
         * When set, GetSpacing can return negative spacing.
         */
        TEXT_ENABLE_NEGATIVE_SPACING = 0x0010,
        /**
         * When set, GetHyphenationBreaks may return true for some character
         * positions, otherwise it will always return false for all characters.
         */
        TEXT_ENABLE_HYPHEN_BREAKS    = 0x0040,
        /**
         * When set, the text has no characters above 255 and it is stored
         * in the textrun in 8-bit format.
         */
        TEXT_IS_8BIT                 = 0x0080,
        /**
         * When set, the text may have UTF16 surrogate pairs, otherwise it
         * doesn't.
         */
        TEXT_HAS_SURROGATES          = 0x0100,
        /**
         * When set, the RunMetrics::mBoundingBox field will be initialized
         * properly based on glyph extents, in particular, glyph extents that
         * overflow the standard font-box (the box defined by the ascent, descent
         * and advance width of the glyph). When not set, it may just be the
         * standard font-box even if glyphs overflow.
         */
        TEXT_NEED_BOUNDING_BOX       = 0x0200,
        /**
         * When set, optional ligatures are disabled. Ligatures that are
         * required for legible text should still be enabled.
         */
        TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0400,
        /**
         * When set, the textrun should favour speed of construction over
         * quality. This may involve disabling ligatures and/or kerning or
         * other effects.
         */
        TEXT_OPTIMIZE_SPEED          = 0x0800

Revision Source

<p>As I study the code, I'm going to fill this page. Every sentence is of uncertainy. So, I don't use "maybe" or "perphaps". But that doesn't mean I'm sure that is correct. I just don't want to mess up readability with those unnessesary words. If you find errors, correct them.</p>
<h2 id="Text_rendering_on_Linux"><span style="font-size: x-large;">Text rendering on Linux</span></h2>
<p>Of cource, gfx takes text, and it breaks down to textruns. Then, what exactly happening under the hood? Basically, there is two dives into gfx to render the page. One is for making gfx do glyph-level layout, and auquiring the result of textruns, in turn, using that information, gecko do css-box-level layout with frames (a.k.a. reflow). The other is for actually making gfx draw graphics using the combined glyph-level- and css-box-level- geometric information.</p>
<h3 id="Cairo"><span style="font-size: x-large;">Cairo</span></h3>
<p>This is lying under gfx, with wearing thebes. ;) Cairo interacts with gfx's text rendering in some way. One is by becoming by proxy of gfx and Freetype. Because Freetype's glyph data is destined to Cairo, gfx instructs Freetype only via Cairo. Thus, actual glyph vector data are stop at Cairo, in the form which Cairo likes(cairo_scaled_font_t). To complicate this, mozilla-central contains cairo. What's happening here? Is it modified and/or used on Linux? Also, Cairo is used even on Windows and Mac OS X. So, gfxFont is associated with Cairo to some extent.</p>
<h3 id="tree_cairo">tree cairo</h3>
<p>This cairo is the one residing in the system.</p>
<h3 id="moz_cairo">moz cairo</h3>
<p>This cairo is the one shipped with Firefox. By default, this is used by most of time. False gdb, memory maps. This really dismayed me.......</p><h3 id="Pango"><span style="font-size: x-large;">Pango</span></h3>
<p>Pango is for doing layout of glyphs. But, gfx doesn't use the high level PangoLayout. Instead, it interacts it deeply. First of all, Pango doesn't render at all. Pango is only used for calculating positions of glyphs. Then evenry resultant information are passed back to gfx. How gfx communicate with Pango?</p>
<h3 id="Fontconfig"><span style="font-size: x-large;">Fontconfig</span></h3>
<p>This enables font selection. Various CSS values are passed as FC_Pattern. Genelly FC_Pattern is used passing around information between gfx, pango, freetype. Because of modular neture, pango uses callbacks. Thus this kind of method is neccesary.</p>
<p>To understand its function, it's crucial to understand what's "Pattern" and many verbs applied to them.<br>
Pattern is a set of various information which can represent a single particular font or a set of fonts. If it represent actual fonts, it contains really many information related to it, which is aquired from actual fonts files such *.ttc, *.ttf. On the other hand, when it represent a set of fonts, it merely contains such as font-style=sans-serif. If you can guess, it contains famous "font family", "style", "size", etc... And it also contains very specific little-known information such as weight, the language of the rendered text, the producer of the font. Turning to the developer's view, it can also contain the file path of the font, hinting, bitmap or vector font, RGB, BGR, RGBV, BGRV. Basically, it can contain virtually any information related font. And more importantly it can contain custom ones(gfx uses this feature). This object very important and powerful. That's why in gfxPangoFonts.cpp, we pass around them.<br>
OK. Patterns are great. Then how do we use them to render a simple text with style using 'proper' font such as this:<br>
<br>
&lt;p style="font-family: New Times Roman"&gt;Sample Text&lt;/p&gt;<br>
<br>
Be careful, it's possible the font doesn't exist on Linux. What'd happen in such case? Keep in mind the possibility while reading next paragraphs.<br>
<br>
Firstly, the style information is passed down to gfxPangoFonts.cpp from the gecko's CSS style system. I'll omit this. It's irrelevant to this discussion, so just take granted that somehow we get the style information of "font-family: New Times Roman".<br>
<br>
Next, we make a pattern from that information like this way:<br>
FcPattern p = FcPatternCreate();<br>
p-&gt;FcPatternAdd("font-family","New Times Roman");<br>
<br>
Next, we add computed values implied from CSS to it, by inheriting or cascading:<br>
p-&gt;FcPatternAdd("font-size","12pt");<br>
//...<br>
<br>
Assume we've put every information into the pattern as much as possible into the newly-created pattern from the CSS style system.<br>
Currently, this pattern is very abstract. It doesn't specify no actual font installed on the linux system. Thus we can't use them for rendering. Before that, we must make it refer to a particular font(in other words, a mega-pieces of bytes inside *.ttc). Only after that, cairo and freetype grok the bits of bytes, and do their job. That means somehow we must modify the pattern to make it specify an existing font. Then, the complete pattern is passed to cairo to make cairo_scaled_font_t, with that I can draw glyphs of the text. Also we accsess Freetype via Cairo. we don't directly use freetype at all except few cases.<br>
<br>
FcPatternMatch<br>
FcPatternSort<br>
FcDefaultSubstitute<br>
FcConfigSubstitute<br>
<br>
I'll explain another important aspect of FcPattern which I intentionally omitted until now to simplify discussion. Patterns can have multiple values for each property.<br>
<br>
FcPattern p = FcPatternCreate()<br>
p-&gt;FcPatternAdd("font-family","New Times Roman");<br>
p-&gt;FcPatternAdd("font-family","DejaVu Serif");<br>
<br>
</p><h3 id="Freetype"><span style="font-size: x-large;">Freetype</span></h3>
<p>This extracts glyphs from actual font files residing in the system. At this level, RTL glyphs are exactly same as LTR glyphs. This means. glyph's coordinate is tied to screen coordinate, not the text coordinate in which the glyph may belong to. So, while we render glyphs, we must do x-=width.</p>
<h3 id="The_files"><span style="font-size: x-large;">The files</span></h3>
<p>gfxFont.cpp gfxFont.h: this is for platform-independent header related Fonts.</p>
<p>gfxPangoFont.cpp</p>
<h3 id="Various_caches:"><span style="font-size: x-large;">Various caches:</span></h3>
<p>textrun, glyph metrics, extents.</p>
<h3 id="The_flowchart."><span style="font-size: x-large;">The flowchart.</span></h3>
<p>1st: Glyph Layout part.</p>
<p>How extents are retreaved??? And cached??</p>
<p>gfx_pango_fc_font_get_glyph_extents() is called every time glyph extents is needed by Pango's shapers.</p>
<p>2nd: Glyph Rendering part.</p>
<p>nsSVGGlyphFrame::FillCharacters -&gt; gfxTextRun::Draw -&gt; gfxFont::Draw()</p>
<p>gfxFont.cpp:333 gfxFont::Draw() does final rendering of all glyphs rendered on Firefox, even including UI.</p>
<h3 id="The_types">The types</h3>
<p>gfxFontEntry</p>
<p>gfxFontStyle</p>
<p>gfxFcFont</p>
<p>gfxPangoFontGroup gfxPangoFontset </p>
<p>gfxTextRun: this is almost always treated as a collection. How about the assumption? next text run's x must be larger than the previous one's x? If I were do vertical layout directly, it'll break everything?</p>
<p><a class=" link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=385263#c15" rel="freelink">https://bugzilla.mozilla.org/show_bu...?id=385263#c15</a></p>
<p>  gfxFontGroup has<br>
    PangoFont has<br>
      gfxFont has<br>
        cairo_scaled_font</p>
<p>Case Studies</p>
<p>Justification. -&gt; CSS style text-align and text-justify -&gt; NS_STYLE_TEXT_ALIGN_JUSTIFY, mTextAlign hmm text-align doesn't reach to gfx???</p>
<p> </p>
<p> </p>
<p>        /**<br>
         * When set, the text string pointer used to create the text run<br>
         * is guaranteed to be available during the lifetime of the text run.<br>
         */<br>
        TEXT_IS_PERSISTENT           = 0x0001,<br>
        /**<br>
         * When set, the text is known to be all-ASCII (&lt; 128).<br>
         */<br>
        TEXT_IS_ASCII                = 0x0002,<br>
        /**<br>
         * When set, the text is RTL.<br>
         */<br>
        TEXT_IS_RTL                  = 0x0004,<br>
        /**<br>
         * When set, spacing is enabled and the textrun needs to call GetSpacing<br>
         * on the spacing provider.<br>
         */<br>
        TEXT_ENABLE_SPACING          = 0x0008,<br>
        /**<br>
         * When set, GetSpacing can return negative spacing.<br>
         */<br>
        TEXT_ENABLE_NEGATIVE_SPACING = 0x0010,<br>
        /**<br>
         * When set, GetHyphenationBreaks may return true for some character<br>
         * positions, otherwise it will always return false for all characters.<br>
         */<br>
        TEXT_ENABLE_HYPHEN_BREAKS    = 0x0040,<br>
        /**<br>
         * When set, the text has no characters above 255 and it is stored<br>
         * in the textrun in 8-bit format.<br>
         */<br>
        TEXT_IS_8BIT                 = 0x0080,<br>
        /**<br>
         * When set, the text may have UTF16 surrogate pairs, otherwise it<br>
         * doesn't.<br>
         */<br>
        TEXT_HAS_SURROGATES          = 0x0100,<br>
        /**<br>
         * When set, the RunMetrics::mBoundingBox field will be initialized<br>
         * properly based on glyph extents, in particular, glyph extents that<br>
         * overflow the standard font-box (the box defined by the ascent, descent<br>
         * and advance width of the glyph). When not set, it may just be the<br>
         * standard font-box even if glyphs overflow.<br>
         */<br>
        TEXT_NEED_BOUNDING_BOX       = 0x0200,<br>
        /**<br>
         * When set, optional ligatures are disabled. Ligatures that are<br>
         * required for legible text should still be enabled.<br>
         */<br>
        TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0400,<br>
        /**<br>
         * When set, the textrun should favour speed of construction over<br>
         * quality. This may involve disabling ligatures and/or kerning or<br>
         * other effects.<br>
         */<br>
        TEXT_OPTIMIZE_SPEED          = 0x0800</p>
Revert to this revision