How Does Pango Work with Xft

- Digest of Discussion with Owen Taylor <otaylor@redhat.com> Edit by Frank Yung-Fong Tang <ytang0648@aol.com>

  Date:
  
1/23/2003 2:08:10 PM Eastern Standard Time
  From:
  

Right now, Pango selects a single shaper module for each Unicode range.  There is no provision to check if a font has GDL tables, and use a different Graphite specific shaper module.

It wouldn't be impossible to add such a facility (it would require some extensions to fontconfig, but these extensions are needed already to deal with fonts that have, say, Arabic glyphs without the Arabic OpenType tables.)

The goals of the Graphite project are obviously a little different than for Pango. I'm not sure that the extra capabilities that Graphite support would offer really excites me that much, personally.

To state something that may be a bit controversial, my opinion is that the set of "hard" scripts out there is pretty finite, and not going to go up in the future. Rather than trying to make it possible to handle arbitrary new scripts, I think time would be better spent creating the necessary specifications, fonts, and code to fit the dozen or so remaining complex scripts into OpenType.

Date:
  
1/27/2003 5:48:20 PM Eastern Standard Time
  From:
  

The Pango application interfaces divide more or less into two layers:

  1. High-level interface
  2. Low-level interface

The high-level interface is pretty much purely character based; once you've laid-out a paragraph of text using PangoLayout, you can get the positions of individual elements of the Paragraph (pango_xy_to_index, PangoLayoutIter, etc.), but that's about the only sub-paragraph access you have.

GTK+ and GDK work pretty much completely with the high-level interface; the only partial exception to this is the code for actually drawing Pango objects to the screen which touches the lower level interfaces a bit.

There are various good reasons for sticking to the higher level interfaces:


That being said, various people have used Pango at a more-raw level when creating HTML widgets (GtkHTML2 and GtkHTML3) that use Pango.

Even at the lower level, it should be pointed out that Pango still is a paragraph-based system. You don't get access to simple "draw_character()/draw_glyph()" type API's; you just get more detailed access to the internals of how drawing a paragraph of text works.

Glyph codes are actually opaque integers in the Pango system; there is no exported relationship at the application level between a Glyph code and anything externally meaningful, though it happens that for the Xft and FT2 backends, the Pango glyph code matches the TrueType glyph index.

Date:
  
1/27/2003 5:48:20 PM Eastern Standard Time
  From:
  


The model of Pango looks something like:

Paragraph  =>  Item          =>      Run
                Character  <cluster>  Glyph

In the first step of analysis paragraph is broken down into "items" by:
Then each item is converted into glyphs. Line breaking may turn a single item in to several "runs". Characters are related to glyphs in a N:M fashion by the idea of a cluster.

N characters => 1 cluster => M glyphs


[ If this sounds familiar, this model fairly closes matches the windows   Uniscribe API, though the details are considerably different ]

The high-level API is mostly dealing with Paragraphs and characters; it mostly hides items/runs/glyphs.

Q: FreeType2 deal with Glyph (and optionally Character) level .
A: Yes.

Q: Xft deal with both String level, Character level and Glyph level.
A: Yes. Pango only really deals with Xft at the Glyph level.

Q: How about GDK/GTK? does it api deal with Paragraph level only?
A: Pretty much. There is no X/Xft-style DrawString/DrawChar/DrawGlyph. (The idea has been floated to add this sort of simplistic API; the reason for adding it would mostly for cross-platform API's sitting on top of GTK+ that expect such a thing.)


The place where I would hope you could insert Graphite is at the level of converting:

Font + Character string  =>  Glyph string

This is the:

  void (*script_shape) (PangoFont        *font, 
            const char       *text,
            int               length,
            PangoAnalysis    *analysis,
            PangoGlyphString *glyphs);

method of PangoEngineShape.

To cut in any higher:

I don't really see why Graphite support should need to come in any higher, except in whatever is needed to select the Graphite
shaper and fonts when appropriate.

Q:  I think ATSUI is also Paragraph level

A: My memory of ATSUI is that it is fairly similer to the high-level
API of Pango, though the clearest API analogies are:

PangoLayout     <=> Java2D text interfaces
Low level Pango <=> Uniscribe

Q:  Are those low level pango api really "internal private functions"? or they are still public function for upper level to call?

The ones I was referring to in my earlier mail are public and supported API; the Pango interfaces comprise about 5 pieces:
  1. Public high-level API (PangoLayout)
  2. Public low-level API  (What is used to implement PangoLayout)
  3. Shape-engine only API (What, e.g., the arabic-xft shaper uses)
  4. Backend-only API  (What is used to implement libpangoxft)
  5. Internal Pango API
Headers are installed for 1-4), but 3) and 4) have lower levels of compatibility degrees, and you need special #defines to use them.

(PANGO_ENABLE_ENGINE, PANGO_ENABLE_BACKEND)

(*script_shape) is part of 3). It's in pango/pango-engine.h.
 

Date:
  
1/27/2003 4:42:50 PM Pacific Standard Time
  From:
  

Pango gets its font coverages from fontconfig (this means that Pango doesn't have to load up a font to know what characters it covers.)

As I understand it, fontconfig has all the Mozilla magic; I think it essentially computes:

(Characters in cmap) - (Blank characters - Characters that are supposed to be blank)

TO BE CLEAN UP....



Subj: Re: [Silgraphite-devel] Re: Pango and SILGraphite was Re: Possible Pango 1.4 ideas 
Date: 1/30/2003 7:22:52 AM Pacific Standard Time
From: otaylor@redhat.com
To: ytang0648@aol.com
CC: ftang@netscape.com, Sharon_Correll@sil.org, gtk-i18n-list@gnome.org, silgraphite-devel@lists.sourceforge.net
Sent from the Internet (Details)
 
ytang0648@aol.com writes:

> Owen:
> I am reading the Pango 1.1.6 code
> and it seems there are several example about the script_shape you talk about under the pango-1.1.6/modules directory.

Yes, basically a "shaper module" is just an implementation of
script_shape.

> One question. How does pango decide which shaper to use ? What is
> the algorithm (based on PangoCoverage ?) to dertermine which shaper
> to be used?

The current algorithm is that modules are registered by:

Backend (Xft fonts, old style X fonts, win32 fonts, etc.)
Covered ranges

And for a given backend, Pango always picks the same shaper for the
same range.

This system would clearly need to be extended a bit if we had
different shapers for different subtypes of fonts (OpenType,
Graphite) fonts within the same Xft backend.

Regards,
                                        Owen

Subj: Re: [Silgraphite-devel] Re: Pango and SILGraphite was Re: Possible Pango 1.4 ideas 
Date: 1/30/2003 12:06:17 PM Pacific Standard Time
From: otaylor@redhat.com
To: ytang0648@aol.com
CC: ftang@netscape.com, Sharon_Correll@sil.org, gtk-i18n-list@gnome.org, silgraphite-devel@lists.sourceforge.net
Sent from the Internet (Details)
 



ytang0648@aol.com writes:

> In a message dated 1/30/2003 10:22:46 AM Eastern Standard Time, otaylor@redhat.com writes:
>
> >
> > > One question. How does pango decide which shaper to use ? What is
> > > the algorithm (based on PangoCoverage ?) to dertermine which shaper
> > > to be used?
> >
> > The current algorithm is that modules are registered by:
> >
> >  Backend (Xft fonts, old style X fonts, win32 fonts, etc.)
> >  Covered ranges
> >
> > And for a given backend, Pango always picks the same shaper for the
> > same range.
> >
> > This system would clearly need to be extended a bit if we
> > had
> > different shapers for different subtypes of fonts (OpenType,
> > Graphite) fonts within the same Xft backend.
> >
> > Regards,
> >                                         Owen

> hum... so the OT xft font currently is not a subclass of xft font
> backend ?  Are you saying that in 1.1.6 you will use the same shaper
> to deal with a Thai OpenType font and a Thai TrueType font ? ( I
> know the OpenType Thai is not supported, but in case you do, is that
> will be the case?)

Yep. For OpenType vs. "legacy hardcoded shaping", I don't think
this is a big problem. If we have code for both, they're is no
problem putting them into the same module. But clearly Graphite
would need some changes in this area.

> I guess backend take higher priority than the coverage, right ?

Backend *has* to match, so yes, it's higher priority. (Note
that it doesn't make sense for Graphite to be a different
*backend*; backends imply an incompatible font rendering technology,
and a new backend would require specific support in everything
that used Pango.)

> Since Graphite will be able to handle all unicode range without
> particular algorithm for a particular coverage, the better way to
> trigger (switch to) it's shapper is to check the availability of one
> uniq table ('Sil '). and if that table is available, use the
> Graphite Shaper for all the Unicode conde point that you can find in
> the 'cmap'.

The first thing you would clearly need to do is to add some
idea of what tables a font has to the information that fontconfig
queries from a font ... 'gsub','gpos','gdef', and 'Sil ' being
the ones that are immediately interesting.

Then you need to figure out how to work that information into
the query that Pango does against fontconfig. This is the
hard bit.

The code to do this query is currently in
pangofc-fontmap.cI:pango_fc_font_map_get_patterns(), which
is called from pango_fc_font_map_load_fontset(), which is
called from pango-context.c:add_engines().

Then we go from the set of patterns to the single best
pattern with a call to pango_fontset_get_font().

One conceivable scheme:

- Instead of determining a single shaper for the codepoint/script
   (See http://bugzilla.gnome.org/show_bug.cgi?id=91542 for
   changing from codepoints to scripts in shaper selection), we
   determine a set of possible shapers.

- We add a list of shapers as an optional argument to
   PangoFontMap::load_fontmap. (The virtual function is
   ENABLE_BACKEND, so can be changed, there would have
   to be an extended version of the public function.)

- We add an extra Xft-specific interface that Xft shaper
   engines implement to get a required table. (*)

- We add those tables to the fontconfig query, so that
   fonts with a 'Sil ' or 'gsub' table sort before fonts
   without that table.

- We add a "do you support this font" interface to
   PangoEngineShape that we can use to pick the right
   shaper once we have the font. (Perhaps the current
   get_coverage() could be used, but if there is a better
   way of doing it, we could change that.)

Note also that this is also one of the really speed critical
bits of Pango...

> I am not that clear about the PangoCoverage in the shaper code. Does
> that refer to the coverage of the hard wire logic? or does that
> refer to the coverage of a particular TrueType font? I guess in the
> case of the shaper api, it refer to the hard wire logic, right?

The get_coverage() shaper method is basically dead code.

The original idea was that a shaper module could get involved in
deciding the coverage of a particular font, so, say, if you had an
Arabic font without the proper tables.

But as the code ended up, the selection of font is done completely
with information that fontconfig queries from the fonts in
advance, so there is no real place for the shaper to get involved.

> Do you use the same PangoCoverage data type in other places refer to
> the Unicode code point coverage of a particular font ?

No. The coverage of a font is currently computed by the backend, not
by the shaper.

> Thanks for your help. 1.1.6 is the version I should look into, right?

Well, actually, the current version of Pango is 1.2.0 (1.2.1 very
shortly), but nothing has changed structurally since 1.1.6.

Regards,
                                        Owen

(*) Multiple ways of doing this. It might be the right time
    to switch PangoEngine over to a GObject, or we could
    do something ad-hoc.

Subj: Re: [Silgraphite-devel] Re: Pango and SILGraphite was Re: Possible Pango 1.4 ideas 
Date: 1/30/2003 12:18:54 PM Pacific Standard Time
From: otaylor@redhat.com
To: ytang0648@aol.com
CC: ftang@netscape.com, Sharon_Correll@sil.org, gtk-i18n-list@gnome.org, silgraphite-devel@lists.sourceforge.net
Sent from the Internet (Details)
 



ytang0648@aol.com writes:

> In a message dated 1/30/2003 10:22:46 AM Eastern Standard Time, otaylor@redhat.com writes:
>
> >
> > The current algorithm is that modules are registered by:
> >
> >  Backend (Xft fonts, old style X fonts, win32 fonts, etc.)
> >  Covered ranges
> >
>
> I guess the "Backend" you refer to is the PANGO_RENDER_TYPE_xxx, right?
> Where is the registeration taking place?
>
> I can only see code to query it ( say pango_x_get_shaper_map callign
> pango_find_map
>
> but where is the code register it? is that register through code in
> the lib init time. Or it is through some build time configuration
> file registration ? Do you have a "how to add a shaper" or "how to
> add a render" cheat sheet? (or previous email) that I could read :)

pango-querymodules is used run script_engine_list() function
of a set of modules and write out a pango.modules file.

The 2 second of installing a new moudle is:

modversion=`pkg-config --variable=pango_module_version pango`
cp $my_module.so $libdir/pango/$modversion/modules/
pango-querymodules > $sysconfdir/pango/pango.modules

Regards,
                                        Owen