summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--trunk/AUTHORS2
-rw-r--r--trunk/COPYING482
-rw-r--r--trunk/ChangeLog1340
-rw-r--r--trunk/ChangeLog.pre-1-05211
-rw-r--r--trunk/ChangeLog.pre-1-101274
-rw-r--r--trunk/ChangeLog.pre-1-121748
-rw-r--r--trunk/ChangeLog.pre-1-14928
-rw-r--r--trunk/ChangeLog.pre-1-161827
-rw-r--r--trunk/ChangeLog.pre-1-21570
-rw-r--r--trunk/ChangeLog.pre-1-41762
-rw-r--r--trunk/ChangeLog.pre-1-6799
-rw-r--r--trunk/ChangeLog.pre-1-8488
-rw-r--r--trunk/HACKING113
-rw-r--r--trunk/MAINTAINERS4
-rw-r--r--trunk/Makefile.am73
-rw-r--r--trunk/NEWS1636
-rw-r--r--trunk/README95
-rw-r--r--trunk/README.win3250
-rw-r--r--trunk/THANKS13
-rw-r--r--trunk/acinclude.m457
-rwxr-xr-xtrunk/autogen.sh23
-rw-r--r--trunk/configure.in971
-rw-r--r--trunk/docs/Makefile.am140
-rw-r--r--trunk/docs/TEXT/glossary49
-rwxr-xr-xtrunk/docs/check.docs29
-rw-r--r--trunk/docs/layout.eps231
-rw-r--r--trunk/docs/layout.fig75
-rw-r--r--trunk/docs/layout.gifbin0 -> 5572 bytes
-rw-r--r--trunk/docs/pango-docs.sgml124
-rw-r--r--trunk/docs/pango-overrides.txt0
-rw-r--r--trunk/docs/pango-querymodules.149
-rw-r--r--trunk/docs/pango-querymodules.xml53
-rw-r--r--trunk/docs/pango-sections.txt1062
-rw-r--r--trunk/docs/pango.types30
-rw-r--r--trunk/docs/pango_markup.sgml250
-rw-r--r--trunk/docs/rotated-text.pngbin0 -> 23044 bytes
-rw-r--r--trunk/docs/tmpl/atsui-fonts.sgml37
-rw-r--r--trunk/docs/tmpl/coverage-maps.sgml136
-rw-r--r--trunk/docs/tmpl/engines.sgml116
-rw-r--r--trunk/docs/tmpl/fonts.sgml1023
-rw-r--r--trunk/docs/tmpl/freetype-fonts.sgml222
-rw-r--r--trunk/docs/tmpl/glyphs.sgml555
-rw-r--r--trunk/docs/tmpl/layout.sgml868
-rw-r--r--trunk/docs/tmpl/main.sgml488
-rw-r--r--trunk/docs/tmpl/modules.sgml87
-rw-r--r--trunk/docs/tmpl/opentype.sgml551
-rw-r--r--trunk/docs/tmpl/pango-engine-lang.sgml53
-rw-r--r--trunk/docs/tmpl/pango-engine-shape.sgml54
-rw-r--r--trunk/docs/tmpl/pango-renderer.sgml212
-rw-r--r--trunk/docs/tmpl/pango-version.sgml110
-rw-r--r--trunk/docs/tmpl/pangocairo.sgml409
-rw-r--r--trunk/docs/tmpl/pangofc-decoder.sgml55
-rw-r--r--trunk/docs/tmpl/pangofc-font.sgml122
-rw-r--r--trunk/docs/tmpl/pangofc-fontmap.sgml114
-rw-r--r--trunk/docs/tmpl/scripts.sgml182
-rw-r--r--trunk/docs/tmpl/tab-stops.sgml147
-rw-r--r--trunk/docs/tmpl/text-attributes.sgml838
-rw-r--r--trunk/docs/tmpl/utils.sgml225
-rw-r--r--trunk/docs/tmpl/vertical.sgml100
-rw-r--r--trunk/docs/tmpl/win32-fonts.sgml258
-rw-r--r--trunk/docs/tmpl/x-fonts.sgml313
-rw-r--r--trunk/docs/tmpl/xft-fonts.sgml308
-rw-r--r--trunk/docs/version.xml.in1
-rw-r--r--trunk/examples/Makefile.am31
-rw-r--r--trunk/examples/cairoshape.c209
-rw-r--r--trunk/examples/cairosimple.c93
-rw-r--r--trunk/examples/cairotwisted.c458
-rw-r--r--trunk/examples/pangowin32tobmp.c450
-rw-r--r--trunk/modules/Makefile.am74
-rw-r--r--trunk/modules/Module.mk35
-rw-r--r--trunk/modules/arabic/Makefile.am41
-rw-r--r--trunk/modules/arabic/arabic-fc.c224
-rw-r--r--trunk/modules/arabic/arabic-lang.c152
-rw-r--r--trunk/modules/arabic/arabic-ot.c461
-rw-r--r--trunk/modules/arabic/arabic-ot.h80
-rw-r--r--trunk/modules/basic/Makefile.am74
-rw-r--r--trunk/modules/basic/basic-atsui.c205
-rw-r--r--trunk/modules/basic/basic-fc.c250
-rw-r--r--trunk/modules/basic/basic-win32.c946
-rw-r--r--trunk/modules/basic/basic-x.c720
-rw-r--r--trunk/modules/basic/tables-big.i4397
-rw-r--r--trunk/modules/basic/tables-small.i603
-rw-r--r--trunk/modules/hangul/Makefile.am24
-rw-r--r--trunk/modules/hangul/hangul-defs.h91
-rw-r--r--trunk/modules/hangul/hangul-fc.c498
-rw-r--r--trunk/modules/hangul/tables-jamos.i401
-rw-r--r--trunk/modules/hebrew/Makefile.am22
-rw-r--r--trunk/modules/hebrew/hebrew-fc.c358
-rw-r--r--trunk/modules/hebrew/hebrew-shaper.c477
-rw-r--r--trunk/modules/hebrew/hebrew-shaper.h50
-rw-r--r--trunk/modules/indic/Makefile.am44
-rw-r--r--trunk/modules/indic/indic-fc.c347
-rw-r--r--trunk/modules/indic/indic-lang.c253
-rw-r--r--trunk/modules/indic/indic-ot-class-tables.c522
-rw-r--r--trunk/modules/indic/indic-ot.c535
-rw-r--r--trunk/modules/indic/indic-ot.h238
-rw-r--r--trunk/modules/indic/mprefixups.c116
-rw-r--r--trunk/modules/indic/mprefixups.h51
-rw-r--r--trunk/modules/khmer/Makefile.am21
-rw-r--r--trunk/modules/khmer/khmer-fc.c720
-rw-r--r--trunk/modules/makefile.msc63
-rw-r--r--trunk/modules/module.def5
-rw-r--r--trunk/modules/pangorc8
-rw-r--r--trunk/modules/syriac/Makefile.am23
-rw-r--r--trunk/modules/syriac/syriac-fc.c212
-rw-r--r--trunk/modules/syriac/syriac-ot.c361
-rw-r--r--trunk/modules/syriac/syriac-ot.h69
-rw-r--r--trunk/modules/thai/Makefile.am41
-rw-r--r--trunk/modules/thai/thai-charprop.c164
-rw-r--r--trunk/modules/thai/thai-charprop.h99
-rw-r--r--trunk/modules/thai/thai-fc.c355
-rw-r--r--trunk/modules/thai/thai-lang.c139
-rw-r--r--trunk/modules/thai/thai-shaper.c548
-rw-r--r--trunk/modules/thai/thai-shaper.h80
-rw-r--r--trunk/modules/tibetan/Makefile.am20
-rw-r--r--trunk/modules/tibetan/tibetan-fc.c573
-rw-r--r--trunk/pango-uninstalled.pc.in7
-rw-r--r--trunk/pango-view/GLASS.txt170
-rw-r--r--trunk/pango-view/HELLO.txt54
-rw-r--r--trunk/pango-view/Makefile.am194
-rw-r--r--trunk/pango-view/pango-view.c23
-rw-r--r--trunk/pango-view/pangocairo-view.c8
-rw-r--r--trunk/pango-view/pangoft2-view.c8
-rw-r--r--trunk/pango-view/pangox-view.c8
-rw-r--r--trunk/pango-view/pangoxft-view.c8
-rw-r--r--trunk/pango-view/test-arabic.txt7
-rw-r--r--trunk/pango-view/test-chinese.txt7
-rw-r--r--trunk/pango-view/test-devanagari.txt9
-rw-r--r--trunk/pango-view/test-gurmukhi.txt26
-rw-r--r--trunk/pango-view/test-hebrew.txt13
-rw-r--r--trunk/pango-view/test-ipa.txt8
-rw-r--r--trunk/pango-view/test-justify.txt5
-rw-r--r--trunk/pango-view/test-lao.txt2
-rw-r--r--trunk/pango-view/test-latin.txt9
-rw-r--r--trunk/pango-view/test-long-paragraph.txt18
-rw-r--r--trunk/pango-view/test-mixed.markup9
-rw-r--r--trunk/pango-view/test-mixed.txt9
-rw-r--r--trunk/pango-view/test-nko.txt15
-rw-r--r--trunk/pango-view/test-opentype-language.markup5
-rw-r--r--trunk/pango-view/test-syriac.txt18
-rw-r--r--trunk/pango-view/test-tamil.txt13
-rw-r--r--trunk/pango-view/test-thai.txt11
-rw-r--r--trunk/pango-view/test-tibetan.txt12
-rw-r--r--trunk/pango-view/viewer-cairo.c53
-rw-r--r--trunk/pango-view/viewer-cairo.h42
-rw-r--r--trunk/pango-view/viewer-main.c162
-rw-r--r--trunk/pango-view/viewer-pangocairo.c427
-rw-r--r--trunk/pango-view/viewer-pangoft2.c162
-rw-r--r--trunk/pango-view/viewer-pangox.c122
-rw-r--r--trunk/pango-view/viewer-pangoxft.c151
-rw-r--r--trunk/pango-view/viewer-render.c711
-rw-r--r--trunk/pango-view/viewer-render.h86
-rw-r--r--trunk/pango-view/viewer-win32.c748
-rw-r--r--trunk/pango-view/viewer-x.c241
-rw-r--r--trunk/pango-view/viewer-x.h70
-rw-r--r--trunk/pango-view/viewer.h99
-rwxr-xr-xtrunk/pango-zip.sh.in52
-rw-r--r--trunk/pango.pc.in14
-rw-r--r--trunk/pango/Makefile.am501
-rw-r--r--trunk/pango/break.c1738
-rwxr-xr-xtrunk/pango/check.defs29
-rw-r--r--trunk/pango/ellipsize.c767
-rw-r--r--trunk/pango/fonts.c1855
-rw-r--r--trunk/pango/glyphstring.c360
-rw-r--r--trunk/pango/makefile.msc290
-rw-r--r--trunk/pango/mapping.c328
-rw-r--r--trunk/pango/mini-fribidi/Makefile.am31
-rw-r--r--trunk/pango/mini-fribidi/README23
-rw-r--r--trunk/pango/mini-fribidi/fribidi.c957
-rw-r--r--trunk/pango/mini-fribidi/fribidi.h56
-rw-r--r--trunk/pango/mini-fribidi/fribidi.patch1369
-rw-r--r--trunk/pango/mini-fribidi/fribidi_char_type.c75
-rw-r--r--trunk/pango/mini-fribidi/fribidi_config.h24
-rw-r--r--trunk/pango/mini-fribidi/fribidi_tab_char_type_2.i5607
-rw-r--r--trunk/pango/mini-fribidi/fribidi_types.c86
-rw-r--r--trunk/pango/mini-fribidi/fribidi_types.h313
-rw-r--r--trunk/pango/mini-fribidi/fribidi_types.i21
-rw-r--r--trunk/pango/module-defs-fc.c.win3231
-rw-r--r--trunk/pango/module-defs-win32.c.win3225
-rw-r--r--trunk/pango/modules.c763
-rw-r--r--trunk/pango/modules.h34
-rw-r--r--trunk/pango/opentype/COPYING15
-rw-r--r--trunk/pango/opentype/COPYING.FTL174
-rw-r--r--trunk/pango/opentype/COPYING.GPL340
-rw-r--r--trunk/pango/opentype/Makefile.am59
-rw-r--r--trunk/pango/opentype/README18
-rw-r--r--trunk/pango/opentype/ftglue.c300
-rw-r--r--trunk/pango/opentype/ftglue.h150
-rw-r--r--trunk/pango/opentype/harfbuzz-buffer.c227
-rw-r--r--trunk/pango/opentype/harfbuzz-buffer.h106
-rw-r--r--trunk/pango/opentype/harfbuzz-dump-main.c272
-rw-r--r--trunk/pango/opentype/harfbuzz-dump.c748
-rw-r--r--trunk/pango/opentype/harfbuzz-dump.h34
-rw-r--r--trunk/pango/opentype/harfbuzz-gdef-private.h101
-rw-r--r--trunk/pango/opentype/harfbuzz-gdef.c1228
-rw-r--r--trunk/pango/opentype/harfbuzz-gdef.h127
-rw-r--r--trunk/pango/opentype/harfbuzz-gpos-private.h683
-rw-r--r--trunk/pango/opentype/harfbuzz-gpos.c6304
-rw-r--r--trunk/pango/opentype/harfbuzz-gpos.h168
-rw-r--r--trunk/pango/opentype/harfbuzz-gsub-private.h448
-rw-r--r--trunk/pango/opentype/harfbuzz-gsub.c4592
-rw-r--r--trunk/pango/opentype/harfbuzz-gsub.h132
-rw-r--r--trunk/pango/opentype/harfbuzz-impl.h83
-rw-r--r--trunk/pango/opentype/harfbuzz-open-private.h81
-rw-r--r--trunk/pango/opentype/harfbuzz-open.c1431
-rw-r--r--trunk/pango/opentype/harfbuzz-open.h285
-rw-r--r--trunk/pango/opentype/harfbuzz.c19
-rw-r--r--trunk/pango/opentype/harfbuzz.h23
-rw-r--r--trunk/pango/opentype/makefile.msc19
-rw-r--r--trunk/pango/pango-attributes.c1986
-rw-r--r--trunk/pango/pango-attributes.h274
-rw-r--r--trunk/pango/pango-break.h117
-rw-r--r--trunk/pango/pango-color-table.h1521
-rw-r--r--trunk/pango/pango-color.c259
-rw-r--r--trunk/pango/pango-context.c1640
-rw-r--r--trunk/pango/pango-context.h113
-rw-r--r--trunk/pango/pango-coverage.c494
-rw-r--r--trunk/pango/pango-coverage.h58
-rw-r--r--trunk/pango/pango-engine-private.h46
-rw-r--r--trunk/pango/pango-engine.c174
-rw-r--r--trunk/pango/pango-engine.h379
-rw-r--r--trunk/pango/pango-font.h383
-rw-r--r--trunk/pango/pango-fontmap.c269
-rw-r--r--trunk/pango/pango-fontmap.h95
-rw-r--r--trunk/pango/pango-fontset.c404
-rw-r--r--trunk/pango/pango-fontset.h127
-rw-r--r--trunk/pango/pango-glyph-item-private.h63
-rw-r--r--trunk/pango/pango-glyph-item.c664
-rw-r--r--trunk/pango/pango-glyph-item.h54
-rw-r--r--trunk/pango/pango-glyph.h135
-rw-r--r--trunk/pango/pango-gravity.c298
-rw-r--r--trunk/pango/pango-gravity.h109
-rw-r--r--trunk/pango/pango-impl-utils.h100
-rw-r--r--trunk/pango/pango-item.c154
-rw-r--r--trunk/pango/pango-item.h72
-rw-r--r--trunk/pango/pango-language.c730
-rw-r--r--trunk/pango/pango-language.h48
-rw-r--r--trunk/pango/pango-layout-private.h82
-rw-r--r--trunk/pango/pango-layout.c6074
-rw-r--r--trunk/pango/pango-layout.h286
-rw-r--r--trunk/pango/pango-markup.c1471
-rw-r--r--trunk/pango/pango-matrix.c467
-rw-r--r--trunk/pango/pango-matrix.h117
-rw-r--r--trunk/pango/pango-modules.h60
-rw-r--r--trunk/pango/pango-ot-buffer.c380
-rw-r--r--trunk/pango/pango-ot-info.c791
-rw-r--r--trunk/pango/pango-ot-private.h105
-rw-r--r--trunk/pango/pango-ot-ruleset.c716
-rw-r--r--trunk/pango/pango-ot-tag.c489
-rw-r--r--trunk/pango/pango-ot.h185
-rw-r--r--trunk/pango/pango-renderer.c1275
-rw-r--r--trunk/pango/pango-renderer.h243
-rw-r--r--trunk/pango/pango-script-lang-table.h199
-rw-r--r--trunk/pango/pango-script-table.h2981
-rw-r--r--trunk/pango/pango-script.c381
-rw-r--r--trunk/pango/pango-script.h133
-rw-r--r--trunk/pango/pango-tabs.c370
-rw-r--r--trunk/pango/pango-tabs.h76
-rw-r--r--trunk/pango/pango-types.h146
-rw-r--r--trunk/pango/pango-utils.c1643
-rw-r--r--trunk/pango/pango-utils.h143
-rw-r--r--trunk/pango/pango.def369
-rw-r--r--trunk/pango/pango.h47
-rw-r--r--trunk/pango/pango.rc.in30
-rw-r--r--trunk/pango/pangoatsui-fontmap.c825
-rw-r--r--trunk/pango/pangoatsui-private.h101
-rw-r--r--trunk/pango/pangoatsui.c201
-rw-r--r--trunk/pango/pangoatsui.h79
-rw-r--r--trunk/pango/pangocairo-atsui.h57
-rw-r--r--trunk/pango/pangocairo-atsuifont.c302
-rw-r--r--trunk/pango/pangocairo-atsuifont.h36
-rw-r--r--trunk/pango/pangocairo-atsuifontmap.c108
-rw-r--r--trunk/pango/pangocairo-context.c438
-rw-r--r--trunk/pango/pangocairo-fc.h57
-rw-r--r--trunk/pango/pangocairo-fcfont.c256
-rw-r--r--trunk/pango/pangocairo-fcfontmap.c206
-rw-r--r--trunk/pango/pangocairo-font.c744
-rw-r--r--trunk/pango/pangocairo-fontmap.c249
-rw-r--r--trunk/pango/pangocairo-private.h145
-rw-r--r--trunk/pango/pangocairo-render.c788
-rw-r--r--trunk/pango/pangocairo-win32.h55
-rw-r--r--trunk/pango/pangocairo-win32font.c318
-rw-r--r--trunk/pango/pangocairo-win32fontmap.c105
-rw-r--r--trunk/pango/pangocairo.def31
-rw-r--r--trunk/pango/pangocairo.h149
-rw-r--r--trunk/pango/pangofc-decoder.c86
-rw-r--r--trunk/pango/pangofc-decoder.h110
-rw-r--r--trunk/pango/pangofc-font.c933
-rw-r--r--trunk/pango/pangofc-font.h151
-rw-r--r--trunk/pango/pangofc-fontmap.c2055
-rw-r--r--trunk/pango/pangofc-fontmap.h177
-rw-r--r--trunk/pango/pangofc-private.h74
-rw-r--r--trunk/pango/pangoft2-fontmap.c353
-rw-r--r--trunk/pango/pangoft2-private.h126
-rw-r--r--trunk/pango/pangoft2-render.c710
-rw-r--r--trunk/pango/pangoft2.c601
-rw-r--r--trunk/pango/pangoft2.def78
-rw-r--r--trunk/pango/pangoft2.h110
-rw-r--r--trunk/pango/pangoft2.rc.in30
-rw-r--r--trunk/pango/pangowin32-fontcache.c434
-rw-r--r--trunk/pango/pangowin32-fontmap.c1334
-rw-r--r--trunk/pango/pangowin32-private.h282
-rw-r--r--trunk/pango/pangowin32.c1787
-rw-r--r--trunk/pango/pangowin32.def29
-rw-r--r--trunk/pango/pangowin32.h118
-rw-r--r--trunk/pango/pangowin32.rc.in30
-rw-r--r--trunk/pango/pangox-fontcache.c248
-rw-r--r--trunk/pango/pangox-fontmap.c1675
-rw-r--r--trunk/pango/pangox-private.h122
-rw-r--r--trunk/pango/pangox.aliases220
-rw-r--r--trunk/pango/pangox.c1807
-rw-r--r--trunk/pango/pangox.h131
-rw-r--r--trunk/pango/pangoxft-font.c613
-rw-r--r--trunk/pango/pangoxft-fontmap.c377
-rw-r--r--trunk/pango/pangoxft-private.h68
-rw-r--r--trunk/pango/pangoxft-render.c897
-rw-r--r--trunk/pango/pangoxft-render.h141
-rw-r--r--trunk/pango/pangoxft.h94
-rw-r--r--trunk/pango/querymodules.c284
-rw-r--r--trunk/pango/reorder-items.c114
-rw-r--r--trunk/pango/shape.c139
-rw-r--r--trunk/pangocairo-uninstalled.pc.in7
-rw-r--r--trunk/pangocairo.pc.in11
-rw-r--r--trunk/pangoft2-uninstalled.pc.in7
-rw-r--r--trunk/pangoft2.pc.in12
-rw-r--r--trunk/pangowin32-uninstalled.pc.in6
-rw-r--r--trunk/pangowin32.pc.in12
-rw-r--r--trunk/pangox-uninstalled.pc.in6
-rw-r--r--trunk/pangox.pc.in12
-rw-r--r--trunk/pangoxft-uninstalled.pc.in7
-rw-r--r--trunk/pangoxft.pc.in11
-rwxr-xr-xtrunk/sanitize-la.sh3
-rw-r--r--trunk/tests/Makefile.am75
-rw-r--r--trunk/tests/boundaries.utf8765
-rw-r--r--trunk/tests/cxx-test.C33
-rw-r--r--trunk/tests/dump-boundaries.c132
-rw-r--r--trunk/tests/gen-all-unicode.c45
-rwxr-xr-xtrunk/tests/runtests.sh.in55
-rw-r--r--trunk/tests/test-ot-tags.c131
-rw-r--r--trunk/tests/testboundaries.c362
-rw-r--r--trunk/tests/testcolor.c94
-rw-r--r--trunk/tests/testiter.c243
-rw-r--r--trunk/tests/testscript.c260
-rw-r--r--trunk/tools/Makefile.am20
-rwxr-xr-xtrunk/tools/add-copyright62
-rwxr-xr-xtrunk/tools/compress-table.pl123
-rwxr-xr-xtrunk/tools/gen-color-table.pl74
-rw-r--r--trunk/tools/gen-script-for-lang.c323
-rwxr-xr-xtrunk/tools/gen-script-table.pl117
-rw-r--r--trunk/tools/maps/README12
-rw-r--r--trunk/tools/maps/tis-620185
351 files changed, 139457 insertions, 0 deletions
diff --git a/trunk/AUTHORS b/trunk/AUTHORS
new file mode 100644
index 00000000..181b49d0
--- /dev/null
+++ b/trunk/AUTHORS
@@ -0,0 +1,2 @@
+Owen Taylor <otaylor@redhat.com>, with help from many others.
+See file named THANKS for a list.
diff --git a/trunk/COPYING b/trunk/COPYING
new file mode 100644
index 00000000..bf50f20d
--- /dev/null
+++ b/trunk/COPYING
@@ -0,0 +1,482 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/trunk/ChangeLog b/trunk/ChangeLog
new file mode 100644
index 00000000..2df69618
--- /dev/null
+++ b/trunk/ChangeLog
@@ -0,0 +1,1340 @@
+2007-07-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.17.5 ===
+
+ * configure.in: Version 1.17.5
+
+ * NEWS: Updated.
+
+2007-07-24 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 150883 – Unicode LRO defect
+
+ * modules/arabic/arabic-fc.c (arabic_engine_shape):
+ * modules/arabic/arabic-ot.c (Get_Joining_Class),
+ (Arabic_Assign_Properties):
+ * modules/arabic/arabic-ot.h:
+ Correctly handle Arabic shaping in left-to-right runs.
+
+2007-07-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 347236 – provide pango_cairo_font_get_scaled_font
+
+ * docs/Makefile.am:
+ * docs/pango-sections.txt:
+ * docs/tmpl/atsui-fonts.sgml:
+ * docs/tmpl/opentype.sgml:
+ * docs/tmpl/pango-engine-lang.sgml:
+ * docs/tmpl/pango-engine-shape.sgml:
+ * docs/tmpl/pangocairo.sgml:
+ * pango/pangoatsui.h:
+ * pango/pangocairo-atsuifont.h:
+ * pango/pangocairo-font.c (pango_cairo_font_get_scaled_font):
+ * pango/pangocairo-private.h:
+ * pango/pangocairo.h:
+ Export PangoCairoFont and cleanup various standard macros.
+
+2007-07-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 449482 – Build error when xft not present
+
+ * docs/Makefile.am: Make docs build without xft.
+
+2007-07-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/arabic/arabic-fc.c:
+ * modules/basic/basic-fc.c:
+ * modules/hebrew/hebrew-fc.c:
+ * modules/syriac/syriac-fc.c:
+ * modules/thai/thai-fc.c:
+ Update copyright headers.
+
+2007-07-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/basic-atsui.c: Remove list of supported scripts.
+ Supporting all is what we really want and that's already there.
+
+2007-07-05 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/Makefile.am:
+ * modules/basic/basic-fc.c:
+ * modules/basic/basic-win32.c:
+ * modules/basic/basic-x.c:
+ * modules/basic/basic-common.h:
+ Remove unused empty header file basic-common.h
+
+2007-07-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.17.4 ===
+
+ * configure.in: Version 1.17.4
+
+ * NEWS: Updated.
+
+2007-06-27 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 451547 – FAIL: runtests.sh
+
+ * tests/Makefile.am: Don't run tests if cross-compiling.
+ (though cross-compiling tests work under scratchbox, so I'm not
+ quite sure how good this change is.)
+
+2007-06-26 Richard Hult <richard@imendio.com>
+
+ * pango/pangoatsui.c: (_pango_atsui_font_set_atsu_font_id):
+ * pango/pangocairo-atsuifont.c:
+ (pango_cairo_atsui_font_create_metrics_for_context),
+ (_pango_cairo_atsui_font_new): Move the remaining uses of font_id
+ from PangoCairoATSUIFont to PangoATSUIFont.
+
+2007-06-24 Richard Hult <richard@imendio.com>
+
+ Bug 449543 - Ship pangoatsui.h
+
+ * pango/pangoatsui-fontmap.c:
+ * pango/pangoatsui-private.h:
+ * pango/pangoatsui.c:
+ * pango/pangoatsui.h:
+ * pango/pangocairo-atsuifont.c:
+ * pango/pangocairo-atsuifont.h: Move get_atsu_font_id from the
+ cairo atsui font class to the atsui base class. Make the members
+ of the atsui font private and adapt all users of them.
+
+ * pango/Makefile.am: Ship pangoatsui.h.
+
+ * modules/basic/basic-atsui.c: (basic_engine_shape): Adapt to the
+ above changes.
+
+2007-06-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango.types: Add missing types.
+
+2007-06-20 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (pango_font_description_get_type),
+ (pango_font_metrics_get_type):
+ * pango/glyphstring.c (pango_glyph_string_get_type):
+ * pango/pango-attributes.c (pango_attr_list_get_type):
+ * pango/pango-color.c (pango_color_get_type):
+ * pango/pango-item.c (pango_item_get_type):
+ * pango/pango-language.c (pango_language_get_type):
+ * pango/pango-layout.c (pango_layout_line_get_type),
+ (pango_layout_iter_get_type):
+ * pango/pango-matrix.c (pango_matrix_get_type):
+ * pango/pango-ot-info.c (pango_ot_info_get_type):
+ * pango/pango-ot-ruleset.c (pango_ot_ruleset_get_type):
+ * pango/pango-tabs.c (pango_tab_array_get_type):
+ * pango/pangoatsui-fontmap.c (pango_atsui_family_get_type),
+ (pango_atsui_face_get_type):
+ * pango/pangofc-fontmap.c (pango_fc_face_get_type),
+ (pango_fc_family_get_type):
+ * pango/pangowin32-fontmap.c (pango_win32_family_get_type),
+ (pango_win32_face_get_type):
+ * pango/pangox-fontmap.c (pango_x_font_map_get_type),
+ (pango_x_face_get_type), (pango_x_family_get_type):
+ * pango/pangox.c (pango_x_font_get_type):
+ Add G_UNLIKELY() to type registration block in _get_type() functions.
+
+2007-06-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.17.3 ===
+
+ * configure.in: Version 1.17.3
+
+ * NEWS: Updated.
+
+2007-06-18 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 448342 – pango_layout_index_to_line_x() counts lines from 1
+
+ * pango/pango-layout.c (pango_layout_index_to_line):
+ Count lines from zero, not one!
+
+2007-06-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in:
+ * tests/cxx-test.C: Include pangocairo.h too.
+
+2007-06-18 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 447568 – improve docs on what absolute size means
+
+ * pango/fonts.c: Improve docs.
+
+2007-06-15 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc : updated
+
+2007-06-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-font.c
+ (_pango_cairo_font_private_scaled_font_data_destroy):
+ Check for NULL before dereferencing. Patch from Keith Packard.
+
+2007-06-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 447189 – fonts.c: pango_font_face_is_synthesized returns NULL
+
+ * pango/fonts.c (pango_font_face_is_synthesized): Fix
+ return value.
+
+2007-06-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-attributes.c (pango_attr_font_desc_equal):
+ Compare set fields of two font descriptions for equality
+ too, as pango_font_description_equal() doesn't check the
+ mask.
+
+2007-06-12 Richard Hult <richard@imendio.com>
+
+ * pango/pangocairo-atsuifontmap.c: Implement
+ get_font_type().
+
+2007-06-12 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangocairo-win32fontmap.c: Implement
+ PangoCairoWin32FontMap::get_font_type().
+
+2007-06-12 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangowin32-private.h (struct PangoWin32Face): Add
+ is_synthetic field.
+
+ * pango/pangowin32-fontmap.c: Implement
+ PangoWin32Face::is_synthesized().
+
+ * pango/pangocairo-win32font.c
+ * pango/pangocairo-win32fontmap.c: Update for the changes to
+ PangoCairoFontMap and PangoCairoFont.
+
+2007-06-12 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 445832 – pango_cairo_update_layout() always invalidates layout
+
+ * pango/pangocairo-context.c (_pango_cairo_update_context),
+ (pango_cairo_update_context), (pango_cairo_update_layout):
+ Don't invalidate layout if matrix and font options didn't change.
+
+2007-06-11 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-attributes.h:
+ * pango/pango-font.h:
+ * pango/pango-glyph.h:
+ * pango/pango-gravity.h:
+ * pango/pango-language.h:
+ * pango/pango-layout.h:
+ * pango/pango-matrix.h:
+ * pango/pango-ot-private.h:
+ * pango/pango-ot.h:
+ * pango/pango-renderer.h:
+ * pango/pango-script.h:
+ * pango/pango-tabs.h:
+ * pango/pango-utils.h:
+ * pango/pangoatsui-private.h:
+ * pango/pangocairo-atsui.h:
+ * pango/pangocairo-atsuifont.h:
+ * pango/pangocairo-fc.h:
+ * pango/pangocairo-private.h:
+ * pango/pangocairo-win32.h:
+ * pango/pangocairo.h:
+ * pango/pangofc-decoder.h:
+ * pango/pangofc-font.h:
+ * pango/pangofc-fontmap.h:
+ * pango/pangoft2-private.h:
+ * pango/pangoft2.h:
+ * pango/pangowin32-private.h:
+ * pango/pangox-private.h:
+ * pango/pangoxft-render.h:
+ * pango/pangoxft.h:
+ Add G_GNUC_CONST and G_GNUC_PURE annotations.
+
+2007-06-11 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-ot.h: New engine public macros:
+
+ PANGO_OT_TAG_MAKE()
+ PANGO_OT_TAG_MAKE_FROM_STRING()
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/opentype.sgml:
+ Update.
+
+2007-06-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 446018 – Bus error in the pango_ot_tag_from_language()
+
+ * pango/pango-ot-tag.c (pango_ot_tag_from_script),
+ (pango_ot_tag_to_script), (pango_ot_tag_from_language),
+ (pango_ot_tag_to_language): Make sure int access is
+ aligned.
+
+2007-06-12 Richard Hult <richard@imendio.com>
+
+ * pango/pangoatsui-fontmap.c (pango_atsui_face_is_synthesized):
+ Implement is_synthesized for the ATSUI backend.
+
+2007-06-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 440588 – Add pango_font_face_is_synthesized()
+
+ * pango/pango-font.h:
+ * pango/fonts.c:
+ New PangoFontFace method is_synthesized.
+ New public API:
+
+ pango_font_face_is_synthesized()
+
+ * pango/pangofc-fontmap.c (pango_fc_face_is_synthesized):
+ Implement new method.
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/fonts.sgml:
+ * pango/pango.def:
+ Update.
+
+2007-06-12 Richard Hult <richard@imendio.com>
+
+ * pango/pangocairo-atsuifont.c:
+ * pango/pangocairo-atsuifontmap.c: Update for the changes to
+ PangoCairoFontMap and PangoCairoFont.
+
+2007-06-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 446355 – the parsing with pango_parse_markup is not coherent
+
+ * pango/pango-markup.c (pango_parse_markup): Use
+ pango_attr_list_insert() instead of pango_attr_list_change() as
+ merging adjacent attributes of the same kind is not a safe operation
+ and can change the derived font of a segment in an unexpected and
+ incorrect way.
+
+2007-06-11 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fontmap.c: Make sure all enabled font backends
+ included (reported by Vincent Isambart).
+
+2007-06-11 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango_markup.sgml: Add 'gravity', 'gravity_hint', and
+ 'letter_spacing' span attributes.
+
+2007-06-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 438801 – underline should add "error" type.
+
+ * docs/pango_markup.sgml: Add "error" underline type to docs.
+
+2007-06-10 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 347236 – provide pango_cairo_font_get_scaled_font
+ Bug 347235 – Add pango_cairo_font_map_get_font_type
+ Bug 353291 – Provide pango_cairo_font_map_new_for_font_type
+
+ * pango/pangocairo-font.c: New public API:
+
+ pango_cairo_font_get_scaled_font()
+
+ * pango/pangocairo-fontmap.c: New public API:
+
+ pango_cairo_font_map_new_for_font_type()
+ pango_cairo_font_map_get_font_type()
+
+ * pango/pangocairo-fcfontmap.c:
+ Implement get_font_type() method.
+
+ * pango/pangocairo.h:
+ * pango/pangocairo-private.h:
+ * docs/pango-sections.txt:
+ * docs/tmpl/pangocairo.sgml:
+ * pango/pangocairo.def:
+ Update.
+
+2007-06-09 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 337593 – move glyph extents code (and cache) from
+ pangocairo-*font.c into pangocairo-font.c
+
+ * pango/pangocairo-fontmap.c:
+ * pango/pangocairo-fcfontmap.c:
+ Remove per-fontmap renderer. We've not been using it for a while
+ and there is no reason to use it.
+
+ * pango/pangocairo-font.c
+ * pango/pangocairo-fcfont.c:
+ Most most code (including glyph extents caching) from fcfont.c to
+ font.c. Simplifies individual backends a lot. ATSUI and Win32
+ cairo backends should adapt.
+
+ * pango/pangocairo-render.c
+ * pango/pangocairo-private.h:
+ Update to reflect above changes.
+
+2007-06-05 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (pango_font_description_merge),
+ (pango_font_description_merge_static),
+ (pango_font_description_copy),
+ (pango_font_description_copy_static),
+ (pango_font_description_hash), (pango_font_description_to_string),
+ (pango_font_description_to_filename):
+ Add missing g_return_if_fail()s. Pointed out by fcrozat.
+
+2007-06-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/shape.c (pango_shape): Zero glyphs->num_glyphs before
+ calling into shape engine.
+
+ * pango/pango-engine.c (fallback_engine_shape): Improve, to support
+ clusters and what not.
+
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info):
+ Use "pango_script_get_sample_language (PANGO_SCRIPT_LATIN)" instead
+ of hardcoding "en".
+ Handle cairo_scaled_font_extents() failure.
+
+2007-06-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.17.2 ===
+
+ * configure.in: Version 1.17.2
+
+ * NEWS: Updated.
+
+2007-06-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/tmpl/main.sgml:
+ * pango/pango-layout.c (process_item):
+ * pango/pango-ot-info.c:
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line):
+ Fix various typos reported by Peter Moulder.
+
+2007-06-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/opentype.sgml:
+ * modules/arabic/arabic-fc.c (arabic_engine_shape):
+ * modules/basic/basic-fc.c (basic_engine_shape):
+ * modules/hebrew/hebrew-fc.c (hebrew_engine_shape):
+ * modules/indic/indic-fc.c (indic_engine_shape):
+ * modules/khmer/khmer-fc.c (khmer_engine_shape):
+ * modules/syriac/syriac-fc.c (syriac_engine_shape):
+ * modules/thai/thai-fc.c (thai_engine_shape):
+ * modules/tibetan/tibetan-fc.c (tibetan_engine_shape):
+ * pango/pango-ot-ruleset.c (pango_ot_ruleset_get_for_description),
+ (pango_ot_ruleset_new_from_description):
+ * pango/pango-ot.h:
+ * pango/pangoft2.def:
+ Rename pango_ot_ruleset_get_for() to
+ pango_ot_ruleset_get_for_description().
+
+ New engine API: pango_ot_ruleset_new_from_description().
+
+2007-06-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 443206 – PANGO_SCRIPT_UNKNOWN should not cause a run break
+ Patch from Martin Hosken
+
+ * pango/pango-script.c: Treat Unknown script like Common and other
+ non-"real" scripts.
+
+2007-05-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c: Improve docs.
+
+2007-05-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.17.1 ===
+
+ * configure.in: Version 1.17.1
+
+ * NEWS: Updated.
+
+2007-05-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/test-mixed.markup:
+ * pango-view/test-mixed.txt:
+ Fix Japanese text. Patch from Ben Konrath
+
+2007-05-25 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/mini-fribidi/fribidi_tab_char_type_2.i:
+ Fix wrong Unicode version in header.
+
+2007-05-24 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 357790 – Rendering problem for malayalam consonant RA (U+0D30)
+
+ * modules/indic/indic-ot-class-tables.c:
+ * modules/indic/indic-ot.c (indic_ot_reorder):
+ Commit remaining fix for malayalam.
+
+2007-05-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/tmpl/opentype.sgml:
+ * docs/tmpl/pango-engine-lang.sgml:
+ * docs/tmpl/pango-engine-shape.sgml:
+ Add stability note.
+
+2007-05-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/tmpl/vertical.sgml: Document how Pango's vertical text support
+ works.
+
+2007-05-23 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 440603 – Minor ABI change
+
+ * pango/pango-context.c (pango_context_init),
+ (pango_context_set_language), (pango_context_get_language):
+ Make itemization use pango_language_get_default() if context has no
+ language set on it. Ditto for pango_context_get_metrics() if both
+ input language and context language are NULL.
+
+2007-05-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/Makefile.am:
+ * pango-view/test-nko.txt:
+ New test text for N'Ko.
+
+2007-05-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 440603 – Minor ABI change
+
+ * pango/pango-language.c (pango_language_includes_script):
+ * pango/pango-ot-tag.c (pango_ot_tag_from_language):
+ Accept language == NULL as legitimate input.
+
+2007-05-20 Richard Hult <richard@imendio.com>
+
+ * pango/pangocairo-atsuifont.c: (_pango_cairo_atsui_font_new): Improve
+ the fix for bug #433805 so that the metrics actually are right, thanks
+ to Mitch for noticing and debugging help.
+
+2007-05-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 438705 – Test runs non-existent "/bin/bash" on HP-UX 11.11
+
+ * docs/check.docs:
+ * pango/check.defs:
+ Use /bin/sh instead of /bin/bash.
+
+2007-05-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/Makefile.am:
+ * pango-view/test-opentype-language.markup:
+ Add a test file showing off OpenType language-system support
+ used with DejaVu Sans.
+
+2007-05-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 438814 – synaptic crash with pango 1.17.0
+
+ * pango/pango-layout.c (process_item): Make sure we find some break
+ point even if overflowing the line.
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/hebrew/hebrew-fc.c (hebrew_engine_shape):
+ Port to new OpenType APIs. Add standard features.
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/thai/Makefile.am:
+ * modules/thai/thai-fc.c (thai_get_font_info), (thai_engine_shape),
+ (thai_make_unknown_glyph):
+ * modules/thai/thai-shaper.c (get_glyphs_list), (add_cluster),
+ (thai_set_glyphs):
+ * modules/thai/thai-shaper.h:
+ Port to new OpenType APIs and cleanup a bit. Add standard features.
+
+ * modules/thai/thai-ot.c:
+ * modules/thai/thai-ot.h:
+ Removed. Not needed anymore.
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 385168 – indic, khmer, and tibetan modules don't apply ccmp
+ Bug 385477 – kern feature is not supported in OpenType layout for
+ Tibetan.
+
+ * modules/khmer/khmer-fc.c (khmer_engine_shape):
+ * modules/tibetan/tibetan-fc.c (tibetan_engine_shape):
+ Port to new OpenType APIs. Add standard features (ccmp,
+ locl, calt, kern, mark, mkmk).
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/indic/indic-fc.c:
+ Add ccmp, locl, calt; kern, mark, and mkmk features.
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-ot.h:
+ * pango/pango-ot-private.h:
+ * pango/pango-ot-ruleset.c (pango_ot_ruleset_add_feature),
+ (pango_ot_ruleset_get_feature_count):
+ Add new engine API:
+
+ pango_ot_ruleset_get_feature_count()
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/opentype.sgml:
+ * pango/pangoft2.def:
+ Updated.
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/arabic/arabic-fc.c (arabic_engine_shape):
+ * modules/basic/basic-fc.c (basic_engine_shape):
+ * modules/syriac/syriac-fc.c (syriac_engine_shape):
+ Move ruleset creation after populating buffer.
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/indic/indic-fc.c (indic_engine_shape), (create):
+ Port to new OpenType APIs.
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 436699 – N'Ko support
+ Patch by Eugeniy Meshcheryakov
+
+ * modules/arabic/arabic-fc.c (create):
+ * modules/arabic/arabic-ot.c (Get_Joining_Class):
+ Add N'Ko support to the Arabic module.
+
+2007-05-15 Richard Hult <richard@imendio.com>
+
+ Bug 433805 - [Atsui] Approximate char/digit width width often 0
+
+ * pango/pangocairo-atsuifont.c:
+ (pango_cairo_atsui_font_get_metrics): Improve the metrics so it really
+ is average instead of max glyph width. Also keep the metrics per
+ language in the font so it's not constantly recreated.
+ (pango_cairo_atsui_font_describe_absolute): Implement.
+
+ * pango/pangocairo-atsuifontmap.c: Set default resolution.
+
+2007-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/Makefile.am: Add various test txt files recently
+ added.
+
+ * pango-view/test-mixed.markup: A language-tagged version of
+ test-mixed.txt.
+
+2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.17.0 ===
+
+ * configure.in: Version 1.17.0
+
+ * NEWS: Updated.
+
+2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 325714 – Pango should respect $LANGUAGE
+
+ * pango/pango-language.c (pango_language_matches),
+ (parse_default_languages), (_pango_script_get_default_language),
+ (pango_script_get_sample_language):
+ Make pango_script_get_sample_language() use the value of env var
+ PANGO_LANGUAGE or LANGUAGE (checked in that order) to make better
+ guesses. The env var should be a list of language tags, like "en:fa"
+ for example where makes Pango choose Persian (fa) fonts instead of
+ Arabic (ar) fonts...
+
+2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-language.c (pango_script_get_sample_language):
+ * pango/pango-script.c: Move pango_script_get_sample_language()
+ from pango-script.c to pango-language.c. Fits better.
+
+2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 325714 – Pango should respect $LANGUAGE
+ Bug 414264 – Pango vertical writing support is different with real
+ CJK usage.
+
+ * modules/arabic/arabic-fc.c (arabic_engine_shape):
+ * modules/basic/basic-fc.c (basic_engine_shape):
+ * modules/syriac/syriac-fc.c (syriac_engine_shape):
+ Remove fallback_shape() paths. Remove get_ruleset().
+ Use pango_ot_ruleset_get_for(), that correctly works for multiple
+ languages. Also makes basic shaper apply the 'vert' feature for
+ vertical text. Removes a net 500 lines.
+
+ Other OpenType modules need to be ported over time, however some
+ extensions may be needed. For example, the Hebrew shaper uses
+ fallback code if no GPOS tables are available. Currently using
+ pango_ot_ruleset_get_for() one cannot see which features were
+ found.
+
+2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 414264 – Pango vertical writing support is different with
+ real CJK usage.
+
+ * pango-view/test-mixed.txt: Add a line of Japanese text that
+ has brackets that should be rotated in vertical text.
+
+2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 325714 – Pango should respect $LANGUAGE
+
+ * pango/pango-ot.h:
+ * pango/pango-ot-ruleset.c (pango_ot_ruleset_get_for),
+ (pango_ot_ruleset_description_hash),
+ (pango_ot_ruleset_description_equal),
+ (pango_ot_ruleset_description_copy),
+ (pango_ot_ruleset_description_free):
+ Add new engine API:
+
+ PangoOTRulesetDescription
+ pango_ot_ruleset_get_for()
+ pango_ot_ruleset_description_hash()
+ pango_ot_ruleset_description_equal()
+ pango_ot_ruleset_description_copy()
+ pango_ot_ruleset_description_free()
+
+ The main addition is pango_ot_ruleset_get_for() that
+ takes a ruleset description, ie. script/language and list
+ of GSUB/GPOS features to apply, and returns a ruleset.
+ It manages all the work to cache rulesets, so modules
+ don't have to do that anymore. Given that modules do not
+ deal with just one ruleset anymore (because we want to
+ respect language, and allow user-selected features), this
+ makes their life way easier.
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/opentype.sgml:
+ Update.
+
+2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-ot-buffer.c (pango_ot_buffer_get_glyphs),
+ (pango_ot_buffer_output):
+ * pango/pango-ot-ruleset.c (pango_ot_ruleset_substitute),
+ (pango_ot_ruleset_position):
+ * pango/pango-ot.h:
+ Mark some arguments const.
+
+2007-05-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 325714 – Pango should respect $LANGUAGE
+
+ * pango/pango-ot.h:
+ * pango/pango-ot-private.h:
+ * pango/pango-ot-tag.c (pango_ot_tag_from_script),
+ (pango_ot_tag_from_language):
+ * pango/pango-ot-info.c (pango_ot_info_find_script),
+ (pango_ot_info_find_language), (pango_ot_info_find_feature),
+ (pango_ot_info_list_languages), (pango_ot_info_list_features):
+ * pango/pango-ot-ruleset.c (pango_ot_ruleset_new),
+ (pango_ot_ruleset_new_for), (pango_ot_ruleset_add_feature),
+ (pango_ot_ruleset_maybe_add_feature),
+ (pango_ot_ruleset_maybe_add_features):
+ Add new engine API:
+
+ PANGO_OT_NO_FEATURE
+ PANGO_OT_NO_SCRIPT
+ PANGO_OT_TAG_DEFAULT_SCRIPT
+ PANGO_OT_TAG_DEFAULT_LANGUAGE
+ pango_ot_ruleset_new_for()
+ pango_ot_ruleset_maybe_add_feature()
+ pango_ot_ruleset_maybe_add_features()
+
+ Using pango_ot_ruleset_new_for() and
+ pango_ot_ruleset_maybe_add_features() drastically simplifies ruleset
+ building in modules, and does correct script and language selection
+ too. Modules need to be updated to use it though.
+
+ * docs/pango-docs.sgml:
+ * docs/pango-sections.txt:
+ * docs/tmpl/opentype.sgml:
+ Update.
+
+2007-05-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/viewer-render.c (do_output), (parse_options):
+ Add --language.
+
+2007-05-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/arabic/arabic-fc.c (maybe_add_gsub_feature),
+ (maybe_add_gpos_feature), (get_ruleset):
+ * modules/basic/basic-fc.c (get_ruleset):
+ * modules/hebrew/hebrew-fc.c (maybe_add_gsub_feature),
+ (maybe_add_gpos_feature), (get_ruleset):
+ * modules/indic/indic-fc.c (maybe_add_GSUB_feature),
+ (maybe_add_GPOS_feature):
+ * modules/khmer/khmer-fc.c (maybe_add_GSUB_feature),
+ (maybe_add_GPOS_feature):
+ * modules/syriac/syriac-fc.c (maybe_add_gsub_feature),
+ (maybe_add_gpos_feature), (get_ruleset):
+ * modules/thai/thai-ot.c (maybe_add_gsub_feature),
+ (maybe_add_gpos_feature), (thai_ot_get_ruleset),
+ (lao_ot_get_ruleset):
+ * modules/tibetan/tibetan-fc.c (maybe_add_GSUB_feature),
+ (maybe_add_GPOS_feature):
+ Use PANGO_OT_DEFAULT_LANGUAGE and PANGO_OT_ALL_GLYPHS instead
+ of hardcoded 0xFFFF.
+
+2007-05-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * ChangeLog.pre-1-16: Split ChangeLog.
+
+2007-05-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/Makefile.am:
+ * pango/pango-ot.h:
+ * pango/pango-ot-tag.c (pango_ot_tag_from_script),
+ (pango_ot_tag_to_script), (lang_compare_first_component),
+ (pango_ot_tag_from_language), (pango_ot_tag_to_language):
+ New public API:
+
+ PANGO_OT_DEFAULT_SCRIPT
+ pango_ot_tag_from_script()
+ pango_ot_tag_to_script()
+ pango_ot_tag_from_language()
+ pango_ot_tag_to_language()
+
+ * tests/Makefile.am:
+ * tests/test-ot-tags.c:
+ Test case for new functions.
+
+ * pango/pangoft2.def:
+ * docs/pango-docs.sgml:
+ * docs/pango-sections.txt:
+ * docs/tmpl/main.sgml:
+ * docs/tmpl/opentype.sgml:
+ Updated.
+
+2007-05-10 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 437534 – pango_language_includes_script is buggy
+
+ * pango/pango-language.c (lang_compare_first_component),
+ (lang_info_compare), (script_for_lang_compare),
+ (pango_language_includes_script): Fix script_for_lang table lookup.
+
+2007-05-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-fontmap.c (pango_fc_font_description_from_pattern),
+ (pango_fc_face_describe): Don't set gravity in
+ pango_fc_font_description_from_pattern() if it was not set on the
+ pattern. This is a bit different from other properties, but that
+ really is how gravity works (unlike say weight that not having it said
+ means normal weight).
+
+2007-05-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-script-lang-table.h: Update from latest fontconfig
+ sources.
+
+ * tools/gen-script-for-lang.c (scripts_for_line): Make it handle
+ PANGO_SCRIPT_UNKNOWN.
+
+2007-05-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-language.c (script_for_lang_compare),
+ (pango_language_includes_script):
+ * pango/pango-script.c: Move pango_language_includes_script() from
+ pango-script.c to pango-language.c that it belongs.
+
+2007-05-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-matrix.h: Minor include reordering.
+
+2007-05-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/Makefile.am:
+ * pango/pango-script.h:
+ * pango/pango-types.h:
+ * pango/pango-utils.c:
+ * pango/pango-language.c:
+ * pango/pango-language.h:
+ Move PangoLanguage stuff into pango-language.[ch]
+
+2007-05-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 436988 – Adding PangoScript to PangoAnalysis
+
+ * pango/pango-item.h:
+ * pango/pango-context.c (itemize_state_add_character):
+ Add a 'script' member to PangoAnalysis. It's added as a guint8
+ in the padding available in that struct, though it's value is a
+ PangoScript.
+
+ * pango/pangox.c (itemize_string_foreach):
+ Update.
+
+2007-05-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 416515 – Time is not aligned with date on vertical panel
+
+ * pango/pango-context.c (itemize_state_init),
+ (itemize_state_update_for_new_run): centered_baseline should only
+ be set from context->resolved_gravity and never changed through
+ markup. This means that pango_context_set_base_gravity has no
+ equivalent markup. Doesn't sound limiting to me: you need to rotate
+ the layout to get real vertical, so it's not just a matter of markup
+ anyway. At least not at this point.
+
+2007-05-07 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 436154 – Error building the pango.modules file while cross
+ compiling
+
+ * modules/Makefile.am: Make local pango.module generation work with
+ cross-compilation.
+
+2007-05-05 Richard Hult <richard@imendio.com>
+
+ Bug 434160 - [atsui] Italic versions of some faces can't be created
+
+ * pango/pangoatsui-fontmap.c:
+ * pango/pangoatsui-private.h:
+ * pango/pangocairo-atsuifont.c: Follow the other backends and create
+ italic faces when they are not available. Apply synthetic italic
+ in two cases, when the font manager hands out italic faces that are
+ not in fact italic, and for the ones we've created ourselves.
+
+2007-05-04 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 435709 – pango_cairo_context_[sg]et_shape_renderer()
+
+ * pango/pangocairo.h:
+ * pango/pangocairo-context.c:
+ * pango/pangocairo-render.c:
+ New API
+
+ PangoCairoShapeRendererFunc and
+ pango_cairo_context_[sg]et_shape_renderer()
+
+ * docs/pango-sections.txt, docs/tmpl/pangocairo.sgml: Document new API.
+
+ * examples/Makefile.am, examples/cairoshape.c: New example to show off
+ new API/feature.
+
+2007-05-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/Makefile.am:
+ * pango/pangocairo-context.c:
+ * pango/pangocairo-fontmap.c:
+ Rip non-fontmap stuff from pangocairo-fontmap.c into
+ pangocairo-context.c.
+
+2007-05-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-context.c (pango_itemize): Improve docs about freeing
+ returned items.
+
+2007-05-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/test-long-paragraph.txt: New test text that contains a
+ Persian monologue by YarAli PourMoghaddam which is a single paragraph
+ of more than 10,000 chars and 2,400 words. Used for testing the
+ effect of previous change.
+
+2007-05-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (process_item): When breaking item to fit it
+ into current line, go from the beginning, adding char at a time until
+ it doesn't fit anymore instead of removing chars from the end. The
+ difference is a O(n) as opposed to O(n^2) algorithm were n is the
+ number of lines in the paragraph (assuming constant chars per line).
+
+2007-05-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/viewer-render.c (output_body), (do_output): Save
+ one layout rendering per view. Down to two from three now.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/test-justify.txt: New test text with long Latin and
+ Arabic lines, suitable for --justify testing.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 64538 – pango_layout_set_justify() doesn't work
+
+ * pango/pango-layout.c (process_item), (justify_clusters),
+ (justify_words): If no space found, justify by inserting space
+ between clusters.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-glyph-item.c (pango_glyph_item_letter_space):
+ * pango/pango-item.c (pango_item_split):
+ * pango/pango-layout.c (distribute_letter_spacing), (shape_run),
+ (debug), (process_item), (process_line), (pad_glyphstring_right),
+ (pad_glyphstring_left), (zero_line_final_space),
+ (adjust_line_letter_spacing), (pango_layout_line_postprocess):
+ Fix letter-spacing with justification. We now distribute
+ letter-spacing equally on both sides of clusters, instead of putting
+ it all on one side.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 64538 – pango_layout_set_justify() doesn't work
+
+ * pango/pango-layout.c (zero_line_final_space), (justify_clusters),
+ (justify_words), (pango_layout_line_postprocess): Implement
+ justification by expanding spaces!
+ Based on early patch from Mathias Hasselmann.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Patch from Mathias Hasselmann
+
+ * docs/tmpl/main.sgml:
+ * pango/break.c (pango_default_break):
+ * pango/pango-break.h:
+ Add is_expandable_space to PangoLogAttr.
+
+2007-05-02 Mathias Hasselmann <mathias.hasselmann@gmx.de>
+
+ * pango-view/viewer-render.c (make_layout), (parse_options):
+ Add --justify.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 355789 – Pango misaligns word-wrapped text due to trailing
+ whitespace
+
+ * pango/pango-layout.c (zero_line_final_space),
+ (pango_layout_line_postprocess): Make logical-final whitespace
+ on wrapped lines zero-width.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (process_line), (pango_layout_check_lines):
+ Keep track of line start_offset in break state.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (process_line),
+ (pango_layout_line_postprocess): Add a "wrapped" argument to
+ pango_layout_line_postprocess(). Going to use it for eg whether we
+ should justify the line.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (process_line): Set is_wrapped to true on
+ BREAK_EMPTY_FIT too.
+
+2007-05-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout-private.h: Remove stale prototype of
+ _pango_layout_iter_get_line_readonly().
+
+2007-05-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (get_items_log_attrs): Add note about
+ how we should not be using pango_break() here.
+
+2007-04-28 Mathias Hasselmann <mathias.hasselmann@gmx.de>
+
+ * pango-view/viewer-render.c (make_layout), (parse_alignment),
+ (parse_options): Add option for testing text alignment.
+
+2007-04-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/Makefile.am: Link freetype to harfbuzz-dump, for
+ those systems that don't track dependencies automatically.
+
+2007-04-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/glyphs.sgml:
+ Add PANGO_UNITS_ROUND to docs.
+
+2007-04-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-types.h: Move PANGO_UNITS_ROUND here...
+ * pango/pangofc-private.h: ...from here.
+
+ * pango/pango-gravity.c: Document that pango_gravity_to_rotation()
+ returns angle in radians but pango_matrix_rotate() takes degrees.
+
+ * pango/pango-layout.c (pango_layout_run_get_extents):
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line):
+ Retain metrics hinting when centering baseline (used for Latin, etc
+ in vertical mode).
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_metrics),
+ (pango_cairo_fc_font_glyph_extents_cache_init): Respect metrics
+ hinting setting when moving glyphs around for vertical writing.
+
+ * pango/pangocairo-fcfont.c (_pango_cairo_fc_font_new): Apply
+ the gravity rotation before the pattern's matrix, such that
+ vertical text gets correct italic direction.
+
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info):
+ Make hexbox font inherit most properties from the current font.
+ That is, bold hexbox digits for a bold font, etc.
+
+2007-04-30 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangowin32-fontmap.c (get_family_nameA, get_family_nameW):
+ A font name in encoding UCS4_ENCODING_ID actually is in UTF-16,
+ not UCS-4. (#429397, Akihiro Okamura)
+
+2007-04-27 Richard Hult <richard@imendio.com>
+
+ * modules/basic/basic-atsui.c (basic_engine_shape): Correct the
+ signature by making PangoAnalysis const, fixes build warning.
+
+2007-04-27 Richard Hult <richard@imendio.com>
+
+ * pango/pangocairo-atsuifont.c (pango_cairo_atsui_font_get_metrics):
+ Use maxAdvanceWidth instead of avgAdvanceWidth, the latter is 0 for
+ many fonts. This is a temporary solution, see bug #433805 for details.
+
+2007-04-27 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.16.4 ===
+
+ * configure.in: Version 1.16.4
+
+ * NEWS: Updated.
+
+2007-04-27 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 432991 – developer docs for libpango are broken
+
+ * configure.in: Add --disable-doc-cross-references.
+
+ * docs/Makefile.am: Make sure --disable-doc-cross-references is
+ set in order to make dist.
+
+ * Makefile.am: Add --disable-doc-cross-references to
+ DISTCHECK_CONFIGURE_FLAGS.
+
+2007-04-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.16.3 ===
+
+ * configure.in: Version 1.16.3
+
+ * NEWS: Updated.
+
+2007-04-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info):
+ Improved hexbox position.
+
+2007-04-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-ot-buffer.c (apply_gpos_ltr), (apply_gpos_rtl),
+ (pango_ot_buffer_output):
+ * pango/pango-types.h:
+ * pango/pangofc-font.c (pango_fc_font_kern_glyphs):
+ * pango/pangofc-private.h:
+ Quantize kerning adjustment, otherwise all the metrics hinting
+ effort will be ruined by a non-whole-pixel kerning value.
+ In the future we want to take lsb_delta and rsb_delta into the
+ game before quantizing the adjustment here, but we don't have
+ those values handy right now.
+
+2007-04-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.16.2 ===
+
+ * configure.in: Version 1.16.2
+
+ * NEWS: Updated.
+
+2007-04-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/harfbuzz-gdef.c (_HB_GDEF_Check_Property):
+ * pango/opentype/harfbuzz-gpos.c (HB_Done_GPOS_Table),
+ (Lookup_PairPos):
+ * pango/opentype/harfbuzz-open.c (Get_Class1):
+ Copy fixes from harfbuzz stable branch. Includes a leak fix,
+ a kerning fix, and an array out-of-bound access fix.
+
+2007-04-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/Makefile.am: Add EXEEXT around to make it build on OS/2
+ Patch from Dave Yeo.
+
+2007-03-18 Richard Hult <richard@imendio.com>
+
+ Bug 419262 - Don't create coverage every time it's asked for
+
+ * pango/pangoatsui.c: (pango_atsui_font_get_coverage):
+ * pango/pangoatsui-fontmap.c: Pass around a PangoATSUIFace instead of
+ the postscript name string. Move the coverage creation from the font to
+ the face, and get the coverage from the face instead of creating it
+ every time.
+
+ * pango/pangocairo-atsui.h:
+ * pango/pangocairo-atsuifont.c: (_pango_cairo_atsui_font_new): Use the
+ face instead of the postscript name.
+
+ * pango/pangoatsui-private.h:
+ * pango/pangocairo-atsuifontmap.c: Add getters for the postscript name
+ and coverage for the face.
+
+2007-03-14 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangowin32-fontmap.c: Add missing declaration of
+ pango_win32_family_get_type(). (#417946, Ivan Wong)
+
+2007-03-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango-sections.txt:
+ * pango/pangowin32-fontmap.c:
+ * pango/pangowin32.c:
+ Add new symbols to docs.
+
+2007-03-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.16.1 ===
+
+ * configure.in: Version 1.16.1
+
+ * NEWS: Updated.
+
+ * README: Updated.
+
+2007-03-10 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangowin32-private.h
+ * pango/pangowin32.c
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * pango/pangocairo-win32font.c
+ * pango/pangowin32.def: Move functions defined in one file and
+ used in another to the file where used, make them static, and drop
+ from pangowin32-private.h. Prefix all private non-static functions
+ with underscore. Also functions used only by the pangocairo DLL
+ are considered private. (#120195)
+
+2007-03-10 Tor Lillqvist <tml@novell.com>
+
+ * README: Uniscribe is optional only at run-time.
+
+2007-03-07 Tor Lillqvist <tml@novell.com>
+
+ * configure.in
+ * modules/basic/Makefile.am
+ * modules/basic/basic-win32.c: Make building with Uniscribe (using
+ the <usp10.h> header) mandatory. Mingw's w32api headers do include
+ usp10.h now so one doesn't need to copy it from the Platform SDK
+ any longer. At runtime using Uniscribe is still optional,
+ depending on whether usp10.dll is found or not. I think it
+ isn't necessarily present on Windows 2000 machines, for instance.
+
+ * modules/basic/basic-win32.c (lang_name): Instead of a hardcoded
+ case statement, use GetLocaleInfo() to get the language ISO639
+ code.
+ (charset_name): Remove, unused.
+ (itemize_shape_and_place, uniscribe_shape, basic_engine_shape):
+ Constify the PangoAnalysis parameter to match the prototype of
+ PangoEngineShapeClass::script_shape().
+
+2007-03-03 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 414297 – Fails to build with --enable-static
+ --with-included-modules in thai lang module
+ Patch from Loïc Minier
+
+ * modules/thai/Makefile.am: Include LIBTHAI_LIBS in static module
+ too.
+
+2007-02-27 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 412654 – SED variable undefined in the `libtool --config' output
+ used by configure
+
+ * configure.in: export SED before calling libtool
+
+2007-02-26 Tor Lillqvist <tml@novell.com>
+
+ This change was supposed to go in the trunk before 1.16.0, but it
+ didn't quite get there in time. So, to have a clear cut for this
+ somewhat fundamental change in underlying workings (although there
+ should be no user-visible changes), I will build and distribute
+ Win32 binaries only starting from 1.16.1.
+
+ Use wide character API for fonts on Windows. Rename functions and
+ variables that deal with LOGFONTW structs to emphasize
+ this. (#407315)
+
+ * pango/pangowin32.c
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c: Use LOGFONTW all over the place
+ instead of LOGFONT, and adapt code accordingly. Use wide character
+ Win32 API.
+
+ * pango/pangowin32.c (pango_win32_font_neww): Renamed from
+ pango_win32_font_new(), as it now takes a LOGFONTW pointer. This
+ is a private function and can be renamed though it is exported as
+ it is used from the pangocairo DLL.
+ (pango_win32_font_logfont): Mention explicitly in doc comment that
+ it returns a LOGFONTA, and recommend to use
+ pango_win32_font_logfontw() instead.
+ (pango_win32_font_logfontw): New function.
+
+ * pango/pangowin32-fontcache.c
+ (pango_win32_font_cache_load): Must keep this function that takes
+ a LOGFONTA pointer as it is declared in the public header.
+ (pango_win32_font_cache_loadw): New public function that takes a
+ LOGFONTW pointer.
+
+ * pango/pangowin32-fontmap.c
+ (pango_win32_font_description_from_logfont): Mention explicitly in
+ the doc comment that it takes a LOGFONTA pointer.
+ (pango_win32_font_description_from_logfontw): New public function
+ that takes a LOGFONTW pointer.
+ (pango_win32_make_matching_logfontw): Rename from
+ pango_win32_make_matching_logfont() to emphasize it takes a
+ LOGFONTW pointer.
+
+ * pango/pangowin32.h: Declare new public functions.
+
+ * pango/pangowin32-private.h: Declare new private functions, drop
+ removed ones.
+
+ * pango/pangocairo-win32font.c (_pango_cairo_win32_font_new):
+ Simplify now that we call pango_win32_make_matching_logfontw().
+
+ * pango/pangowin32.def: Add new functions, rename internal
+ functions that now use LOGFONTW.
+
+2007-02-26 Tor Lillqvist <tml@novell.com>
+
+ Fix brokenness in the code that tries to ensure that all fonts
+ also have italic variants. Now the code hopefully actually does
+ what it was supposed to. (Which is not necessarily the right thing
+ to do, though. It can be argued that we should not list
+ synthesized italic font styles, we should just silently generate
+ them if asked for. We don't want synthesized italic (or synthesized
+ bold) styles showing up in the font selector. They don't show up
+ when using a fontconfig-based Pango backend either.) (#110521)
+
+ * pango/pangowin32-fontmap.c
+ (logfont_nosize_hash, logfont_nosize_equal): Don't use the
+ lfItalic field as such, just its nonzeroness. When being
+ enumerated, italic fonts show up with lfItalic=255, but our code
+ looks up italic versions of fonts by passing a key LOGFONT with
+ lfItalic=1.
+ (first_match): Not needed any more, see below.
+ (ensure_italic): This is now called on the entries in the
+ size_infos hash table, not families. The code used to randomly
+ look for the first matching font in size_infoswith the family name
+ being handled.
+ (pango_win32_font_map_init): Iterate through the size_infos hash
+ table with ensure_italic, not through the families table.
+
+ * pango/pangowin32-fontcache.c
+ (logfontw_hash, logfontw_equal): Look at just nonzeroness of
+ lfItalic here, too.
+
+Local Variables:
+coding: utf-8
+End:
+vim: encoding=utf-8:
diff --git a/trunk/ChangeLog.pre-1-0 b/trunk/ChangeLog.pre-1-0
new file mode 100644
index 00000000..4b8b9ec1
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-0
@@ -0,0 +1,5211 @@
+Thu Mar 7 22:55:13 2002 Owen Taylor <otaylor@redhat.com>
+
+ ===== Released 1.0.0 =====
+
+ * NEWS: Final updates for 1.0.0.
+
+ * README AUTHORS: Update.
+
+2002-03-07 jacob berkman <jacob@ximian.com>
+
+ * autogen.sh: pass --enable-gtk-doc to configure
+
+2002-03-08 Tor Lillqvist <tml@iki.fi>
+
+ * pango-zip.sh.in: Use PANGO_MODULE_VERSION in modules path.
+
+ * pango/pangoft2.def: Add the pango_ot_* symbols from the static
+ libpango-ot library.
+
+Thu Mar 7 14:42:50 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: As we do in other modules, default to
+ --disable-gtk-doc, and run the check we used to do
+ for the default when the --enable-gtk-doc is specified.
+ (Alain Rouge)
+
+Thu Mar 7 10:51:16 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Fix some problems with setting
+ library variables for --enable-explicit-deps. (Laszlo Peter,
+ #73851)
+
+Wed Mar 6 12:44:00 2002 Owen Taylor <otaylor@redhat.com>
+
+ * Pango 1.0.0 rc2.
+
+Wed Mar 6 12:12:21 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c: Add some text names to weight map for
+ weights that were added to the PangoWeight enumeration
+ but not here. (#73728, Arnaud Charlet)
+
+2002-03-06 Manish Singh <yosh@gimp.org>
+
+ * pango/Makefile.am: install-exec-hook should always exist,
+ because the automake rules assume it to be there if it is
+ included anywhere in the Makefile.am. So put only the body
+ of it inside DISABLE_EXPLICIT_DEPS.
+
+Wed Mar 6 11:43:46 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Fix problem where == was used instead if =.
+ (#73694, Martin Gansser)
+
+ * modules/Makefile.am (install-data-local): Simplify
+ the rule to create the pango.modules file to avoid
+ problems with differing shared library suffixes.
+ pango-querymodules run without any arguments does the
+ right thing by default. (#73694, Martin Gansser)
+
+ * configure.in: Add a PANGO_MODULE_VERSION variable
+ defining the subdir in which modules are installed.
+
+ * pango/querymodules.c pango/modules.c modules/*/*.am:
+ Install modules in lib/pango/MODULE_VERSION/modules
+
+ * pango.pc.in (pango_module_version): Export pango_module_version
+ variable so that 3rd parties can determine where to install
+ libraries.
+
+Wed Mar 6 11:40:45 2002 Owen Taylor <otaylor@redhat.com>
+
+ * Pango 1.0.0 rc1.
+
+ * pango/Makefile.am: Use install-exec-hook not
+ install-exec-local when running sanitize-la.sh.
+
+2002-03-06 Tor Lillqvist <tml@iki.fi>
+
+ * pango/Makefile.am (install-exec-local): Ignore return status
+ from for loop, in case the last test -f happens to fail. Handle
+ also the libpangowin32 .la file.
+
+ * pango/Makefile.am (libpangoft2_1_0_la_LDFLAGS): Use
+ pangoft2_export_symbols, not pangowin32_export_symbols.
+
+ * pango/pango.rc.in
+ * pango/pangowin32.rc.in
+ * pango/pangoft2.rc.in
+ * pango/Makefile.am
+ * pango-zip.sh.in: : Adapt to new shared library naming scheme,
+ also for Win32 import library names.
+
+2002-03-05 Manish Singh <yosh@gimp.org>
+
+ * configure.in: require GLIB 2.0.0 at minimum
+
+2002-03-05 jacob berkman <jacob@ximian.com>
+
+ * tests/Makefile.am (*boundaries_LDADD): more $(PANGO_API_VERSION)
+ fixing
+
+Tue Mar 5 15:41:17 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/*/Makefile.am: Fix pangoxft-$(PANGO_API_VERSION).
+ (Reported by Manish Singh.)
+
+Tue Mar 5 11:00:20 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in **/Makefile.am *.pc.in: Switch over to
+ GLib/GTK+ style library versioning. Update version numbers
+ to 1.0.0.
+
+2002-03-03 jacob berkman <jacob@ximian.com>
+
+ * Makefile.am (EXTRA_DIST): add sanitize-la.sh
+
+Sat Mar 2 21:57:55 2002 Owen Taylor <otaylor@redhat.com>
+
+ * examples/Makefile.am (pango.modules): Write
+ examples/pango.modules in terms of .la files rather than
+ direct shared objects to avoid having to know soname
+ extension.
+
+ * pango/querymodules.c (main): Use G_MODULE_SUFFIX or
+ .la to compare with filenames when querying modules,
+ rather than hardcoded .so/.la.
+
+ * configure.in (USE_LA_MODULES): On aix, load .la files
+ since we can't guess the soname extension.
+
+Fri Mar 1 00:46:49 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure: Default to --disable-static.
+
+ * configure.in pangoft2.pc.in pangoxft2.pc.in pangox.pc.in:
+ Add a --enable-explicit-deps option to control whether dependency
+ libraries are written into .la files and .pc files.
+ Default is auto: if static libraries are off
+ and shlib dependencies are found, don't write deps.
+
+ * pango/Makefile.am sanitize-la.sh: Shell script used
+ to strip dependencies out of .la files.
+
+ * configure.in: Default to --disable-gtk-doc.
+
+ * Makefile.am: Add a slightly modified distcheck rule
+ that passes --enable-gtk-doc to the configure inside.
+ (So that 'make dist' succeeds inside.)
+
+Fri Mar 1 14:37:47 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_get_glyph_extents):
+ Treat glyph 0 as an 0 size, non-drawn glyph consistent
+ with other backends. (#71931)
+
+Fri Mar 1 14:25:22 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules.c: Don't crash on out-of-BMP values.
+
+ * pango/mini-fribidi/fribidi_get_type.c (_pango_fribidi_get_type):
+ Return FRIBIDI_TYPE_LTR for all non-BMP characters.
+
+Fri Mar 1 12:11:50 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_line_get_vis2log_map):
+ Fix problem with positions at the ends of lines
+ (#63328, reported by Dov Grobgeld.)
+
+2002-02-28 Sven Neumann <sven@gimp.org>
+
+ * configure.in: align --help output.
+
+2002-02-28 Alex Larsson <alexl@redhat.com>
+
+ * pango/pangoft2.c (pango_ft2_font_get_face):
+ Check for errors when loading font face, fall back to sans,
+ exit with warning if no font found.
+
+2002-02-28 Sven Neumann <sven@gimp.org>
+
+ * modules/arabic/Makefile.am: don't link libpango-ot into the module.
+ * pango/Makefile.am: added libpango-ot.la to libpangoft2_la_LIBADD.
+ Should fix #72934, reported by Raymond Wan.
+
+2002-02-28 Sven Neumann <sven@gimp.org>
+
+ * configure.in: beautified configure --help output.
+
+Wed Feb 27 11:10:07 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (libpangoft2_la_LIBADD): Move .la
+ files to beginning of link line ... may prevent some
+ problems with linking to installed libraries.
+ (#61359, _)
+
+Wed Feb 27 08:55:32 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (pango_querymodules_LDADD): Add
+ $(X_EXTRA_LIBS) (reported Richard Warren)
+
+Tue Feb 26 19:06:07 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mini-xft/minixftint.h: Fix some C++ style
+ comments. (David L. Cooper II)
+
+Tue Feb 26 16:43:05 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (pango-enum-types.c): Make
+ pango-enum-types.c depend on pango-enum-types.h
+
+Tue Feb 26 15:50:35 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_get_font): Try
+ to load something (load sans) if we can't load a font
+ that Xft listed. (Workaround for #72299, reported
+ by Gediminas Paulauskas)
+
+Mon Feb 25 16:36:47 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hebrew/hebrew-x.c pango/mini-fribidi/fribidi-types.h:
+ Fix trailing , on enumerations.
+ (#72572, Miroslaw Dobrzanski-Neumann)
+
+Sun Feb 24 13:40:55 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c (pango_xft_pattern_equal):
+ Rewrite to reduce the number of strcmps.
+
+ * pango/pangoxft-fontmap.c (pango_xft_font_map_load_font):
+ Compute the patterns as for load_fontset(), then just
+ return the first. This takes advantage of our caching
+ strategy.
+
+Sun Feb 24 12:12:09 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c (pango_xft_font_map_new_font):
+ Fix problem where we unref'ed before we ref'ed resulting
+ in entries in the cache that shouldn't have been there.
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_new_font):
+ Same.
+
+Sat Feb 23 21:40:27 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 0.26
+
+ * NEWS: Updates.
+
+Sat Feb 23 17:34:26 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-{ft2,x,xft}.c: Patch from Sven Neumann
+ to extend and make consistent the set of zero-width characters
+ that are not displayed. (#71931)
+
+Sat Feb 23 13:07:02 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-font.h pango/pango-fontmap.h pango/pango-fontset.h:
+ Add some class padding for future expansion.
+
+Wed Feb 20 16:58:24 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/{naqshfont.[ch],mulefont.[ch],langboxfont.[ch]}:
+ Fix recode functions to take gunichar * since we pass that in.
+ (#72059, reported by Miroslaw Dobrzanski-Neumann)
+
+Sun Feb 17 18:50:30 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 0.25
+
+ * configure.in: Add X_EXTRA_LIBS to XFT_LIBS.
+
+ * NEWS: Updates
+
+ * pango/mini-xft/minixftdpy.c
+ * pango/mini-xft/minixftstr.c: Fix some problems
+ with signed arguments to to isupper()/tolower().
+ (#71705, Morten Welinder)
+
+2002-02-15 Hans Breuer <hans@breuer.org>
+
+ * examples/makefile.am pango/makefile.am : added
+ makefile.msc to EXTRA_DIST
+
+Thu Feb 14 14:46:26 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Respect QTDIR if set. Look for qt3 as well as qt2.
+
+2002-02-14 Sven Neumann <sven@gimp.org>
+
+ * configure.in: updated the list of available modules (bug #71411).
+
+2002-02-10 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc : update version,
+ use -FImsvc_recommended_pragmas.h and add $(DIRENT_LIBS) to
+ pangoft2 linking
+
+2002-02-09 Darin Adler <darin@bentspoon.com>
+
+ * pango/fonts.c: (getword): isspace -> g_ascii_isspace
+ (pango_font_description_from_string): isspace -> g_ascii_isspace
+ * pango/modules.c: Remove unneeded <ctype.h> include.
+ * pango/pango-markup.c: (xml_isspace): New.
+ (pango_parse_markup): isspace -> xml_isspace
+ (span_parse_func): isdigit -> g_ascii_isdigit
+ * pango/pango-utils.c: (pango_trim_string): isspace -> g_ascii_isspace
+ (pango_skip_space): isspace -> g_ascii_isspace
+ (pango_scan_word): isspace -> g_ascii_isspace
+ (pango_scan_string): isspace -> g_ascii_isspace
+ (pango_scan_int): isspace -> g_ascii_isspace
+ * pango/pangoft2-fontmap.c: Remove unneeded <ctype.h> include.
+ * pango/pangox-fontmap.c: Remove unneeded <ctype.h> include.
+
+2002-02-07 Tor Lillqvist <tml@iki.fi>
+
+ * examples/pangoft2topgm.c (main): Accept also outfile name on
+ command line, fopen it separately then. Needed on Windows where
+ stdout is in text mode.
+
+ * modules/arabic/Makefile.am
+ * modules/hebrew/Makefile.am: Use -no-undefined on Windows,
+ otherwise libtool won't produce DLLs, and there will be no such to
+ install
+
+Sat Feb 2 18:27:38 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (pango_querymodules_LDADD): Try removing
+ libpango.la from the link line since it will be pulled
+ in from the other libraries to avoid duplicate inclusion.
+ (#70400.)
+
+ * pangox.pc.in (Libs): Add @X_XTRA_LIBS@ (#70400)
+
+2002-02-01 Havoc Pennington <hp@redhat.com>
+
+ * pangoxft.pc.in (Description, Name): fix cut-and-paste mess
+ name/description
+
+2002-02-01 Anders Carlsson <andersca@gnu.org>
+
+ * pango/pangoxft-fontmap.c (pango_xft_get_font_map):
+ move to next element in list.
+
+Tue Jan 29 11:35:11 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 0.24
+
+ * NEWS: Updates
+
+Mon Jan 28 20:23:59 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-markup.c (pango_parse_markup): Fix problem
+ with detected root node. (Based on patch from Matthias Clasen,
+ #69600)
+
+Mon Jan 28 19:41:20 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (pango_context_load_font[set]): Add some
+ return-if-fails to catch loading size 0 fonts.
+
+Thu Jan 24 18:05:54 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (get_items_log_attrs): Fix problems with
+ computing the length of the paragraph delimiter. (Reported by Evan Martin)
+
+2002-01-24 Sven Neumann <sven@gimp.org>
+
+ * configure.in
+ * modules/arabic/Makefile.am
+ * modules/arabic/arabic-ft2.c: added arabic shaper for FT2 ported
+ from arabic-xft.c by Andreas Bogk <andreas@convergence.de>.
+
+Wed Jan 23 16:49:24 2002 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer-ft2.c: Remove this file; pangofttopgm
+ is the test case for the FT2 backend now.
+
+ * examples/Makefile.am: Don't dist moc_viewer-qt.cc.
+
+ * examples/Makefile.am: Build pangofttopgm if we have FT2.
+
+ * examples/pangoft2topgm.c (main): Warning fixes.
+
+2002-01-21 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_markup_with_accel): fix
+ memory leak of "text", reported by Jason Tackaberry
+
+2002-01-20 Alexander Larsson <alla@lysator.liu.se>
+
+ * pango/pangoft2.c (pango_ft2_draw_hline):
+ Clean up underline drawing. Fixes segfaults.
+
+Sat Jan 19 11:50:32 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Add a AC_TRY_LINK() for qt, since broken setups
+ seem to be common.
+
+ * configure.in: Save ACLOCAL_FLAGS for --enable-maintainer-mode rebuilds.
+
+2002-01-18 Alexander Larsson <alla@lysator.liu.se>
+
+ * pango/pangoft2-private.h:
+ Add glyph_cache_destroy to PangoFont. This is slightly ugly, we
+ should perhaps have it in the FontMap, but it was easy.
+
+ Added cached_glyph to PangoFT2GlyphInfo. This can be used by
+ apps that want to have a glyph cache. Only one user per PangoContext
+ though. Right now it is only internally accessible.
+
+ Added pango_ft2_font_get_cache_glyph_data(), pango_ft2_font_set_cache_glyph_data() and
+ pango_ft2_font_set_glyph_cache_destroy() to access this functionallity
+
+ * pango/pangoft2.c:
+ Implement glyph caching for pango_ft2_render_layout(). Unbounded
+ caching right now. We should probably limit this in order to not
+ use a lot of memory if the user displayed a lot of glyphs once,
+ and then doesn't use them anymore.
+
+2002-01-17 jacob berkman <jacob@ximian.com>
+
+ * modules/hebrew/Makefile.am (common_sources): include missing
+ header file
+
+Wed Jan 16 14:45:23 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_check_lines):
+ A string ending in a paragraph delimiter has an
+ empty line at the end. (#68079, Arjan J. Molenaar.)
+
+Wed Jan 16 09:25:34 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_from_string): Initialize
+ the static_family field. (Fix from Zack Rusin)
+
+2002-01-14 Havoc Pennington <hp@pobox.com>
+
+ * pango/pango-layout.c: slight correction to
+ pango_layout_get_extents(), docs still need to be clearer, but
+ at least they aren't a cut-and-paste of glyph string docs now.
+
+ * docs/tmpl/glyphs.sgml: add note about special-case use of
+ PANGO_SCALE with font sizes
+
+ * pango/fonts.c: fix docs to be correct about PANGO_SCALE
+
+2002-01-13 Havoc Pennington <hp@pobox.com>
+
+ * pango/fonts.c: fix up docs to be clearer about PANGO_SCALE,
+ as suggested by Dennis Bjorklund
+
+2002-01-11 Havoc Pennington <hp@pobox.com>
+
+ * docs/pango_markup.sgml: fix cross-references in here
+
+2002-01-11 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_attributes): allow
+ setting attrs to NULL
+
+2002-01-11 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_iter_get_index): docs tweak
+ (pango_layout_iter_next_cluster): update iter->index here
+
+Fri Jan 11 15:01:13 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_make_pattern)
+ pango/pangoxft-fontmap.c (pango_xft_make_pattern):
+ Split comma separated family names and add them in
+ pieces, so they are all visible to Xft.
+
+ * pango/pangoxft-fontmap.c: Remove duplicate XFT_FAMILY
+ in call to XftListFonts.
+
+Thu Jan 10 16:27:24 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mini-fribidi/fribidi.c: Fix read of unitialized
+ memory (#66067, Hidetoshi Tajima)
+
+Thu Jan 10 15:04:31 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/glyphstring.c (pango_glyph_string_extents_range):
+ Don't offset the logical rect by y_offset - this generally
+ is not desired, since it means that the logical height
+ of a line could change if it included accented characters.
+ (#67921, Dov Grobgeld)
+
+2002-01-09 Alex Larsson <alexl@redhat.com>
+
+ * pango/pangoxft-fontmap.c (pango_xft_font_map_load_fontset):
+ Add g_error if font match fails, referencing bug #68030, which
+ is the "libXrender is broken" bug.
+
+Wed Jan 9 18:51:02 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (pango_context_load_font):
+ g_return_if_fail() if the desc's family is NULL.
+ (#67947, report from Darin Adler.)
+
+Wed Jan 9 11:23:31 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (s-enum-types-h): Include glib-object.h,
+ Add G_BEGIN_DECLS/END_DECLS to pango-enum-types.h. (#68325,
+ Mikael Hermansson)
+
+Tue Jan 1 20:52:00 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_merge[_static]):
+ Update the field mask in the merged description.
+
+2002-01-02 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.c (pango_win32_render_layout_line): Silence gcc
+ -Wall, initialise a couple of variables.
+
+ * pango/pangowin32-fontcache.c (pango_win32_font_cache_load): Set
+ lfCharSet to DEFAULT_CHARSET always. Conditional debugging output
+ with the PING() macro.
+
+ * pango/pangowin32-fontmap.c: Make the size_infos hash table
+ actually work like it is suppposed to, not that I know if it
+ matters. I think that it's useless to store all the different
+ charset vviews of the same actual ttf font in the list. Will have
+ to do more testing.
+ (logfont_nosize_hash): Lowercase face name before calculating
+ hash.
+ (logfont_nosize_equal): Compare face names ignoring case.
+ (pango_win32_insert_font): Store "courier new" also under the name
+ "courier", as that is what gtk-demo (and presumably often other
+ applications, too?) looks for.
+
+Thu Dec 27 14:19:46 2001 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-x.c: Mark as only an approximate
+ match for Hebrew, so the Hebrew shaper will be used
+ in preference. (#67557, Dov Grobgeld)
+
+Wed Dec 26 11:52:28 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-fontmap.c (pango_font_map_load_fontset)
+ * pango/pango-context.c (pango_context_load_fontset):
+ return_val_if_fail() if desc->family is not set.
+
+Sat Dec 22 12:14:25 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 0.23, require glib-1.3.12
+
+ * pango/makefile.msc (PANGO_VER): 0.23.
+
+ * NEWS: Updated.
+
+Sat Dec 22 11:49:38 2001 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/arabic-ot.c: Patch from Roozbeh
+ Pournader to update for shaping class changes
+ in Unicode 3.1.1.
+
+Thu Dec 20 00:18:10 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_picture_render): Fix
+ doc comment.
+
+Wed Dec 19 22:40:24 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (get_line_extents_layout_coords):
+ Remove incorrect special casing of initial line.
+ (Reported by Darin Adler)
+
+Tue Dec 18 12:33:03 2001 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/*-x.c (pango_engine_shape): Syllable
+ array needs to start at length 2, not 1. Also, some
+ cleanups. (Memory overrun reported by Joshua Pritikin
+ #66850)
+
+2001-12-17 Darin Adler <darin@bentspoon.com>
+
+ * pango/pangoft2.c: Fix doc comment.
+ * pango/pangoft2.h: Move include outside G_BEGIN_DECLS.
+ * pango/querymodules.c: (main): Add const to avoid warning.
+ * tests/dump-boundaries.c: (fail): Remove unused local.
+
+2001-12-14 Sven Neumann <sven@gimp.org>
+
+ * modules/hebrew/hebrew-x.c (hebrew_engine_get_coverage): use
+ (PangoLanguage *) instead of (const gchar *) to please the compiler.
+
+2001-12-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * examples/Makefile.am, modules/arabic/Makefile.am,
+ modules/basic/Makefile.am, modules/hangul/Makefile.am,
+ modules/hebrew/Makefile.am, modules/indic/Makefile.am,
+ modules/tamil/Makefile.am, modules/thai/Makefile.am,
+ pango/Makefile.am, pango/mini-fribidi/Makefile.am,
+ pango/opentype/Makefile.am, tests/Makefile.am: Compile with
+ -DG_DISABLE_DEPRECATED. See #52790.
+
+2001-12-12 Sven Neumann <sven@gimp.org>
+
+ * pango/mini-xft/minixftinit.c: include config.h so the definition
+ of MINI_XFTCONFIG_DIR is actually used (spotted by Sebastian Klemke
+ <packet@convergence.de>).
+
+2001-12-12 Alexander Larsson <alla@lysator.liu.se>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_load_fontset):
+ Initialize MiniXft library before calling MiniXftConfigSubstitute.
+
+ * pango/mini-xft/minixftdir.c (MiniXftDirScan):
+ Changed back filename from MiniXftCache to XftCache for
+ compat with Xft.
+
+2001-12-11 Alex Larsson <alexl@redhat.com>
+
+ * pango/pangoft2.c (pango_ft2_render):
+ Fix the details in clipping to the bitmap size.
+
+Mon Dec 10 14:22:22 2001 HideToshi Tajima <hidetoshi.tajima@sun.com>
+
+ * modules/basic/tables-big.i: change "EUC-CN" to "GB2312" which
+ is the canonical name for gb2312.1980 charset used in libcharset.
+ (#66174)
+
+Mon Dec 10 09:18:09 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_index_to_pos):
+ Fix problem with returned width on lines other than
+ the first line (#66274).
+
+ * pango/pangox,ft2,win32.c (pango_*_render_layout):
+ Fix problem where indent wasn't honored (#66275).
+ [ Note, however, there are remaining problems - see, #66626 ]
+
+Thu Dec 6 19:07:31 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (get_items_log_attrs): Fix problem
+ where length passed in didn't get adjusted for paragraph
+ delimiters.
+
+Thu Dec 6 12:10:53 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/break.c (pango_default_break): Simplify by
+ being lazy and calling g_utf8_strlen() (causes a
+ two passes over the array but shouldn't be a huge
+ performance loss). Fix bug where attributes weren't
+ set correctly for empty strings. Handle internal
+ NULLs consistently with other functions (truncate)
+ rather than dying with an assertion failure. (#65183)
+
+Thu Dec 6 10:03:49 2001 HideToshi Tajima <hidetoshi.tajima@sun.com>
+
+ * modules/basic/basic-x.c
+ (conv_eucjp): handle codeset1(right half of jisx0201.1976)
+ and codeset3(jisx0212.1990) of EUCJP
+ (conv_16bit): renamed from the old conv_euc - handle 16bit
+ character sets only.
+ * modules/basic/tables-big.i: add jisx0212, jisx0201 and big5.
+
+2001-12-04 Manish Singh <yosh@gimp.org>
+
+ * pango/modules.c
+ * pango/querymodules.c: g_module_symbol takes a gpointer *, not just
+ a gpointer.
+
+2001-12-03 Matthias Clasen <matthiasc@poet.de>
+
+ * docs/pango-sections.txt, docs/tmpl/fonts.sgml,
+ docs/tmpl/modules.sgml: Updates.
+
+ * pango/modules.c: Documentation fixes.
+
+2001-12-04 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2-fontmap.c
+ (pango_ft2_font_map_init): set n_families to -1 (uninitialized).
+ (pango_ft2_font_map_list_families): set n_faces to -1 (uninitialized).
+ This makes list_families and list_faces work again for PangoFT2.
+
+2001-12-01 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/pango-fontset.c: Documentation fixes.
+
+2001-11-29 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/pango-fontset.c: Documentation updates.
+
+Thu Nov 29 11:40:51 2001 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer-qt.cc: Include qpainter.h - apparently
+ needed for Qt 3. (Patch from Dennis Dementiev)
+
+2001-11-27 Alex Larsson <alexl@redhat.com>
+
+ * pango/pangoft2-private.h
+ * pango/pangoft2-fontmap.c (_pango_ft2_font_desc_from_pattern):
+ Take extra parameter include_size that determines if the
+ descriptor includes the size.
+
+ * pango/pangoft2.c (_pango_ft2_font_new):
+ Include size in ft2font->description.
+
+ * pango/pangoxft-private.h
+ * pango/pangoxft-fontmap.c (_pango_xft_font_desc_from_pattern):
+ Take extra parameter include_size that determines if the
+ descriptor includes the size.
+
+ * pango/pangoxft-font.c:
+ Include size in xfont->description.
+
+Mon Nov 26 19:24:21 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in tests/Makefile.am tests/cxx-test.C: Add
+ a test program that includes all headers in a C++ program.
+ (#52606)
+
+2001-11-26 Alex Larsson <alexl@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_get_coverage):
+ Don't leak filename copy.
+
+ * pango/pangoxft-fontmap.c (pango_xft_font_map_load_font):
+ Don't leak matched pattern
+
+Mon Nov 26 18:17:00 2001 Owen Taylor <otaylor@redhat.com>
+
+ * tests/Makefile.am tests/gen-all-unicode.c: Instead
+ of including all-unicode.txt in the distribution, include
+ a small program to generate it.
+
+ * modules/hangul/hangul-x.c (render_syllable_with_ksc5601): When
+ falling back to uncomposed Jamos, if we can't render a Jamo
+ in any way, use the unknown glyph rather than nothing.
+
+ * modules/hangul/hangul-x.c (hangul_engine_shape): Prevent
+ overflows for invalid sequences which can be of arbitrary
+ length. (#50086)
+
+ * modules/arabic/arconv.c: New versions from Roozbeh Pournader.
+
+ - Replacing the tables with automatically-generated ones
+ - Using binary search instead of linear search for table lookup
+ - Updating all the names with Unicode names (eg Nun -> Noon)
+ - Fixed the Hamza mixup, using the Unicode rules
+ - Updating missed cases (eg Superscript Alef was missing from
+ arabic_isvowel)
+ - Removing too-intelligent cases which made the code non-compliant
+ (eg Alef with Hamza above+Kasra was changing to Alef with Hamza below)
+ - Removing 'connecttoleft' from 'charstruct' (replacing it with a macro)
+ - Indenting in the GNU style
+
+2001-11-26 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/pangoft2.c (pango_ft2_font_get_coverage): Documentation.
+
+ * modules/basic/basic-ft2.c (basic_engine_get_coverage): Use
+ pango_font_get_coverage().
+
+Mon Nov 26 11:31:01 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am: Workaround to work a little better with
+ automake-1.5 - make $(libpango_la_OBJECTS) as well as $(OBJECTS)
+ depend on pango_built_headers.
+
+Sun Nov 25 22:35:46 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (have_fribidi) README: Disable --with-fribidi; it offers
+ no advantages and until either fribidi is updated to use Glib-2.0
+ always, or the Glib dependecy is removed from fribidi entirely, there
+ will be problems with this option.
+
+ * pango/mini-fribidi/README: Update fribidi URL.
+
+2001-11-24 Manish Singh <yosh@gimp.org>
+
+ * acconfig.h
+ * configure.in: support for --with-xftconfig-dir= path to system
+ XftConfig file
+
+ * pango/pango-utils.c
+ * pango/pangox.c: include "config.h", not <config.h>
+
+ * pango/pangoxft-fontmap.c: this file is pangoxft-fontmap.c, not
+ pangoxft-fontmap.h :)
+
+ * pango/mini-xft/minixftint.h
+ * pango/mini-xft/minixftinit.c: add code for searching common
+ locations for the XftConfig file. We search MINI_XFTCONFIG_DIR
+ if configure defines it for us (as above), then $sysconfdir,
+ then (only on !_WIN32) /etc/X11 and /usr/X11R6/lib/X11.
+
+
+Sat Nov 24 13:44:21 2001 Kristian Rietveld <kristian@planet.nl>
+
+ * pango/pango-fontmap.c (pango_font_map_real_load_fontset):
+ free the font description when we don't need it anymore
+
+2001-11-23 Padraig O'Briain <padraig.obriain@sun.com>
+
+ * pango/break.c (pango_default_break):
+ Fix for bug 65183; i.e. do not call g_utf8_next_char(next) when
+ next is end.
+
+2001-11-23 Hans Breuer <hans@breuer.org>
+
+ * testfonts.c : removed the arbitrary limit to 10 fonts.
+ Instead make the command line params useful again and reduce
+ the default result bitmap size by decreasing the default
+ font size.
+
+ * pango/pangowin32-fontcache.c (pango_win32_font_cache_load):
+ Don't always turn on anti-aliasing. Respect the users settings
+ from 'Properties of Display/Effects'.
+
+ * pango/makefile.msc : updated, version 0.22
+ * pango/pango.def : updated externals
+
+ * pango/font.c pango/pango-coverage.c pango-utils.c
+ pango/pangowin32.c pango/shape.c :
+ coding style and static correctness
+
+2001-11-22 Matthias Clasen <matthiasc@poet.de>
+
+ * docs/pango-sections.txt: Remove duplicates.
+
+ * docs/tmpl/fonts.sgml: Document PANGO_TYPE_FONTSET
+ and PANGO_TYPE_FONTSET_SIMPLE.
+
+ * pango/pangoxft-font.c: Fix typos in some doc comments.
+
+Thu Nov 22 14:23:07 2001 Owen Taylor <otaylor@redhat.com>
+
+ * Version 0.22
+
+ * configure.in (GLIB_REQUIRED_VERSION): Require
+ GLib-1.3.11
+
+Wed Nov 21 12:54:39 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (PANGO_MINOR_VERSION): Version 0.22.
+
+ * NEWS: Updated
+
+ * docs/pango-sections.txt Makefile.am: Update.
+
+ * pango/pango-layout.c (process_item): Don't look
+ like a doc comment.
+
+2001-11-22 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-fontcache.c (pango_win32_font_cache_load):
+ Always turn on anti-aliasing.
+
+2001-11-21 Tor Lillqvist <tml@iki.fi>
+
+ * pango/testfonts.c: Fix a couple of bugs, update for current
+ Pango API. It's not completely clear to me what the program is
+ supposed to do with the command line args. It does load a matching
+ font, but does nothing with it. It then always lists *all* font
+ families, and renders a string in each. This causes a huge image
+ with associated swapping to death if you have lots of fonts... I
+ added a restriction, only the first 10 fonts are rendered.
+
+2001-11-20 Alex Larsson <alexl@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_finalize):
+ Don't free font_pattern if we opened the XftFont, since the
+ XftFont claims ownership of it.
+
+2001-11-20 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_load_font): Fix
+ typo.
+
+2001-11-18 Alex Larsson <alexl@redhat.com>
+
+ * pango/pangoft2.[ch] (pango_ft2_get_context):
+ Take both dpi_x and dpi_y as arguments. Doesn't currently handle
+ dpi_x correctly, but at least the API is in.
+
+2001-11-18 Alex Larsson <alexl@redhat.com>
+
+ * pango/pango-context.[ch]:
+ Add new function pango_context_load_fontset() to wrap
+ pango_font_map_load_fontset().
+ Add PangoContext arguments to load_font and load_fontset.
+
+ * pango/pango-fontmap.[ch]:
+ * pango/pangoft2-fontmap.c:
+ * pango/pangowin32-fontmap.c:
+ * pango/pangox-fontmap.c:
+ * pango/pangoxft-font.c:
+ * pango/pangoxft-fontmap.c
+ Add PangoContext arguments to load_font and load_fontset.
+
+2001-11-19 Tor Lillqvist <tml@iki.fi>
+
+ * pango-zip.sh.in: Suffix package names with datestamp. Add
+ the Pango modules.
+
+ * pango/pango.def: pango_context_add_font_map ->
+ pango_context_set_font_map. Add pango_fontset_*.
+
+ * pango/pangoft2.def: Reflect Alexander's changes.
+
+ * pango/mini-xft/minixftinit.c (get_xft_default_path): New
+ function. Use pango_get_sysconf_subdirectory () to construct a
+ suitable path.
+
+ * pango/mini-xft/minixftint.h: On Win32, don't use the hardcoded
+ /usr/X11R6/lib/X11/XftConfig path (or any other hardcoded path),
+ but instead the function get_xft_default_path().
+
+ * pango/mini-xft/minixftcache.c (MiniXftFileCacheSave): On Win32,
+ don't use link() and unlink() for the lock file. Instead, use a
+ lock directory.
+
+2001-11-18 Alexander Larsson <alla@lysator.liu.se>
+
+ * pango/pangoxft-fontmap.c:
+ Add XFT_MATRIX and XFT_MINSPACE macro definitions if missing.
+
+2001-11-17 Alexander Larsson <alla@lysator.liu.se>
+
+ * configure.in:
+ Check for LEX and YACC. This will be made optional later,
+ with the build sources checked in to cvs.
+ Generate pango/mini-xft/Makefile
+
+ * modules/basic/basic-ft2.c:
+ Use the new pangoft2 API.
+
+ * pango/Makefile.am:
+ Build mini-xft.
+ Add new files.
+
+ * pango/pango-context.[ch]:
+ Support only one fontmap per context.
+ Use pango_font_map_load_fontset() and PangoFontset instead
+ of internal fontset.
+
+ * pango/pango-fontmap.[ch]:
+ New virtual function pango_font_map_load_fontset() and
+ default implementation that uses pango_font_map_load_font().
+
+ * pango/pango-utils.[ch] (pango_lookup_aliases):
+ Utility function for looking up aliases. This can be
+ used by backend that has no backend specific aliases.
+
+ * pango/pangoft2-fontcache.c:
+ Removed file.
+
+ * pango/pangoft2-fontmap.c:
+ * pango/pangoft2-private.h:
+ * pango/pangoft2.c:
+ * pango/pangoft2.h:
+ Major rewrite. Doesn't handle fontsets. Uses mini-xft so that
+ it will always match the PangoXft backend. Simplified the
+ public API.
+
+ * pango/pangowin32.c:
+ * pango/pangox.c:
+ pango_context_add_font_map -> pango_context_set_font_map
+
+ * pango/pangoxft-font.c:
+ * pango/pangoxft-fontmap.c:
+ * pango/pangoxft-private.h:
+ New code to handle fontsets.
+
+ * pango/mini-xft/*:
+ Mini version of libXft from XFree86 in order to have
+ the pangoFT2 and pangXft backends have same config files and
+ generate the same fonts.
+
+2001-11-14 Matthias Clasen <matthiasc@poet.de>
+
+ * docs/Makefile.am (MKDB_OPTIONS): Add --sgml-mode.
+
+2001-11-11 Matthias Clasen <matthiasc@poet.de>
+
+ * docs/Makefile.am (IGNORE_HFILES): Add pangoxft-private.h.
+
+ * pango/pango-utils.c (pango_language_from_string): Fix typo in
+ documentation.
+
+ * docs/tmpl/text-attributes.sgml: Document PangoColor, PangoLanguage,
+ PangoAttrLanguage, PangoAttrFloat and PangoAttrShape.
+
+ * docs/tmpl/layout.sgml: Document PangoWrapMode and PangoLayoutIter.
+
+ * docs/tmpl/tab-stops.sgml: Document PangoTabAlign and PangoTabArray.
+
+ * docs/tmpl/fonts.sgml: Document PangoFontMask.
+
+ * pango/fonts.c (pango_font_description_unset_fields): Fix typo in
+ documentation.
+
+ * docs/tmpl/opentype.sgml: Remove documentation templates of the
+ unimplemented functions pango_ot_ruleset_set_glyph_loader and
+ pango_ot_ruleset_set_alternate_func and the related typedefs
+ PangoOTGlyphLoader and PangoOTAlternateFunc.
+
+ * docs/tmpl/x-rendering.sgml: Document PangoGetGCFunc and
+ PangoFreeGCFunc typedefs.
+
+2001-11-08 Tor Lillqvist <tml@iki.fi>
+
+ * pango-zip.sh.in: Build separate developer package.
+
+ * pango/pango.def: Add pango_color_parse.
+
+Mon Nov 5 12:23:07 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft.h pango/pangoxft-font.c: Add a function
+ pango_xft_picture_render() to render onto an Xft picture
+ directly linstead of using the XftDraw wrapper object.
+
+2001-11-03 Hans Breuer <hans@breuer.org>
+
+ * pango/modules.c : don't bother with module dir
+ recalculation if LIBDIR isn't defined
+
+ * pango/pangowin32-fontmap.c : make it compile again
+ after the g_ascii_* change below. Use EnumFontFamiliesExA
+ to ensure to use the ascii version, though defining
+ UNICODE for G_OS_WIN32 will break at other place anyway.
+
+ * pango/makefile.msc : use (hopefully temporary) DIRENT_CFLAGS
+ and DIRENT_LIBS (see #63667)
+
+Fri Nov 2 13:56:58 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c: Patch from Alex Larsson to improve
+ line breaking algorithm so that it doesn't do O(n^2) --
+ each character is shaped at most twice - once to get the
+ widths, and once if the run is broken. Also, quite a
+ bit of cleanup to consistently use the ParaBreakState
+ object to keep track of the state of the line-break
+ process. (#62014)
+
+Fri Nov 2 08:50:16 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/{fonts.c,pango-color.c,pango-utils.c,
+ pangoft2-fontmap.c,pangowin32-fontcache.c,
+ pangowin32-fontmap.c, pangox-fontmap.c}:
+ Patch from Darin Adler, with updates, to use
+ g_ascii_* instead of locale-dependent variants
+ (#55833).
+
+ * pango/fonts.c: Use g_ascii_dtostr, g_ascii_strtod().
+
+2001-10-31 Tor Lillqvist <tml@iki.fi>
+
+ * pango/modules.c (process_module_file): Neat Win32 feature: A
+ prebuilt Pango package can be installed in a random location
+ (i.e., not the same used when configuring and building the
+ software). The pango.modules file provided with the package
+ contains paths on the packager's system, not the end-users. We
+ notice this, and replace with the corresponding path in the
+ installation directory on the end-user's machine.
+
+ * pango/pango-utils.c: Use G_WIN32_DLLMAIN_FOR_DLL_NAME.
+ (pango_get_sysconf_subdirectory,pango_get_lib_subdirectory): No
+ need to call g_path_get_basename on the DLL name, DllMain already
+ does it.
+
+Wed Oct 31 11:00:55 2001 Owen Taylor <otaylor@redhat.com>
+
+ * modules/tamil/tamil-{xft,x}.c: Make a number of functions
+ static to avoid symbol clashes when both tamil-x.c and
+ tamil-xft.c are linked statically into the same library.
+ (#63436, Raymond Wan)
+
+2001-10-30 Matthias Clasen <matthiasc@poet.de>
+
+ * docs/pango-sections.txt, pango/pango-ot.h: Remove declarations
+ of unimplemented functions pango_ot_ruleset_set_glyph_loader and
+ pango_ot_ruleset_set_alternate_func and the related typedefs
+ PangoOTGlyphLoader and PangoOTAlternateFunc.
+
+ * pango/opentype/pango-ot-info.c,
+ pango/opentype/pango-ot-ruleset.c: Documentation updates.
+
+2001-10-30 Sven Neumann <sven@gimp.org>
+
+ * tests/Makefile.am: don't link against pangox at all.
+
+ Please keep in mind that building on UNIX does not necessarily mean
+ that X11 is available.
+
+Mon Oct 29 11:54:06 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pangox.pc.in (Cflags): Add @X_CFLAGS@ (#63095, Dan Winship)
+
+2001-10-29 Tor Lillqvist <tml@iki.fi>
+
+ * pango-zip.sh.in: New file, used to build distribution package
+ for Windows.
+
+ * Makefile.am (EXTRA_DIST): Add pango-zip.sh.
+
+ * configure.in: Check for lib.exe, set MS_LIB_AVAILABLE. Generate
+ pango-zip.sh.
+
+ * README.win32: Mention the ways to build Pango on Windows.
+
+ * modules/Makefile.am
+ * examples/Makefile.am: Se SOSUFFIX to so on Unix, dll on Windows.
+
+ * pango/Makefile.am: Add rules to create MSVC import library if
+ MS_LIB_AVAILABLE. Add rules to install and uninstall mingw and
+ MSVC import libraries.
+
+ * tests/Makefile.am: Link with libpangox.la only on Unix.
+
+2001-10-27 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/modules.c: Typo fix.
+
+ * docs/tmpl/text-attributes.sgml, docs/tmpl/freetype-fonts.sgml,
+ docs/tmpl/xft-fonts.sgml, docs/tmpl/win32-fonts.sgml,
+ docs/tmpl/glyphs.sgml, docs/tmpl/x-rendering.sgml,
+ docs/tmpl/pango-indic.sgml: Updates.
+
+2001-10-26 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/fonts.c, pango/pangoft2.c, pango/pangowin32.c,
+ pango/pango-fontmap.c, pango/pangoxft-font.c, pango/pangox-fontmap.c,
+ pango/pangoft2-fontmap.c, pango/pangoxft-fontmap.c,
+ pango/pangowin32-fontmap.c, docs/pango-sections.txt,
+ docs/tmpl/coverage-maps.sgml, docs/tmpl/fonts.sgml,
+ docs/tmpl/freetype-fonts.sgml, docs/tmpl/glyphs.sgml,
+ docs/tmpl/layout.sgml, docs/tmpl/main.sgml, docs/tmpl/modules.sgml,
+ docs/tmpl/tab-stops.sgml, docs/tmpl/text-attributes.sgml,
+ docs/tmpl/win32-fonts.sgml: Documentation updates.
+
+Thu Oct 25 11:06:54 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 0.21, require GLib-1.3.6
+
+ * NEWS: Updates.
+
+Fri Oct 26 12:32:25 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Don't use AC_CHECK_LIB to check for
+ win32, since that causes problems with autoconf-2.13.
+
+ * docs/Makefile.am: Fix to install images.
+
+Thu Oct 25 11:05:01 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_run_get_extents): Allow
+ NULL run_logical. (#63014, Tony Graham)
+
+Thu Oct 18 15:48:14 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.h: Remove the rest of the
+ silly pango file-reading code from PANGO_ENABLE_BACKEND,
+ so I can use it in gtkimmodule.c. It's nothing
+ that should be in Pango longterm, but it's not
+ enough code to worry about removing before Pango-2.0.
+ (#61602, Sven Neumann)
+
+Thu Oct 18 14:40:04 2001 Owen Taylor <otaylor@redhat.com>
+
+ (Fixes from Frank Belew, #58905)
+
+ * pango/pangox.c (pango_x_apply_ligatures): Fix label
+ at end of block.
+
+ * pango/mini-fribidi/fribidi.c pango/mini-fribidi/fribid.patch:
+ Use g_alloca() instead of mix of MSVC specific and GCC specific
+ stuff.
+
+2001-10-15 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/tmpl/x-fonts.sgml
+ * pango/break.c
+ * pango/fonts.c: small documentation fixes.
+
+2001-10-15 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoxft-font.c: another missing comment end marker and some
+ fixes in gtk-doc comments.
+
+ * pango/break.c
+ * pango/pango-layout.c
+ * pango/pangoft2.c
+ * docs/pango-sections.txt
+ * docs/tmpl/fonts.sgml
+ * docs/tmpl/x-fonts.sgml: documentation updates.
+
+Sun Oct 14 18:42:56 2001 Manish Singh <yosh@gimp.org>
+
+ * pango/pangox.c: add missing comment end marker to make it compile
+
+2001-10-14 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/pangox.c, pango/pangoxft-font.c, pango/pangoxft-fontmap.c,
+ docs/pango-sections.txt, docs/tmpl/fonts.sgml: Documentation updates.
+
+2001-10-13 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/pango-utils.c, pango/pangoxft-font.c: Documentation updates.
+
+2001-10-10 Tor Lillqvist <tml@iki.fi>
+
+ * pango/.cvsignore: Add module-defs-win32.c.
+
+ * pango/Makefile.am (pangoinclude_HEADERS): Include also
+ WIN32_HFILES.
+
+2001-10-09 Matt Wilson <msw@redhat.com>
+
+ * pango/pangox.c (get_font_metrics_from_string): protect from
+ indexing off the end of the embedding_levels array by only doing
+ so if we're not finished.
+
+2001-10-04 Havoc Pennington <hp@pobox.com>
+
+ * pango/break.c (pango_default_break): fix wrong
+ check for incorrect attrs_len
+
+2001-10-04 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_read_alias_file):
+ use g_object_new() instead of g_new() to create a PangoFT2Face.
+ Fixes bug #61603.
+
+2001-10-04 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Retract my change to Xrender+Xft+Xft+FreeType.h
+ checks from yesterday, instead enclose nested AC_CHECK_* calls in
+ brackets.
+
+2001-10-03 Havoc Pennington <hp@redhat.com>
+
+ * pango/break.c (MAYBE_START_NEW_SENTENCE): remove assertion I
+ shouldn't have put in there
+
+2001-10-03 Havoc Pennington <hp@redhat.com>
+
+ * pango/break.c (pango_default_break): try to fix up the sentence
+ breaking a bit, specifically for sentences that started at the end
+ of a previous sentence we were messing things up.
+
+ * tests/dump-boundaries.c: new program to dump logical attrs to stdout
+
+ * tests/testboundaries.c (check_invariants): oops, fix for
+ pango_get_log_attrs() change
+
+2001-10-03 Havoc Pennington <hp@redhat.com>
+
+ * pango/break.c (pango_break)
+ (pango_default_break) (pango_get_log_attrs): require one more
+ log attr in the buffer passed in, to account for the end position
+ (pango_default_break): allow length of -1
+
+ * pango/pango-engine.h (struct _PangoEngineLang): change
+ script_break virtual function to match pango_break
+
+ * pango/pango-layout.c (get_items_log_attrs): update pango_break usage
+
+2001-10-03 Sven Neumann <sven@gimp.org>
+
+ * pango/fonts.c (pango_font_description_to_string): don't include
+ family name if PANGO_FONT_MASK_FAMILY is not set.
+
+ * pango/pangoft2-fontmap.c: make it compile with DEBUGGING being
+ defined.
+
+2001-10-03 Tor Lillqvist <tml@iki.fi>
+
+ Add the Win32 GDI Pango backend to autoconfiguration:
+
+ * configure.in: Call AC_LIBTOOL_WIN32_DLL. Check for native Win32
+ or Cygwin, set automake conditional PLATFORM_WIN32. Check for
+ native Win32, set OS_WIN32. Refactor the
+ Xrender+Xft+Xft+FreeType.h checks not to use AC_CHECK_LIBs inside
+ eachother, autoconf 2.52e on Cygwin generated bad shell code for
+ that. Check for gdi32 library, set automake conditional
+ HAVE_WIN32. Add the basic-win32 module, add INCLUDED_WIN32_MODULES
+ and INCLUDE_BASIC_WIN32. Write pango/module-defs-win32.c. Generate
+ pangowin32*.pc.
+
+ * pangowin32.pc.in
+ * pangowin32-uninstalled.pc.in: New files.
+
+ * Makefile.am: Add pangowin32*.pc.in.
+
+ * .cvsignore: Add pangowin32*.pc.
+
+ * modules/basic/Makefile.am: Add the basic-win32 backend. Use
+ -no-undefined on PLATFORM_WIN32.
+
+ * pango/Makefile.am: Add the Win32 backend. Use -no-undefined on
+ PLATFORM_WIN32. Use the .def files on OS_WIN32. Link libpangoft2
+ with GLIB_LIBS.
+
+ * pango/pango-utils.c: (DllMain): New function, on
+ G_OS_WIN32. Used to get the actual DLL name, which is tucked away.
+ (pango_get_sysconf_subdirectory, pango_get_lib_subdirectory):
+ (Win32): Append VERSION to the registry key passed to
+ g_win32_get_package_installation_subdirectory(). Use the real DLL
+ name from above instead of assuming the DLL has a certain name.
+
+ Other Win32 backend fixes:
+
+ * pango/pangowin32-fontmap.c: (free_coverages_foreach): Remove, unused.
+
+ * pango/pangowin32.c: Remove unused variables.
+
+ * pango/pangowin32.def: Add pango_win32_font_get_glyph_index.
+
+ * pango/pangowin32.h: Remove pango_win32_font_get_coverage, which
+ is static.
+
+Mon Oct 1 16:02:54 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c: g_string_printfa => g_string_append_printf.
+
+Sat Sep 29 12:21:44 2001 Manish Singh <yosh@gimp.org>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_for_display):
+ Typo fix: s/pang/pango/ in warning message
+
+Fri Sep 28 11:27:57 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_iterator_get_font): Use
+ PANGO_FONT_MASK_* not PANGO_ATTR_* when manipulating the
+ mask. Add fields to mask for PANGO_ATTR_FONT_DESC so
+ it won't be overwritten by later attributes.
+ (Fixes from Tony Graham, #61297)
+
+Thu Sep 27 12:08:23 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c (pango_log2vis_get_embedding_levels):
+ Fix wrapper version to have boolean result. (#61248,
+ Eric Lemings.)
+
+Tue Sep 25 11:54:03 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 0.20
+
+ * NEWS: Updated
+
+ * configure.in (GLIB_REQUIRED_VERSION): Require GLib 1.3.9
+
+ * examples/Makefile.am (EXTRA_DIST): Add the viewer-qt
+ in case someone (say Tim) makes dist without qt installed.
+ (reported by Tony Graham)
+
+ * examples/Makefile.am (pango.modules): Don't use
+ grep -q (reported by Tony Graham)
+
+ * docs/pango-sections.txt: Fix small typo.
+
+Tue Sep 25 11:18:24 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_unset_fields): Change
+ things so that when you unset fields, the old values are
+ kept around persistantly. I don't like this much, but it
+ makes some hacks using PangoFontDescription easier. (In
+ particular, with GtkCellRendererText, being able to
+ toggle on-and-off a setting with a boolean.)
+
+ * pango/{pangoft2-fontmap.c, pangowin32-fontmap.c, pangox-fontmap.c}:
+ Fix for changed signature of g_ascii_strup/strdown.
+
+Mon Sep 24 19:18:48 2001 Owen Taylor <otaylor@redhat.com>
+
+ Patch from Alex Larsson
+
+ * pango/pango-layout.c (pango_layout_index_to_line_and_extents,
+ pango_layout_index_to_line): Extract out some code portions
+ into separate functions and fix problems with cursor motion
+ in multi-paragraph layouts.
+
+ * pango/pango-layout.c (pango_layout_index_to_pos): Fix
+ for multi-paragraph layouts.
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually): Fix
+ for multi-paragraph layouts.
+
+Mon Sep 24 18:19:22 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_index_to_pos): Fix
+ handling of the last index in a paragraph.
+ (#60630, fix based on patch from Padraig O'Briain.)
+
+ * pango/pango-layout.c (update_run): Take the start
+ index of the run as an argument since we don't have
+ sufficient information to compute it when
+ iter->run == NULL.
+
+Fri Sep 21 18:55:18 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_from_string): Set
+ PANGO_FONT_MASK_FAMILY. (#60888, reported by Mario Motta)
+
+2001-09-21 Matthias Clasen <matthiasc@poet.de>
+
+ * pango/fonts.c (append_field, pango_font_description_to_string):
+ replace g_string_sprintfa by g_string_printfa.
+
+2001-09-21 Hans Breuer <hans@breuer.org>
+
+ * pango/pango.def : updated externals
+
+ * pango/makefile.msc : build ft2 backend too.
+
+ * pango/pangowin32-fontmap.c
+ - Convert PangoWin32FamilyEntry into PangoWin32Family deriving
+ from PangoFontFamily.
+ - Convert PangoWin32FontEntry into PangoWin32Face deriving
+ from PangoFontFace.
+ - Change the list_families() method of the PangoWin32FontMap
+ to list PangoFontFamily * rather than names.
+
+ * pango/pangowin32.c : reflect PangoFontDescription api change
+
+ * pango/pangowin32.h : don't include pango.h but only the
+ required headers
+
+ * modules/basic/basic-win32.c : #include "pango-engine.h"
+
+ * pango/testfonts.c : reflect recent pango api changes
+
+2001-09-20 Sven Neumann <sven@gimp.org>
+
+ * pango/fonts.c (pango_font_description_set_family,
+ pango_font_description_copy): unset the static_family flag so the
+ family_name gets freed on the next call.
+
+2001-09-20 James Henstridge <james@daa.com.au>
+
+ * pango/Makefile.am (s-enum-types-c): fix rule so that flags get
+ registered as flags and rather than enums (enums still get
+ registered as enums).
+
+ * pango/pango-font.h: add get_type routine to header.
+
+ * pango/fonts.c (pango_font_metrics_get_type): add get_type()
+ routine.
+
+Wed Sep 19 19:28:52 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-fontmap.c: Remove pango_font_map_free_families,
+ which was no longer in the headers, no longer needed, and
+ no longer working.
+
+ * pango/pango-fontmap.c (pango_font_map_list_families)
+ * pango/pango-context.c (pango_context_list_families): Remove
+ references to pango_font_map_free_families.
+
+2001-09-19 Havoc Pennington <hp@redhat.com>
+
+ * pango/opentype/fterrcompat.h: header to abstract the difference
+ between FreeType 2.0.3 and 2.0.4 error codes, based on the
+ configure check.
+
+ * configure.in: check for the tterrors.h header in FreeType 2.0.3,
+ and define HAVE_FREETYPE_2_0_3 if we have it
+
+Wed Sep 19 10:48:04 2001 Tim Janik <timj@gtk.org>
+
+ * Released 0.19.
+
+Tue Sep 18 23:27:52 2001 Tim Janik <timj@gtk.org>
+
+ * configure.in (GLIB_REQUIRED_VERSION): require glib 1.3.8.
+
+Tue Sep 18 17:29:20 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-fontmap.c pango/pangoft2-private.h: Include
+ parent_instance structures.
+
+ * pango/fonts.c (pango_font_family_get_type): Pass in right
+ class structure.
+
+Tue Sep 18 15:47:08 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (PANGO_MINOR_VERSION): Up to 0.19.
+
+ * pango/pango-font.h pango/pango-fontmap.[ch] pango/fonts.c
+ pango/pangoxft-fontmap.c pango/pangoft-fontmap.c pango/pango-context.[ch]
+ pango/pangox-fontmap.c: Add new PangoFontFace and PangoFontFamily
+ object types, and change the font listing API to list faces and
+ families, instead of face names and font descriptions.
+
+ * pango/pango-font.h pango/fonts.c: Make PangoFontDescription
+ an opaque heap-allocated structure, add accessors and
+ convenience functions.
+
+ * pango/pango-font.h pango/pango-private.h: Make PangoFontMetrics
+ heap allocated, protect the structure definition with
+ #ifdef PANGO_ENABLE_BACKEND, and add getters for the fields.
+
+ * pango/pango-attributes.[ch] ( pango_attr_iterator_get_font):
+ instead of providing a base font description and one to fill
+ in, provide a single font description to modify based on
+ the attributes.
+
+ * pango/pango-attributes.[ch]: Fix PangoAttrFontDesc to have
+ a PangoFontDescription by reference, not by value.
+
+ * pango/pango-utils.[ch]: make pango_parse_style() and friends
+ take pointers to individual enumerations instead of to a
+ PangoFontDescription structure.
+
+ * pango/*.c: Fix for the PangoFontDescription and PangoFontMetrics
+ changes.
+
+ * pango/pango-{break,engine,indic,ot,xft}.h pango/Makefile.am
+ pango/opentype/Makefile.am: Protect portions with
+ PANGO_ENABLE_ENGINE to shrink the public API.
+
+ * modules/*/Makefile.am: -DPANGO_ENABLE_ENGINE.
+
+ * pango/{pangox.h,pangox-private.h} modules/basic/basic-x.c: Move
+ pango_x_font_get_unknown_glyph() into public header since it is
+ used from modules.
+
+ * pango/pango-{context,font,fontmap,modules.utils}.h pango/Makefile.am:
+ Protect portions with PANGO_ENABLE_BACKEND to shrink the public API.
+
+ * pango/*.h: Use G_BEGIN/END_DECLS
+
+ * examples/viewer-qt.[cc,h]: Fix for changes to font listing API,
+ PangoFontDescription.
+
+ * pango/pango-indic.h modules/indic/*: Since we install this
+ header fix it up to Pango conventions, namespece
+ ZERO_WIDTH_JOINER, ZERO_WIDTH_NON_JOINER.
+
+ * docs/pango-sections.txt: Updated.
+
+2001-09-18 Matt Wilson <msw@redhat.com>
+
+ * modules/basic/Makefile.am (basic_xft_libadd): add
+ $(pangoxftlibs) so we get proper dependencies noted in the module.
+
+Tue Sep 11 11:31:53 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-fontmap.c pango/modules.c
+ pango/pango-utils.c pango/querymodules.c: Use
+ g_build_filename() where appropriate.
+
+Thu Sep 6 21:13:56 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-color.c: Fix problem with green/blue
+ confusion.
+
+2001-09-10 Alex Larsson <alexl@redhat.com>
+
+ * pango/fonts.c:
+ * pango/glyphstring.c:
+ * pango/pango-attributes.c:
+ * pango/pango-color.c:
+ * pango/pango-tabs.c:
+ * pango/pango-utils.c:
+ Update to the new g_boxed_type_register_static API.
+
+Mon Sep 3 19:37:02 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 0.18
+
+ * NEWS: Updated.
+
+ * pango/pangoxft-font.c (pango_xft_font_finalize): Actually
+ free the XftFont (and description). Lack of such pointed out
+ by David Turner.
+
+Sun Sep 2 12:08:15 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c pango/pango-utils.c: Make
+ a couple of functions static.
+
+ * pango/mini-fribidi/{fribidi_tables.i,fribidi.patch}:
+ Make data arrays static.
+
+Thu Aug 30 17:34:52 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-color.c: New file, move color handling
+ here.
+
+ * pango/pango-attributes.[ch] pango/pango-markup.c
+ pango/pango-color.c: Export pango_color_parse, change
+ it to take a PangoColor as its argument.
+
+Fri Aug 24 12:21:50 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_text): Handle
+ text == NULL, length == 0 again.
+
+Thu Aug 23 19:44:34 2001 Tim Janik <timj@gtk.org>
+
+ * pango/pango-layout.c (pango_layout_check_lines): pass ""
+ as default text into pango_layout_set_text() as NULL isn't
+ allowed anymore.
+
+Wed Aug 22 19:52:18 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_text): Simply
+ use g_utf8_validate() to validate the text, avoiding
+ problem where layout was left in hosed state for invalid
+ UTF-8, and also a bug with reading one-past length.
+
+2001-08-16 Alexander Larsson <alexl@redhat.com>
+
+ * pango/pangowin32.c:
+ Fully convert the truetype unicode table to host endianness when reading it.
+ Add a cache of one to find_segment since it showed up on a profile.
+
+2001-08-15 Jens Finke <jens@gnome.org>
+
+ * pango.spec.in: Updated to match gpp standard.
+
+2001-08-14 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c (pango_ft2_render): composite with "saturate"
+ semantics instead of "over" so joining glyphs get drawn correctly.
+
+2001-08-14 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c (pango_ft2_render): composite glyphs over the
+ buffer instead of simply copying into it so glyphs with overlapping
+ ink rectangles do not overwrite each other.
+
+Sun Aug 12 10:33:02 2001 Owen Taylor <otaylor@redhat.com>
+
+ * docs/Makefile.am pango/Makefile.am: Set GPATH to fix srcdir !=
+ builddir problems with GNU make.
+
+2001-08-10 Hans Breuer <hans@breuer.org>
+
+ * pango/pangowin32.c (pango_win32_render) : restore
+ the previously selected font into the device context.
+
+ (pango_win32_font_get_glyph_extents) : info->ink_rect.y needs
+ to be negative to get underlines right
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_list_fonts) :
+ Don't g_assert_not_reached () on !family case. This is what
+ the X version does as well. Testcase for win32: testfonts.c
+
+ * pango/testfonts.c : (new file) simple test program for win32
+ which renders all or selected fonts into a bitmap
+
+ * pango/makefile.msc : re-enable testfonts compiling
+
+2001-08-09 Matthias Clasen <matthiasc@waldgeist.poet.de>
+
+ * pango/pango-layout.c (pango_layout_line_get_empty_extents):
+ Remove unneeded inc_rect parameter.
+ (pango_layout_line_get_extents): Treat lines containing only
+ tabs as empty lines. (#57051)
+
+2001-08-09 Alexander Larsson <alexl@redhat.com>
+
+ * pango/pangowin32.h:
+ * pango/pangowin32-private.h:
+ * pango/pangowin32.c:
+ * pango/pangowin32-fontmap.c:
+ * modules/basic/basic-win32.c:
+ * pango/pangowin32.def:
+ Large rewrite of the win32 backend to use real glyph indexes
+ instead of unicode codes. Also drops the subfont thing, thereby
+ simplifying the code immensely. This looses some functionality,
+ but i will add that back soon using global (non backend-specific)
+ aliases.
+ This is the first cut, and is not perfect. It still has some issues
+ and imperfections, but it so clearly better than the current
+ imlementation that I'm checking it in anyway.
+
+2001-08-04 Alexander Larsson <alexl@redhat.com>
+
+ * pango/makefile.msc:
+ Don't build the non-existant testfont binary
+ Use glib-mkenums instead of the old mkenums.pl
+ copy module-defs-win32.c.win32 to module-defs-win32.c
+
+ * pango/module-defs-win32.c.win32:
+ Include the built in basic-win32 stuff.
+
+2001-07-27 Darin Adler <darin@bentspoon.com>
+
+ * modules/indic/gujarati-x.c: Remove unused prototype.
+
+2001-07-20 Hans Breuer <hans@breuer.org>
+
+ * pango/pango-layout.c (pango_layout_line_get_vis2log_map) :
+ make implementation static too.
+
+ * pango/pango.def pango/pangowin32.def : updated exports
+
+ * pango/pangowin32.c : correct PangoLanguage changes
+
+ * pango/mini-fribidi/fribidi.c : removed gccism for msvc build
+
+Thu Jul 19 16:44:43 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (font_set_load): Don't corrupt the
+ font description passed in.
+
+Fri Jul 13 14:24:59 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (pango_querymodules_DEPENDENCIES): Fix dependencies
+ to work without XFT.
+
+Thu Jul 12 16:32:42 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (pango_querymodules_DEPENDENCIES): Add
+ an explicit dependency on libpangoxft.la, to fix
+ parallel make problem (#56818)
+
+ * pango/Makefile.am (CLEANFILES): Fix problem where
+ name of stamp files didn't match actual name.
+
+2001-07-12 Darin Adler <darin@bentspoon.com>
+
+ * modules/arabic/arabic-x.c: (arabic_engine_shape): Remove stray
+ semicolon.
+
+ * modules/arabic/arconv.h:
+ * modules/arabic/arconv.c: (shape), (doublelig), (arabic_reshape):
+ Use long* instead of int* for parameter to match what's passed in.
+
+ * modules/indic/bengali-x.c: Add missing <string.h> include.
+ (pango_indic_make_ligs): Use local variable that was added but not
+ ever used.
+ (pango_indic_engine_shape): Remove unused locals.
+
+ * modules/indic/devanagari-x.c: Add missing <string.h> include.
+ (pango_indic_engine_shape): Remove unused local.
+
+ * modules/indic/gujarati-x.c: Add missing <string.h> include.
+ (pango_indic_engine_shape): Remove unused local
+
+ * modules/tamil/tamil-x.c: (tamil_engine_shape): Initialize a
+ variable to quiet the compiler's unused warning.
+
+ * pango/.cvsignore: Ignore more generated files.
+
+ * pango/opentype/ftxgpos.c: (Get_Anchor): Add code to set up the
+ ap variable. The old code would just use the uninitialized value.
+
+ * pango/opentype/ftxopen.c: (Load_Coverage): Remove unused local.
+
+ * pango/opentype/pango-ot-ruleset.c: (pango_ot_ruleset_shape):
+ Remove unused local.
+
+ * pango/pango-attributes.c: (pango_attr_list_get_type),
+ (pango_color_get_type): Add needed function type casts (just
+ warnings under gcc, but could be errors in other compilers).
+
+ * pango/pangoxft-font.c: (pango_xft_font_get_metrics),
+ (pango_xft_font_get_coverage), (pango_xft_get_shaper_map),
+ (pango_xft_font_find_shaper): Switch from lang char* to
+ PangoLanguage*. The code was still compiling, but would not have
+ worked.
+
+2001-07-02 James Henstridge <james@daa.com.au>
+
+ * pango/glyphstring.c (pango_glyph_string_copy): copy function.
+ (pango_glyph_string_get_type): implement get_type function.
+
+ * pango/pango-glyph.h (pango_glyph_string_get_type): get_type
+ function prototype.
+ (pango_glyph_string_copy): prototype for copy function.
+
+ * pango/pango-utils.c (pango_language_get_type): implementation.
+
+ * pango/pango-types.h (pango_language_get_type): get_type function.
+
+ * pango/pango-tabs.c (pango_tab_array_get_type): implementation.
+
+ * pango/pango-tabs.h (pango_tab_array_get_type): get_type function.
+
+ * pango/fonts.c (pango_font_description_get_type): implementation.
+
+ * pango/pango-font.h (pango_font_description_get_type): add
+ get_type function for typecode.
+
+Mon Jul 2 06:12:18 2001 Tim Janik <timj@gtk.org>
+
+ * pango/pangoxft-font.c:
+ * pango/pangox.c:
+ * pango/pangowin32.c:
+ * pango/pangoft2.c: s/shutdown/dispose/ to adapt to
+ GObject changes.
+
+Sun Jul 1 22:59:02 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-markup.c (text_handler): Use gssize,
+ not size_t, gssize isn't defined here on all
+ systems.
+
+2001-06-29 Havoc Pennington <hp@redhat.com>
+
+ * configure.in (QTDIR): don't get confused by qt3
+
+Thu Jun 28 21:49:30 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (GLIB_REQUIRED_VERSION): Require GLib-1.3.7
+
+ * pango/pangoft2-fontmap.c pango/pangowin32-fontmap.c
+ pango/pangox-fontmap.c pango/pangoxft-fontmap.c:
+ Fix args to g_type_init().
+
+Tue Jun 26 15:11:30 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (font_set_get_font)
+ pango/pango-context.c (add_engines): Couple of
+ bug fixes for the last change.
+
+ * configure.in: Abort out when AM_PATH_GLIB fails.
+
+Tue Jun 26 10:19:02 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c (pango_language_matches): Handle
+ language == NULL as matching nothing but '*'.
+
+ * pango/pango-context.[ch] (pango_context_get_metrics): Add a
+ (slowish) function to get the metrics for a font description,
+ including fallbacks as with pango_itemize(), rather than a single
+ font.
+
+Sat Jun 23 10:01:20 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_entry_get_coverage):
+ * pango/pangoft2-fontmap.c (pango_ft2_font_entry_get_coverage):
+ pango/pango-markup.c:
+ modules/arabic/arabic-xft.c (arabic_engine_shape):
+ modules/arabic/arabic-x.c (arabic_engine_shape):
+ pango/pango-context.c (pango_itemize):
+ pango/pangox.c (get_font_metrics_from_string):
+ pango/pangoft2.c (get_font_metrics_from_string):
+ Adapt to 64-bit changes in glib.
+
+ * pango/Makefile.am: Modify generation rules to
+ use glib-mkenums (ugh, loong command lines), and
+ to reduce rebuilding by using stamp files.
+
+2001-06-22 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc : changed version to 0.17
+
+ * pango/pango.def : updated externals
+
+ * pango/pangowin32-fontmap.c :
+ * pango/pangowin32-private.h :
+ * pango/pangowin32.c : adapted to PangoLanguage usage
+
+Sat Jun 9 17:36:09 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-types.h pango/pango-utils.c: Add a new PangoLanguage
+ type to represent language tags; these can efficiently be compared
+ and don't need to be copied. Also add pango_language_matches()
+ to match a language tag against a pattern.
+
+ * pango/pango-item.[ch] pango/pango-layout.c: Move extra_attrs
+ from PangoItem to PangoAnalysis. Add a language tag field to
+ PangoAnalysis. (#55894)
+
+ * pango/pango-attributes.[ch] (pango_attr_iterator_get_font): Return
+ the language tag as well.
+
+ * pango/pango-attributes.[ch]: Rename PangoAttrLang to PangoAttrLanguage,
+ and make it hold a PangoLanguage.
+
+ * pango/pango-context.[ch]: Rename pango_context_{get,set}_lang() to
+ pango_context_{get,set}_language().
+
+ * **.[ch]: Adapt to PangoLanguage and s/lang/language/ changes.
+
+ * modules/basic/basic-x.c modules/basic/tables-big.i: Add support
+ for ordering character sets differently for different language
+ tags.
+
+ * pango/itemize.c: Remove old, unused file.
+
+ * pango/pango-context.c (pango_itemize): Reduce number of mallocs
+ by allocating one array of PangoAnalysis instead of many arrays.
+
+2001-06-12 Havoc Pennington <hp@redhat.com>
+
+ * docs/Makefile.am (dist-hook): don't ignore errors from missing
+ index.sgml
+
+ * NEWS: update
+
+ * configure.in: increment version to 0.17
+
+Thu Jun 7 14:06:25 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually):
+ Add a 'strong' parameter to allow moving either the strong
+ or the weak cursor visually, instead of the strong cursor.
+
+2001-06-07 Havoc Pennington <hp@redhat.com>
+
+ * pango/Makefile.am: add libpango.la to _DEPENDENCIES for the
+ other libs
+
+ * configure.in: use AM_PATH_GLIB_2_0
+
+ * autogen.sh: support AUTOGEN_SUBDIR_MODE
+
+ * Makefile.am: dist the .pc.in files
+
+Tue Jun 5 10:40:17 2001 Owen Taylor <otaylor@redhat.com>
+
+ * docs/reference/tmpl/*.smgl: Patch from Matthias
+ Clasen fixing various typos. (#55744)
+
+Thu May 31 19:35:27 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_line_x_to_index):
+ Make the hack for avoiding the last index of the line more
+ sophisticated in order to deal with newlines internal
+ to the layout and the case where the second half of the
+ last character is specifically selected. (Fixes #51190)
+
+Thu May 31 12:31:20 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox-fontmap.c (pango_x_font_map_for_display):
+ Actually advance through list. (Problem noticed
+ by Erwann Chenede)
+
+ * modules/Makefile.am (install-data-local): Move rule
+ for generation of /etc/pango/pango.modules to here,
+ since we are now built _after_ the library. (Problem
+ noticed by KUSANO Takayuki)
+
+Tue May 29 18:17:11 2001 Owen Taylor <otaylor@redhat.com>
+
+ * autogen.sh (have_libtool): Fix GNU sedism
+
+Tue May 29 17:41:44 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Use $PKG_CONFIG, not pkg-config.
+
+Mon May 28 18:15:55 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually):
+ Set *trailing properly at end of line.
+
+Mon May 28 11:51:45 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules.c (map_add_engine): Fix problem with
+ information loss when converting leaves to branches.
+ (Problem found by Toshio MARUYAMA)
+
+Wed May 23 12:59:26 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c (pango_x_make_font_struct): Load the
+ font struct for "fixed" in the case of a broken font list
+ where fonts listed by XListFonts aren't loadable.
+
+Fri May 18 16:44:25 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (ensure_tab_width): Use the font
+ at the beginning of the paragraph, not the context's
+ font.
+
+Fri May 18 11:30:57 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/disasm.c: Use ISO C99 varargs when
+ available.
+
+Thu May 17 11:16:23 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mapping.c: Fixup docs, remove some FIXMEs that are
+ no longer applicable.
+
+ * pango/pango-layout.c: Move by graphemes, not characters.
+
+ * pango/pango-layout.c (pango_layout_line_x_to_index):
+ Position at the closest grapheme boundary, not at character
+ boundaries.
+
+ * pango/pango-layout.c (pango_layout_line_index_to_x):
+ Return positions of grapheme boundaries, not character
+ boundaries.
+
+Tue May 1 16:03:48 2001 Owen Taylor <otaylor@redhat.com>
+
+ * autogen.sh (libtool_version): Require libtool 1.4 when
+ build out of CVS.
+
+ * **/Makefile.am: Add inter-library dependencies,
+ especially for the modules. Many cleanups to the
+ module makefiles.
+
+ * configure.in modules/indic/Makefile.am: Remove
+ INCLUDE_ANY_INDIC conditional which doesn't seem to have
+ any point and was definitely suspect as done.
+
+ * modules/tamil/tamil-xft.c (MODULE_ENTRY): Fix prefix
+ to be _pango_tamil instead of _pango_basic.
+
+ * Makefile.am: Build modules/ after pango/ so we can
+ make the modules depend on libpango/libpangox.
+
+ * examples/Makefile.am: Remove spurious rule to rebuild
+ makefile.mingw.
+
+Mon May 14 19:10:11 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c: Fix to correspond to extremely
+ odd choice of sign convention in libXft. (#51476)
+
+Wed May 9 10:11:06 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (install-data-local): Get rid
+ of grep -q (pointed out by Tony Graham).
+
+2001-05-06 Alexander Larsson <alla@lysator.liu.se>
+
+ * configure.in:
+ Fix Xft detection by setting CPPFLAGS before trying
+ the Xft/XftFreetyp.h header file.
+ Use CPPFLAGS instead of CFLAGS.
+
+2001-01-06 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc : reflect new version number, removed
+ external fribidi dependency from link step as well
+
+ * pango/pango.def : updated externals
+
+ * pango/pangowin32.c : initialize approximate_(digit|char)_width
+ similar to what the other backends do
+
+Fri May 4 11:07:04 2001 Owen Taylor <otaylor@redhat.com>
+
+ * NEWS: Update for 0.16
+
+ * docs/pango-sections.txt: Update.
+
+ * configure.in (PANGO_MINOR_VERSION): 0.16
+
+Wed May 2 11:57:45 2001 Owen Taylor <otaylor@redhat.com>
+
+ * examples/Makefile.am (QT_LIBS): Remove space that
+ was confusing libtool.
+
+2001-05-04 Alex Larsson <alla@lysator.liu.se>
+
+ * pango/pangoft2.c (get_font_metrics_from_subfonts):
+ Set approximate_digit_width and approximate_char_width. The
+ digit one could be done better (see bug 53425).
+
+2001-05-03 Michael Natterer <mitch@convergence.de>
+
+ * configure.in: also check for the the Xft header.
+
+Wed May 2 11:35:16 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (have_freetype): Add check to make sure
+ #include FT_ERRORS_H works. (#54043)
+
+2001-05-02 Sven Neumann <sven@convergence.de>
+
+ * configure.in: do not try to build modules using Xft if X is not
+ available or was explicitely disabled.
+
+Tue May 1 23:30:53 2001 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/hangul-x.c (hangul_engine_shape): Fix numeric
+ format in warning.
+
+ * pango/pangox.c (get_font_metrics_from_string): Fix assorted
+ brokenness.
+
+Tue May 1 19:27:00 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c (pango_x_render): Rewrite the newline
+ arrow drawing code to act a little better on a range
+ of different sizes of fonts.
+
+2001-04-27 Havoc Pennington <hp@redhat.com>
+
+ * pango/pangox-fontmap.c: Move some fontmap stuff to
+ pangox-private.h to access fontmap->resolution in pangox.c
+
+ * pango/pangox.c (get_font_metrics_from_subfonts): multiply
+ avg. width by PANGO_SCALE, and consider that avg width from X is
+ in decipoints
+
+ * modules/basic/basic-x.c: mark some chars unknown when shaping,
+ with a flag PANGO_X_UNKNOWN_FLAG
+
+ * pango/pangox.c (pango_x_font_get_metrics): use lookup_lang not
+ lang when calling get_font_metrics_from_string
+ (pango_x_render): render unknown chars
+
+ * pango/pango-layout.c:
+ (pango_layout_set_single_paragraph_mode): add mode where we don't
+ break on para separators, instead we shape them and display glyphs
+ (pango_layout_get_single_paragraph_mode): getter for above
+ (pango_layout_check_lines): handle single paragraph mode
+
+Tue Apr 24 11:45:55 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgdef.c (TT_Load_GDEF_Table): Remove
+ excess call to DONE_Stream left over from conversion
+ from FT1. (reported by Michael Jansson)
+
+2001-04-20 Alexander Larsson <alexl@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_get_metrics):
+ Set approximate_digit_width and approximate_char_width to
+ some cheesy value. Not good, but better than nothing.
+
+Fri Apr 20 11:38:46 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-markup.c (pango_parse_markup): Remove some
+ conditionalization on (md->text == NULL) that is no
+ longer needed with the last change.
+
+2001-04-20 Anders Carlsson <andersca@codefactory.se>
+
+ * pango/pango-markup.c (pango_parse_markup): Discard the parsed text if
+ the input variable text is NULL. This fixes a segfault.
+
+Tue Apr 17 15:44:53 2001 Owen Taylor <otaylor@redhat.com>
+
+ * Release 0.15
+
+ * tests/testboundaries.c: Look for files in $srcdir.
+
+ * Makefile.am (SUBDIRS): Add tests, remove fonts
+
+ * tests/Makefile.am (EXTRA_DIST): added missing stuff
+
+ * fonts/: Remove. Nothing in here is needed any more.
+
+2001-04-16 Havoc Pennington <hp@pobox.com>
+
+ * pango/pango-glyph.h: Removed pango_justify(), since it has no
+ implementation that I can find.
+
+ * pango/pango-attributes.c: docs
+
+ * pango/pango-layout.c: docs
+
+Mon Apr 16 19:20:12 2001 Owen Taylor <otaylor@redhat.com>
+
+ * modules/tamil/tamil-x.c: Remove warning when using fallback
+ shaping.
+
+Mon Apr 16 19:14:00 2001 Owen Taylor <otaylor@redhat.com>
+
+ [ Patches from Vikram Subramanian to update Tamil shapers ]
+
+ * configure.in modules/tamil/tamil-xft.c modules/tamil/Makefile.am:
+ Xft/TT based Tamil rendering engine. Uses glyphs in the
+ private-use-area instead of proper OpenType tables.
+
+ * examples/HELLO.utf8: Add Tamil line
+ * examples/pangox.aliases: Add tamil fonts
+
+ * modules/tamil/tadefs.h modules/tamil/tamil-x.c: Update
+ to use PANGO_LIGATURE_HACK ligatures from BDF files instead
+ of a fixed encoding.
+
+Mon Apr 16 18:12:06 2001 Owen Taylor <otaylor@redhat.com>
+
+ * README: Small updates
+
+ * examples/HELLO.utf8: Insert a RLM on the Yiddish line
+ to correct for fixes to the bidi algorithm.
+
+ * pango/mini-fribidi/*: Update to CVS fribidi which
+ has various bug fixes.
+
+Mon Apr 16 14:26:54 2001 Owen Taylor <otaylor@redhat.com>
+
+ * docs/pango-sections.txt: Update.
+
+ * docs/Makefile.am (EXTRA_DIST): Update to the latest
+ version.
+
+2001-04-14 Hans Breuer <hans@breuer.org>
+
+ * pango/pangowin32-fontmap.c : instead of simply adding one
+ matching font for the magic font names (sans, serif, monospace)
+ stuff any mathing font in the respective family entries
+ (pango_win32_font_map_load_font) : do the same approximation for
+ oblique and italic as the X version does
+
+ * pango/pangowin32.c (pango_win32_font_get_glyph_extents) :
+ initialize ink_rect and logical_rect to some more appropriate values
+ (subfont_has_glyph) : implement glyph availability caching. IMO it
+ needs to be done different to the other backends, because even the
+ decision if a font has a specific glyph is increadeable slow on win32
+
+Fri Apr 13 14:55:20 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mini-fribidi/{fribidi.c,fribidi_get_type.c,fribidi_tables.i}:
+ Update to correspond to FriBidi-0.9.0 (with some small fixes)
+
+ * pango/mini-fribidi/fribidi-0.9.0.patch: Update patch for
+ Fribidi-0.9.0.
+
+2001-04-13 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-font.h: Add macros for CSS font scale factors
+
+2001-04-13 James Henstridge <james@daa.com.au>
+
+ * configure.in: AC_INIT should be the first statement in the file.
+ Also, use $PANGO_MAJOR_VERSION.$PANGO_MINOR_VERSION as the version
+ passed to AM_INIT_AUTOMAKE.
+
+Tue Apr 3 15:05:19 2001 Owen Taylor <otaylor@redhat.com>
+
+ * Release 0.14
+
+ * NEWS: updated.
+
+ * pango/pango/opentype/Makefile.am: make dist fixes.
+
+ * configure.in (PANGO_MINOR_VERSION): Up to 0.14
+
+Mon Apr 2 12:01:03 2001 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer-qt.cc (main): Add the mystic
+ g_type_init ((GTypeDebugFlags) 0);.
+
+2001-04-02 Alexander Larsson <alexl@redhat.com>
+
+ * pango/pangoft2-fontmap.c:
+ Add some initilaization failure warnings if no fonts found
+ or no fontaliases files found.
+
+2001-03-31 Fatih Demir <kabalak@gtranslator.org>
+
+ * .cvsignore: Extended the ignore list to be right
+ and make CVS quiet.
+
+2001-03-18 Tor Lillqvist <tml@iki.fi>
+
+ * pango/makefile.mingw.in
+ * pango/pango.def: Update.
+
+ * pango/module-defs-win32.c.win32: New file.
+
+ * pango/Makefile.am (EXTRA_DIST): Add here.
+
+ * pango/mini-fribidi/makefile.mingw: New file.
+
+ * pango/mini-fribidi/makefile.mingw (EXTRA_DIST): Add here.
+
+Fri Mar 9 11:57:46 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c (pango_x_find_subfont): Remove a lot of
+ instances of "Error parsing ligature info" that somehow
+ crept in.
+
+ * docs/*: Some makefile tweaks, structure updates.
+
+2001-03-15 Sven Neumann <sven@gimp.org>
+
+ * Makefile.am
+ * configure.in
+ * modules/*/Makefile.am
+ * pango/Makefile.am: make it compile without X headers
+
+2001-03-12 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c (pango_ft2_font_describe): set the size field
+
+2001-03-07 Havoc Pennington <hp@redhat.com>
+
+ * pango/pangox.c (pango_x_font_get_metrics): fix a cheesy bug in
+ setting approximate_digit_width
+
+Wed Mar 7 09:21:14 2001 Tim Janik <timj@gtk.org>
+
+ * pango/pango-attributes.c: fixed up g_boxed_type_register_static()
+ since GLib signature changed.
+
+ * got rid of bogus g_type_init() calls.
+
+2001-02-28 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-font.h (struct _PangoFontMetrics): add
+ approximate_digit_width field
+
+ * pango/pangox.c (pango_x_font_get_metrics): make up an
+ approximate digit width number
+
+2001-02-28 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-font.h (struct _PangoFontMetrics): Add
+ approximate_char_width field
+
+ * pango/pangox.c (get_font_metrics_from_subfonts): "compute" the
+ approximate char width. Other backends need to add this.
+
+2001-02-28 Alexander Larsson <alla@lysator.liu.se>
+
+ * pango/pango-attributes.[c]:
+ Added pango_attr_list_get_type, and PANGO_TYPE_ATTR_LIST.
+
+2001-02-20 Havoc Pennington <hp@pobox.com>
+
+ Patch from Soeren Sandmann
+
+ * pango/pangox-fontcache.c (pango_x_font_cache_load): make xlfd
+ arg const
+
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory):
+ G_CONST_RETURN
+ (pango_get_lib_subdirectory): G_CONST_RETURN
+
+2001-02-19 Hans Breuer <hans@breuer.org>
+ * pango/modules.h, pango/pangowin32.c (pango_win32_get_context) :
+ added _pango_included_win32_modules[] to include modules with plain
+ win32 build as well.
+
+ * pango/pango.def : added new exported functions
+
+ * pango/pangowin32-fontmap.c : add unspecified fonts for Monospace,
+ Sans and Serif to avoid crashes if no alias file is provided
+
+ * pango/*/makefile.msc : new files to build on windoze with msvc
+
+2001-02-15 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_line_x_to_index): fix
+ *trailing = FALSE to read *trailing = 0
+
+2001-02-13 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_line_get_x_ranges): fix
+ another "count line lengths to get line start" bug
+
+2001-02-12 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_list_insert_internal):
+ properly update the tail of the list
+ (pango_attr_list_change): flip order of tmp_list2 =
+ tmp_list2->next and prev2 = tmp_list2 to avoid setting
+ prev2 and tmp_list2 to the same value thus creating a
+ mangled list.
+
+ * pango/pango-layout.c (pango_layout_xy_to_index): When returning
+ FALSE, set the index/trailing to the nearest location, instead
+ of setting them to 0.
+ (pango_layout_line_x_to_index): Fix a bug where line->start_index
+ wasn't used. Return boolean for whether we had to clamp the
+ value to get an index.
+
+Mon Feb 12 15:01:38 2001 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (gtk_doc_min_version): Add check for
+ gtk-doc version.
+
+Mon Feb 12 12:45:16 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am: srcdir != build dir fix.
+
+ * docs/Makefile.am: Switching over to the new gtk-doc
+ Makefile.am.
+
+2001-02-11 Havoc Pennington <hp@pobox.com>
+
+ * pango/pangox.c (font_struct_get_ligatures): memory leak fix
+
+2001-02-10 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): (Win32): Use
+ g_win32_get_package_installation_subdirectory(). Use the same
+ directory structure as on Unix, etc\pango and lib\pango under the
+ installation "prefix".
+
+ * config.h.win32
+ * pango/makefile.mingw.in: Use mini-fribidi instead of full
+ FriBiDi.
+
+ * pango/pangowin32.c (pango_win32_render_layout_line): Adapt to
+ changed PangoAttrColor.
+
+ * pango/querymodules.c: Include <io.h> for getcwd() prototype.
+ (query_module): Handle modules with spaces in the path, and
+ backslashes, use g_strescape() (for Windows).
+
+ * pango/mini-fribidi/makefile.mingw: New file
+
+2001-02-05 Alexander Larsson <alexl@redhat.com>
+
+ * pango/pangoft2.c (pango_ft2_render,
+ pango_ft2_render_layout_line): Remove bogus MIN when rendering
+ freetype text. Also draw full underlines.
+
+Sun Feb 4 07:48:47 2001 Tim Janik <timj@gtk.org>
+
+ * pango/pango-attributes.c (pango_color_get_type): pass 0 as
+ first argument to g_type_init().
+
+ * pango/pangoxft-fontmap.c (pango_xft_get_font_map):
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_for_display):
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_for_display):
+ * pango/pangox-fontmap.c (pango_x_font_map_for_display):
+ * pango/pango-context.c (pango_context_new): likewise.
+
+ * i dare saying that i doubt the usefullness of all these
+ g_type_init() calls though.
+
+2001-01-26 Havoc Pennington <hp@redhat.com>
+
+ * pango/pangox.h (PangoGetGCFunc): take a PangoColor not a
+ PangoAttrColor
+
+ * pango/pango-attributes.h: add PangoColor, add PANGO_ATTR_INVALID
+ as a placeholder for zero in the PangoAttrType enum, corresponds
+ to G_TYPE_INVALID.
+
+ * pango/pango-attributes.c: Add PangoColor type, use for
+ PangoAttrColor
+ (pango_color_get_type): new function
+ (pango_color_copy): new function
+ (pango_color_free): new function
+
+Thu Jan 25 14:47:17 2001 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-sections.txt pango/pango-docs.sgml pango/tmpl/*:
+ Updates for new functions.
+
+2001-01-23 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_copy): New function
+
+2001-01-23 Alex Larsson <alla@lysator.liu.se>
+
+ * pango/pango-item.c (pango_item_free):
+ Free item->extra_attrs list.
+
+ * pango/pango-layout.c (process_item):
+ Don't leak copy of item.
+
+ * pango/pango-utils.c (read_config_file):
+ If the config file open fails, don't leak the
+ temp buffers.
+
+2001-01-23 <alla@lysator.liu.se>
+
+ * modules/basic/basic-ft2.c (basic_engine_get_coverage):
+ Don't leak PangoCoverage.
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_load_font):
+ Move name free closer to allocation.
+ (pango_ft2_font_map_read_alias_file): Don't leak faces.
+ (pango_ft2_font_entry_get_coverage): Don't leak font as
+ filename and cache_file_name.
+
+2001-01-22 Havoc Pennington <hp@redhat.com>
+
+ * tests/testboundaries.c (check_line_char): s/is_break/is_line_break/g;
+
+ * pango/pango-layout.c, pango/pango-layout.h: Add PangoWrapMode
+ for PangoLayout
+
+ * pango/break.c (pango_default_break): implement char break log
+ attr
+
+ * pango/pango-break.h (struct _PangoLogAttr): rename is_break
+ is_line_break, add is_char_break field
+
+2001-01-18 Alex Larsson <alla@lysator.liu.se>
+
+ * pango/pangoft2.c (get_font_metrics_from_subfonts):
+ Use correct font metrics information.
+
+2001-01-07 Tor Lillqvist <tml@iki.fi>
+
+ * pango/fonts.c (pango_font_description_to_filename): Allow '+' in
+ the filename.
+
+ * pango/pangowin32.c (get_font_metrics_from_string): Adopt to new
+ prototype for g_utf8_to_ucs4).
+
+ * pango/module-defs.c.win32: Removed.
+
+ * pango/module-defs-ft2.c.win32: New file, hand-written until GNU
+ configure is used on Win32, too.
+
+ * pango/makefile.mingw.in
+ * pango/Makefile.am (EXTRA_DIST): Corresponding changes.
+
+ * pango/pango.def: Update.
+
+Sat Jan 6 20:23:54 2001 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/arabic-x.c (arabic_engine_shape): Adapt
+ to new g_utf8_to_ucs4() prototype.
+
+ * modules/basic/basic-ft2.c: Include pango-engine.h
+
+ * pango/pangoft2.h: Don't include pango.h, which would
+ pull in pango-enums.h and thus break module building,
+ just include neeeded pango-layout.h
+
+Fri Jan 5 16:12:37 2001 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/{arabic-xft,arabic}.c pango/{pango-context.c,pangoft.c,pangox.c}:
+ Adopt to new prototype for g_utf8_to_ucs4 (etc.).
+
+2001-01-05 Alexander Larsson <alla@lysator.liu.se>
+
+ * .cvsignore: Add pangoft2.pc
+
+ * Makefile.am:
+ * configure.in:
+ Build and install pangoft2.pc
+
+ * pangoft2.pc:
+ New file.
+
+2001-01-04 Havoc Pennington <hp@redhat.com>
+
+ * modules/indic/Makefile.am (INCLUDES): add X_CFLAGS
+
+ * modules/hangul/Makefile.am (INCLUDES): add X_CFLAGS
+
+ * modules/tamil/Makefile.am (INCLUDES): add X_CFLAGS
+
+ * modules/thai/Makefile.am (INCLUDES): add X_CFLAGS
+
+2001-01-04 Havoc Pennington <hp@redhat.com>
+
+ * pango/Makefile.am (install-data-local): put creation of module
+ file here. Fixes problem if you 'make install' with no preceding
+ 'make' reported by Michael Meeks.
+
+ * modules/Makefile.am (install-data-local): remove creation of module file
+ from here
+
+ * Makefile.am (SUBDIRS): remove pango-config
+
+ * configure.in: use pkg-config to detect GLib cflags/libs
+
+ * pangoxft.pc (Description): fix name/description
+
+2001-01-04 Alexander Larsson <alla@lysator.liu.se>
+
+ * modules/arabic/arabic-x.c:
+ * modules/arabic/arabic-xft.c:
+ * modules/basic/basic-ft2.c:
+ * modules/basic/basic-win32.c:
+ * modules/basic/basic-x.c:
+ * modules/hangul/hangul-x.c:
+ * modules/indic/bengali-x.c:
+ * modules/indic/devanagari-x.c:
+ * modules/indic/gujarati-x.c:
+ * modules/indic/gurmukhi-x.c:
+ * modules/indic/myanmar-x.c:
+ * modules/tamil/tamil-x.c:
+ * modules/thai/thai-x.c:
+ Change all modules to use a define to the script engine name. Also
+ Fixes some errors in the names (they were different in the same module).
+
+ * pango/.cvsignore:
+ add module-defs*.[ch]
+
+2001-01-03 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ * modules/arabic/Makefile.am:
+ * modules/arabic/arabic-x.c:
+ * modules/basic/Makefile.am:
+ * modules/basic/basic-x.c:
+ * modules/hangul/Makefile.am:
+ * modules/hangul/hangul-x.c:
+ * modules/indic/Makefile.am:
+ * modules/indic/bengali-x.c:
+ * modules/indic/devanagari-x.c:
+ * modules/indic/gujarati-x.c:
+ * modules/indic/gurmukhi-x.c:
+ * modules/indic/myanmar-x.c:
+ * modules/tamil/Makefile.am:
+ * modules/tamil/tamil-x.c:
+ * modules/thai/Makefile.am:
+ * modules/thai/thai-x.c:
+ Rename all x modules from abc to abc-x.
+
+ * modules/arabic/arabic.c:
+ * modules/basic/basic.c:
+ * modules/hangul/hangul.c:
+ * modules/indic/bengali.c:
+ * modules/indic/devanagari.c:
+ * modules/indic/gujarati.c:
+ * modules/indic/gurmukhi.c:
+ * modules/indic/myanmar.c:
+ * modules/tamil/tamil.c:
+ * modules/thai/thai.c:
+ These were all copied to file-x.c and then removed.
+
+2001-01-03 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ Update the default list of included modules for
+ --with-included-modules=yes to include all new modules.
+ Split INCLUDED_MODULES and module-defs.c into per shaper
+ engine type lists.
+
+ * modules/arabic/Makefile.am:
+ Build libpango-arabic-xft.la if INCLUDE_ARABIC_XFT.
+
+ * modules/arabic/arabic-xft.c:
+ Change module prefix to _pango_arabic_xft_
+
+ * modules/basic/Makefile.am:
+ Build static libs for all included modules.
+
+ * modules/basic/basic-ft2.c:
+ Change module prefix to _pango_basic_ft2_
+
+ * modules/basic/basic-xft.c:
+ Change module prefix to _pango_basic_xft_
+
+ * pango/Makefile.am:
+ Include correct module-defs-XXX in libs.
+
+ * pango/modules.h:
+ Split _pango_included_modules[] into separate lists.
+
+ * pango/pangox.c:
+ * pango/pangoft2.c:
+ * pango/pangoxft-fontmap.c:
+ Register built in modules.
+
+2000-12-22 Alexander Larsson <alla@lysator.liu.se>
+
+ * pango/pangoft2.c:
+ Remove timing printfs.
+
+ * pango/pangoft2-private.h:
+ Disable debug.
+
+2000-12-21 Tor Lillqvist <tml@iki.fi>
+
+ * modules/basic/basic-win32.c (script_engine_load): Only a script
+ engine here.
+
+ * pango/makefile.mingw.in: Add the built pango-enum-types.[ch].
+
+ * pango/pango.def
+ * pango/pangoft2.def: Update.
+
+ * pango/opentype/pango-ot.def
+ * pango/opentype/makefile.mingw.in: New files.
+
+ * pango/opentype/Makefile.am (EXTRA_DIST): Add them.
+
+ * configure.in (included_modules): Generate
+ pango/opentype/makefile.mingw.
+
+2000-12-21 Alexander Larsson <alexl@redhat.com>
+
+ * pango-config.in:
+ Change usage to say pango-config instead of glib-config.
+ Add support for pangoft2.
+
+ * modules/basic/Makefile.am:
+ Compile and install pango-basic-ft2 if freetype was found.
+
+ * modules/basic/basic-ft2.c:
+ Remove lang engine. Make the glyph from the glyph index instead
+ of the unicode index. The id is really BasicScriptEngineFT2.
+
+ * pango/Makefile.am:
+ Compile and install pangoft2 if freetype was found.
+
+ * pango/pangoft2-fontcache.c (pango_ft2_font_cache_load):
+ Init face->generic.data to 0, since this field will be used
+ to cache the current size of the face.
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_for_display):
+ Use g_object_new instead of g_type_create_instance.
+ (pango_ft2_font_entry_get_coverage): Use G_DIR_SEPARATOR_S
+ instead of \\. (pango_ft2_font_entry_get_coverage): Init result
+ to NULL. Don't write to file if open failed.
+
+ * pango/pangoft2-private.h:
+ Add PangoFT2GlyphInfo.
+
+ * pango/pangoft2.c (pango_ft2_get_face): Export function, and make
+ sure it sets the correct face size. (pango_ft2_load_font,
+ pango_ft2_get_per_char, pango_ft2_font_get_kerning):
+ PANGO_FT2_GLYPH_INDEX stores the glyph index, not the unicode value.
+ (pango_ft2_font_get_glyph_extents): Cache glyph extents.
+ (pango_ft2_has_glyph): Remove function.
+ (pango_ft2_font_finalize): Free glyph info cache.
+
+ * pango/pangoft2.h:
+ Export pango_ft2_get_face, remove pango_ft2_has_glyph.
+
+Wed Dec 20 19:53:09 2000 Owen Taylor <otaylor@redhat.com>
+
+ * docs/Makefile.am (IGNORE_HFILES): Add opentype/.
+
+ * modules/{basic/basic,arabic/arabic}-xft.c: Include
+ pango-engine.h.
+
+ * pango/pangoxft.h: Don't include pango.h to avoid
+ getting pango-enum-types.h.
+
+ * pango/Makefile.am (pangoinclude_HEADERS): Move
+ XFT_HFILES out of pango_headers, since mkenums.pl
+ shouldn't be run on it.
+
+2000-12-20 Havoc Pennington <hp@redhat.com>
+
+ * configure.in: fix freetype check a bit
+
+Tue Dec 19 22:47:16 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in pango-config.in pangoxft.pc.in
+ modules/basic/Makefile.am: Since Xft may only be available
+ statically without shlib deps, check for FreeType libs explicitly
+ and include them when linking, otherwise things won't work. Also,
+ define FREETYPE_CFLAGS from freetype-config --cflags.
+
+ * modules/basic/basic-xft.c pango/pangoxft-font{,map}.c: Fool
+ Xft into not converting glyph indices by loading the
+ face unencoded then calling FT_Set_Charmap ourselves.
+
+ * pango/Makefile.am pango/pango-ot.h pango/opentype/* :Add start
+ of opentype handling - most of the actually meat of the code here
+ is the OpenType layout code from FreeType 1 ported to freetype2
+ and adapted slighlty for our purposes. Also, includes a
+ incomplete OpenType-table-dumping code useful for figuring
+ out what is going on.
+
+ * pango/pangoxft.h pango/pangoxft-font.h: Add calls for
+ getting FT_Face and PangoOTInfo from PangoXftFont.
+
+ * modules/arabic/{Makefile.am,arabic-ot.[ch],arabic-xft.c}:
+ Initial support for rendering Arabic with OpenType fonts.
+
+2000-12-18 Havoc Pennington <hp@redhat.com>
+
+ Fix build breakage, reported by Alex Larsson and Yasushi Shoji
+
+ * pango/pangox.h: don't include pango.h, just individual headers
+
+ * configure.in: check for perl, add --disable-rebuilds configure
+ option, automatically disable rebuilds if no perl
+
+ * pango/Makefile.am: use located perl to run makeenums.pl,
+ and don't try to rebuild if we did --disable-rebuilds
+ (EXTRA_DIST): add built headers
+
+ * modules/*/*.[hc]: don't include pango.h, include specific headers
+
+2000-12-15 Havoc Pennington <hp@pobox.com>
+
+ * pango/pango-glyph.h: move pango_shape and pango_reorder_items in
+ here.
+
+ * pango/pango-break.h: move most of pango.h in here, so that
+ pango.h can be the only file that includes pango-enum-types.h, so
+ that changing any header doesn't end up rebuilding all of pango
+ due to a rebuild of pango-enum-types.h.
+
+ * pango/makeenums.pl: script to generate pango-enum-types.[hc]
+
+ * pango/Makefile.am (pango_headers): built pango-enum-types.h,
+ pango-enum-types.c that do enum type registration; add
+ pango-break.h; do some assorted rearranging to handle the
+ built headers
+
+ * pango/pango.h: moved most of it to pango-break.h
+
+ * pango/break.c: include individual headers, not pango.h
+
+ * pango/shape.c: ditto
+
+ * pango/reorder-items.c: ditto
+
+ * pango/querymodules.c: ditto
+
+ * pango/pango-layout.c: ditto
+
+ * pango/pango-indic.c: ditto
+
+ * pango/mapping.c: ditto
+
+ * pango/itemize.c: ditto
+
+ * pango/fonts.c: ditto
+
+2000-12-15 Havoc Pennington <hp@redhat.com>
+
+ * modules/Makefile.am (install-data-local): touch
+ sysconfdir/pango/pango.modules even if there are no dynamic
+ modules, so pango won't spew warnings about pango.modules not
+ existing, and to simplify RPM file lists
+
+ * pango/pango-context.c (fallback_engine_shape): fix this to
+ avoid incrementing i twice
+ (fallback_shaper): fix initializer
+
+ * pango/querymodules.c (query_module): don't call g_module_close()
+ on a module that doesn't get opened successfully
+
+ * pango/modules.c: do not include modules.h
+ (init_modules): do not do the builtin modules here,
+ they are done by pangox
+
+ * pango/pangox.c (pango_x_get_context): register included modules
+ here
+
+ * pango/pangoxft-font.c: do not include modules.h
+
+ * pango/Makefile.am (libpango_la_SOURCES): move modules.c,
+ back in here (but not modules.h, which actually goes with
+ module-defs.c)
+
+2000-12-14 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-context.c (add_engines): Use a fallback shaper if
+ no engine is found for a range, the fallback shaper shapes to
+ glyphs of 0. This is just to let other code depend on the
+ invariant that there's a shape engine for all characters.
+
+ * tests/all-unicode.txt: Huge file containing all Unicode
+ characters, for robustness testing. Not in EXTRA_DIST
+ for now, not sure we should torture people that way...
+
+ * pango/fonts.c (pango_font_find_shaper): remove the assert that
+ we found a shaper, and instead let things fall back to the fallback
+ shaper
+
+Thu Dec 14 20:34:18 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft.h pango/pangoxft-font.c: (PANGO_TYPE_XFT_FONT): Add
+ PANGO_XFT_IS_FONT to the public header.
+
+Thu Dec 14 19:00:46 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/pango-indic-script.h: Fix macro breakage.
+
+ * modules/basic/tables-big.i: Remove extra copy of basic_ranges.
+
+ * modules/thai/thai.c: Fix various warnings.
+
+ * configure.in Makefile.am pangoxft.pc.in pango-config.in
+ modules/basic/Makefile.am modules/basic/basic-xft.c
+ pango/Makefile.am pango/pangoxft-font.[ch] pango/pangoxft-fontmap.c
+ pango/pangoxft.h pango/pangoxft-private.h: Initial support
+ for rendering via Xft and the Xrender extension.
+
+2000-12-14 Havoc Pennington <hp@redhat.com>
+
+ * pango/fonts.c (pango_font_find_shaper): add assertion that
+ shaper != NULL to catch engine problems faster
+
+ * pango/Makefile.am (libpangox_la_SOURCES): modules.[hc] and
+ module-defs.c have to go in libpangox for now since the modules
+ use the X stuff, and static linkage won't let you play games here
+
+ * examples/Makefile.am (pango_viewer_LDADD): fix order of link
+
+ * modules/indic/pango-indic-script.h (pango_indic_get_char): make
+ this a macro, so it doesn't collide between modules
+
+ * modules/*/Makefile.am: Fix to work if the module isn't included
+
+ * examples/Makefile.am: don't query modules if we didn't build any
+
+ * modules/indic/gurmukhi.c (MODULE_ENTRY): fix prefix
+
+ * modules/indic/bengali.c (MODULE_ENTRY): fix prefix
+
+ * modules/indic/gujarati.c (MODULE_ENTRY): fix prefix
+
+ * modules/indic/devanagari.c (MODULE_ENTRY): fix prefix
+
+ * modules/indic/myanmar.c (MODULE_ENTRY): uniquely prefix the functions
+
+ * modules/Makefile.am (MODULES): handle case where there are no
+ modules to query
+
+ * configure.in: Fix up include_modules stuff to work with Indic
+
+ * pango/glyphstring.c (pango_glyph_string_set_size): Just
+ g_error() if the glyph string exceeds maximum integer size,
+ instead of mysteriously crashing later.
+
+2000-12-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangoft2.c (pango_ft2_ft_strerror): Update for newest
+ FreeType2.
+ (pango_ft2_font_finalize): gcc warns about empty format strings,
+ so use just a space...
+
+2000-12-11 Havoc Pennington <hp@redhat.com>
+
+ * tests/boundaries.utf8: Add some jamo and viramas and unicode
+ para separators and \r\n and so on, crashes the text widget nicely
+
+2000-12-11 Elliot Lee <sopwith@redhat.com>
+
+ * modules/thai/thai.c, pango/break.c: #include <string.h>
+
+Mon Dec 11 15:20:24 2000 Owen Taylor <otaylor@redhat.com>
+
+ * examples/HELLO.utf8: Add a tab into to Yiddish line
+ to force correct segmentation around the parentheses.
+
+2000-11-30 Havoc Pennington <hp@pobox.com>
+
+ * modules/thai/thai.c: delete lang engine
+
+ * modules/tamil/tamil.c: delete lang engine
+ (tamil_engine_x_new): fix type tag for shape engine
+
+ * modules/indic/myanmar.c: delete lang engine
+ (pango_engine_x_new): fix type tag for shape engine
+
+ * modules/indic/gurmukhi.c: delete lang engine
+ (pango_indic_engine_x_new): fix type tag for shape engine
+
+ * modules/indic/gujarati.c: delete lang engine
+ (pango_indic_engine_x_new): fix type tag for shape engine
+
+ * modules/indic/devanagari.c: delete lang engine
+ (pango_indic_engine_x_new): fix type tag for shape engine
+
+ * modules/indic/pango-indic-script.h (SCRIPT_ENGINE_DEFINITION):
+ delete lang engine
+
+ * modules/indic/bengali.c: delete the lang engine
+ (pango_indic_engine_x_new): fix type tag for shape engine
+
+ * modules/hangul/hangul.c: delete the lang engine
+ (hangul_engine_x_new): fix type tag for shape engine
+
+ * modules/basic/basic.c: delete the lang engine
+ (basic_engine_x_new): fix type tag for shape engine
+
+ * modules/basic/basic-win32.c: delete the lang engine
+ (basic_engine_win32_new): this was a shape engine,
+ use correct type tag
+
+ * modules/basic/basic-ft2.c: delete the lang engine
+
+ * modules/arabic/arabic.c: Delete the lang engine
+ (arabic_engine_x_new): this is a shape
+ engine, not a lang engine, fix type tag
+
+ * pango/pango-layout.c (pango_layout_index_to_line_x): handle
+ the fact that paragraph delimiters aren't in the layout lines
+ (pango_layout_index_to_pos): update to handle paragraph
+ delimiters
+
+ * pango/break.c (pango_find_paragraph_boundary): New function
+ to find paragraph boundaries
+
+ * pango/pango-layout.c (get_items_log_attrs): don't separate calls
+ to pango_break() when directional level changes
+
+ * pango/pango-layout.h (struct _PangoLayoutLine): put start index
+ of the line into the struct
+
+ * pango/pango-layout.c (pango_layout_get_cursor_pos): Fixups to
+ reflect the fact that paragraph separators are removed from the
+ input text.
+
+ * pango/pango-layout.c (can_break_at): don't
+ special-case start of line and whitespace-following-alphabetic
+ here, because pango_break() already handles that properly
+
+ * tests/testboundaries.c, tests/Makefile.am, tests/runtests.sh:
+ Add directory for test programs, and a script to run them all
+
+ * configure.in: Create Makefile in tests
+
+ * pango/break.c (pango_break): Try for a real implementation of
+ the Unicode text boundary algorithms
+ (pango_get_log_attrs): Allow length to be -1
+
+ * pango/pango-context.c (pango_itemize): use pango_item_new(),
+ assert that items added to the list are sane.
+
+ * pango/pango-layout.c (pango_layout_check_lines): Reimplement
+ to honor the paragraph boundaries from pango_break()
+
+ * pango/pango-layout.c (process_item): use pango_item_split() here
+
+ * pango/pango-item.c (pango_item_split): New function to split an
+ item into two items
+
+Fri Dec 1 11:49:50 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (get_tab_pos): Make sure that
+ we don't end up in an infinite loop due to zero-width
+ tabs. (Fix problem found by Hans Breuer)
+
+2000-12-01 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory): Use
+ g_file_test().
+
+2000-11-30 Tor Lillqvist <tml@iki.fi>
+
+ * pango/makefile.mingw.in (DEFINES): Define PANGO_VERSION.
+
+ Changes by Hans Breuer:
+
+ * pango/pango-layout.c (shape_tab): Add a FIXME comment.
+
+ * pango/pango-markup.c (compare_xcolor_entries): Use g_strcasecmp.
+
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory): Use second
+ fallback location if there is no pango subdir in the Windows
+ directory.
+
+ * pango/pangowin32-fontmap.c
+ (pango_win32_font_entry_get_coverage): Check if fopen succeeded.
+
+ * pango/pangowin32-private.h (DEBUGGING): Turn off.
+
+ * pango/pangowin32.c (pango_win32_unicode_classify): We can in
+ fact get out of the loop. Return invalid value in that case.
+ (subfont_has_glyph): Improve performance a bit.
+
+ * pango/querymodules.c: Small change for MSVC build.
+
+ * modules/basic/basic-win32.c (basic_engine_get_coverage):
+ Performance improvement.
+
+ * examples/viewer-win32.c (main): Disable double buffering on the
+ layout widget, but only when building with GTK+ 1.3.2 or newer.
+
+Wed Nov 29 11:08:52 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mini-fribidi/fribidi.c pango/mini-fribidi/fribidi-tables.i:
+ Some tiny changes to correspond to fribidi-0.15
+
+ * pango.pc.in pango-config.in pango/Makefile.am:
+ Move headers into separate subdir, to avoid
+ clashes with future versions of Pango.
+
+2000-11-20 Tor Lillqvist <tml@iki.fi>
+
+ * Makefile.am (EXTRA_DIST): Add README.win32.
+
+ * examples/pangoft2.aliases: Add this file to CVS.
+
+ * examples/Makefile.am (EXTRA_DIST): Add it here.
+
+2000-11-21 Elliot Lee <sopwith@redhat.com>
+
+ * modules/*/*.c: Fix warnings - mostly include string.h for strcmp.
+
+2000-11-20 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (update_run): Fix this to make iteration
+ over runs work properly
+
+2000-11-19 Tor Lillqvist <tml@iki.fi>
+
+ * README.win32: New file.
+
+ * pango/fonts.c (pango_font_description_to_filename): New
+ function. As pango_font_description_to_string, but with result
+ that is better suitable as a filename: No spaces or other strange
+ characters, all in lowercase.
+ (pango_font_describe): Implement this function, call the
+ corresponding method.
+
+ * pango/pango-font.h: Declare pango_font_description_to_filename.
+
+ * pango/pangowin32.c (pango_win32_font_describe)
+ * pango/pangoft2.c (pango_ft2_font_describe): Implement these.
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_entry_get_coverage)
+ * pango/pangowin32-fontmap.c (pango_win32_font_entry_get_coverage):
+ Implement file-based persistent caching of coverages.
+
+ * pango/pangoft2-private.h (struct _PangoFT2FontEntry)
+ * pango/pangowin32-private.h (struct _PangoWin32FontEntry): Move
+ struct definition here from the -fontmap files.
+
+ * pango/pango.def: Updates.
+
+Fri Nov 17 16:12:34 2000 Owen Taylor <otaylor@redhat.com>
+
+ * Released 0.13
+
+ * NEWS: Updates for 0.13
+
+Fri Nov 17 16:04:19 2000 Owen Taylor <otaylor@redhat.com>
+
+ * tools/Makefile.am (EXTRA_DIST): Add maps/tis-620
+
+ * Makefile.am (EXTRA_DIST): Added TODO.xml
+
+ * pango/Makefile.am (EXTRA_DIST): Add .def files
+ for Win32.
+
+ * examples/Makefile.am (EXTRA_DIST): Add a couple
+ of missing files.
+
+ * docs/Makefile.am (dist-hook): Add back accidentally
+ removed rule to distribute TEXT/*.
+
+Thu Nov 16 18:59:21 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/glyphstring.c (pango_glyph_string_extents_range): Test
+ against start not zero.
+
+Thu Nov 16 13:23:43 2000 Owen Taylor <otaylor@redhat.com>
+
+ * docs/pango-sections.txt docs/tmpl/modules.sgml: Add
+ pango_module_register ().
+
+ * pango/modules.c: Make ordering of module lookup
+ predictable.
+
+ * pango/modules.c (pango_module_register): Add a
+ useful doc comment.
+
+ * pango/pango-modules.[ch]: Fix indentation.
+
+ * .cvsusers: Added
+
+2000-11-16 Havoc Pennington <hp@redhat.com>
+
+ * pango/modules.c (handle_included_module): Declare variable j so
+ it compiles
+
+2000-11-15 Elliot Lee <sopwith@redhat.com>
+
+ * pango/modules.c: Make some vars static.
+ Implement pango_module_register function.
+ * pango/pango-modules.h, pango/modules.h: Move declaration of
+ PangoIncludedModule to pango-modules.h for public use.
+
+Wed Nov 15 16:56:38 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (process_item): Fix problem with
+ unbreakable words at start of line longer than line width.
+
+Wed Nov 15 15:04:00 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_get_extents_internal):
+ Fix problem where right-aligned lines weren't getting properly
+ offset because width was left as -1.
+
+Tue Nov 14 18:45:24 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/shape.c (pango_shape): Every character must
+ be part of some cluster, so when we dont' have an engine
+ at all (pathalogical, happens now for formatting characters),
+ create a cluster with one glyph=0 and 0 size.
+
+Wed Nov 15 10:50:38 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (process_line): Rewrite of good
+ portions of line-break code to be more readable, work
+ better, and maybe even be a little faster.
+
+2000-11-14 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_get_item_properties): get the
+ value of any rise attribute
+ (pango_layout_run_get_extents): take rise into account
+
+2000-11-15 Tor Lillqvist <tml@iki.fi>
+
+ * config.h.win32: Define HAVE_FRIBIDI.
+
+ * pango/pango.def: Add new functions.
+
+ * pango/pango{win32*,ft2*}.[ch]: Add my name to copyright notice.
+
+Tue Nov 14 11:10:24 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_run_get_extents):
+ Fix low underline code to deal with run_ink == NULL.
+
+ * pango/pango-utils.c (pango_read_line): Return number
+ of lines read to allow decent parse errors line numbers.
+
+ * pango/pangox-fontmap.c (pango_x_font_map_read_alias_file):
+ Fix line number count.
+
+ * examples/pangox.aliases: Include extra international fonts
+ for all styles, not just roman, reindent so it looks
+ halfway legible.
+
+Mon Nov 13 14:02:48 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c pango/pango-indic.c: Some doc comment
+ fixes.
+
+2000-11-13 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_get_cursor_pos): Don't need
+ to check_lines, pango_layout_get_iter() will do that
+ (next_cluster_start): don't ever return a value past the end
+ of the glyph string
+
+2000-11-13 Havoc Pennington <hp@redhat.com>
+
+ * examples/pangox.aliases: Add italic/bold variants
+
+2000-11-13 Elliot Lee <sopwith@redhat.com>
+
+ Patches from long ago:
+ * pango/pango-layout.c: Make pango_layout slightly more robust.
+ Do check_lines before getting cursor position.
+
+2000-11-13 Havoc Pennington <hp@redhat.com>
+
+ * docs/pango-sections.txt: Add new PangoLayoutIter entry points
+
+ * pango/glyphstring.c (pango_glyph_string_extents_range): New
+ function
+
+ * pango/pango-layout.c: Create PangoLayoutIter for iterating over
+ a layout's visual elements
+
+ * pango/pango-layout.c (pango_layout_check_lines): plug
+ a memleak (attr iterator not freed)
+
+ * pango/pango-tabs.c (pango_tab_array_free): plug a memleak
+ (array->tabs not freed)
+
+Mon Nov 13 09:17:34 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c: Remove fribidi include.
+
+ * pango.pc.in (Requires): Substitute fribidi reference only
+ when necessary
+
+ * Makefile.am (pkgconfigdir): pkgconfigdir is $(libdir)/pkgconfig
+
+ * modules/indic/Makefile.am (EXTRA_DIST): Add pango-indic-script.h
+
+ * fonts/Makefile.am (EXTRA_DIST): Remove devnag*
+
+ * configure.in: Up version to 0.13
+
+ * docs/pango-docs.sgml: Reorganize, add all new chapters.
+
+ * docs/pango-sections.txt: Update
+
+ * docs/Makefile.am (IGNORE_HFILES): add mini-fribidi
+ pango-intset.h
+
+2000-11-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * pango/pango-attributes.c, pango/pango-attributes.h: Renamed
+ pango_attribute_compare to pango_attribute_equal. Renamed compare
+ member of PangoAttrClass to equal. Renamed some static functions
+ from ..._compare to ..._equal.
+
+ * pango/fonts.c, pango/pango-font.h, pango/pango-context.c:
+ Renamed pango_font_description_compare to
+ pango_font_description_equal.
+
+ * docs/pango-sections.txt, docs/tmpl/fonts.sgml,
+ docs/tmpl/text-attributes.sgml: Changed accordingly.
+
+2000-11-12 Havoc Pennington <hp@pobox.com>
+
+ * pango-config.in: Remove UNICODE_LIBS UNICODE_CFLAGS
+
+ * modules/thai/Makefile.am (pango_thai_la_LIBADD): ditto
+
+ * modules/basic/Makefile.am: ditto
+
+ * pango/Makefile.am: ditto
+
+Mon Nov 13 02:55:38 2000 Robert Brady <robert@suse.co.uk>
+
+ * examples/pangox.aliases: Added
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0, for
+ this comes with X.
+
+Mon Nov 13 02:39:44 2000 Robert Brady <robert@suse.co.uk>
+
+ * pango/modules/hangul/hangul.c: Replace fallback shaper
+ with a call to pango_x_fallback_shape, this sets the
+ cluster array properly.
+
+Sun Nov 12 18:36:38 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (included_modules): Remove checks
+ for iconv - we now depend on g_iconv wrapper defined
+ in GLib.
+
+ * modules/basic/basic.c: Use g_iconv_* not iconv().
+
+ * pango/itemize.c pango/pango-context.c modules/thai/thai.c:
+ Remove spurious iconv.h includes.
+
+Sun Nov 12 16:07:06 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in pango/pango-utils.[ch] pango/Makefile.am
+ pango/mini-fribidi/*: Include a stripped-down version of fribidi
+ to avoid the extra dependency. No fribidi symbols are
+ exported so conflicts with the real fribidi should not
+ happen. Library can optionally be compiled with the
+ real libfribidi.
+
+ * pango/pango-utils.[ch]: Wrappers for
+ fribidi_ functions when compiling with fribiid.
+
+ * modules/basic/basic-ft2.c modules/basic/basic-win32.c
+ modules/basic/basic.c modules/thai/thai.c pango/Makefile.am
+ pango/itemize.c pango/pango-context.c pango/pangoft2.c
+ pango/pangowin32.c pango/pangox.c: Use pango_ versions of fribidi
+ functions.
+
+2000-11-12 Robert Brady <robert@suse.co.uk>
+
+ * pango/pango-indic.c (pango_shift_vowels): Don't corrupt the
+ array.
+
+2000-11-12 Havoc Pennington <hp@pobox.com>
+
+ * pango/pango-layout.c (pango_layout_get_text): Add accessor to
+ get the text from the layout
+
+2000-11-11 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.c (pango_win32_render): Add code to call
+ SetTextAlign, but commented out.
+
+ * pango/makefile.mingw.in (PANGO_OBJS): Add new objects.
+
+ * pango/pango.def: Add new functions.
+
+2000-11-08 Robert Brady <rwb197@zepler.org>
+
+ * pango/fonts/devnag.README: Updated to point to the new fonts
+
+ * examples/HELLO.utf8: Added a few new entries.
+
+ * modules/Makefile.am, configure.in: s/devanagari/indic/
+
+ * modules/devangari: Removed.
+
+ * modules/indic: New shapers for Devanagari,
+ Bengali, Gurmukhi, Gujarati, and Burmese, that make use of
+ the below facilities.
+
+ * pango/fonts/devnag18.bdf: Removed.
+
+ * pango/docs/TEXT/ligatures: Documentation on the ligatures.
+
+ * examples/pangox.aliases: Added fonts for the new Indic renderers
+ to sans, serif and monospace.
+
+ * pango/pangox-fontmap.c, pango/pangox-private.h: Add a
+ per-PangoXFontMap cache for X Atoms.
+
+ * pango/pango-intset.c, pango/pango-intset.h: Integer set.
+
+ * pango/pangox.c, pango/pangox.h: Mainly add two new functions,
+ font_struct_get_ligatures, to parse X font properties for ligature
+ info, and pango_x_apply_ligatures, which does that actual ligation.
+
+ Also add utility functions pango_x_fallback_shaper,
+ pango_x_find_first_subfont.
+
+ * pango/pango-indic.c, pango/pango-indic.h: Utility functions for
+ Indic scripts.
+
+ * pango/Makefile.am: Add pango-intset, pango-indic.
+
+Thu Nov 2 16:21:22 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules/arabic: new version of Arabic shaper from Karl
+ Koehler.
+
+2000-11-01 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-markup.c (pango_parse_markup): Return the accel
+ keyval
+
+2000-11-01 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-markup.c (text_handler): Fix bug where not all text
+ was appended when parsing accelerators
+
+2000-11-01 Pablo Saratxaga <pablo@mandrakesoft.com>
+
+ * modules/thai/thai.c: added aliases for X11 font names used on
+ Solaris
+ * modules/arabic/{arabic,naqshfont}.c: changed X11 font registry from
+ "symbol-0" to "urdunaqsh-0"; using "symbol-0" isn't really usable;
+ you get almost always the bad font...
+
+2000-11-01 Havoc Pennington <hp@pobox.com>
+
+ * pango/pango-attributes.c (pango_attr_scale_new): Add a new
+ attribute for scaling a font; also required adding PangoAttrFloat.
+ (pango_attr_iterator_get_font): Add PANGO_ATTR_SCALE handling.
+
+ * pango/pango-utils.c (pango_parse_stretch): Take a plain string
+ not a GString
+ (pango_parse_weight): ditto
+ (pango_parse_variant): ditto
+ (pango_parse_style): ditto
+
+ * pango/pangox-fontmap.c (pango_x_font_map_read_alias_file): pass
+ GString::str instead of the GString itself to pango_parse_*
+
+ * pango/pangoft2-fontmap.c (pango_ft2_insert_face): ditto
+
+ * pango/pangowin32-fontmap.c
+ (pango_win32_font_map_read_alias_file): ditto
+
+ * pango/pango-layout.c (get_tab_pos): adapt to new pango_itemize()
+ signature
+ (pango_layout_check_lines): Raise attr list copy/creation out of
+ the loop over paragraphs. Adapt to pango_itemize() changes.
+
+ * pango/pango-context.c (pango_itemize): pass in a starting
+ index and a cached iterator
+ (add_engines): Easy optimization, pass in
+ n_chars instead of recomputing it. Also, pass on the start
+ index and cached iterator.
+
+ * docs/pango-sections.txt: Add new stuff
+ docs/pango_markup.sgml: Docs on markup format
+
+ * pango/pango-layout.c (pango_layout_get_attributes): New function
+ to retrieve the AttrList from a layout
+ (pango_layout_set_markup): Set layout from markup
+ (pango_layout_set_markup_with_accel): Set layout from markup
+ including accelerator parsing.
+
+ * pango/pango-attributes.h (pango_parse_markup): New function to
+ convert a tag string to an attribute list
+
+ * pango/pango-markup.c (pango_parse_markup): implement
+
+ * docs/Makefile.am, docs/pango-docs.sgml, docs/pango-sections.txt,
+ docs/pango_markup.sgml: oooooh, documentation for the above patch!
+
+ * docs/tmpl/pango-unused.sgml: Remove from CVS; just causes
+ problems, and was full of checked-in conflict markers.
+
+Tue Sep 12 10:21:08 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules.c (pango_map_get_entry): Added docs
+ for the publically exported functions in this module,
+ even though they are really only semi-public
+ (for people implementing new types of #PangoFont),
+ not public
+
+ * pango/pango-utils.c (pango_read_line): Minor bug
+ tweak.
+
+Sun Oct 29 01:27:39 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-fontcache.c pango/pangoft2.[ch]
+ pango/pangowin32.h: Fix up doc comments not to
+ have obvious errors that gtk-doc barfs on. Correct
+ parameter descriptions still need to be filled in.
+
+ * configure.in pango/docs/Makefile.am: upgrade to
+ have a real install rule, etc.
+
+ * pango/docs/pango-sections.txt: Add various missing
+ functions.
+
+Wed Oct 25 15:39:49 2000 Tim Janik <timj@gtk.org>
+
+ * *.c: adapted g_Type_register_*() calls. GLib wants an additional
+ flag field to specify tape flags per node. added 0s all over the place,
+ making the assumption that no pango types are abstract ones.
+
+2000-10-03 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango.def
+ * pango/pangoft2.def: Add new entry points.
+
+ * pango/pango-coverage.c (pango_coverage_set): Remove unnecessary
+ loop calling memset() with same parameters 64 times ;-)
+
+ * pango/makefile.mingw.in (PANGO_OBJS): Add pango-tabs.o.
+
+ Some small changes that have been laying around on my disk. The
+ Win32 and FT2 backends aren't "production quality" yet. For
+ speedup, need to cache at least the coverage info.
+
+ * pango/pangoft2.c (pango_ft2_get_coverage): New function.
+
+ * modules/basic/basic-win32.c: Use "BasicScriptEngineLangWin32" to
+ be unique.
+
+ * modules/basic/basic-ft2.c: Add comments explaining what Unicode
+ ranges the table entries covers. Use "BasicScriptEngineLangFT2" to
+ be unique.
+ (basic_engine_get_coverage): Test calling
+ pango_ft2_get_coverage().
+ (basic_engine_ft2_new): Set corect engine type. Not that this
+ apparently is used for anything, the X11 basic shaper module also
+ sets its type as TYPE_LANG.
+
+ * examples/viewer-ft2.c (split_paragraphs): Just end the string
+ upon encountering an invalid character. Don't return.
+
+2000-09-29 Martin Baulig <baulig@suse.de>
+
+ * Makefile.am (pkgconfigdir): Set this to `$(libexecdir)/pkgconfig';
+ this is the directory where pkg-config actually looks.
+
+ * *.pc.in: Made the pkg-config scripts actually work.
+
+2000-09-28 Havoc Pennington <hp@pobox.com>
+
+ * pango/pango-tabs.c (pango_tab_array_new_with_positions): was
+ pango_tab_array_new_with_defaults; apparently I didn't check in
+ the modified version at work
+
+2000-09-27 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-tabs.c (pango_tab_array_get_tabs): Change to return
+ allocated array.
+
+2000-09-25 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c: Add a tab array field to PangoLayout,
+ and use it when laying out the text (if it's set, otherwise
+ use default tabs-are-8-spaces thing)
+
+ * pango/pango-tabs.c, pango/pango-tabs.h: tab-related data types
+
+Sun Sep 10 03:01:53 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_attributes): Fix
+ bug where wrong attribute list was unreferenced.
+
+ * pango/pango-attributes.[ch]: Add function
+ pango_attr_list_splice() to splice contents of one
+ attribute list into another attribute list.
+
+ * pango/pango-utils.h: Add include of pango-font.h since
+ it now depends on declarations from there.
+
+2000-09-08 Jonathan Blandford <jrb@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_list_change): Minor fixes
+ to Owen's patch below to make it work.
+
+ * pango/pango-attributes.c (pango_attribute_copy): Copy the
+ start_index/end_index explicitly rather then rely on the copy
+ function doing it for you, as none did so.
+
+Thu Sep 7 05:12:09 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_list_change): Fix up to
+ match the docs, correct bugs found by Jonathan Blandford.
+
+2000-09-04 Robert W Brady <robert@susu.org.uk>
+
+ * modules/basic/tables-big.i: Use iso10646-1 fonts
+ for Georgian, Ethiopic, Cherokee, Canadian, Ogham,
+ Runic.
+
+Thu Aug 31 11:29:33 2000 Owen Taylor <otaylor@redhat.com>
+
+ * tools/maps/tis-620: Check in this file, since it
+ isn't from the Unicode consortium.
+
+Wed Aug 30 21:42:42 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (QTDIR): Add /usr/lib/qt-2.2.0 to the
+ list.
+
+ * modules/basic/tables-big.i: Updated using fixed
+ make-table.sh. Added koi8-r and iso8859-1
+
+ * modules/basic/tables-small.i: Add note noting
+ non-maintainence.
+
+ * tools/make-table.sh: Fix for mapping tables with
+ 3 columns provided by KUSANO Takayuki.
+
+2000-08-29 Elliot Lee <sopwith@redhat.com>
+
+ * pango/pango-context.h, pango/pango-font.h,
+ pango/pango-fontmap.h, pango/pango-layout.h: Utilize G_GNUC_CONST
+
+Mon Aug 21 22:02:38 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (load_font): Don't produce a warning
+ unless loading all fonts fails, if loading all fonts fails,
+ try with "Sans [style]", if that fails, try with "Sans",
+ if that fails, exit - we are completely screwed.
+
+ * pango/pangox-fontmap.c (pango_x_font_map_load_font): Equate
+ PANGO_STYLE_OBLIQUE and PANGO_STYLE_ITALIC, but with a big
+ penalty.
+
+2000-08-21 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangoft2-fontmap.c: Get font directory path with
+ pango_config_key_get("PangoFT2/FontPath"). If no such key exists
+ in the pangorc file, use the ft2fonts subdirectory of
+ LIBDIR/pango, and on Windows, also %WinDir%\fonts.
+
+ * pango/{pango,pangoft2,pangowin32}.rc.in: New files (resource
+ files used when building Win32 DLLs, contain version information).
+
+ * pango/Makefile.am: Add the new files.
+
+ * configure.in: Define major and minor version numbers separately.
+ Output also the makefile.mingw and *.rc files.
+
+ * pango/pangoft2.c (pango_ft2_render): Handle also ft_pixel_mode_mono
+ glyphs.
+
+ * pango/pangoft2*: Portability enhancements (non-gcc).
+
+Sun Aug 20 13:45:08 2000 Owen Taylor <otaylor@redhat.com>
+
+ * TODO.xml TODO: Move most all of the TODO items here to the XML file.
+ This needs to be built using the Python script gtk+/docs/make-todo.
+
+2000-08-20 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango-utils.c (pango_parse_*): Add parameter telling
+ whether to print warning or not if string isn't recognised. Use
+ g_strncasecmp().
+
+ * pango/pango-utils.h: Change prototype accordingly.
+
+ * pango/pangox-fontmap.c
+ * pango/pangowin32-fontmap.c: Change calls correspondingly.
+
+ * pango/pangowin32.h:
+ * pango/pangowin32.c: Cosmetic changes, dead code removal.
+
+ * pango/pangoft2.h
+ * pango/pangoft2-private.h
+ * pango/pangoft2.c
+ * pango/pangoft2-fontmap.c
+ * pango/pangoft2-fontcache.c: New files implementing a FreeType2
+ backend. Used only on Win32 so far, but doesn't contain
+ Win32-specific code per se, so if somebody wants to try it out on
+ X11, too, be my guest.
+
+ It works, more or less, but there are some details still to sort
+ out. Performance needs to be improved. Debugging printouts still
+ present. Font path currently hardcoded to C:\windows\fonts, heh.
+
+ Owen says he doesn't think it's a good idea to use ths on Win32,
+ but I'll try anyway. If it turns out using the native Win32 GDI
+ backend is better after all, oh well.
+
+ * pango/makefile.mingw: Delete. Move contents to
+ makefile.mingw.in.
+
+ * pango/makefile.mingw.in: New file. Add rules for
+ FreeType2 backend. Add FreeType2 CFLAGS and LIBS.
+
+ * pango/Makefile.am: Generate makefile.mingw.
+ (EXTRA_DIST): Add FreeType2 backend sources, and
+ makefile.mingw{,.in}
+
+ * pango/module-defs.c.win32
+ * pango/pangoft2.def: New files.
+
+ * modules/engine.def: Delete. Was duplicate of module.def.
+
+ * modules/basic/basic-win32.c: Couple of cosmetic changes.
+
+ * modules/basic/Makefile.am: Generate makefile.mingw.
+ (EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in}
+
+ * modules/basic/makefile.mingw: Delete. Move contents to
+ makefile.mingw.in.
+
+ * modules/basic/makefile.mingw.in: New file. Add rule for
+ basic-ft2. Add FreeType2 CFLAGS and LIBS.
+
+ * examples/viewer-win32.c: Replace division or multiplication with
+ 1000 (which was the old PANGO_SCALE value) to use PANGO_SCALE and
+ PANGO_PIXELS instead.
+ (read_file): Fix error messages.
+ (draw): Get HDC from GDK once for all paragraphs.
+ * examples/viewer-win32.c:
+
+ * examples/viewer-ft2.c: New file. The FT_Bitmap (256-level
+ bitmap) produced by the FreeType2 backend is copied to the
+ GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes,
+ this is kinda circular dependency between Pango and GTK+.
+
+ * examples/makefile.mingw: Delete. Move contents to
+ makefile.mingw.in.
+
+ * examples/makefile.mingw.in: New file. Add rules for
+ viewer-ft2. Add FreeType2 CFLAGS and LIBS.
+
+ * examples/Makefile.am: Generate makefile.mingw.
+ (EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and
+ makefile.mingw{,.in}
+
+2000-08-11 Havoc Pennington <hp@redhat.com>
+
+ * pangox.pc.in (Cflags): remove /usr/include
+
+ * pango.pc.in (Cflags): remove /usr/include
+
+2000-08-08 Elliot Lee <sopwith@redhat.com>
+
+ * modules/arabic/arabic.c: #include <string.h>
+ * pango/modules.c: Fix incorrect list rearrangement.
+ * pango/pango-layout.c (pango_layout_line_x_to_index): Pay
+ attention to shape attributes
+ (not perfect since the layout of chars inside a shape is
+ unknown, but gives start index).
+
+2000-08-07 Elliot Lee <sopwith@redhat.com>
+
+ * pango/modules.c: If the first pango_skip_space fails, remember
+ to free enginepair before continuing.
+ * pango/pango-layout.c (pango_layout_set_attributes): unref old
+ attr list after reffing new one.
+ * pango/pango-attributes.c (pango_attr_list_insert_internal):
+ Proper fix from Owen for the infinite loop.
+
+2000-08-03 Elliot Lee <sopwith@redhat.com>
+
+ * pango/modules.c: Fix segfault when tmp_list has no 'prev' pointer.
+ * pango/pango-attributes.c (pango_attr_list_insert_internal):
+ Infinite loops do not fast programs make.
+ * pango/pango-context.c: Set a default font size so that things
+ don't go boom if someone forgets to set it themselves.
+ * pango/pango-layout.c (pango_layout_index_to_pos): Exclude
+ newlines from consideration.
+ (pango_layout_line_index_to_x): Take shape attributes into
+ consideration when determining position.
+
+Wed Aug 2 12:00:53 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_get_extents):
+ Fix problem with the way extents for the layout lines
+ were summed together in the vertical direction.
+
+Sat Jul 29 21:26:30 2000 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer-qt.[ch] (ViewerWindow): Remove
+ hardcoded path to my home directory! Allow specifying
+ the file on the command line.
+
+ * pango/modules.c (process_module_file): Fix bug in
+ parsing of range strings.
+
+2000-07-31 Havoc Pennington <hp@redhat.com>
+
+ * pango.pc.in, pangox.pc.in: pkg-config info files
+
+ * Makefile.am: dist/install .pc files
+
+ * configure.in: output .pc files
+
+2000-07-28 Martin Baulig <baulig@suse.de>
+
+ * pango/pango-layout.c (pango_layout_finalize): Destroy
+ the layout->font_desc to avoid a memory leak.
+
+2000-07-27 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango.def
+ * pango/pangowin32.def: New files, forgot to commit earlier.
+
+Sat Jul 22 10:52:06 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c: include <stdlib.h>
+
+ * configure.in: s/FRIBID_CONFIG/FRIBIDI_CONFIG/.
+
+Fri Jul 21 15:17:26 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (pango_itemize): A bit of code
+ cleanup.
+
+ * pango/pango-attributes.[ch]: Add a new attribute type
+ PangoAttrShape, for imposing specific shapes on glyphs.
+ This is used for handling embedded pixmaps and similar
+ objects.
+
+ * pango/pango-layout.c: Hnadle PangoAttrShape.
+
+ * pango/pango-context.[ch]:
+
+Fri Jul 21 09:59:10 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules.c (process_module_file): Free buffer strings.
+
+ * pango/pangox-fontmap.c (pango_x_real_get_coverage_win): Add
+ caching of coverage maps on a persistant subwindow of the
+ root window. This window contains a property for
+ each "lang|xlfd,xlfd" which is the result of pango_coverage_to_bytes.
+
+ * pango/pango-context.c (pango_context_finalize): Free
+ the font description.
+
+ * pango/pango-coverage.c (pango_coverage_to/from_bytes): Added
+ functions to covert a PangoCoverage structure too and
+ from a flat block of bytes.
+
+ * configure.in (X_LIBS): Add a check to detect fribidi being
+ compiled against glib-1.2.x.
+
+2000-07-20 Tor Lillqvist <tml@iki.fi>
+
+ * examples/pangowin32.aliases: Add some more fonts. Document where
+ to get the fonts.
+
+ * pango/pangowin32.c (subfont_has_glyph): Use 0xFFFE to produce
+ the default glyph.
+ (create_bitmap_dibsection): Zero out the bitmap.
+
+ * pango/pangowin32-fontmap.c (pango_win32_guess_subranges): Set
+ some additional Unicode subranges for fonts that claim covering
+ the Vietnamese codepage.
+
+2000-07-19 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Don't try to use the ! command, not available in all
+ systems. Move the ! inside the test instead.
+
+ * pango-config.in: Change order of --cflags output, so that we can
+ build with both GLib 1.2 and 1.3 installed.
+
+ * modules/devanagari/dev-ligatures.h: No C++ comments, thanks.
+
+ * pango/break.c: Fix gccism, non-constant initailiser.
+
+ * pango/pango-fontmap.c (pango_font_map_list_fonts,
+ pango_font_map_list_families): Don't return value from void
+ functions.
+
+ * pango/pango-utils.c: Must have at least empty statement after
+ a label.
+
+ * examples/pangowin32.aliases: Add Tahoma and Angsana New, these
+ common fonts have Thai characters.
+
+ * pango/pangowin32-private.h: Rename fonts and n_fonts members
+ to logfonts and n_logfonts, as that is what they are.
+
+ * pango/pangowin32.c: Bug fixes. Works much better now.
+ (pango_win32_font_get_glyph_extents): Set y offset correctly.
+ (subfont_has_glyph): Call SetTextAlign. Select the font into the
+ HDC before calling GetTextMetrics.
+
+2000-07-18 Tor Lillqvist <tml@iki.fi>
+
+ * pango/Makefile.am (EXTRA_DIST): Add the pangowin32 sources.
+
+ * pango/pangox.c (lang_texts): Add some non-ASCII to the
+ Finnish and Swedish strings.
+
+ * modules/module.def: New file.
+
+ * modules/Makefile.am (EXTRA_DIST): Add it.
+
+ * modules/basic/Makefile.am (EXTRA_DIST): Add basic-win32.c.
+
+ * */makefile.mingw: Small updates.
+
+ * pango/pangowin32.c
+ * pango/pangowin32-fontmap.c
+ * modules/basic/basic-win32.c
+ * examples/viewer-win32.c: Bug fixes. Remove dead code.
+ Now the Win32 implementation seems to work, except
+ for a few glitches.
+
+2000-07-16 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c
+ * pango/pangox-fontmap.c
+ * pango/pangowin32-fontmap.c: Move the get_{style,variant,
+ weight,stretch} functions to pango-utils.c, and rename
+ them to pango_parse_*. Would otherwise be duplicated in
+ pangox and angowin32.
+
+ * pango/pango.def: Export them.
+
+ * pango/pango-font.h: Add PANGO_WEIGHT_ULTRALIGHT,
+ PANGO_WEIGHT_LIGHT, PANGO_WEIGHT_EXTRABOLD and PANGO_WEIGHT_HEAVY
+ values to PangoWeight.
+ * pango/pango-utils.c: Recognize the new weight strings.
+
+ * pango/pangowin32.c (pango_win32_list_subfonts): Don't g_free the
+ subfont_list from the subfonts_by_subrange hash table...
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_read_alias_file):
+ Also set the other properties in the LOGFONT, not only the face name.
+
+ (pango_win32_insert_font): Insert a pointer to a freshly allocated
+ LOGFONT in the hash table, not the one passed in as a parameter,
+ which could be (and in fact, *is*) a pointer to an auto
+ variable. Quantize the description weight values to exact
+ PANGO_WEIGHT_* values.
+ (pango_win32_get_unknown_glyph): Use subfont 1.
+
+ * examples/viewer-win32.c: (split_paragraphs): Don't include the
+ newline.
+ (draw): Correct 1st parameter to gdk_win32_hdc_{get,release}.
+
+2000-07-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.h
+ * pango/pangowin32-private.h
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * pango/makefile.mingw
+ * modules/basic/basic-win32.c
+ * modules/basic/makefile.mingw
+ * examples/viewer-win32.c
+ * examples/makefile.mingw
+ * examples/pangowin32.aliases: New files. Start of a Win32
+ implementation. Does not work yet.
+
+ * configure.in: Chek for dirent.h and unistd.h.
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): New functions, for better
+ portability, to enable installation-time choice of directory (on
+ Windows) instead of compile-time. Use these instead of SYSCONFDIR
+ "/pango" and LIBDIR "/pango".
+
+ (pango_split_file_list): Fix comment, the function splits on
+ searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
+ for portability. Don't try to expand '~' as home directory on
+ Windows.
+
+ (read_config): Use pango_get_sysconf_subdirectory().
+
+ * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
+ Don't crash if a module file cannot be opened.
+
+ * pango/querymodules.c: Include config.h Conditionalize inclusion
+ of dirent.h and unistd.h. Use platform-specific shared library
+ extension. Use pango_get_lib_subdirectory().
+
+Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
+
+ * Released 0.12
+
+ * examples/pangox.aliases: Add clealyu fonts
+
+ * configure.in: Use AM_PATH_GLIB_2_0()
+
+ * pango-config.in: Use @FRIBIDI_LIBS@, not -lfribidi
+
+ * pango-config.in: Fix accidental inclusion
+ -I lib/glib/include/
+
+Mon Jul 10 10:42:42 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c (pango_split_file_list): Fix
+ bug in home directory substitution.
+
+2000-07-06 Havoc Pennington <hp@redhat.com>
+
+ * pango/break.c (pango_get_log_attrs): Implement this function, to
+ get logical attributes without a PangoAnalysis.
+ (pango_break): Fix bug in word stop location
+
+Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/Makefile.am: Fix missing \ which was causing
+ srcdir != builddir builds to fail.
+
+Thu Jul 6 15:16:28 2000 Owen Taylor <otaylor@redhat.com>
+
+ * docs/pango-sections.txt docs/tmpl/*: Update
+
+2000-07-03 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_index_to_pos): Handle the
+ case where the byte offset is outside the layout.
+
+Sun Jul 2 18:06:01 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (get_tab_pos): Fix up set_font_description()
+ for tab spaces.
+
+Sun Jul 2 17:59:56 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.[ch] (pango_attr_list_insert_before): New
+ function that inserts before other attributes with matching
+ start index.
+
+ * pango/pango-layout.[ch] (pango_layout_set_font_description): Add
+ the ability to set a default font description on the layout, overriding
+ the font description from the context.
+
+Sun Jul 2 17:19:11 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-types.h: Add a PANGO_PIXELS macro to convert
+ from pango units to device units and round.
+
+ * pango/pango-layout.[ch]: Add convenience functions
+ pango_layout_get_pixel_extents, pango_layout_get_size,
+ pango_layout_get_pixel_size pango_layout_line_get_pixel_extents.
+
+Fri Jun 30 16:46:31 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.[ch] Makefile.am: A bunch of simple functions
+ for reading from files, manipulating strings as necessary for
+ config files. Also, a simple gnome-config/win.ini style
+ config file reader.
+
+ * pango/modules.c: Remove DOTFILES stuff. Instead, read names
+ of modules file from pangorc. (Which can be set from PANGO_RC_FILE).
+ Rewrite parsing code using pango-utils.c.
+
+ * pango/pangox-fontmap.c: Read list of files from
+ PangoX/AliasFiles key. Rewrite parsing code for alias files using
+ pango-utils.c.
+
+ * examples/pangox.aliases: Move to new name from pangox_aliases,
+ reformat using new parsing code.
+
+ * examples/pangorc (AliasFiles) examples/pango-viewer: Add a
+ pangorc file for in-place testing.
+
+ * pango/querymodules.c (main): Add comment to the top of
+ the output indicating that the file should not be hand-edited.
+
+Thu Jun 29 18:13:47 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-coverage.c: Fix various aspects of expanding
+ coverage tables beyond the first 256 blocks. (Based on
+ patch from ChiDeok Hwang.)
+
+Thu Jun 29 16:35:41 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/{*.c,Makefile.am}: New version from Karl
+ Koehler merged with the changes for the GLib unicode functions.
+
+Wed Jun 21 12:11:56 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Remove tests for libunicode
+
+ * pango/utils.[ch]: Removed. The functions from here are now in
+ GLib.
+
+ * **.[ch]: Removed use of libunicode and utils.c in favor of
+ Unicode functions in GLib. Requires latest GLib from CVS.
+
+2000-06-14 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_list_copy): Function to
+ copy the attribute list.
+
+2000-06-13 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-layout.h: Convert PangoLayout to GObject
+
+ * pango/pango-context.h: Convert to PangoContext to GObject
+
+2000-06-11 Elliot Lee <sopwith@redhat.com>
+
+ * pango/fonts.c (pango_font_description_compare): g_strcasecmp
+ returns 0 when strings are equal - negate return value.
+
+2000-06-09 Elliot Lee <sopwith@redhat.com>
+
+ * pango/pango-coverage.[ch]: Return 'coverage' from
+ pango_coverage_ref.
+
+2000-06-08 Elliot Lee <sopwith@redhat.com>
+
+ * modules/Makefile.am: Add DOTMODULESDIR define to make it easier
+ to change location of .modules files.
+ * pango/modules.c: Likewise. Also scan the config directory for
+ multiple config files instead of pango.modules. Also fclose()
+ opened files.
+
+Thu Jun 8 14:43:35 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-modules.h: pango/Makefile.am: Add a new
+ header pango-modules.h to export a few parts of the
+ modules API needed by code for new types of fonts.
+
+2000-06-08 Elliot Lee <sopwith@redhat.com>
+
+ * pango-config.in: Include X_LIBS in libraries for 'pangox' target.
+
+2000-06-07 Havoc Pennington <hp@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_iterator_copy): New
+ function to copy a PangoAttrIterator.
+
+Mon Jun 5 20:45:12 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox-fontmap.c (pango_x_shutdown_display): Add
+ a function to free cached information for a particular
+ display. (This is basically pango_x_fontmap_destroy())
+
+ * pango/pangox.c pango/pangox-private.h pango/pangox-fontmap.c:
+ Make a XFont always keep a pointer to (and ref) a fontmap.
+
+Mon Jun 5 15:56:25 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox-fontmap.c (pango_x_font_map_for_display): Remove
+ excessive ref.
+
+ * pango/pangox-fontcache.c (pango_x_font_cache_unload): Fix
+ problem with unloading fonts.
+
+ * pango/pangox-fontmap.c pango/pangox-private.h pangox/pangox.c:
+ Add a simple cache for PangoXFonts; get rid of the eternal caching of
+ all fonts.
+
+Wed May 31 16:11:46 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-fontmap.h (struct _PangoFontMapClass): Remove unused
+ destroy vfunc.
+
+Sat Jun 3 06:01:38 Pablo Saratxaga <pablo@mandrakesoft.com>
+
+ * modules/thai/thai.c: added other common X11 font encoding
+ names fortis-620 fonts.
+
+Thu Jun 1 13:04:06 CEST 2000 Paolo Molaro <lupus@debian.org>
+
+ * configure.in: look for qt also in /usr/lib/qt2.
+
+Wed May 31 10:46:53 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Release 0.11
+
+ * pango.spec.in: Add missing make command.
+
+ * modules/basic/Makefile.am (EXTRA_DIST): Fix up extra-dist.
+
+ * pango/Makefile.am (libpangox_la_SOURCES): Add pangox-private.h
+
+Tue May 30 14:30:24 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_from_string): Use g_strtod().
+
+ * pango/fonts.c (pango_font_description_to_string): Fix bug
+ where spaces where not properly inserted into font description
+ string.
+
+ * pango/fonts.c (pango_font_get_glyph_extents): Fix some
+ 1000 <=> PANGO_SCALE bugs.
+
+ * pango/pangox-fontcache.c (pango_x_font_cache_load): Fix list
+ manipulation bug.
+
+Mon May 29 13:22:36 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c pango/pangox.h (pango_x_font_subfont_xlfd): New
+ function to retrieve the XLFD for a given subfont.
+
+Mon May 29 11:14:34 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox-fontcache.c (pango_x_font_cache_load): Fix bug
+ in MRU list code.
+
+ * pango/pango-layout.c (pango_layout_check_lines): Fix infinite
+ loop in the case where the first item doesn't fit, but
+ whitespace follows that must go onto the same line.
+
+ * examples/viewer-qt.h: Minor changes so it compiles with
+ Qt-2.0. (Though the utf8 codec in Qt-2.0 seems to be slightly
+ buggy.)
+
+Sun May 28 16:24:43 2000 Owen Taylor <otaylor@redhat.com>
+
+ * examples/Makefile.am examples/viewer-qt.cc
+ examples/viewer-qt.h: Since we require GLib-1.3,
+ and thus can no longer build the examples against
+ GTK+-1.2, and since there is a nasty circular dependency
+ if we build examples against GTK+-1.3, rewrite
+ (optional) example program in Qt. (I wasn't going
+ to do it in Xaw or straight Xlib...)
+
+ * configure.in: Added checks for Qt.
+
+ * pango/pango-layout.h: Fix constness.
+
+Sat May 27 22:05:53 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (pangoinclude_HEADERS): Install
+ pango-fontmap.h.
+
+ * pango/pangox-fontcache.c pango/pangox.h: Add a simple
+ cache from XLFD => font struct.
+
+ * pango/pango-fontmap.c: Use this when loading and unloading
+ fonts.
+
+Sat May 27 21:57:03 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (pango_context_add_font_map):
+ Ref font map.
+
+Sat May 27 21:06:13 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/thai/thai.c modules/basic/basic:
+ s/pango_font_set_data/g_object_set_qdata/
+
+ * pango/*.c: s/pango_font_[un]ref/g_object_un[ref]
+
+ * pango/pango-font.h fonts.c: GObject'ify PangoFont.
+
+Sat May 27 20:36:56 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am configure.in: Add libgobject.
+
+ * pango/pango-fontmap.[ch]: GObject'ify PangoFontMap.
+ (Pango now requires GLib-1.3 to compile)
+
+ * pango/pangox-fontmap.c pango/pangox-private.h: Break
+ the fontmap code in libpangox out into a separate file.
+
+Tue May 23 10:32:25 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_text): Allow -1 for
+ the length.
+
+2000-05-24 Matt Wilson <msw@redhat.com>
+
+ * modules/basic/basic.c (conv_8bit): use size_t for arguments to
+ iconv, not int. Fixes 64 bit platforms.
+
+ * modules/basic/basic.c (conv_euc): likewise
+
+Mon May 22 18:19:32 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (process_item): Fix <, <= confusion.
+
+Thu May 18 17:30:00 2000 Robert Brady <rwb197@zepler.org>
+
+ * fonts/devnag18.bdf: Fix advance widths of some glyphs.
+
+Tue May 9 22:09:42 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-types.h (PANGO_SCALE): Change PANGO_SCALE
+ from 1000 to 1024. Wee! Optimization! Actual performance
+ increase is ~1-2% probably not worth keeping it 1024,
+ but I'll leave it this way for a little bit.
+
+ * pango/pango-layout.c (pango_layout_unref): Free the
+ actual layout structure as well.
+
+ * pango/pangox.c: Various optimizations of the code for
+ looking up characters. (mark a few functions inline,
+ precompute signficiant quantities)
+
+Tue May 9 03:22:11 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_check_lines): Fix
+ memory leak by freeing correct list.
+
+ * pango/pango-context.c (pango_context_get_font_description):
+ Change to return a pointer to the context's font description
+ instead of a copy. Not quite 100% kosher but a lot
+ more efficient than the previous. (Should we just refcount
+ font descriptions and get it over with?)
+
+Mon May 8 16:39:48 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (free_run): Call pango_item_free
+ to free items properly including attributes.
+
+Mon May 8 16:19:22 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/thai/* modules/Makefile.am configure.in:
+ Add a simple Thai shaper. (Reasonably complete but
+ intended mostly for an example for the shape docs
+ right now.)
+
+ * pango/pangox.h (PANGO_X_GLYPH_INDEX): Protect
+ arguments to macros.
+
+Sun May 7 06:15:34 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic.c (basic_engine_shape): When
+ handling overstrikes, try to guess a bit better
+ how overstrike glyphs are positioned in the font.
+ (Now works with more of glyphs from clearlyu, though
+ not the Hebrew accents in that font)
+
+ * examples/HELLO.utf8: Insert tab characters to
+ keep the columns in the right order for either
+ global direction. Insert left-to-right marks in
+ a few places to keep leading and trailing punctuation
+ in the right place.
+
+ * modules/basic/basic.c (basic_engine_shape): Don't
+ show RLM and LRM
+
+ * pango/glyphstring.c (pango_glyph_string_extents): Use
+ the logical width set in the glyph string rather than
+ that from the font's metrics.
+
+ * pango/pangox.c (pango_x_render): Treat glyph index
+ 0 as special - representing invisible, 0 size
+ character. We need this sometimes, and it is
+ easier and faster to have this special case
+ than to shape a space.
+
+ * pango/pango-context.c (pango_itemize): Put
+ tabs into separate items. (Sort of lame hack,
+ we do this to make line breaking with tab
+ handling simpler)
+
+ * examples/viewer.c (checkbutton_toggled): Notify
+ all the layouts that the context has changed so
+ the RTL base dir change actually takes effect.
+
+Fri May 5 18:56:45 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/break.c (pango_break): Add ZWS to hacky
+ break algorithm.
+
+ * modules/basic/basic.c (basic_engine_shape): Special
+ case zero-width-space as a temporary hack. (What's the
+ right solution?)
+
+ * modules/basic/tables-big.i: Added support for TIS-620
+ encoding.
+
+ * configure.in pango/modules.[ch] pango/Makefile.am
+ modules/**: First stab at support for linking modules
+ directly into Pango. Add a --with-included-modules=
+ flag that causes the specified modules to be built
+ as convenience libraries and linked directly into
+ libpangox.
+
+Tue May 2 22:59:52 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic.c: Get rid of link list of masks
+ in cache structure in favor of an array. (This is
+ easy to do now since we already have linear indices
+ for the masks from the new table format.)
+
+ * pango/modules.c pango/pango-context.c pango/pangox.c:
+ Modify _pango_find_map() to take quarks for the
+ engine type and render type instead of strings.
+ Get rid of the map hash table in favor of a GList
+ with the most recently used map at the beginning.
+
+ * pango/modules.[ch] pango/pango-context.c pango/pangox.c:
+ Add some utility functions for getting the engine
+ for a particular character in a map. Using modules.c
+ knowledge of map structure, this allows us to save
+ a bunch of useless strcmps.
+
+ * pango/pango-context.c (add_engines): Remove unused
+ lookup of shape mask.
+
+ * modules/basic/tables-{small,big}.i modules/basic/basic.c
+ tools/compress-table.pl: Reencode mask table to avoid binary
+ searches and save a bit of space.
+
+ * modules/basic/basic.c (find_converter): Get rid
+ of gratuitous use of hash tables for looking up
+ iconv converters.
+
+ * modules/basic/tables-{small,big}.i modules/basic/basic.c:
+ Use conv_ucs4 instead of conv_8bit for latin-1.
+
+ * pango/pango-layout.c: Avoid calling pango_glyph_string_extents() -
+ just add up the widths from shaping.
+
+Tue May 2 19:16:17 PDT 2000 Manish Singh <yosh@gimp.org>
+
+ * examples/Makefile.am: typo fix
+
+Mon May 1 15:04:02 PDT 2000 Manish Singh <yosh@gimp.org>
+
+ * configure.in: add support for fribidi-config (needs fribidi v0.1.10
+ or higher). Also actually use the FOO_CONFIG variable filled by
+ AC_PATH_PROG for --cflags and --libs.
+
+ * examples/Makefile.am
+ * pango/Makefile.am: use $(FRIBIDI_LIBS)
+
+Mon May 1 11:58:55 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/*: Misc bug fixes from Karl Koehler.
+
+Wed Apr 26 19:55:40 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Add checks looking for iconv in libiconv.
+ (Thanks to Ross Campbell for helping me test this
+ out.)
+
+Mon Apr 24 22:51:06 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Released 0.10
+
+ * modules/arabic/*: Update from Karl Koehler, including
+ support for LangBox fonts
+
+Mon Apr 24 20:28:31 2000 Owen Taylor <otaylor@redhat.com>
+
+ * docs/**: Updates for recent API changes.
+
+Mon Apr 24 18:09:29 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_line_get_empty_extents): Come
+ up with a reasonable guess for metrics for empty lines based
+ on the font metrics.
+
+ * modules/devanagari/devanagari.c (devanagari_engine_shape): A couple
+ of trivial fixups to make things compile.
+
+Sun Apr 23 23:33:10 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually): New
+ function for visual (left-right, not forward-back) cursor
+ navigation within a layout.
+
+Thu Apr 20 22:16:39 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_line_x_to_index): As a hack,
+ for x-positions at the edge of a line, fudge the position to be
+ one before the line end (which is, for programs that don't properly
+ handle the trailing flag), instead of at the end of the line.
+ This works fine for whitespace-broken languages, but won't work
+ right for languages that don't use whitespace to break lines.
+ (GtkText* needs to keep track of whether a cursor is trailing
+ or not)
+
+ * pango/pango-layout.c (pango_layout_check_lines): Prohibit breaking
+ a line at a non-whitespace -> space transition. (So that we
+ never put wrap single character of whitespace at the beginning of
+ a line)
+
+ * pango/break.c (pango_break): Always allow a break before
+ the first char.
+
+ * pango/pango-layout.c (pango_layout_line_x_to_index): Remove the return
+ value from the function, make it return the appropriate index
+ depending on the base direction of the layoutt.
+
+Fri Apr 7 03:08:09 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in (UNICODE_LIBS): Add back in flockfile
+ check which was accidentally removed.
+
+2000-04-21 Robert Brady <rwb197@zepler.org>
+
+ * modules/devanagari/dev-ligatures.h: Add some more ligature
+ mappings.
+
+ * modules/devanagari.c: New version, now syllable-based, with
+ proper RA handling.
+
+Mon Apr 17 12:04:20 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.[ch]: Add a function pango_layout_line_get_x_ranges(),
+ to allow handling selections not as attributes. Which is necessary,
+ since currently setting the background/foreground results in
+ splitting shaped runs.
+
+Fri Apr 14 13:20:05 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_check_lines): Fix bug with
+ indent handling.
+
+ * pango/pango-layout.c (process_item): Never break a line at
+ a non-break position, even if that position ends an item.
+
+Fri Apr 14 10:43:09 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c (pango_x_render_layout_line): Fix a missing
+ PANGO_SCALE factor for UNDERLINE_SINGLE.
+
+ * pango/pango-layout.c (pango_layout_get_cursor_pos): New function
+ to determine cursor positions corresponding to a particular
+ index.
+
+Wed Apr 12 15:44:22 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.[ch]: Add PANGO_ATTR_FONT_DESC, which
+ allows an entire font description to be specified as a single
+ attribute, instead of as 6 separate attributes.
+
+Wed Apr 12 13:59:22 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in modules/Makefile.am modules/devanagari/*: Added Devanagari
+ shaper from Robert Brady <rwb197@zepler.org>
+
+ * examples/HELLO.utf8: Added Hindi from Emacs
+
+ * examples/dev-example.utf: Some syllable strings for testing
+ the Devanagari shaper.
+
+ * examples/pangox_aliases: Added
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev
+
+ * fonts/devnag18.bdf fonts/devnag.README: Devanagari font
+ from http://crl.NMSU.Edu/~mleisher/devnag.html currently
+ required for operation of the devanagari shaper.
+
+Tue Apr 4 22:03:42 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Released 0.9
+
+ * modules/arabic/arabic.c (find_unic_font): Keep on
+ searching past the first iso-10646 font if the first
+ font doesn't have the required ligatures.
+
+Tue Apr 4 20:56:29 2000 Owen Taylor <otaylor@redhat.com>
+
+ * docs/tmpl/* docs/Makefile.am docs/pango-sections.txt
+ pango/pango-attributes.c pango/pangox.c: Doc updates.
+
+Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.h: Add user data to PangoContext
+
+ * pango/pangox.[ch] examples/viewer.c: Rework system for create GC's
+ so that the necessary information is stored on the PangoContext
+ instead of being passed to layout_render()
+
+ * pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9
+ wants UCS-4 not UCS2; switch accordingly.
+
+ * pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions
+ to get overall font metrics, possibly per-language. (Right now,
+ just font ascent, descent.) The implementation of this for
+ X is horribly complex.
+
+Mon Apr 3 20:30:20 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mapping.c (pango_glyph_string_x_to_index): Fix handling
+ of positions at character limits.
+
+ * modules/basic/basic.c (basic_engine_shape): Fix bug that
+ was causing mirrored characters not to mirror.
+
+Mon Apr 3 15:16:06 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/glyphstring.c (pango_glyph_string_get_logical_widths):
+ Fix off-by-one error for RTL runs.
+
+ * configure.in: Add -lglib to AC_CHECK_LIB(fribidi...)
+ (How did this work?) From Matt Wilson.
+
+ * pango/pango-layout.c (pango_layout_check_lines): Correctly deal
+ with handling character offsets when breaking lines.
+
+ * modules/arabic/arabic.c (arabic_engine_shape): Fix problem with
+ setting unknown glyph when no arabic-capable font found.
+
+Fri Mar 31 11:29:47 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.[ch] (pango_x_render_layout[_line]) examples/viewer.c: Add
+ capability to render foreground / background colors. The interfaces
+ here are possibly certainly not right, or convenient, but
+ they should be a start.
+
+Thu Mar 30 17:06:39 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/*.[ch]: New version of Arabic module
+ from Karl Koehler, supporting:
+
+ - More extensive ligatures
+ - Some Hamza handling
+ - Vowel marks
+ - mule-arabic font
+ - LangBox font
+ - Persian (farsi) (needs testing)
+
+Thu Mar 30 16:49:06 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic.c pango/utils.c (find_converter): Use
+ "UTF-8" with the dash as the charset name for utf-8.
+ (Change suggested by Adrian Havill <havill@turbolinux.co.jp>)
+
+ * pango/pango-layout.[ch]: Add function to get logical attributes
+ of the text string.
+
+Mon Mar 13 11:47:53 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c pango/pangox.c (pango_x_render_layout): Handle right
+ alignment for width == -1, align within total width of layout.
+
+Mon Mar 13 10:54:48 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-item.[ch]: Memory management functions for PangoItem.
+
+ * pango/*.[ch]: Random constification.
+
+ * pango/pangox.c pango/pango-layout.c pango/pango-context.c:
+ Add an extra_attrs field to PangoItem. Use this to handle underlining
+ for PangoLayout.
+
+ * examples/viewer.c (reload_font): Make paragraphs global
+ to save the complexity of passing it around all over the place.
+
+ * pango/pango-layout.[ch] (pango_layout_context_changed): Add
+ a function to reset the layout on changes to the layout's
+ context.
+
+ * pango/pangox.c (pango_x_make_matching_xlfd): Prefer bitmap
+ to scaleable if the discrepancy is < 1 pixel. (Probably not
+ the ideal criterion.)
+
+ * pango/pangox.c (pango_x_font_map_for_display): Fix resolution
+ computation error.
+
+ * pango/pango-layout.c (pango_layout_check_lines): Handle
+ text with embedded newlines.
+
+ * pango/pangox.c (pango_x_render_layout): Fix y to refer
+ to the top of the layout, not the baseline of the first
+ line.
+
+ * pango/pango-layout.c (process_item): Don't wrap if width is
+ set to -1.
+
+ * Makefile.am configure.in **/*.[ch]: move libpango/ directory
+ and fix all headers to install under include/pango/
+
+Thu Mar 9 19:55:21 2000 Owen Taylor <otaylor@redhat.com>
+
+ * Release pango-0.8
+
+ * docs/TEXT/coding-style: Added some notes about coding style
+ within Pango.
+
+ * modules/*.[ch]: New version from Karl Koehler adding support
+ for vowels marks, better ligatures.
+
+ * docs/tmpl/*: Doc updates
+
+ * libpango/pango-layout.[ch] libpango/pangox/.[ch]: Add functions
+ for handling paragraphs as 2-D objects, not simple lists of lines,
+ to make things easier for people using pango-layout.
+
+ * examples/viewer.c: Simplify using the now 2-D layout-capabable
+ PangoLayout.
+
+ * libpango/fonts.c (pango_font_{get_coverage,find_shaper}): Allow
+ NULL language tag.
+
+ * libpango/modules.c (_pango_find_map): Fix for allowing
+ NULL language tag.
+
+Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pango-layout.[ch]: First draft of highlevel
+ driver. It currently only handles a paragraph as a list
+ of lines, but it is probably necessary to make it handle
+ 2D layout for a paragraph as well
+
+ * examples/viewer.c: Move over to new layout driver
+ (much of the code moved into pango-layout.c)
+
+ * libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(),
+ add pango_glyph_string_get_logical_widths.
+
+ * libpango/pango-itemize.c: Handle 0-length text properly.
+
+ * libpango/pangox.c: When loading particular sized fonts,
+ use the original XLFD, since XFree86 doesn't handle wildcards
+ in aliases properly.
+
+ * libpango/pangox.[ch] (pango_x_render_layout_line): Add function
+ to render an entire PangoLayoutLine.
+
+ * libpango/reorder-items.c: Add a note to the effect
+ that pango_reorder_items() is basically replaced by a
+ similar function in PangoLayout.
+
+Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/arconv.c (shapecount): Fix from Karl
+ Koehler to joining behavior.
+
+ * modules/Makefile.am modules/arabic/*: Added arabic
+ shaper from Karl Koehler <koehler@or.uni-bonn.de>
+
+ * modules/basic/tables-{small,big}.i: Remove arabic
+ from the ranges that the basic shaper marks as "exact".
+
+ * examples/HELLO.utf8: Partially alphabetize, add arabic.
+
+Mon Mar 6 21:03:28 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pango-layout.[ch]: Started work on highlevel layout driver.
+
+Mon Mar 6 20:55:32 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/mapping.c example/viewer.c:
+ * modules/hangul/hangul.c modules/basic/basic.c modules/tamil/tamil.c:
+
+ Convert log_clusters[] use from char offsets to byte offset - should
+ make it easier to have all interface deal with stuff in byte offsets.
+
+ * libpango/mapping.c libpango/pango-glyph.h: Rename x_to_cp and cp_to_x
+ to make them "member functions" of glyph_string.
+
+ * libpango/pango-types.h: Add a rectangle type for use in storing
+ glyph/glyph-string extents, plus macros for extracting ascent/descent.
+
+ * libpango/fonts.c libpango/pango-font.h libpango/pangox.c: Virtualize
+ glyph extents function into the font.
+
+ * libpango/pangox.c modules/*/*.c examples/viewer.c: Convert over to
+ new rationalized unit system - everything in 1000ths of a point
+ or 1000ths of a glyph unit.
+
+ * libpango/pango-glyph.h libpango/glyphstring.c: Add function to get
+ extents of a glyph string. (We may want to fastpath the width in
+ the future, since getting the width seems to be a very common
+ and time-critical operation)
+
+Mon Feb 28 19:46:35 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/fonts.c libpango/pango-fonts.h: Add functions
+ to convert font descriptions to and from human-readable
+ strings.
+
+ * examples/viewer.c: Use functions from libpango instead
+ of rolling our own font-description conversion functions.
+
+Fri Feb 25 15:04:21 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/{fonts.c,pango-font.h,pango-context.[ch],pangox.c,
+ pango-attributes.c,examples/viewer.c: Add size to the
+ font description structure instead of continually passing
+ it around as an extra argument.
+
+ * libpango/pangox.c: Take screen resolution into account when
+ choosing fonts, instead of assumming point == pixel.
+
+Fri Feb 25 12:32:01 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in examples/Makefile.am: If GTK+ test fails,
+ just skip the example program.
+
+ * pango-config.in pango.spec.in: Add a simple pango-config
+ script to the build. (pango-config --libs pangox really
+ should add the X libraries, but we'll omit that for the
+ moment.)
+
+Sat Feb 19 18:51:35 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pangox.c (pango_x_make_matching_xlfd): Fix problem
+ where charsets specified in alias files where being ignored
+ and treated as wildcards.
+
+Sat Feb 19 17:46:49 2000 Owen Taylor <otaylor@redhat.com>
+
+ * README: Fix Dov's name.
+
+Wed Feb 16 19:55:05 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Release 0.7
+
+ * examples/Makefile.am (aliasdir): Install example
+ pangox_aliases file.
+
+ * examples/Makefile.am (bin_PROGRAMS): Install
+ pango-viewer.
+
+ * docs/tmpl/*: Updated templates.
+
+Wed Feb 16 16:39:46 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pango-coverage.c (pango_coverage_get): Make refcounted.
+
+ * libpango/modules.c (struct _PangoEnginePair): Since we don't
+ currently unload engines, cache loaded engines. (Not really
+ quite satisfactory, but should work OK)
+
+ * libpango/pango-context.c (pango_context_get_font_description):
+ Added a global font description.
+
+ * libpango/modules.c (_pango_find_map): Allow NULL
+ language tags.
+
+ * libpango/pango-context.c (pango_itemize) examples/viewer.c:
+ Switch itemize over to take a PangoAttrList.
+
+ * examples/viewer.c: Conform to changes in itemization interface
+
+ * libpango/font.[ch]: Add a compare function for FontDescription
+
+ * libpango/pango-attributes.[ch]: Change the iteration iterface
+ to be more convenient.
+
+ * libpango/pango-context.[ch]: Add the ability to set a default font.
+
+ * libpango/pango-context.[ch]: Take the font for itemization from
+ the attributes on the text.
+
+ * libpango/pangox.c: Cache currently loaded fonts, and cache
+ coverages.
+
+Tue Feb 15 02:35:56 2000 Owen Taylor <otaylor@redhat.com>
+
+ * docs/**: Add documentation for attributes.
+
+ * Makefile.am libpango/pango-attributes.[ch]: Finish initial
+ implementation of attributes APIs.
+
+Mon Feb 14 22:04:38 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pango-attributes.[ch]: Start of attribute lists.
+
+Fri Feb 11 16:04:50 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/Makefile.am: make dist fixups.
+
+ * Makefile.am pango.spec.in: Add a spec file
+
+ * examples/HELLO.utf8: Change Maltese to a different
+ phrase to include some unique Maltese characters.
+ (Suggestion from Steven R. Loomis)
+
+ * libpango/Makefile.am modules/Makefile.am libpango/modules.c:
+ Move pango.modules file to /var
+
+Thu Feb 10 23:45:49 2000 Owen Taylor <otaylor@redhat.com>
+
+ * docs/**: Added recent API changes.
+ * libpango/pango-context.c: Doc comment fixes
+
+ * configure.in: Add in directories from unicode-config
+ when running AC_CHECK_LIB on libunicode.
+
+Thu Feb 10 23:45:27 2000 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Up version to match 0.6 release that
+ was made yesterday.
+
+ * examples/viewer.c (main): Look for fixed if sans
+ isn't found as an initial font.
+
+ * modules/Makefile.am: Add an install rule to
+ run pango-querymodules.
+
+ * modules/*/Makefile.am (module_LTLIBRARIES): Set up
+ appropriate install rules.
+
+ * libpango/Makefile.am: Break the X code out into a
+ separate library.
+
+Thu Feb 10 20:19:39 2000 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer.c: Fix some runtime and compile-time warnings.
+
+ * modules/hangul/hangul.c (hangul_engine_shape): Shape the
+ string with the unknown glyph rather than giving a warning
+ when the font doesn't have any of the necesary charsets.
+
+Thu Feb 10 19:57:27 2000 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer.c: Add style selector, rewrite family
+ selector to use list_families().
+
+ * libpango/pango-context.[ch] libpango/pango-font.h libpango/pangox.c
+ libpango/fonts.c: Add calls to list families, modify list_fonts()
+ call to take an optional "family" parameter for the purpose of
+ listing the fonts within a family.
+
+Wed Feb 9 14:04:35 2000 Owen Taylor <otaylor@redhat.com>
+
+ * TODO: updates.
+
+ * docs/*: Added some docs on font handling, both general
+ and for X.
+
+Tue Feb 8 15:05:17 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pangox.c: Moved the primary size and charset matching
+ inside of Pango instead of on the font server. This allows us
+ to do better matching, and only scale scaleable fonts, and not
+ scale bitmaps. Also, match size and charset simultaneously,
+ so that we can handle the cases where all sizes are not available
+ in all charsets better.
+
+Mon Feb 7 20:27:35 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pangox.c (pango_x_names_for_size): Start at reworking
+ code to do size and charset lookups simultaneously. twill compile
+ once I get home.
+
+Mon Feb 7 16:49:32 2000 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer.c (make_families_menu): Switch the option
+ menu for a combo box.
+
+ * examples/pangox_aliases: Add a demo alias file.
+
+ * libpango/pangox.c: Add a font-alias mechanism allowing.
+
+ * examples/viewer.c (make_font_selector): Added a spin-button for
+ size.
+
+Wed Feb 2 20:49:21 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pangox.c (pango_x_get_unknown_glyph): Add a call to get
+ a glyph for unknown an unknown char.
+
+ * modules/basic/basic.c: use pango_x_get_unknown_glyph.
+
+ * libpango/utils.[ch] (_pango_guchar4_to_utf8): Added util function
+ for coverting wide chars to utf8.
+
+ * libpango/pangox.c (pango_x_font_get_coverage pango_x_font_get_shaper):
+ Initial implementations.
+
+Wed Feb 2 11:12:12 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pango-types.h: Conditionally define G_N_ELEMENTS() when
+ using glib-1.3.
+
+ * modules/basic/basic.c modules/hangul/hangul.c modules/tamil/tamil.c:
+ Replace MEMBERS() with G_N_ELEMENTS().
+
+ * libpango/pango-engine.h: Added a get_coverage() function
+ to the PangoEngineShape vtable.
+
+ * modules/basic/basic.c modules/hangul/hangul.c modules/tamil/tamil.c:
+ Added get_coverage() functions. The basic.c one is incredibly
+ inefficient (but caching may make that matter that much).
+ The Hangul one needs checking.
+
+Wed Feb 2 00:07:13 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pango-*.h: The great header file reorganization.
+ Split up roughtly by objects.
+
+ * libpango/pango-font.h libpango/fonts.h: Add generic
+ font-loading and listing interfaces.
+
+ * libpango/pangox.c: Implement font-listing/loading interfaces
+ for X.
+
+ * libpango/pango-context.[ch]: Flesh out context structure.
+ Add appropriate accesors, font loading-methods, etc.
+
+ * libpango/pango-coverage.[ch]: Coverage map objects.
+
+ * examples/viewer.c: First stab at adding font-selection. Majorly
+ deficient for the moment until we add font lists and fallbacks
+ based on coverage maps.
+
+Thu Jan 27 16:50:51 2000 Owen Taylor <otaylor@redhat.com>
+
+ * docs/**: Updates to match recent API changes.
+
+Mon Jan 17 22:03:24 2000 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/hangul.c modules/tamil/tamil.c:
+ Updated to use new X font mechanism.
+
+ * libpango/pangox.[ch]: Misc bugfixes, no longer segfaults.
+
+Mon Jan 17 18:29:39 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pangox.[ch] modules/basic/basic.c: back away from
+ the strict charset model to having subfonts arbitrarily indexed. The
+ charset-index model didn't allow proper fallbacks.
+
+ Add a function pango_x_list_subfonts() function that lists
+ subfonts in the proper order for a given list of charsets.
+
+ (segfaults currently, will fix pronto)
+
+Sat Jan 15 03:17:35 2000 Owen Taylor <otaylor@redhat.com>
+
+ * pango/glyphstring.c pango/mapping.c pango/pangox.c
+ modules/basic.c examples/viewer.c:
+
+ Switch GlyphStrings to have a single array of
+ PangoGlyphInfo instead of multiple arrays. Rename
+ PangoGlyphIndex to PangoGlyph.
+
+Sat Jan 15 01:06:45 2000 Owen Taylor <otaylor@redhat.com>
+
+ * libpango/pangox.c libpango/pangox.h libpango/fonts.c
+ libpango/glyphstring.c modules/basic/basic.c:
+
+ Eliminate PangoCFont; For X, encode charset into upper
+ 16 bits of 32 bit glyph IDs. Revise X core <=> module
+ interfaces to support this change.
+
+ Remove support for X_XLFD_FONT_RANGES, which has been
+ disavowed by its proponents, in favor of checking metrics
+ to figure out if the relevant characters are there.
+
+ Rework operation of basic module to be faster and simple.
+
+ * modules/Makefile.am: temporarily comment out Tamil and
+ Hangul modules until I finish mucking with the
+ X font interfaces.
+
+Fri Jan 14 12:08:43 2000 Owen Taylor <otaylor@redhat.com>
+
+ * examples/HELLO.utf8: Add Pango properly spelled.
+
+ * **/Makefile.am: make dist fixes.
+
+Thu Jan 13 17:49:45 2000 Owen Taylor <otaylor@redhat.com>
+
+ * TODO: Updated.
+
+Thu Jan 13 16:57:22 2000 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer.c: reindented.
+ * README: updated
+
+Wed Jan 12 16:49:03 2000 Owen Taylor <otaylor@redhat.com>
+
+ * Huge rename from GScript to Pango.
+
+ * modules/tamil/* examples/muru.utf fonts/tscakaram.pcf:
+
+ Tamil module from Sivaraj Doddannan <sivaraj@intelligroup.com>
+
+Mon Aug 2 18:32:59 1999 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Check for libunicode.
+
+ * examples/viewer.c libgscript/break.c
+ libgscript/itemize.c modules/basic/basic.c:
+
+ Use libunicode functions for conversion.
+
+ * modules/basic/basic.c: Add support for
+ simple accent composition; fix bidi
+ swapping to correctly swap clusters
+ as a unit.
+
+1999-07-26 <otaylor@localhost.localdomain>
+
+ * libgscript/mapping.c (g_script_cp_to_x): Fix
+ buggy algorithm.
+
+1999-07-31 Changwoo Ryu <cwryu@adam.kaist.ac.kr>
+
+ * modules/hangul/Makefile.am (EXTRA_DIST): Added tables-*.i
+ files.
+
+1999-07-29 Raja R Harinath <harinath@cs.umn.edu>
+
+ * modules/hangul/Makefile.am (INCLUDES): Use
+ -I$(top_srcdir)/libgscript.
+
+1999-07-30 Changwoo Ryu <cwryu@adam.kaist.ac.kr>
+
+ * modules/hangul/*, Makefile.am, configure.in: Added the Hangul
+ shaping module.
+
+Wed Jul 28 14:45:00 1999 Owen Taylor <otaylor@redhat.com>
+
+ * Released version 0.4
+
+Wed Jul 28 14:43:41 1999 Owen Taylor <otaylor@redhat.com>
+
+ * libgscript/reorder-items.c: Return NULL correctly.
+
+ * libgscript/mapping.c:
+ Fixed buggy algorithm for cp to x.
+ Fixed reversed interpolation for x to cp.
+
+Wed Jul 28 14:42:40 1999 Owen Taylor <otaylor@redhat.com>
+
+ * libgscript/mapping.c: Fix bugs
+
+Thu Jul 22 09:36:08 1999 Owen Taylor <otaylor@redhat.com>
+
+ * Released version 0.3
+
+Wed Jul 21 18:46:14 1999 Owen Taylor <otaylor@redhat.com>
+
+ * libgscript/gscriptx.c (g_script_x_extents): Fix
+ same off-by-one bug here too...
+
+Wed Jul 21 18:44:55 1999 Owen Taylor <otaylor@redhat.com>
+
+ * libgscript/gscriptx.c (g_script_x_glyph_extents): Fix
+ an off-by-one error in computing indexes into the
+ per-char information.
+
+Tue Jul 20 20:09:09 1999 Owen Taylor <otaylor@redhat.com>
+
+ * docs/tmpl/engines.sgml: First pass at documenting
+ engine interfaces.
+
+Tue Jul 20 16:10:48 1999 Owen Taylor <otaylor@redhat.com>
+
+ * **: Documentation improvements.
+
+Tue Jul 20 15:05:45 1999 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/{basic.c,tables-{big,small}.i}:
+ Rewrote basic module to support subset fonts meaningfully.
+ This meant revising the algorithm used to look
+ up a font for each character independently.
+ Which required aggresive caching here and in the
+ font code to give half-way decent performance.
+
+ Added support for ISO-10646-1 fonts.
+
+ * libgscript/fonts.c (g_script_font_[get/set]_data): Add the
+ ability to add user data to a font.
+
+ * libgscript/gscriptx.[ch]: Add functions to allow:
+ - Querying all XLFD's matching a set of character
+ sets for a font.
+ - Loading a component font with a particular XLFD.
+ - Finding the range of present characters for a given XLFD.
+
+ Also added tons of caching.
+
+Wed Jul 14 19:11:41 1999 Owen Taylor <otaylor@redhat.com>
+
+ * libgscript/gscriptx.c (g_script_x_glyph_extents):
+ Fixed min/max confusion.
+
+Mon Jul 12 17:14:53 1999 Owen Taylor <otaylor@redhat.com>
+
+ * docs/TEXT/glossary (CFont): Expanded.
+
+ * libgscript/fonts.c (g_script_cfont_unref): Fixed
+ leak. (Pointed out by Raph)
+
+ * libgscript/gscriptx.c: Handle the case where
+ fontstruct->per_char == NULL.
+
+Sun Jul 11 23:44:42 1999 Owen Taylor <otaylor@redhat.com>
+
+ * Made version 0.2
+
+ * **/Makefile.am: Fixes for srcdir != builddir
+
+Sun Jul 11 23:41:19 1999 Owen Taylor <otaylor@redhat.com>
+
+ * docs/tmpl/glyphs.sgml: SGML fix.
+
+Sun Jul 11 22:53:11 1999 Owen Taylor <otaylor@redhat.com>
+
+ * libgscript/mapping.c: Implemented g_script_cp_to_x()
+ and g_script_x_to_cp().
+
+ * examples/viewer.c: Added clicking on a character to
+ identify it as a test of the above.
+
+ * gscript/gscript.h gscript/gglyphstring.c modules/basic/basic.c:
+ Add another field into the GGlyphString which holds
+ a mapping from glyphs to logical clusters.
+
+ * libgscript/gscript.h (struct _GScriptLangRange):
+ Make it start-length like everything else, not
+ start-end.
+
+Sun Jul 11 00:18:56 1999 Owen Taylor <otaylor@redhat.com>
+
+ * docs/tmpl/gscript-x.sgml: Fix sgml error.
+
+Sat Jul 10 23:40:40 1999 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic.c: Added ability to use
+ multibyte character sets. (Right now, they have
+ to be converted by iconv into EUC encoding, but
+ that can easily be extended).
+
+ Added simply CJK support. This really bloats and
+ slows down the module because the range-based
+ encoding we use to map characters onto character-sets
+ wasn't designed for CJK-style charsets. But it's
+ better than nothing for now.
+
+ * libgscript/reorder-items.c (reorder_items_recurse): Fix
+ bug with variable initialization.
+
+ * examples/viewer.c (draw): Compute line increments.
+
+ * libgscript/gscriptx.c (g_script_x_[glyph]_extents): Added
+ logical_ascent/descent parameters.
+
+ * examples/viewer.c: Commented
+
+Sat Jul 10 04:35:10 1999 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in Makefile.am: automake'd and libtoolized.
+
+Sat Jul 10 00:00:00 1999 Owen Taylor <otaylor@redhat.com>
+
+ * It renders! Start a ChangeLog
+
diff --git a/trunk/ChangeLog.pre-1-10 b/trunk/ChangeLog.pre-1-10
new file mode 100644
index 00000000..4f184514
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-10
@@ -0,0 +1,1274 @@
+2005-08-15 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.10.0 ===
+
+ * configure.in: Version 1.10.0
+
+ * NEWS: Updated.
+
+2005-08-15 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/mini-fribidi/fribidi_tab_char_type_2.i: Updated to
+ that of FriBidi 0.10.5 which corresponds to Unicode 4.1.
+
+ * pango/mini-fribidi/README: Added note to reflect above change.
+
+ * pango/mini-fribidi/fribidi_tables.i: Removed. Not needed
+ since 2002.
+
+2005-08-15 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-script.c (pango_script_get_sample_language):
+ Glagolitic shouldn't have Coptic as a sample language; it was used
+ to write Old Church Slavonic. Tifinagh shouldn't have Berber
+ as a sample language, since it isn't the *primary* script used
+ to write Berber.
+
+2005-08-15 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.c (pango_fc_font_create_metrics_for_context)
+ pango/pangofc-private.h pango/pangocairo-fcfcont.c: Cut out the meat of
+ pango_fc_font_get_metrics_for_context() and export it (privately),
+ so that PangoCairoFcFont can create a variant that sets the font
+ options on the context it creates. (#311522)
+
+2005-08-15 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_line_get_extents):
+ Fix unconditional access to logical_rect. (#312691,
+ Hans Breuer)
+
+2005-08-15 Tor Lillqvist <tml@novell.com>
+
+ * pango/pango.def: Add pango_item_get_type and
+ pango_layout_line_get_type. Thanks to Vittorio Palmisano for
+ noticing.
+
+2005-08-15 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/opentype/ftglue.h: Replace perror with perror_.
+ Remove FT_BEGIN_STMNT and FT_END_STMNT. (#313477)
+
+2005-08-14 Behdad Esfahbod <pango@behdad.org>
+
+ * examples/HELLO.utf8: Remove some characters at the beginning
+ of the file and add a line break.
+
+2005-08-09 Keith Packard <keithp@keithp.com>
+
+ reviewed by: otaylor
+
+ * examples/cairoview.c: (update), (expose), (main):
+ Switch to Xlib regions as pixman is destined to disappear.
+
+2005-08-08 Roozbeh Pournader <roozbeh@farsiweb.info>
+
+ * docs/tmpl/scripts.sgml, modules/arabic/arabic-ot.c,
+ pango/pango-script.c, pango/pango-script.h,
+ pango/pango-script-table.h, tools/gen-script-table.pl: Updated to
+ Unicode 4.1, adding new scripts and Arabic joining data. (#312884)
+
+2005-08-05 Tor Lillqvist <tml@novell.com>
+
+ * pango-zip.sh.in: Add pangocairo files. Get the DLLs from "bin"
+ unconditionally, that's where libtool installs them since a long
+ time.
+
+ * pango/Makefile.am (install-def-files, uninstall-def-files):
+ Install/uninstall also pangocairo .def and .lib files.
+
+2005-07-30 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc : updated
+
+ * pango/pangocairo-win32font.c(...get_metrics) : dont use ascent
+ where descent is meant. Fixes size of edit boxes for gtk+-2.7
+
+2005-07-30 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Use egrep for khmer, like the rest, to
+ fix --with-included-modules. (#311930, Sebastien Bacher)
+
+2005-07-29 J. Ali Harlow <ali@juiblex.co.uk>
+
+ * pango/Makefile.am: Look for pango.def, pangoft2.def and
+ pangowin32.def files in the source directory. Fixes #311971.
+
+2005-07-26 Manish Singh <yosh@gimp.org>
+
+ * pango/pango-utils.c (pango_is_zero_width): put parens around bitwise
+ &, to appease gcc.
+
+2005-07-26 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.9.1 ===
+
+ * configure.in: Version 1.9.1
+
+ * NEWS: Updated
+
+2005-07-26 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c, pango/opentype/ftxgpos.c: Skip lookups
+ with lookup index out of range. (Patch from Behdad Esfahbod, #171170)
+
+2005-07-26 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-fontmap.c (pango_cairo_context_get_font_options):
+ Fix mixed code and declarations (#311626, Kazuki IWAMOTO)
+
+ * pango/pangocairo-win32font.c (pango_cairo_win32_font_install):
+ Fix typo (#311627, Kazuki IWAMOTO)
+
+2005-07-26 Owen Taylor <otaylor@redhat.com>
+
+ Fixes for signed/unsigned in PangoAttrIterator ((#166700,
+ Morten Welinder)
+
+ * pango/pango-attributes.c (pango_attr_iterator_range):
+ Clamp results to G_MAXINT to avoid negative numbers from
+ signed/unsigned conversions.
+
+ * pango/pango-attributes.c: Make PangoAttrIterator
+ start_index/end_index unsigned to match PangoAttribute.
+ Change various local variables to match.
+
+ * pango/ellipsize.c (advance_iterator_to)
+ pango/pango-attributes.c (pango_attr_iterator_range)
+ pango/pango-glyph-item.c (pango_glyph_item_apply_attrs)
+ pango/pango-layout.c (pango_layout_line_get_empty_extents):
+ Always check the return value from pango_attr_iterator()
+ to deal with potential infinite loops when trying to
+ advance to position G_MAXINT.
+
+ * pango/pango-layout.c (pango_layout_set_text): Handle
+ the case where the text passed in is longer than
+ than G_MAXINT and length < 0.
+
+ * pango/pango-attributes.c (pango_attr_list_splice): Be
+ careful about integer overflow - clamp addition.
+ (#163246, Morten Welinder)
+
+2005-07-26 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c (oryaCharClasses):
+ Change U+0B30 from _rv to _rb. Oriya doesn't have a vattu
+ form of ra. (#151393, Gautam Sengupta, fix from
+ Gora Mohanty)
+
+ * modules/indic/indic-ot-class-tables.c (oryaCharClasses):
+ Change U+B02 from _ma to _mp. Anusvara appears after not
+ above in Oriya. (#311575, Gora Mohanty)
+
+ * modules/indic/indic-ot-class-tables.c (oryaCharClasses):
+ Classify unicode standard additions U+0B35 (va),
+ U+0B71 (wa) as _ct. (Also #311575)
+
+2005-07-26 Behdad Esfahbod <pango@behdad.org>
+
+ * examples/cairoview.c, examples/pangoft2topgm.c,
+ examples/renderdemo.c, examples/renderdemo.h: Fixed a couple of leaks
+ and freed memory after use.
+
+2005-07-25 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_install): Set
+ font options as well.
+
+ * pango/pango-layout.c (line_set_resolved_dir): Always set
+ line->resolved_dir to one of LTR or RTL. (#171439, Reported
+ by Chris Blizzard)
+
+2005-07-25 Tor Lillqvist <tml@novell.com>
+
+ * configure.in
+ * pango/pangocairo-win32font.c (_pango_cairo_win32_font_new): Fix
+ a few typos that prevented build on Win32.
+
+ * pango/pango.def: Add pango_is_zero_width.
+
+2005-07-23 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/pango-utils.c, pango/pango-utils.h (pango_is_zero_width): New
+ function added.
+
+ * modules/basic/basic-common.h, modules/basic/basic-fc.c,
+ modules/basic/basic-win32.c, modules/basic/basic-x.c,
+ modules/hangul/hangul-fc.c, modules/arabic/arabic-fc.c,
+ modules/indic/indic-fc.c, modules/indic/indic-ot.h,
+ modules/syriac/syriac-fc.c: Use the new pango_is_zero_width function.
+ (#306639, Behnam Esfahbod)
+
+2005-07-22 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c (get_context_matrix): Handle context == NULL.
+ (Reported by Behdad Esfahbod)
+
+2005-07-22 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am configure.in: Use -export-symbols-regex
+ to control symbol exports, including not exporting the symbols
+ from opentype/.
+
+ * modules/*/Makefile.am: Control symbol exports here as well,
+ simplify using AC_SUBST() of MODULE_LIBTOOL_OPTIONS from configure.in.
+
+ * pango/pangox-fontmap.c (engine_shape_covers): Cut-and-paste
+ engine_shape_covers to avoid using a symbol from libpango.
+
+ * pango/pango-utils.c: Make accidentally exported pango_aliases_ht
+ static.
+
+2005-07-22 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c: Add some missing statics on functions
+ added in the recent layout iter patch.
+
+2005-07-22 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftglue.c (ftglue_realloc): Remove
+ an unecessary set of block2.
+
+2005-07-22 Owen Taylor <otaylor@redhat.com>
+
+ Patch from David Turner. Review and testing by Behdad Esfahbod
+
+ * pango/opentype/ftglue.[ch] Makefile.am: Glue layer that provides
+ implementation of the internal functions that the opentype code
+ expects in terms of publically exported FreeType API.
+
+ * pango/opentype/ftxgdef.c pango/opentype/ftxgpos.c
+ pango/opentype/ftxgsub.c pango/opentype/ftxopen.c
+ pango/opentype/otlbuffer.c pango/opentype/pango-ot-info.c
+ pango/opentype/pango-ot-ruleset.c: Remove includes of
+ internal headers. Small changes to work with ftglue.[ch]
+
+ * pango/opentype/fterrcompat.h: Remove: no longer needed.
+
+ * pango/opentype/ftxgpos.c: Use FT_IS_SFNT(face) rather
+ than poking at FT_MODULE_CLASS (face->driver)->module_name.
+
+ * pango/opentype/ftxopen.c (Free_FeatureList): Free
+ fl->ApplyOrder. (Found by Behdad)
+
+2005-07-21 Manish Singh <yosh@gimp.org>
+
+ * pango/pangofc-fontmap.c (fontset_hash_key_hash, font_hash_key_hash):
+ use GPOINTER_TO_UINT() instead of bare casts to guint.
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ Based on patch from Gustavo J. A. M. Carneiro (#305975)
+
+ * pango/pango-layout.[ch] (pango_layout_line_ref)
+ pango/pango-attributes.[ch] (pango_attr_list_ref): Return the
+ argument to _ref() functions.
+
+ * pango/pango-item.[ch]: Register PangoItem boxed type.
+
+ * pango/pango-layout.[ch]: Register PangoLayoutLine boxed type.
+
+2005-07-22 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangowin32.c: No need to include modules.h here any
+ longer.
+ (pango_win32_get_context): Remove unused variable.
+ (pango_win32_render_layout_line): Fix underlining. (#304692)
+ Mention in the doc comment that the DC's text alignment needs to
+ have TA_BASELINE and TA_LEFT for underlining to be correct.
+
+ * pango/pangowin32-fontmap.c: Include modules.h here instead.
+ (pango_win32_font_map_class_init): Define variable i.
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_add): Fix an
+ excess copy. (pango_fc_font_map_get_patterns): Add back
+ a call to FcPatternDestroy() that got dropped somehow.
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot.c: Minor formatting tweak to license
+ header.
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_load_font): Load a
+ fontset and return the first font to take advantage of existing
+ caching.
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c modules/indic/indic-ot.[ch]:
+ license on these ICU-derived files is X license, not LGPL.
+
+ * modules/khmer/khmer-fc.c: Add the X license text here in addition
+ to the LGPL.
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (_pango_xft_font_new): Force on
+ metrics hinting for all Xft fonts (this fixes font
+ metrics - glyph metrics were fixed earlier).
+ (#307196, Alex Jones)
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * README: Update information about the location of Xft.
+ (#172637, Karel 'Clock' Kulhavy)
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * README: Fix URL to tml's download page (#169467,
+ Brandon Bergren)
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init)
+ Move registration of included modules to here from
+ pango/pangowin32.c (pango_win32_get_context). (#309337, Hans
+ Breuer)
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c: Change the char
+ class for U+0A5C from _cn (consonant with nukta) to _ct.
+ (#309459, Sukhjinder Sidhu)
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c: Enable touching
+ letters for Sinhala with the ZWJ + al-lakuna combination.
+ (#302577, Harshula)
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_text): Avoid calling
+ memcpy with a NULL argument. (#310021, Morten Welinder)
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ Merges of fixes from Arabic module (#308813, Emil Soleyman-Zomalan)
+
+ * modules/syriac/syriac-fc.c (syriac_engine_shape): Fix
+ bug where cluster was getting set to 0 for non-spacing
+ marks rather than to the cluster of the base character.
+ (#149126, Behdad Esfahbod)
+
+ * modules/syriac/syriac-fc.c (syriac_engine_shape): Turn
+ on zero-width-marks setting. [Not clear that this is
+ needed here, since it is mostly set in the Arabic engine
+ to handle legacy fonts, but it shouldn't hurt]
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ Fix up places where there is missing or incomplete
+ Copyright and License information (Reported by William N. Ray,
+ #310072)
+
+ * pango/opentype/fterrcompat.h: Mark as FreeType/GPL licensed.
+
+ * pango/opentype/FT-license.txt: Make this the dual-licensing
+ description that covers the FreeType code (FreeType's
+ LICENSE.TXT) rather than the FTL.
+
+ * pango/opentype/FTL.TXT: Move the FTL (referenced from
+ FT-license.txt) to here.
+
+ * modules/basic/basic-common.h modules/hebrew/hebrew-shaper.h
+ modules/thai/thai-charprop.c modules/thai/thai-shaper.h
+ tools/gen-script-for-lang.c tests/testcolor.c:
+ Add LGPL header and copyright information.
+
+ * modules/indic/indic-ot.[ch] modules/indic/indic-ot-class-tables.c
+ modules/thai/thai-ot.[ch]: Add LGPL header.
+
+ * modules/thai/thai-shaper.c modules/thai/thai-charprop.h:
+ Minor fixes to copyright information.
+
+ * modules/arabic/arabic-ot.c: Add Freetype license boilerplate.
+
+2005-07-21 Matthias Clasen <mclasen@redhat.com>
+
+ * configure.in: Check for a new enough cairo.
+
+2005-07-19 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-fcfontmap.[ch]: Rework handling of context-specific
+ options: drop get_render_key() and add a opaque "context
+ key" (get_context_key() and friends). Also add a function to get
+ the resolution.
+
+ * pango/pango-fcfontmap.c pango/pangofc-font.h:
+ - Move the 'lang' into the fontset key lookup and get rid of the
+ funky list-of-hash-tables
+ - Make lookups of fontsets and fonts dependent on the context key
+ for the context.
+ - Simplify the pattern/fontset caching to have one finite-size
+ cache rather than an infinite first-level and a finite-size
+ second level.
+
+ * pango/pangocairo.h pango/pangocairo-private.h
+ pango/pangocairo-fontmap.c: Add
+ pango_cairo_context_get/set_resolution(),
+ pango_cairo_context_set/get_font_options to allow controlling the
+ resolution and font rendering options for a specific PangoContext.
+
+ * pango/pangocairo-fcfont.c pango/pangocairo-fcfontmap
+ pango/pangocairo-win32font.c: Implement resolution and font
+ options handling adapt to related Cairo changes.
+
+ * docs/pango-sections.txt docs/Makefile.am pango/pangowin32.c:
+ Doc updates and build fixes.
+
+ * pango/pangofc-fontmap.c (pango_fc_make_pattern): Create
+ patterns with FC_SIZE as well as FC_PIXEL_SIZE to work around
+ a libgnomeprint bug. (#309477)
+
+2005-07-09 Tor Lillqvist <tml@novell.com>
+
+ * configure.in: Call AC_CANONICAL_HOST before looking at $host.
+ Check for windres on Win32.
+
+ * pango/Makefile.am: Don't use the scripts in GLib's build/win32
+ to compile the rc files into resource object files. (This means we
+ lose the build number increment magic, but I doubt it was that
+ useful anyway.) Instead use windres directly. To pass a normal .o
+ file produced by windres through libtool, which wants .lo files,
+ pass it directly to the linker using a -Wl option.
+
+ Libtool installs/uninstalls the import libraries, no need to do it
+ ourselves. Do install/uninstall the .def files, though.
+
+ * pango/pango.rc.in
+ * pango/pangoft2.rc.in
+ * pango/pangowin32.rc.in: Correspondingly, use 0 instead of
+ BUILDNUMBER.
+
+2005-06-27 Tor Lillqvist <tml@novell.com>
+
+ * modules/khmer/Makefile.am (INCLUDES): Drop superfluous trailing
+ slash in -I path.
+
+2005-06-24 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_line_get_extents): Don't
+ key off zero-height to know whether to use the "empty extents" ...
+ this can cause infinite recursion, instead just check
+ !line->runs. (Part of #306415, Thomas Fitzsimmons)
+
+2005-06-24 Owen Taylor <otaylor@redhat.com>
+
+ * docs/pango_markup.sgml (linkend): Fix a stray newline
+ (#308887, Ryan Lortie)
+
+2005-06-22 Owen Taylor <otaylor@redhat.com>
+
+ * modules/khmer/khmer-fc.c (khmer_engine_shape): Add back
+ accidentally dropped line (Pointed out by Behdad Esfahbod)
+
+2005-06-21 Behdad Esfahbod <pango@behdad.org>
+
+ * modules/khmer/khmer-fc.c: Fix C89 var after code issues.
+
+ * modules/khmer/.cvsignore: Copied from other modules.
+
+2005-06-21 Owen Taylor <otaylor@redhat.com>
+
+ Fix up the operation of PangoLayoutIter, especially for Bidi
+ (#89541, based on a patch from Amit Aronovitch)
+
+ * pango/pango-layout.c: Many changes to make iteration
+ consistently in visual order.
+
+ * pango/pango-layout.c (pango_layout_iter_next_char): Iterate
+ through each character in the layout exactly once. (Including
+ a hack to get two iterator positions for \r\n)
+
+ * pango/pango-layout.c (pango_layout_iter_next_cluster): Only
+ iterate through real clusters: that is, positions in the
+ layout that have glyphs.
+
+ * pango/pango-layout.c (pango_layout_iter_get_char_extents):
+ Fix to give exactly the same results as
+ pango_glyph_string_index_to_x: the previous positions didn't
+ completely occupy the entire line.
+
+ * pango/pango-layout.c (pango_layout_iter_next_line): Remove
+ unneeded updating of iter->index and an associated FIXME.
+
+ * tests/testiter.c tests/Makefile.am: Add a (somewhat reworked)
+ test from Amit for the operation of PangoLayoutIter.
+
+2005-06-21 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-render.c (get_renderer): Go back to
+ honoring alpha in the XftColor passed in; it was a 1.6 => 1.8
+ regression. (#169622, based on a patch from Mikael Magnusson)
+
+2005-06-21 Owen Taylor <otaylor@redhat.com>
+
+ * modules/khmer configure.in modules/Makefile.am
+ modules/makefile.msc: Add a Khmer module by
+ Jens Herden and Javier Sola. (#125605)
+
+2005-06-20 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.9.0 ===
+
+ * NEWS: Update for 1.9.0
+
+ * README: Update
+
+2005-06-18 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/break.c (pango_find_paragraph_boundary): Optimization.
+ Do not g_utf8_get_char at all. (#305323, Paolo Borelli)
+
+2005-06-16 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_unlock_face): Remove
+ excess return. (#307741, Damien Carbery)
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c (guruCharClasses): Mark
+ U+A33, U+A36 as _cn, not _ct, since they are combinations
+ of other characters with nutka. (#304174, Sukhjinder Sidhu)
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ Misc fixes from Stepan Kasal, #169928
+
+ * pangoxft.pc.in: Add requirement on pangoft2
+
+ * pangoxft-uninstalled.pc.in: Fix cut-and-paste
+ errors in Name/Description when copying from
+ pangox-uninstalled.
+
+ * configure.in: Don't call AC_SUBST() unnecessary
+ for XFT_CFLAGS/LIBS.
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c (pango_parse_style): Fix some
+ missing case variants in the switch statement.
+ (#169852, Morten Welinder)
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-script-table.h (struct): Hand edit
+ to fix a bug in the 4.0.0 data tables.
+ (#173096, Sukhjinder Sidhu)
+
+ * tools/gen-script-table.pl: Some updates to handle
+ newer formats (not actually regenerating tables at the
+ moment, since the changes are large)
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ #307433, Sebastien Bacher
+
+ * Makefile.am (EXTRA_DIST): Name the Change.pre-*
+ correctly.
+
+ * pango/Makefile.am (libpango_1_0_la_SOURCES): Add
+ pango-color-table.h.
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c: Fix docs, handle a lone '~'
+ (#169851, Morten Welinder)
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Force off gtk-doc in absence of Cairo.
+ (#305652, Amit Aronovitch)
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/pango-ot-info.c (pango_ot_info_finalize)
+ pango/opentype/pango-ot-ruleset.c (pango_ot_ruleset_finalize):
+ Chain up from finalize. (#307547, Paolo Borelli)
+
+ * pango/opentype/pango-ot-info.c (pango_ot_info_finalizer):
+ make accidentally public function static.
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ * pango/ellipsize.c (shape_ellipsis): Fix FALSE/TRUE
+ typo that was causing crashes with fonts not containing
+ ".". (#304039, Sebastien Bacher)
+
+ * pango/pango-context.c (itemize_state_fill_shaper): Allow
+ font to be NULL.
+
+2005-06-14 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (itemize_state_finish): Fix
+ potential leak of state->base_font. (#168930, Ben Maurer,
+ Aivars Kalvans)
+
+2005-06-10 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-fcfont.c: Add a (hopefully temporary) cache
+ in front of getting metrics from Cairo.
+
+ * pango/pangocairo-fcfont.c: Remove some cast checks in critical
+ code paths.
+
+2005-05-17 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.[ch]: Add a new context_substitute() virtual
+ function that replaces default_substitute() and adds a
+ PangoContext argument.
+
+ * pango/pangocairo.h pango/pangocairo-fontmap.c docs/pango-sections.txt:
+ Add pango_cairo_context_set/get_hinting() to control
+ hinting on individual contexts.
+
+ * pango/pangocairo-fcfont.c pango/pangocairo-fcfontmap.c:
+ Implement hinting control for the for the fontconfig/cairo
+ backend.
+
+Tue May 17 07:21:53 2005 Manish Singh <yosh@gimp.org>
+
+ * examples/cairoview.c: update for new cairo_xlib_surface API.
+
+2005-05-16 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_glyph_extents):
+ pango/pangocairo-render.c (pango_cairo_renderer_draw_glyphs):
+ Handle glyph == 0.
+
+ * modules/indic/indic-ot.h modules/basic/basic-common.h:
+ Treat LINE SEPARATOR as a zero-width character.
+
+2005-05-16 Owen Taylor <otaylor@redhat.com>
+
+ * examples/cairoview.c: Include Xlib.h explicitely before
+ include Xutil.h, since Xutil.h doesn't include Xlib.h on
+ some platforms. (#304317, Damien Carbery)
+
+Fri May 13 23:54:29 2005 Manish Singh <yosh@gimp.org>
+
+ * examples/cairoview.c: #include Xutil.h explicitly, update
+ for renamed cairo API.
+
+2005-05-11 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-win32font.c (pango_cairo_win32_font_install):
+ Update for cairo API change.
+ (pango_cairo_win32_font_get_metrics): Fix x/y typo.
+
+2005-05-07 Owen Taylor <otaylor@redhat.com>
+
+ * examples/cairoview.c (update): Remove some accidentally
+ deleted code.
+
+2005-05-07 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-fontmap.c pango/pangocairo-render.c
+ examples/cairosimple.c pango/pangocairo-fcfont.c
+ examples/cairoview.c: Update for Cairo API changes.
+
+2005-04-29 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_glyph_extents):
+ Get the ascent/descent from Cairo to fix bugs in metrics computation
+ with a transformation in effect.
+
+2005-05-01 Owen Taylor <otaylor@redhat.com>
+
+ * examples/cairoview.c: Fix for the change of cairo_clip() not to preserve
+ the path.
+
+2005-04-28 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangocairo-win32font.c (pango_cairo_win32_font_get_font_face):
+ Correct parameters passed to MultiByteToWideChar(). Pass -1 as
+ source string length so that the target string gets
+ zero-terminated. Size of target array is in number of WCHARs, not
+ number of bytes.
+
+ Add support to pangowin32 for TrueType fonts with coverage outside
+ the BMP. Fix handling of surrogate pairs in the Uniscribe
+ shaper. (#302238)
+
+ * pango/pangowin32-private.h (PangoWin32Face): Rename the
+ unicode_table field to cmap. Keep track of its format (4 or 12).
+ (format_12_cmap): Add struct for a format 12 cmap.
+
+ * pango/pangowin32.c: Corresponding changes. Rename internal
+ functions a bit.
+ (get_format_12_cmap): New function, reads a format 12 cmap.
+ (font_get_cmap): Look for both format 12 (which is preferred) and
+ format 4 cmaps.
+ (pango_win32_font_get_glyph_index,
+ pango_win32_font_calc_coverage): Handle also format 12 cmaps.
+
+ * modules/basic/basic-win32.c: Handle surrogate pairs in wchar_t
+ strings properly.
+ (unichar_index): New function. Given a wchar_t string and an index
+ into it, calculate the index of the corresponding Unicode
+ character. Each surrogate pair in the wchar_t is just one Unicode
+ character.
+ (set_up_pango_log_clusters, itemize_shape_and_place): Use
+ unichar_index() instead of direct index into wchar_t string.
+
+Wed Apr 27 15:45:06 2005 Manish Singh <yosh@gimp.org>
+
+ * examples/cairoview.c: Update to new Cairo API for writing out PNGs.
+
+2005-04-28 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-defs.h: Cleanups.
+
+2005-04-25 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-fc.c (render_basic): handles zero width
+ chars, patch by Young-Ho Cha. (#157565)
+
+Mon Apr 18 15:49:36 2005 Manish Singh <yosh@gimp.org>
+
+ * examples/cairoview.c: Update to new Cairo API for setting color
+ and opacity.
+
+2005-04-12 Tor Lillqvist <tml@novell.com>
+
+ * pango/opentype/Makefile.am: Rename LDADDS to
+ libpango_ot_la_LIBADD to actually make libpango-ot.la link with
+ it.
+
+ * pango/pangowin32.def: Rename get_scale_factor to
+ get_metrics_factor here, too. (#300222, Ivan Wong)
+
+Fri Apr 8 15:30:55 2005 Manish Singh <yosh@gimp.org>
+
+ * examples/cairoview.c: #include <pixman.h> since the cairo headers
+ don't include it for us anymore.
+
+2005-04-08 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-font.c (_pango_cairo_font_install): Remove
+ stray return. (#173046, Damien Carbery)
+
+Thu Apr 7 22:45:32 2005 Manish Singh <yosh@gimp.org>
+
+ * configure.in: Test for renamed cairo_ft_scaled_font_lock_face().
+
+2005-04-07 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Test for renamed
+ cairo_win32_scaled_font_select_font().
+
+ * pango/pangocairo-win32font.c: Fix various compilation errors.
+
+ * pango/pangocairo-fcfont.c pango/pangocairo-win32font.c
+ pango/pangocairo-fontmap.c: Use new matrix API.
+
+ * pango/pangocairo-fcfont.c pango/pangocairo-win32font.c
+ pango/pangocairo-render.c: Update to new Cairo font API.
+
+ * pangpopangowin32.h pango/pangowin32-private.h pango/pangowin32.c
+ pango/pangocairo-win32font.c modules/basic/basic-win32.c: Rename
+ get_scale_factor() to get_metrics_factor() to match Cairo.
+
+2005-04-04 Hans Breuer <hans@breuer.org>
+
+ * pango/pangocairo-win32font.c(pango_cairor_win32_font_get_metrics) :
+ variable declaration on the start of the block, not C99 everywhere.
+
+ * examples/viewer-win32.c : updated to not so recent Pango api changes
+
+ * pango/makefile.msc : pangocairo build win32 version, not freetype
+
+2005-04-01 Carl Worth <cworth@cworth.org>
+
+ * examples/cairosimple.c: (main): Update to track removal of
+ cairo_set_target_png from cairo.
+
+2005-03-24 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * modules/thai/thai-fc.c (tis620_1), modules/thai/thai-shaper.c
+ (Mac_shape_table): Added more MacThai PUA glyphs that are not defined
+ in vendor data at Unicode.org, but just available in actual fonts.
+
+2005-03-20 Tor Lillqvist <tml@novell.com>
+
+ * modules/basic/basic-win32.c (make_langid): Leave out some
+ languages that don't have any own digits.
+ (itemize_shape_and_place): Force fRTL for each item returned from
+ ScriptItemize() to the bidi embedding parity for the whole
+ run. Pango passes us a run that it correctly has analyzed should
+ be of a certain direction, but ScriptItemize() still might split
+ it into items, some of which have neutral direction. (#170931)
+ (text_is_simple): Use g_utf8_to_utf16().
+
+2005-03-18 Hans Breuer <hans@breuer.org>
+
+ * pango/pango.def pango/pangocairo.def : updated externals
+
+ * pango/pangowin32.c(pango_win32_render_transformed) : matrix elements
+ xy and yx are needed the other way around for XFORM
+
+2005-03-17 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-win32font.c (_pango_cairo_win32_font_new):
+ Set win32font->logfont. (How was this working at all?)
+
+2005-03-15 Owen Taylor <otaylor@redhat.com>
+
+ * docs/tmpl/main.sgml (pango_unichar_direction): Fix
+ PANGO_DIRECTION_LTR/RTL cut-and-paste. (Tim Janik)
+
+2005-03-15 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c: Include the effect of the
+ CTM in the FC_PIXEL_SIZE we set in the FcPattern.
+ (Fixes problems with getting the wrong font when drawing
+ the same font at multiple scales. Reported by Keith
+ Packard.)
+
+ * pango/pangofc-fontmap.h pango/pangocairo-fcfontmap.c
+ pango/pangocairo-fc.h pango/pangocairo-fontfont.c: Add
+ the PangoFontDescription to create_font() ... we need it
+ to get the right pixel size to combine with the CTM.
+
+ * pango/pangofc-fontmap.c (pango_fc_fontmap_get_dpi):
+ Extract out the logic for finding the DPI from the
+ size-listing code.
+ (pango_fc_font_map_get_render_key): Handle mix of
+ absolute and not sizes correctly.
+
+Sat Mar 5 13:51:04 2005 Manish Singh <yosh@gimp.org>
+
+ * pango/mini-fribidi/fribidi_types.[ch]: const correctness for
+ _pango_fribidi_prop_to_type
+
+ * tools/Makefile.am: dist gen-script-table.pl and gen-color-table.pl
+
+2005-03-04 Owen Taylor <otaylor@redhat.com>
+
+ Reduce non-shared data (#168899, inspired by patches
+ from Tommi Komulainen and Ross Burton)
+
+ * pango/pango-color.c pango/pango-color-table.h
+ tools/gen-color-table.pl: Redo storage of colors to
+ use offsets into a static string rather than embedded
+ strings. (Inspired by a patch from Tommi Komulainen,
+ #168899)
+
+ * pango/break.c pango/fonts.c pango/pango-color.c
+ pango/pango-layout.c pango/pango-markup.c
+ pango/pango-script-lang-table.h
+ pango/mini-fribidi/fribidi_types.c
+ tools/gen-script-for-lang.c: Add const in various places
+
+ * modules/arabic/arabic-fc.c modules/hebrew/hebrew-fc.c:
+ modules/indic/{indic-fc.c,indic-ot-class-tables.c,
+ indic-ot.h} modules/syriac/syriac-ot.c (syriac): Further
+ addition of const.
+
+2005-03-04 Owen Taylor <otaylor@redhat.com>
+
+ * NEWS: Updates from stable branch.
+
+2005-03-03 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot.[ch] modules/indic-ot-class-tables.c:
+ Split out handling of sinhala al-lakuna character from
+ handling of Virama in the state table to avoid implicit
+ formation of conjucts for Sinhala. (Patch from
+ Harshula, #161981)
+
+ * modules/indic/indic-fc.c modules/indic/indic-ot.h:
+ Add a new script flag SF_PROCESS_ZWJ indicating
+ whether zero width characters should be passed to
+ gsub/gpos.
+
+ * modules/indic/indic-ot-class-tables.c: Set SF_PROCESS_ZWJ
+ for Sinhala. (#161981, Harshula)
+
+2005-03-03 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-fontmap.c (pango_font_map_load_font): Add
+ a g_return_if_fail() if desc doesn't have a family.
+ (#165866, Kees Cook)
+
+2005-03-03 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-render.c (pango_xft_renderer_draw_glyphs):
+ Call XftCharIndex() on the right font. (#163511)
+
+2005-03-03 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxopen.c (Coverage_Index1, Coverage_Index2,
+ Get_Class2): For all binary searches, handle the case where
+ the number of items is 0. (#162977, Nick Lamb)
+
+ * pango/opentype/ftxgdef.c (TT_GDEF_Build_ClassDefinition):
+ Handle the case where glyph_count == 0 properly. Fix a problem
+ with cleanups on memory allocation failure.
+ (Get_New_Count, Add_Glyph_Property): Avoid reading off the
+ end of the ClassRangeRecord array.
+
+2005-03-02 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_from_string_: For
+ family names that add in numbers add a , to distinguish
+ them from family+size (#166540, debugging/testing by
+ Manish Singh)
+
+2005-03-02 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_iterator_get_attrs):
+ Fix various typos in the docs (#163244, Morten Welinder)
+
+2005-03-02 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_get_glyph_extents):
+ Go back to using Xft-reported metrics for all non-transformed
+ fonts. Reporting non-integer glyph metrics for fonts
+ where people have disabled hinting in their config causes
+ various problems. (reported variously, including #167801,
+ Adam Sampson)
+
+2005-03-02 Owen Taylor <otaylor@redhat.co>m
+
+ [ ChangeLog entry for some changes accidentally committed
+ a while ago ]
+
+ Redo the handling of absolute sizes for PangoAttribute
+ to work around compatibility problems with GtkHTML which
+ was counting on the details of the implementation of
+ size attributes. (#163154)
+
+ * pango/pango-attributes.[ch] docs/tmpl/text-attributes.sgml:
+ Split PANGO_ATTR_SIZE into PANGO_ATTR_SIZE and
+ PANGO_ATTR_ABSOLUTE_SIZE, and use that distinction
+ rather than the boolean field in PangoAttrSize to
+ distinguish between attributes created
+ pango_attr_size_new_absolute() and
+ pango_attr_size_new()
+
+2005-03-01 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (process_item): Don't break
+ lines on LINE_SEPARATOR in single-paragraph mode.
+ (#168589, Damon Chaplin)
+
+2005-03-01 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c: Fix a typo in the last
+ commit (Manish Singh)
+
+2005-03-01 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (xft_font_get_font): Delete
+ FC_SPACING value out of pattern before passing it
+ to Xft, to prevent Xft clipping characters and
+ trashing metrics. (#164879, Billy Biggs)
+
+2005-03-01 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (pango_context_get_metrics): Use
+ the language from the context if %NULL is passed in for
+ @language. (#163472)
+
+2005-03-01 Owen Taylor <otaylor@redhat.com>
+
+ Build fixes from Andrew P. Lentvorski, Jr, #164655
+
+ * pango/pangoft2-render.c: Duplicate the
+ FT_LOAD_TARGET_MONO/FT_LOAD_MONOCHROME back-compat
+ define from pangoft2.c here
+
+ * examples/Makefile.am (pango_xftview_LDADD): Add
+ X_LIBS to pango_xftview_LDADD since some old versions
+ of xft.pc didn't add -lX11.
+
+2005-03-01 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Use PKG_CHECK_MODULES not AM_PATH_GLIB_2_0
+ to avoid a problem where older verisons of AM_PATH_GLIB_2_0
+ silently ignored gmodule-no-export causing mysterious
+ build failures. (#161786)
+
+ * pango/Makefile.am (DISTCLEANFILES): Move some
+ configure.in output files from CLEANFILES to DISTCLEANFILES.
+
+2005-03-01 Tor Lillqvist <tml@novell.com>
+
+ * tests/cxx-test.C: Include pangowin32.h first to avoid
+ a namespace collision. (#163584)
+
+Fri Feb 25 12:14:24 2005 Manish Singh <yosh@gimp.org>
+
+ * pango/pangofc-font.c (pango_fc_font_class_init): map get_font_map
+ to the right function.
+
+ * pango/pangox.c (pango_x_font_class_init): fill in get_font_map.
+
+2005-02-24 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-win32.h pango/pangocairo-win32font.c
+ pango/pangocairo-win32fontmap.c pango/Makefile.am:
+ PangoCairoFontMap for win32 fonts.
+
+ * pango/pangocairo-fontmap.c: Use PangoCairoWin32FontMap
+ when available.
+
+ * pango/pangowin32.h pango/pangowin32-fontmap.h pango/pangowin32.c:
+ Add virtual pango_win32_font_select_font()
+ to prepare a DC for use with a PangoWin32Font, and to release,
+ pango_win32_font_scale_font() to get logical unit => Pango units scale,
+ pango_win32_font_done_font() to release resources.
+
+ * pango/pangowin32-fontmap.[ch]: Add a find_font() virtual method
+ to allow subclasses that change how PangoFont lookup and
+ creation happens.
+
+ * pango/pangowin32-fontmap.c: Move initialization into
+ pango_win32_font_map_init() to facilitate derivation.
+
+ * pango/pangowin2.c pango/pangowin32-fontmap.c
+ pango/pangowin32-private.h: Move PangoWin32Font/PangoWin32FontMap
+ definitions into pangowin32-private.h to allow derivation for
+ PangoCairoWin32Font.
+
+ * modules/basic/basic-win32.c: Use pango_win32_font_select_font()
+ and friends.
+
+ * modules/basic/basic-win32.c: Use g_utf8_to_utf16 instead
+ of g_convert for simplicity and speed.
+
+ * pango/fonts.c (pango_font_get_font_map) pango/pango-font.h
+ pango/pangofc-font.c pango/pangowin32.c pango/pango.c pango/pango.def
+ docs/pango-sections.txt: Add a virtual function to get the fontmap
+ for a font.
+
+ * pango/pangocairo-render.c: Use pango_font_get_font_map()
+ rather than PangoFcFontMap hack.
+
+ * pango/pango-types.h: Move the declaration of PangoFontMap here
+ to avoid interactions between pango-font.h and pango-fontmap.h.
+
+ * pango/pangocairo.h: Remove accidental include
+ of pangofc-fontmap.h.
+
+2005-02-21 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_get_glyph_extents):
+ * pango/shape.c (pango_shape): Minor doc fixes.
+ (#167922, #167924, Billy Biggs)
+
+2005-02-06 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo.h pango/pangocairo-render.c docs/pango-sections.txt:
+ Rename pango_cairo_show_glyphs() to pango_cairo_show_glyph_string().
+ Add pango_cairo_{glyph_string,layout_line,layout}_path()
+
+ * docs/Makefile.am (INCLUDES): Add CAIRO_CFLAGS.
+
+2005-02-06 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc pango/*.def pango/pangocairo.def : updated to
+ build with the new Cairo dependency
+ * pango/Makefile.am : added pangocairo.def to EXTRA_DIST
+
+Thu Feb 3 19:00:17 2005 Manish Singh <yosh@gimp.org>
+
+ * pango/pangocairo-fc.h: spell _pango_cairo_fc_get_render_key
+ correctly.
+
+ * pango/pangocairo-fcfont.c: #include cairo-ft.h
+
+Thu Feb 3 18:23:27 2005 Manish Singh <yosh@gimp.org>
+
+ * configure.in: use CAIRO_LIBS for all libcairo checks, and disable
+ the cairo backend if we don't have Win32 nor FreeType support in
+ cairo.
+
+2005-02-03 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.c (pango_fc_font_real_get_glyph): Fix unpaired
+ lock/unlock_face().
+
+2005-02-03 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Bump to 1.9.0.
+
+ * pango/pangofc-fontmap.h: Document PangoFcFontMap.create_font()
+
+2005-02-03 Owen Taylor <otaylor@redhat.com>
+
+ * examples/cairosimple.c: Open the file with mode "wb", include
+ cairo-png.h.
+
+ * examples/xftview.c examples/cairoview.c: Set WM_NORMAL_HINTS to avoid
+ triggering a metacity bug.
+
+ * examples/cairoview.c: Include cairo-xlib.h.
+
+ * configure.in: Add checks for the Win32 Cairo backend. (not committing
+ the code yet).
+
+ * examples/Makefile.am pango/Makefile.am: add CAIRO_CFLAGS.
+
+ * pango/pangocairo-fc.h pango/pangocairo-fcfont.c
+ pango/pangocairo-fcfontmap.c pango/pangofc-fontmap.[ch]: Rework
+ Cairo/Fontconfig backend to use the current Cairo API. Make
+ some PangoFcFontMap changes to enable that.
+
+ * pango/pango/pangocairo-private.h pango/pangocairo-render.c:
+ Update for cairo_font_t changes.
+
+2005-01-31 Matthias Clasen <mclasen@redhat.com>
+
+ * modules/hebrew/hebrew-fc.c (get_cluster_glyphs): Show
+ unknown glyphs; this may lead to overlapping boxes when
+ accents are involved, but it is better than text vanishing
+ without any traces.
+
+2005-01-29 Tor Lillqvist <tml@novell.com>
+
+ * pango/pango.def: Add missing pango_render_part_get_type.
+ (#165287, Cedric Gustin)
+
+2005-01-25 Tor Lillqvist <tml@novell.com>
+
+ * pango/pango.def: Add a missing entry point.
+
+ * modules/basic/Makefile.am (usp10.h): Don't use -p option to cp,
+ can cause "failed to preserve ownership" errors.
+
+ * modules/*/Makefile.am (INCLUDES): Remove extraneous slash here,
+ too.
+
+2005-01-11 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/Makefile.am (INCLUDES): Remove an extraneous
+ / that was confusing gcc on Win32.
+
+2005-01-10 Owen Taylor <otaylor@redhat.com>
+
+ * Makefile.am (EXTRA_DIST): Add missing ChangeLog.pre*
+
+Sat Jan 8 19:28:17 2005 Owen Taylor <otaylor@redhat.com>
+
+ * Makefile.am configure.in pangocairo.pc.in
+ pangocairo-uninstalled.pc.in: Add a .pc file for
+ pangocairo.
+
+2005-01-08 Matthias Clasen <mclasen@redhat.com>
+
+ * pango.pc.in: Require gmodule-no-export-2.0 instead
+ of gmodule-2.0
+
+Sat Jan 8 16:46:37 2005 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Add checks for Cairo
+
+ * pango/Makefile.am: Add libpangocairo.
+
+ * pango/pangocairo-font.c pango/pangocairo-fontmap.c
+ pango/pangocairo.h pango/pangocairo-private.h
+ pango/pangocairo-fcfont.c pango/pangocairo-fcfontmap.c
+ pango/pangocairo-fc.h: Start of a Cairo/FreeType backend.
+
+ * pango/pangofc-fontmap.[ch]: Add a "get_render_key"
+ virtual function to allow subclasses to specialize the
+ details of how caching works. Add a default implementation
+ that's a little more sophisticated than what was there
+ before.
+
+ * pango/pangoft2-private.h pangofc-font.c pangoft2.c:
+ Move default implementations of has_char(), get_glyph()
+ to the base class.
+
+ * pango/pangofc-private.h pango/pangoft2-private.h:
+ Move PANGO_UNITS_26_6 and friends to pango/pangofc-private.h.
+
+ * examples/renderdemo.[ch] examples/pangoft2topgm.c
+ examples/xftview.c: Allow passing in a custom function
+ to transform drawing.
+
+ * examples/Makefile.am examples/cairoview.c: Add a
+ Cairo/Xlib example program.
+
+ * examples/cairosimple.c: Simple Cairo example with
+ output to a PNG.
+
+ * pango/pango-layout.c (pango_layout_line_get_extents): Fix
+ bug where line ink rect was always including 0, 0.
+
+Thu Jan 6 12:29:31 2005 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_iterator_get_font):
+ Fix reversed test on attr->absolute that was causing
+ pixels sizes to be used inappropriately. (#163105,
+ Ross Burton)
+
+Tue Jan 4 14:14:28 2005 Owen Taylor <otaylor@redhat.com>
+
+ * pango/break.c (enum): Fix trailing comma in enum (#162618)
+
+Tue Jan 4 14:11:43 2005 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_list_splice): Fix
+ doc sentences to parse. (#161812, Morten Welinder)
+
+Tue Jan 4 14:05:13 2005 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-renderer.c (pango_renderer_draw_trapezoid): Rename
+ y1 parameters to y1_ to avoid conflicts with the math.h Bessel
+ function. (#161969)
+
+Fri Dec 31 10:20:55 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c (pango_fc_convert_weight_to_pango):
+ Fix problem where MEDIUM was getting grouped with SEMIBOLD
+ rather than NORMAL.
+ (http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=143832)
+
+Wed Dec 22 13:21:01 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-script.c pango/pango-types.h: Fix a couple
+ of documentation typos (#161647, Torsten Schoenfeld)
+
+2004-12-18 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-private.h
+ * pango/pangowin32.c (pango_win32_font_get_metrics): Cache metrics
+ by language, like the other backends do. Don't try to get the
+ width of the 0..9 digit string if the font doesn't cover digits.
+
+2004-12-17 Tor Lillqvist <tml@iki.fi>
+
+ * pango/Makefile.am: Make the .la files depend on the
+ corresponding .def files.
+
+ * pango/pango.def: Add a couple of missing functions.
+
+Fri Dec 17 14:37:49 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c (pango_fc_convert_weight_to_fc): Use
+ FC_WEIGHT_MEDIUM, not FC_WEIGHT_NORMAL in old-fontconfig
+ case. (#161568, Vincent Noel)
+
+Fri Dec 17 12:44:10 2004 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Fix a couple of typos in the handling of
+ tibetan for --with-included-modules. (#161501, Sebastien Bacher)
+
+Fri Dec 17 12:28:56 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_get_extents_internal): Fix
+ bug in computing logical_rect.x when layout->width == -1.
+ (#161510, Morten Welinder)
+
+Thu Dec 16 14:03:32 2004 Owen Taylor <otaylor@redhat.com>
+
+ * docs/tmpl/pango-renderer.sgml: Add short and long descriptions.
+
diff --git a/trunk/ChangeLog.pre-1-12 b/trunk/ChangeLog.pre-1-12
new file mode 100644
index 00000000..460e435d
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-12
@@ -0,0 +1,1748 @@
+2006-03-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.12.0 ===
+
+ * configure.in: Version 1.12.0
+
+ * NEWS, README: Updated.
+
+2006-03-03 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangowin32-private.h (PING): Fix compilation error with
+ MSVC. (#333115)
+
+2006-03-01 Tor Lillqvist <tml@novell.com>
+
+ * pango/pango-context.c (update_metrics_from_items): Check the
+ font pointer being NULL to avoid crashes for at least one class of
+ "bad" fonts (those without a Unicode cmap) on Win32. It would
+ probably be better to prune out such fonts already in the
+ enumeration phase. That would require opening (CreateFontIndirect)
+ every font, though, to be able to check with GetFontData() whether
+ there is a Unicode cmap. Don't know how much that would slow down
+ the enumeration.
+
+2006-02-28 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangowin32-private.h (PING)
+ * pango/pangowin32.c
+ * modules/basic/basic-win32.c: Use g_print() instead of printf()
+ for debugging output, to enable easy redirection using GLib
+ facilities. (#332855)
+
+2006-02-26 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.11.99 "Just In Case" ===
+
+ * configure.in: Version 1.11.99
+
+ * NEWS: Updated.
+
+2006-02-26 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (pango_layout_set_text): Replace each byte in
+ invalid UTF-8 sequences with '?'. (bug #331995)
+
+ * examples/renderdemo.c: Don't exit on invalid UTF-8 input.
+
+2006-02-25 Hans Breuer <hans@breuer.org>
+
+ * pango/pangocairo-win32font.c(pango_cairo_win32_font_install):
+ return TRUE to glyphs rendered at all (instead of box). This may
+ be compiler specific (what to return w/o return) but fixes bug #332538
+
+ * pango/makefile.msc: updated
+ * pango/pango.def: just some sorting
+
+2006-02-25 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/test-hebrew.txt: Added. Parts of Genesis.
+
+ * examples/Makefile.am: Adjusted.
+
+2006-02-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 332167 – Void function returns value - breaks Solaris build
+ Reported by Damien Carbery
+
+ * pango/pangocairo-fcfont (pango_cairo_fc_font_unlock_face): Simply
+ return.
+
+2006-02-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.11.6 ===
+
+ * configure.in: Version 1.11.6
+
+ * NEWS: Updated.
+
+2006-02-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 328206 – Update/remove some old files
+
+ * docs/TEXT/{coding-style,modules,questions,ligatures,western-design}:
+ Removed.
+
+ * HACKING: Added. Renamed from docs/TEXT/coding-style.
+
+ * Makefile.am: Add HACKING.
+
+2006-02-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 314239 – pangocairo crashes when font cannot be read
+
+ * pango/pangocairo-fcfont.c, pango/pangocairo-font.c: Hack up to not
+ crash if we cannot create cairo_scaled_font_t for PangoFont (font is
+ not readable, removed, etc.)
+
+2006-02-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 331723 – shapers should not crash on failures
+
+ * modules/*/*-fc.c: Return instead of g_return_if_fail when
+ face == NULL.
+
+ * pango/pango-engine.h (PangoEngineShape): Document that a shaper
+ should return an empty glyph string on failure.
+
+2006-02-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c, pango/glyphstring.c, pango/pango-fontmap.c,
+ pango/pango-ot-buffer.c, pango/pangocairo-font.c, pango/pangoft2.c,
+ pango/pangoxft-font.c, pango/shape.c: Change g_critical to g_warning.
+ We already handle them gracefully.
+
+ Bug 331994 – --disable-debug removes G_DISABLE_CAST_CHECKS
+ Patch from charlet@act-europe.fr
+
+ * configure.in: Do not lose PANGO_DEBUG_FLAGS when reassigning.
+
+ Bug 331995 – pango_layout_set_text optimization
+ Patch from charlet@act-europe.fr
+
+ * pango/pango-layout.c: Do not validate input text if asserts are
+ disabled. Moreover, do not truncate input text on invalid sequence.
+
+ Bug 331996 – avoid crashes in win32 font handling
+ Patch from charlet@act-europe.fr
+
+ * pango/pangofc-fontmap.c, pango/pangowin32-fontmap.c,
+ pango/pangowin32.c: if (!font) return NULL in a number of places.
+
+2006-02-17 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 329148 – pango_glyph_item_split: assertion `split_index > 0' failed
+
+ * pango/ellipsize.c (init_state): Do not mistakenly set start_offset = 0.
+
+2006-02-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-types.h, pango/pango-font.h: Move PANGO_GLYPH_EMPTY,
+ PANGO_GLYPH_UNKNOWN_FLAG, and PANGO_GET_UNKNOWN_GLYPH from the former
+ to the latter, and only define if PANGO_ENABLE_ENGINE or
+ PANGO_ENABLE_BACKEND is set.
+
+2006-02-15 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 331038 – pango-querymodules --help and --version
+ Patch from Antoine Dopffer.
+
+ * examples/renderdemo.c, pango/querymodules.c: Add --version option.
+
+2006-02-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Pass gnits instead of gnu to automake.
+
+ * AUTHORS: Contributors move to THANKS.
+
+ * THANKS: New file.
+
+2006-02-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Pass 1.6 and gnu options to automake.
+
+ * modules/Makefile.am: Distribute Module.mk.
+
+ * modules/Module.mk: Common bits for writing module Makefil.am's.
+
+ * modules/*/Makefile.am: Include Module.mk instead of copying common
+ bits.
+
+2006-02-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 330795 – pango_renderer_draw_glyph segfaults when trying to call
+ the class vfunc
+ Opened by Torsten Schoenfeld
+
+ * pango/pango-renderer.c (pango_renderer_draw_trapezoid,
+ pango_renderer_draw_glyph): Bail if method is not implemented.
+
+2006-02-11 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.11.5 ===
+
+ * configure.in: Version 1.11.5
+
+ * NEWS: Updated.
+
+2006-02-10 Tor Lillqvist <tml@novell.com>
+
+ Fix #135098 and #322510.
+
+ * pango/pangowin32-fontmap.c (case_insensitive_hash)
+ (case_insensitive_equal): New helper functions for string hashing
+ based on ASCII case insensitivity..
+ (logfont_nosize_hash): Use case_insensitive_hash().
+ (logfont_nosize_equal): Use case_insensitive_equal().
+ (pango_win32_font_map_init): Use the case-insensitive functions
+ for the PangoWin32FontMap::families hash table.
+ (pango_win32_font_map_load_font): Consequently we don't need to
+ lowercase the name before looking up from the hash table.
+ (get_family_name): Constify parameter.
+ (get_family_name_lowercase): Not needed any longer.
+ (pango_win32_font_description_from_logfont): New public
+ function. Code moved from pango_win32_insert_font(). Use family
+ name as such, don't lowercase it.
+ (pango_win32_insert_font): Use the above new function. Don't
+ bother looking for superfluos copies of the font entry as that
+ shouldn't ever happen. We have pruned out fonts that differ only
+ in charset already earlier.
+
+ * pango/pangowin32.h: Declare pango_win32_font_description_from_logfont().
+
+ * pango/pangowin32.def
+ * docs/pango-sections.txt: Add it here too.
+
+2006-02-09 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 330602 – pango_parse_weight
+ Reported by Morten Welinder.
+
+ * pango/pango-utils.c (pango_parse_weight): Pass 10 as base to
+ strtol.
+
+2006-02-09 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 314548 – pango_shape() is missing const correctness
+ Patch from Antoine Dopffer.
+
+ * modules/arabic/arabic-fc.c, modules/basic/basic-fc.c,
+ modules/basic/basic-x.c, modules/hangul/hangul-fc.c,
+ modules/hebrew/hebrew-fc.c, modules/indic/indic-fc.c,
+ modules/khmer/khmer-fc.c, modules/syriac/syriac-fc.c,
+ modules/thai/thai-shaper.c, modules/thai/thai-shaper.h,
+ modules/tibetan/tibetan-fc.c, pango/pango-context.c,
+ pango/pango-engine-private.h, pango/pango-engine.c,
+ pango/pango-engine.h, pango/pango-glyph.h pango/pango-layout.c,
+ pango/shape.c: Make PangoAnalysis *analysis const in all shaper
+ interfaces.
+
+2006-02-08 Anders Carlsson <andersca@imendio.com>
+
+ * configure.in: Add basic-atsui to basic_modules
+
+2006-02-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 330146 – pango-view --help should list available backends
+ Patch from Antoine Dopffer.
+
+ * examples/renderdemo.c: Show backends in --help output.
+
+2006-02-07 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 330289 – Fix build with gcc 2.95 (pangox.c)
+
+ * pango/pangox.c (get_subfonts_foreach): Fixed.
+
+2006-02-07 Tor Lillqvist <tml@novell.com>
+
+ * examples/viewer-main.c (main): Initialise GError pointer to
+ NULL. Use waitpid() only on Unix.
+
+ * pango-zip.sh.in: Drop the timestamp from the zipfile names.
+
+2006-02-06 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.11.4 ===
+
+ * configure.in: Version 1.11.4
+
+ * NEWS: Updated.
+
+2006-02-06 Behdad Esfahbod <behdad@gnome.org>
+
+ As cairo 1.2 seems to be delayed infinitely, make all cairo HEAD
+ API that we use conditional, to make a release.
+
+ * configure.in: Depend on cairo 1.0.0 again. Check for
+ cairo_scaled_font_get_*() and cairo_scaled_font_text_extents()
+ availability.
+
+ * pango/pangocairo-font.c: Work around if the above functions are not
+ available.
+
+2006-02-06 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.c (pango_matrix_copy, pango_matrix_free): If
+ NULL is passed to _copy, return NULL with no warning. If NULL is
+ passed to _free, do nothing with no warning. Docs updated.
+
+ * examples/viewer-pangoxft.c (render_callback): Multiply x,y by
+ PANGO_SCALE, as pango_xft_render_layout takes coordinates in
+ Pango units weirdly enough.
+
+ * viewer-pangocairo.c (render_callback): Do cairo_translate, to
+ draw correct bounding boxes for x,y nonzero.
+
+ * examples/renderdemo.c (do_output): If context has an all-zero matrix
+ set, interpret it as backend does not support transformation, so
+ warn on --rotate, and do not try to rotate.
+
+ * examples/viewer-pangox.c (pangox_view_get_context): Set an all-zero
+ matrix on context, to negotiate that we don't support transformations.
+
+2006-02-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 328067 – Install pango-view
+
+ Added a rather generic framework for a pango-view example. All
+ backends have their own pango*-view built, and a pango-view binary
+ is built too, that can choose backend via --backend. This one is
+ installed in bindir.
+
+ * examples/Makefile.am: Updated, to build pangox-view, pangoft2-view,
+ pangoxft-view, pangocairo-view, and pango-view.
+
+ * examples/viewer.h, examples/viewer-x.c, examples/viewer-x.h
+ examples/viewer-cairo.c, examples/viewer-cairo.h,
+ examples/viewer-main.c, examples/viewer-pangox.c,
+ examples/viewer-pangoft2.c, examples/viewer-pangoxft.c,
+ examples/viewer-pangocairo.c, examples/pango-view.c,
+ examples/pango-xview.c, examples/pango-ft2view.c,
+ examples/pango-xftview.c, examples/pango-cairoview.c: Added.
+
+ * examples/cairoview.c, examples/xftview.c, examples/pangoft2topgm.c,
+ examples/viewer-qt.cc, examples/viewer-qt.h: Removed.
+
+ * configure.in: Check for Cairo Xlib backend, also AC_DEFINE various
+ backend bits.
+
+2006-02-06 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-fontmap.c (pango_font_map_real_load_fontset): Warn
+ only once per font-description that cannot be loaded.
+
+ * pango/pangox.c: Make it not crash if no font found, like other
+ backends.
+
+2006-02-05 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: AC_DEFINE various version components.
+
+ * *.c: Change various const return types to G_CONST_RETURN.
+
+2006-02-04 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 324408 – tab can result in 0 characters
+
+ * pango/pango-layout.c (shape_tab): Make sure there is
+ at least an space-width of space between tab-aligned text
+ and the text before it.
+
+2006-02-04 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 329528 – implement --wrap in examples/renderdemo.c
+ Patch from Antoine Dopffer.
+
+ * examples/renderdemo.c: Add --wrap option.
+
+2006-02-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-types.h: Change PANGO_GLYPH_EMPTY to 0x0FFFFFFF, to
+ not overlap with PANGO_GLYPH_UNKNOWN_FLAG (0x10000000).
+ Define PANGO_GET_UNKNOWN_GLYPH(wc) that simply returns
+ wc|PANGO_GLYPH_UNKNOWN_FLAG.
+
+ * docs/pango-sections.txt, docs/tmpl/glyphs.sgml: Document new
+ symbols.
+
+ * modules/*/*.c: Use PANGO_GET_UNKNOWN_GLYPH instead of various
+ backend-specific functions.
+
+ * pango/pangofc-font.c, pango/pangoft.c, pango/pangoxft-font.c,
+ * pango/pangowin32.c, pango/pangox.c: Suggest using
+ PANGO_GET_UNKNOWN_GLYPH in docs.
+
+ * pango/pangofc-font.h: Deprecate pango_fc_font_get_unknown_glyph().
+
+ * pango/pangowin32.h: Deprecate pango_win32_get_unknown_glyph().
+
+2006-02-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoft2.c, pango/pangoft2-render.c: Move the
+ FT_IS_SFNT(font) logic into pango_ft2_get_unknown glyph.
+
+2006-02-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: AC_DEFINE the module version, such that
+ pango-querymodules gets rebuilt after module version
+ update.
+
+ * pango/Makefile.am: Do not set -DMODULE_VERSION.
+
+2006-02-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Bump pango_module_version to 1.5.0.
+
+2006-02-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * Makefile.am: Distribute autogen.sh.
+
+2006-02-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Finish the 'glyph 0' work of this morning:
+ PANGO_GLYPH_NULL that I introduced is renamed to
+ PANGO_GLYPH_EMPTY. It means, no rendering should
+ be performed. The backends however, still return
+ 0 if a glyph is not found. The modules then are
+ free to replace this 0 glyph with an unknown
+ character.
+
+ * modules/arabic/arabic-fc.c, modules/basic/basic-atsui.c,
+ modules/basic/basic-fc.c, modules/basic/basic-win32.c,
+ modules/basic/basic-x.c, modules/hangul/hangul-fc.c,
+ modules/hebrew/hebrew-fc.c, modules/indic/indic-fc.c,
+ modules/khmer/khmer-fc.c, modules/syriac/syriac-fc.c,
+ modules/thai/thai-fc.c, modules/tibetan/tibetan-fc.c,
+ pango/pangox.c, pango/pangowin32.c:
+ Adapt to above change. Backends return 0 if glyph not
+ found.
+
+ * pango/fonts.c (pango_font_get_glyph_extents): If font
+ is not usable (!PANGO_IS_FONT (font)), return the generic
+ UNKNOWN_GLYPH metrics. This is used when your backends
+ are misconfigured and you don't find *any* font at all.
+
+ * pango/pango-engince.c: Add unknown glyphs in fallback
+ shaper, instead of empty glyphs.
+
+ * pango/shape.c: Call the fall-back shaper if shaper
+ fails, instead of generating a dummy glyph string ourselves.
+
+ * pango/pango-layout.c (imposed_shape, shape_tab): Use
+ PANGO_GLYPH_EMPTY instead of glyph 0.
+
+ * pango/pango-renderer.c (pango_renderer_draw_glyph): No-op on
+ PANGO_GLYPH_EMPTY instead of glyph 0.
+
+ * pango/pangocairo-atsuifont.c, pango/pangocairo-win32font.c,
+ pango/pangocairo-fcfont.c, pango/pangocairo-font.c,
+ pango/pangocairo-private.h: install_font returns a boolean now.
+
+ * pango/pangocairo-render.c, pango/pangoxft-render.c: Handle font
+ and hex-box failures more gracefully by drawing a generic
+ unknown-box glyph.
+
+ * pango/pangoft2.c, pango/pangoft2-render.c: Draw the generic
+ unknown-box glyph here too. For unknown glyphs though, if
+ the font is TTF (FT_IS_SFNT), use the zero-indexed glyph,
+ otherwise, draw a box of proper size.
+
+2006-02-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoft2.c: Do unknown glyph extents here too.
+
+2006-02-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoxft-font.c, pango/pangoxft-render.c: Guard Xft
+ backend agains crashes too.
+
+2006-02-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/arabic/arabic-fc.c, modules/basic/basic-atsui.c,
+ modules/basic/basic-fc.c, modules/basic/basic-win32.c,
+ modules/basic/basic-x.c, modules/hangul/hangul-fc.c,
+ modules/hebrew/hebrew-fc.c, modules/indic/indic-fc.c,
+ modules/khmer/khmer-fc.c, modules/syriac/syriac-fc.c,
+ modules/thai/thai-fc.c, modules/tibetan/tibetan-fc.c,
+ pango/fonts.c, pango/pango-engine-private.h pango/pango-types.h,
+ pango/pangocairo-fcfont.c, pango/pangocairo-font.c,
+ pango/pangocairo-private.h, pango/pangocairo-render.c,
+ pango/pangofc-decoder.c, pango/pangofc-font.c,
+ pango/pangoft2-render.c, pango/pangoft2.c pango/pangowin32.c,
+ pango/pangox.c, pango/pangoxft-font.c pango/pangoxft-private.h,
+ pango/pangoxft-render.c, pango/shape.c: Use PANGO_GLYPH_NULL for
+ when no glyph should be drawn. Use PANGO_GLYPH_UNKNOWN_FLAG for
+ all backends to mark unknown flags. There's no need for
+ pango_font_get_unknown_glyph() anymore, since all backends know
+ how to handle PANGO_GLYPH_UNKNOWN_FLAG gracefully. We may add
+ that in the future however. (fixes bug #73147, closes bug #329524)
+
+2006-02-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.c (read_config_file): Fix GKeyFile transition.
+
+2006-02-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: AC_DEFINE (HAVE_CAIRO_PNG).
+
+ * examples/cairoview.c: Save to PNG if cairo has PNG support and
+ --output is given.
+
+2006-02-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-font.c: For mini_font, set family to "monospace",
+ not "mono-space" which didn't work!
+
+2006-02-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/xftview.c: Add a default_substitute function to set
+ correct dpi on the pattern.
+
+2006-02-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/viewer-x.c, examples/viewer-x.h: Driver for X-based
+ viewer. Used by pangocairo-view and pangoxft-view currently.
+
+ * examples/Makefile.am, examples/cairoview.c, examples/xftview.c,
+ examples/pangoft2topgm.c, examples/renderdemo.h,
+ examples/renderdemo.c: Adjust to the above change.
+
+2006-02-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/viewer.c: Removed.
+
+2006-02-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.c, pango/pangocairo-font.c: Initialize warning
+ history structs more explicitly. (bug #329459)
+
+2006-01-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/syriac.utf, examples/tibetan.utf, examples/muru.utf,
+ examples/dev-example.utf: Removed/renamed.
+
+ * examples/test-arabic.txt, examples/test-devanagari.txt,
+ examples/test-ipa.txt, test-syriac.txt, test-tamil.txt,
+ test-tibetan.txt: Added.
+
+ * examples/Makefie.am: Change pango-cairoview, pango-xftview,
+ pangoft2topgm to pangocairo-view, pangoxft-view, and pangoft2-topgm
+ respectively.
+
+2006-01-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-font.c (_pango_cairo_get_hex_box_info): Use
+ cairo_scaled_font_text_extents instead of cairo_text_extents.
+
+2006-01-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Require cairo >= 1.1.1.
+
+2006-01-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-private.h, pango/pangocairo-font.c,
+ pango/pangocairo-render.c: Hint hexbox. Also draw a single-row
+ hexbox for very small sizes.
+
+2006-01-31 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 328313 – Use GKeyFile for parsing pangorc
+ Patch from Antoine Dopffer.
+
+ * pango/pango-utils.c (read_config_file): Use GKeyFile to parse
+ config file.
+
+2006-01-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c, pango/glyphstring.c pango/pango-attributes.c,
+ pango/pango-color.c, pango/pango-context.c,
+ pango/pango-coverage.c, pango/pango-fontset.c,
+ pango/pango-glyph-item.c, pango/pango-item.c,
+ pango/pango-layout.c, pango/pango-ot-buffer.c,
+ pango/pango-ot-info.c, pango/pango-ot-ruleset.c,
+ pango/pango-script.c, pango/pango-tabs.c pango/pango-utils.c,
+ pango/pangocairo-fcfontmap.c, pango/pangocairo-fontmap.c,
+ pango/pangox-fontcache.c, pango/pangoxft-render.c:
+ Improve documentation for functions allocating memory,
+ on how the object should be freed.
+
+2006-01-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.11.3 ===
+
+ * configure.in: Version 1.11.3
+
+ * NEWS: Updated.
+
+2006-01-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/shape.c (pango_shape):
+ * pango/fonts.c (pango_font_get_glyph_extents):
+ * pango/pangocairo-font.c (_pango_cairo_font_install):
+ Improve error handling in high-frequency functions: Only warn
+ once.
+
+ * pango-impl-utils.h, pangoutils.h:
+ * pangocairo-private.h, pangocairo-font.c:
+ Add machinery for above: _pango_warning_history and
+ _pango_cairo_warning_history.
+
+2006-01-30 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 328314 – Examples should use GOption instead of argcontext.c
+ Patch from Antoine Dopffer.
+
+ * examples/renderdemo.c: Use GOption for parsing cmd-line
+ options.
+
+ * examples/argcontext.c, examples/argcontext.h: Removed.
+
+2006-01-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/ftxgsub.c: Handle GSUB Lookup type 8,
+ and ReverseChainContextualSubst table. (bug #149696,
+ patch from Aamir Wali)
+
+2006-01-29 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/arabic/arabic-fc.c, modules/basic/basic-fc.c,
+ modules/hebrew/hebrew-fc.c, modules/indic/indic-fc.c,
+ modules/khmer/khmer-fc.c, modules/syriac/syriac-fc.c,
+ modules/thai/thai-ot.c, modules/thai/thai-shaper.c,
+ modules/tibetan/tibetan-fc.c: If locking font face failed,
+ do not assert, just return zero glyphs with an implicit
+ warning.
+
+ * pango/fonts.c, pango/glyphstring.c pango/modules.c,
+ pango/pango-color.c, pango/pango-context.c,
+ pango/pango-coverage.c, pango/pango-fontmap.c,
+ pango/pango-glyph-item.c, pango/pango-item.c,
+ pango/pango-layout.c, pango/pango-markup.c,
+ pango/pango-ot-buffer.c, pango/pango-script.c,
+ pango/pango-tabs.c, pango/pango-utils.c,
+ pango/pangoatsui-fontmap.c, pango/pangocairo-fcfont.c,
+ pango/pangocairo-fcfontmap.c, pango/pangocairo-fontmap.c,
+ pango/pangocairo-win32font.c, pango/pangofc-font.c,
+ pango/pangofc-fontmap.c, pango/pangoft2-fontmap.c,
+ pango/pangoft2-render.c, pango/pangoft2.c,
+ pango/pangowin32-fontcache.c, pango/pangoxft-font.c,
+ pango/pangoxft-render.c, pango/break.c pango/ellipsize.c:
+ Use g_slice for allocating all types. Also, change some
+ g_error's to g_critical's...
+
+2006-01-29 Behdad Esfahbod <behdad@gnome.org>
+
+ Do not crash if the (win32 typically) shaper fails. Bug #304702:
+
+ * pango/pango-engine.c (_pango_engine_shape_shape): Set num_glyphs to
+ zero if failing.
+
+ * pango/pango-shape.c (pango_shape): Instead of crashing if the shaper
+ failed to produce any glyphs, print out a warning message containing
+ the name of the font, and mark the font such that we don't keep
+ printing warning for the same font. Moreover, inject one whitespace
+ glyph per character, so you just see nothing, but everything works
+ otherwise.
+
+2006-01-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * .cvsusers: Removed.
+
+2006-01-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * doc/tmpl/opentype.sgml: Document PangoOTBuffer and PangoOTGlyph.
+
+ * pango/pango-ot-buffer.c, pango/pango-ot-info.c,
+ pango/pango-ot-ruleset.c: Document remaining symbols.
+
+2006-01-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/pango-ot-*: Removed.
+
+ * pango/pango-ot-*: Added.
+
+ * pango/Makefile.am, pango/opentype/Makefile.am, doc/Makefile.am:
+ Adjusted.
+
+2006-01-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-font.h, pango/pangoft2-render.c, pango/pangowin32.c,
+ pango/pangoxft-render.c, docs/tmpl/xft-fonts.sgml,
+ docs/tmp/atsui-fonts.sgml: Documentation improvements.
+
+2006-01-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Use AC_HELP_STRING everywhere. Bump required version
+ to 2.56.
+
+ * doc/tmpl/pango-renderer.sgml (PANGO_TYPE_RENDER_PART): Document it.
+
+2006-01-27 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/Makefile.am: Remove pango.modules on uninstall. (bug #328869)
+
+ * pango/pango-fontmap.c, pango/pangocairo-*font.c: Better error
+ messages.
+
+2006-01-26 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoatsui-fontmap.c: #include <modules.h>. (bug #328632)
+
+2006-01-26 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/modules.h, pango/Makefile.am: Fix more ATSUI stuff in build
+ infrastructure. Sigh... (bug #328632)
+
+2006-01-25 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: If major.minor of required and available glib versions
+ are the same, add -DG_DISABLE_DEPRECATED to GLIB_CFLAGS. (bug #328617)
+
+ * */Makefile.am: Remove hardcoded -DG_DISABLE_DEPRECATED.
+
+2006-01-25 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoatsui-fontmap.c (pango_atsui_family_class_init): Declare
+ int i! (bug #328632)
+
+2006-01-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangolayout.c (pango_layout_get_width): Improve docs to say
+ it may return -1.
+
+2006-01-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-atsuifont.c: Change cwfont to cafont in a couple
+ places.
+
+2006-01-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/indic/pango-indic-script.h: Removed, not used for quite a
+ while.
+
+2006-01-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/pangoft2.aliases: Removed based on an old ChangeLog entry
+ saying: Remove pangoft2.aliases from CVS/distribution; it is
+ no longer used. (#82736, Sven Neumann.)
+
+2006-01-23 Behdad Esfahbod <behdad@gnome.org>
+
+ Make tests/examples do use generated pango.modules. (bug #328291)
+
+ * examples/pangorc, tests/pangorc: Removed. Moved to modules/.
+
+ * examples/pangox.aliases: Removed. Moved to pango/.
+
+ * examples/Makefile.am, tests/Makefile.am: Remove pango.modules
+ creation stuff, copy pangorc from $(srcdir)/../modules/pangorc
+ insteadd.
+
+ * examples/renderdemo.c: Add --pangorc option, default to ./pangorc.
+ Setenv PANGO_RC_FILE to whatever pangorc file decided.
+
+ * tests/*.c: Setenv PANGO_RC_FILE to ./pangorc.
+
+ * pango/pangox.aliases: Added.
+
+ * pango/Makefile.am: Install pangox.aliases.
+
+ * modules/pangorc: Added.
+
+ * modules/Makefile.am: Create pango.modules. Added pangorc.
+
+ * modules/.cvsignore, examples/.cvsignore, tests/.cvsignore: Updated.
+
+2006-01-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/basic-fc.c: Set cluster only on base chars, like the
+ Arabic module does.
+
+ * modules/indic/indic-fc.c: Draw an unknown glyph on missing glyphs,
+ like other modules do. (part of bug #326960, LingNing Zhang)
+
+2006-01-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/TEXT/coding-style: Added "Since:" in the doc example.
+
+2006-01-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * TODO: Removed old file. Filed some bugs out of it.
+
+ * TODO.xml: Removed old file. Filed some bugs out of it.
+
+ * Makefile.am (EXTRA_DIST): Removed TODO.xml.
+
+2006-01-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * MAINTAINERS: Added.
+
+ * AUTHORS: Added myself to contributors.
+
+ * Makefile.am: Added MAINTAINERS to EXTRA_DIST.
+
+2006-01-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fontmap.c (pango_cairo_context_get_font_options):
+ Fix typo in docs.
+
+2006-01-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.c (pango_matrix_get_font_scale_factor): Fix docs.
+
+2006-01-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-types.h, pango/pango-utils.c
+ (pango_matrix_get_font_scale_factor): Make matrix parameter const.
+
+ * pango/fonts.c, pango/pango-context.c, pango/pango-coverage.c,
+ pango/pango-fontset.c, pango/pango-layout.c, pango/pango-renderer.c,
+ pango/pango-types.h, pango/pango-utils.c,
+ pango/pangocairo-atsuifont.c, pango/pangofc-font.c,
+ pango/pangoft2-fontmap.c, pango/pangowin32-fontmap.c,
+ pango/pangowin32.c, pango/pangox-fontmap.c, pango/pangoxft-font.c:
+ Replace "Returns:" with "Return value:" in docs.
+
+2006-01-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Finish ATSUI module work. Bug #322022, Matthias Clasen.
+
+ * docs/tmpl/atsui-fonts.sgml: Added.
+
+ * docs/pango-docs.sgml: Updated to reflect above change.
+
+ * docs/pango-sections.txt: Updated to reflect above change and
+ also document Standard ATSUI symbols.
+
+ * pango/pangocairo-atsuifont.c
+ (pango_cairo_atsui_font_get_atsu_font_id): Add docs.
+
+ * pango/pangoatsui-fontmap.c: Register included ATSUI modules.
+
+2006-01-20 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/cairosimple.c: Small fixes.
+
+2006-01-20 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-font.c (_pango_cairo_get_hex_box_info): Add a
+ comment about using cairo_scaled_font_text_extents instead of
+ cairo_text_extents.
+
+2006-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.11.2 ===
+
+ * configure.in: Version 1.11.2
+
+ * NEWS: Updated.
+
+2006-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/Makefile.am: Move GLIB_CFLAGS before external libraries'
+ CFLAGS. Some formatting changes too.
+
+2006-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/Makefile.am, examples/Makefile.am, pango/Makefile.am,
+ tests/Makefile.am: Adjust the order of *_CFLAGS to the same order
+ known to work. (Fixes bug #325588)
+
+2006-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Fixes bug #314675, Brian Cameron.
+
+ * configure.in: Handle uninstalled cairo.
+
+ * pangocairo-uninstalled.pc.in: Fix typo: libpangoxft->libpangocairo.
+
+2006-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/indic/mprefixups.c (indic_mprefixups_apply): Remove unused
+ variable clusterSave that was leaking too. (bug #316466, Steve Grubbs)
+
+2006-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Fixes bug #71414, allowing to disable building/installing modules.
+
+ * configure.in: Add support for --with-dynamic-modules.
+
+ * */Makefile.am: Adapt to the above change.
+
+2006-01-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Draw hexbox for cairo backend. Bug #313551. Based on patch by
+ LingNing Zhang.
+
+ * pango/pangocairo-private.h (_PangoCairoFontIface): Add new methods:
+ get_font_face and get_scaled_font, and getters:
+ _pango_cairo_font_get_font_face, _pango_cairo_font_get_scaled_font.
+
+ * pango/pangocairo-private.h: Add _PangoCairoHexBoxInfo, and getter
+ _pango_cairo_get_hex_box_info, and
+ _pango_cairo_get_glyph_extents_missing.
+
+ * pango/pangocairo-fcfont.c, pango/pangocairo-atsuifont.c,
+ * pango/pangocairo-win32font.c: Export get_font_face and
+ get_scaled_font methods.
+
+ * pango/pangocairo-fcfont.c: Use _pango_cairo_get_glyph_extents_missing
+ on missing glyphs.
+
+ * pango/pangocairo-font.c: Implement _pango_cairo_font_get_font_face,
+ _pango_cairo_font_get_scaled_font, _pango_cairo_get_hex_box_info, and
+ _pango_cairo_get_glyph_extents_missing.
+
+ * pango/pangocairo-render.c (_pango_cairo_renderer_draw_unknown_glyph):
+ Added.
+ * pango/pangocairo-render.c (pango_cairo_renderer_draw_glyphs):
+ Cleaned up to use the added function above.
+
+2006-01-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * */*.c, */*/*.c: Make sure #include <config.h> is the first include
+ in the file. (bug #158870, based on patch by Luis Menina)
+
+2006-01-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.h (pango_is_zero_width): Move G_GNUC_CONST to
+ after declaration, to be compatible with gcc 2.95. (bug #326847)
+
+2006-01-05 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/Makefile.am,
+ * pango/fonts.c,
+ * pango/glyphstring.c,
+ * pango/pango-attributes.c,
+ * pango/pango-color.c,
+ * pango/pango-impl-utils.h,
+ * pango/pango-item.c,
+ * pango/pango-layout.c,
+ * pango/pango-tabs.c,
+ * pango/pango-utils.c,
+ * pango/pango-utils.h,
+ * pango/pangoatsui-fontmap.c,
+ * pango/pangocairo-font.c,
+ * pango/pangocairo-fontmap.c,
+ * pango/pangofc-fontmap.c,
+ * pango/pangowin32-fontmap.c,
+ * pango/pangox-fontmap.c,
+ * pango/pangox.c,
+ * pango/opentype/pango-ot-info.c,
+ * pango/opentype/pango-ot-ruleset.c: Intern strings to avoid
+ unnecessary strdups in the type system. (bug #325832, Matthias Clasen)
+
+2006-01-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/Makefile.am (IGNORE_HFILES): Add pangocairo-atsui.h and
+ pangoatsui-private.h.
+
+ * docs/pango-sections.txt: Add pango_matrix_get_font_scale_factor and
+ pango_layout_index_to_line_x that were missing.
+
+ * docs/tmpl/glyphs.sgml: Add pango_matrix_get_font_scale_factor where
+ other pango_matrix functions reside.
+
+ * docs/tmpl/layout.sgml: Add pango_layout_index_to_line_x.
+
+2006-01-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-context.c: Use g_slice for ShaperFontElement
+ allocation. (bug #325728, Matthias Clasen)
+
+2006-01-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-attributes.c: Use g_slice for various attribute types
+ allocations. (bug #325040, Matthias Clasen)
+
+2005-12-27 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-context.c (pango_context_init): Use
+ pango_font_description_set_family_static. (bug #325013, Matthias
+ Clasen)
+
+2005-12-27 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/pango-ot-buffer.c: Use g_slice for PangoOTBuffer
+ allocation. (bug #325026, Matthias Clasen)
+
+2005-12-26 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/arabic/arabic-fc.c,
+ * modules/basic/basic-fc.c,
+ * modules/hebrew/hebrew-fc.c,
+ * modules/syriac/syriac-fc.c: Use pango_is_zero_width() to not draw
+ zero-width characters in the OpenType shapers. (Fixes bug #324621)
+
+2005-12-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango.def: Add pango_matrix_get_font_scale_factor. (bug
+ #323978, J. Ali Harlow)
+
+2005-12-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/modules.c (pango_module_load), pango/querymodules.c: Pass
+ G_MODULE_BIND_LOCAL to g_module_open. (Pointed by Federico)
+
+2005-12-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.11.1 ===
+
+ * configure.in: Version 1.11.1
+
+ * NEWS: Updated.
+
+2005-12-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/Makefile.am: Handle module-defs-atsui.c.
+
+2005-12-12 Behdad Esfahbod <behdad@gnome.org>
+
+ Fix bug #323540.
+
+ * pangofc-fontmap.c (get_scaled_size): The logic in there is moved
+ and renamed into pango-utils.
+
+ * pango/pango-types.h,
+ * pango/pango-utils.c (pango_matrix_get_font_scale_factor):
+ New function.
+
+ * pango/pangocairo-fcfont.c (get_font_size): Divide pixel-size by
+ matrix font-scale-factor, since pixel-size is scaled.
+
+2005-12-11 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Undo last change. 2.9.1 has the revised
+ g_slice_free_chain api and 2.9.2 is not released yet!
+
+2005-12-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Bump required glib version to 2.9.2 now that it's
+ released. We are relying on the revised g_slice_free_chain api.
+
+2005-12-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_glyph_extents):
+ Update on missing-box drawing change. Add (!glyph) to the conditional.
+
+2005-12-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_finalize): Free
+ ->fontset_hash. (#323498, Morten Welinder)
+
+2005-12-05 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fcfont.c, pango/pangocairo-private.h,
+ pango/pangocairo-render.c: Draw an empty dashed box on missing glyphs
+ for cairo-fc backend.
+
+2005-12-05 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/mini-fribidi/fribidi.c, pango/mini-fribidi/fribidi_config.h,
+ pango/mini-fribidi/fribidi.patch: Use new g_slice API for TypeLink
+ allocation, instead of GMemChunks.
+
+ * configure.in: Bump required glib version to 2.9.1.
+
+2005-12-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/basic-fc.c: Return NULL, not FALSE!
+
+ * modules/arabic-arabic-fc.c: Add 'cswh' (swash) OpenType feature, as
+ per the Arabic OpenType spec.
+
+2005-11-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/Makefile.am: Add GLIB_LIBS to examples explicitly. (#322885,
+ Manish Singh)
+
+2005-11-29 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fcfont.c: Add a constact fixed-size (256) cache for
+ caching glyph extents, instead of the growing g_hash_table. The cache
+ itself is very similar to the recent gunichar->glyph cache done by
+ Federico. Reviewed by Matthias Clasen.
+
+2005-11-24 Matthias Clasen <mclasen@redhat.com>
+
+ * pango/pango-layout.c: Fix a typo.
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/mapping.c (pango_glyph_string_index_to_x),
+ pango/pango-layout.c (pango_layout_iter_get_char_extents):
+ Remove cast to double in things like a = b / c where a, b,
+ and c are all ints. (#312469, Sven Neumann)
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentyp/pango-ot-buffer.c: Fix typo in docs.
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/querymodules.c: Tiny clean up. Simpler way to suppress
+ gcc strict-aliasing warning. (part of #123307)
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c pango/pango-attributes.c pango/pango-context.c
+ pango/pango-glyph-item.c pango/pango-layout.c
+ pango/pango-script.c pango/pango-utils.c pango/pangofc-font.c
+ pango/pangoft2-fontmap.c pango/opentype/pango-ot-buffer.c
+ pango/opentype/pango-ot-ruleset.c: Added "Since:" tags to all
+ interfaces added after Pango 1.0. (#319116, Brian Cameron)
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in (enable_explicit_deps): Fix typo when checking
+ libtool config deplibs_check_method. Moreover, enable explicit
+ deps if we get anything other than pass_all from libtool. (part of
+ #318750)
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/Makefile.am: Link libpangoxft with -lm. (#318210)
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/querymodules.c: Free used memory. (#316467, Steve Grubb)
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/hangul/hangul-fc.c (hangul_engine_shape): Fix incorrect
+ bounds check. (#316469, Steve Grubb) Moreover, increase max_jamos
+ eight at a time instead of three.
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ Protect against possible division by zeros. (#316468, Steve Grubb)
+
+ * pango/pango-context.c (update_metrics_from_items),
+ pango/pango-fontset.c (pango_fontset_real_get_metrics): If count is
+ zero, do not alter approximate_{char,digit}_width.
+
+ * pango/opentype/disasm.c: Err on invalid DeltaFormat.
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (pango_font_description_get_absolute_size): Remove
+ excess "the" in docs. (#319175, Masao Mutoh)
+
+2005-11-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/basic-fc.c: Reworked basic shaper with OpenType
+ support. (#101079, based on patch from Denis Jacquerye and Noah Levitt)
+
+ * modules/basic/basic-fc.c (basic_scripts): Added Unicode 4.1 addition
+ script PANGO_SCRIPT_GLAGOLITIC that is a "simple" script.
+
+ * modules/arabic/arabic-fc.c, modules/syriac/syriac-fc.c: Replace
+ g_utf8_to_ucs4_fast() with g_utf8_strlen()!
+
+ * pango/opentype/pango-ot-ruleset.c (pango_ot_ruleset_add_feature):
+ Remove reference in docs to pango_ot_ruleset_shape() that was
+ removed long ago.
+
+2005-11-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-font.c: Finish previous patch. Use GType private
+ data, cache it into fcfont->priv. Get rid of
+ PANGO_FC_FONT_GET_PRIVATE (fcfont) and access fcfont->priv. (#322174,
+ Christian Persch)
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_init): Remove redundant
+ priv = fcfontmap->priv initialization.
+
+2005-11-22 Federico Mena Quintero <federico@ximian.com>
+
+ Fixes #322174:
+
+ * pango/pangofc-font.h (struct _PangoFcFont): Replace the
+ "gpointer context_key" field with "gpointer priv". This way we
+ can access the private data quickly, instead of using
+ g_type_instance_get_private().
+
+ * pango/pangofc-private.h: Added prototypes for
+ _pango_fc_font_{get,set}_context_key().
+
+ * pango/pangofc-font.c (struct _PangoFcFontPrivate): Moved the
+ "context_key" field to here.
+ (PANGO_FC_FONT_GET_PRIVATE): Use the "priv" field instead of GType
+ private data.
+ (pango_fc_font_class_init): Don't register GType private data.
+ (pango_fc_font_init): Initialize the private data here.
+ (pango_fc_font_finalize): Free the private data.
+ (_pango_fc_font_get_context_key): Implement.
+ (_pango_fc_font_set_context_key): Implement.
+ (pango_fc_font_get_glyph): Remove the g_return_val_if_fail(); it
+ was appearing quite high in the profile.
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_add): Call
+ _pango_fc_font_set_context_key() instead of setting the
+ fcfont->context_key directly.
+ (_pango_fc_font_map_remove): Likewise; also use
+ _pango_fc_font_get_context_key() instead of accessing the field
+ directly.
+
+2005-11-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoxft-font.c (_pango_xft_font_get_mini_font): Load a font
+ suitable for viewing English text when creating mini font for hex
+ boxes. (#312477)
+
+2005-11-21 Anders Carlsson <andersca@imendio.com>
+
+ Bug #322022, add ATSUI backend:
+
+ * configure.in: Add checks for ATSUI.
+
+ * examples/Makefile.am: Only build pango-cairoview if freetype is
+ detected.
+
+ * modules/basic/Makefile.am: Add basic ATSUI module.
+
+ * pango/Makefile.am: Add ATSUI files for cairo backend.
+
+ * pango/pangocairo-fontmap.c (pango_cairo_font_map_new): Support
+ creating ATSUI font maps here.
+
+ * pango/pangoatsui-fontmap.c:
+ * pango/pangoatsui-private.h:
+ * pango/pangoatsui.c:
+ * pango/pangoatsui.h:
+ * pango/pangocairo-atsui.h:
+ * pango/pangocairo-atsuifont.c:
+ * pango/pangocairo-atsuifont.h:
+ * pango/pangocairo-atsuifontmap.c: Added.
+
+2005-11-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-script.c (pango_script_for_unichar_bsearch): Only update
+ static mid on a match.
+
+2005-11-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-fontmap.c (get_scaled_size): Return double instead of
+ int. (#321891, Sebastien Bacher)
+
+2005-11-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/GLASS.utf8: Make the Kermit notice a "no warranty" clause,
+ to comply with LPGL.
+
+2005-11-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.11.0 ===
+
+ * configure.in: Version 1.11.0
+
+ * NEWS: Updated.
+
+2005-11-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually): Use the
+ new support for negative offsets in g_utf8_pointer_to_offset. So now,
+ we simply do:
+ offset += g_utf8_pointer_to_offset(text+oldindex, text+newindex),
+ instead of doing
+ offset = g_utf8_pointer_to_offset(text, text+index) as we did before.
+
+2005-11-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-renderer.c: Documentation improvements. (#321731)
+
+2005-11-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (pango_font_description_*): General cleanup.
+ (pango_font_description_unset_fields): Set fields being unset to their
+ default value.
+ (pango_font_description_hash, pango_font_description_equal): Do not
+ use mask in these. Use all other fields unconditionally.
+
+2005-11-17 Matthias Clasen <mclasen@redhat.com>
+
+ * modules/hangul/tables-jamos.i: const correctness
+ fixes found by Arjan van de Ven and gcc.
+
+2005-11-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-fontmap.c (fontset_hash_key_equal): Compare language
+ too. (#318168)
+
+2005-11-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/break.c (pango_get_log_attrs): Remove g_utf8_strlen that was
+ only used to give a warning.
+
+ * pango/break.c (pango_default_break): Add gcc-suggested parantheses
+ around boolean expression.
+
+2005-11-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/tmpl/coverage-maps.sgml docs/tmpl/fonts.sgml
+ docs/tmpl/glyphs.sgml docs/tmpl/layout.sgml
+ docs/tmpl/main.sgml docs/tmpl/scripts.sgml
+ docs/tmpl/tab-stops.sgml docs/tmpl/text-attributes.sgml
+ pango/break.c pango/fonts.c pango/pango-fontset.c
+ pango/pango-layout.c pango/pango-script.c pango/pango-utils.c
+ pango/pangofc-decoder.c pango/pangofc-decoder.h
+ pango/pangofc-font.c pango/pangofc-font.h
+ pango/pangoxft-font.c: More documentation improvements.
+
+2005-11-17 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of #101079:
+
+ * pango/opentype/ftxopen.c (Load_Lookup): In extension subtables,
+ offset is relative to the extension subtable, not the original
+ table. (Greg Aumann)
+
+ * pango/opentype/ftxgpos.c (Load_BaseArray): When reading BaseAnchor,
+ skip offsets that are zero. Works around bug in Doulos SIL Regular.
+
+2005-11-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango_markup.sgml docs/tmpl/coverage-maps.sgml
+ docs/tmpl/engines.sgml docs/tmpl/fonts.sgml
+ docs/tmpl/freetype-fonts.sgml docs/tmpl/glyphs.sgml
+ docs/tmpl/layout.sgml docs/tmpl/main.sgml
+ docs/tmpl/modules.sgml docs/tmpl/opentype.sgml
+ docs/tmpl/pango-engine-lang.sgml
+ docs/tmpl/pango-engine-shape.sgml
+ docs/tmpl/pango-renderer.sgml docs/tmpl/pangocairo.sgml
+ docs/tmpl/pangofc-decoder.sgml docs/tmpl/pangofc-font.sgml
+ docs/tmpl/pangofc-fontmap.sgml docs/tmpl/scripts.sgml
+ docs/tmpl/tab-stops.sgml docs/tmpl/text-attributes.sgml
+ docs/tmpl/win32-fonts.sgml docs/tmpl/x-fonts.sgml
+ docs/tmpl/xft-fonts.sgml pango/break.c pango/ellipsize.c
+ pango/fonts.c pango/pango-attributes.c pango/pango-color.c
+ pango/pango-context.c pango/pango-coverage.c
+ pango/pango-fontmap.c pango/pango-glyph-item.c
+ pango/pango-layout.c pango/pango-markup.c pango/pango-tabs.c
+ pango/pango-types.h pango/pango-utils.c
+ pango/pangoft2-render.c pango/pangox.c pango/pangoxft-render.c:
+ Various documentation improvements.
+
+2005-11-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-types.h: Added % to PANGO_DIRECTION_LTR in doc comments.
+
+2005-11-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/GLASS.utf8: Added redistribution permission.
+
+2005-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/khmer/khmer/khmer-fc.c: Fixed bug in khmer module state
+ table. (#320569, Jens Herden)
+
+2005-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Updated Tibetan shaper from Pema Geyleg. (#313513)
+
+ * examples/tibetan.utf: Added.
+
+ * examples/Makefile.am (EXTRA_DIST): tibetan.utf added.
+
+ * modules/tibetan/tibetan-fc.c: Updated Tibetan shaper that is
+ rewritten from scratch. Supports the number pre-combining mark,
+ illegal sequence detection, etc.
+
+2005-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/GLASS.utf8: Added. The infamous "I Can Eat Glass" in
+ vairous languages. Adopted from
+ http://www.columbia.edu/kermit/utf8.html#glass
+
+ * examples/Makefile.am (EXTRA_DIST): GLASS.utf8 added.
+
+2005-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fcfont.c: Respect fontconfig reassignment of
+ pixelsize. (#317121, Funda Wang)
+
+2005-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Updates from #320666:
+
+ * pango/Makefile.am: Remove pango-easy-scripts-table.h.
+
+ * pango/pango-easy-scripts-table.h: Removed. The "easy" table goes
+ into pango-scripts-table.h too.
+
+ * pango/pango-script-table.h: Include "easy" table.
+
+ * pango/pango-script.c: Change gunichar->script last_index caching
+ mechanism. The caching is simply done by making int mid in the
+ bsearch static.
+
+ * tools/Makefile.am: Remove gen-easy-scripts-table.c.
+
+ * tools/gen-easy-scripts-table.c: Removed. The "easy" table is
+ generated in gen-scripts-table.pl too.
+
+ * tools/gen-script-table.h: Generate "easy" table.
+
+2005-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/Makefile.am: Add X_CFLAGS to INCLUDES. We normally are
+ picking them up from XFT_CFLAGS, but we don't require Xft any more
+ for X11. (#320576)
+
+2005-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/break.c (pango_default_break): Remove g_utf8_strlen and
+ work around the logic. Patch by Owen Taylor.
+
+2005-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/mini-fribidi/fribidi.c): Include string.h, needed for memset.
+
+ * pango/mini-fribidi/fribidi.c (fribidi_analyse_string_utf8):
+ Handle short-circuiting of the case when there are ltr letters,
+ no rtl strongs, and base dir is weak rtl. Pointed out by Owen Taylor.
+
+2005-11-11 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (pango_layout_get_alignment): Fix get/set
+ typo in docs. (#321247, Masao Mutoh)
+
+2005-11-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fontmap.c (pango_cairo_update_context): Call
+ get_context_info after g_return_if_fail.
+
+2005-11-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/break.c (pango_break): Do not call strlen when length < 0.
+ Leave it to language engines to handle NULL-terminated strings.
+
+2005-11-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/mini-fribidi/README, pango/mini-fribidi/fribidi.patch,
+ pango/mini-fribidi/fribidi.c: Short-circuit on LTR-only or RTL-only
+ text.
+
+2005-11-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/ftxgpos.c, pango/opentype/ftxopen.c: Remove debug
+ line that got in accidentally.
+
+2005-11-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/renderdemo.c (make_layout): Set layout wrapping to
+ PANGO_WRAP_WORD_CHAR if width is set for the layout. Setting width
+ didn't have any effect previously.
+
+ * pango/pango-layout.c (process_item): Remove the excess
+ letter_spacing adjustment on the item width. (#168593, Damon Chaplin)
+
+ * pango/pango-markup.c (pango_parse_markup), pango/querymodules.c:
+ Replace g_string_new ("") with g_string_new (NULL).
+
+ * pango/pangoft2.c: Use g_malloc'ed memory for unknown FreeType2
+ error, instead of static buffer.
+
+2005-11-09 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/hebrew/.cvsignore, modules/khmer/.cvsignore,
+ modules/tibetan/.cvsignore: Minor clean up and adjustment.
+
+2005-11-07 Federico Mena Quintero <federico@ximian.com>
+
+ Fixes bug #320666:
+
+ Instead of doing a bsearch() for every gunichar to map it to a
+ PangoScript, use a precomputed table for the first 8192 code
+ points. Also, remember the last script that we computed on each
+ invocation; this will also help CJK and the other scripts above
+ U+2000.
+
+ This table also holds information on whether the characters in it
+ are paired characters. We can use this to avoid doing the
+ expensive get_pair_index() call most of the time.
+
+ Many thanks to Matthias Clasen for his suggestions for this patch.
+
+ * tools/gen-easy-scripts-table.c: New program to generate
+ pango_easy_scripts_table.
+
+ * tools/Makefile.am: Build gen-easy-scripts-table.
+
+ * pango/pango-easy-scripts-table.h: New file with a mapping of the
+ first 8192 Unicode characters to their corresponding scripts. The
+ table also says whether each character has a paired char or not.
+
+ * pango/Makefile.am (libpango_1_0_la_SOURCES): Add pango-easy-scripts-table.h.
+
+ * pango/pango-script-table.h: Remove everything below U+2000, and
+ add a note to that effect.
+
+ * pango/pango-script.c (pango_script_for_unichar_with_last_index):
+ New function. This is the old pango_script_for_unichar(), but it
+ lets the caller keep around the computed index in
+ pango_script_table. This works under the assumption that a
+ character is likely to be in the same script block as the
+ preceding character in a string.
+ (pango_script_for_unichar): First, do a quick check against the
+ pango_easy_scripts_table. Then, do the expensive check with
+ pango_script_for_unichar_with_last_index().
+ (pango_script_iter_next): If the character is within the easy
+ script range, find out if it is a paired character by using
+ PANGO_PAIRED_CHAR_FLAG.
+ (struct _PangoScriptIter): Add a last_index_for_script_lookup
+ field. We use this to maintain the last-lookup index from
+ pango_script_for_unichar_with_last_index().
+ (pango_script_iter_next): If the character is not within the easy
+ script range, use pango_script_for_unichar_with_last_index(), and
+ store the index in the last_index_for_script_lookup field of the
+ PangoScriptIter.
+
+2005-11-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-config.in, pango.spec.in: Removed. Not used for a long time,
+ and were out of date.
+
+ * .cvsignore: Remove pango-config and pango.spec.
+
+2005-11-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/break.c: Update to handle new line-breaking types in the
+ Unicode 4.1 UAX#14. (#313907)
+
+ * configure.in: Bump required glib version to 2.9.0. Needed for
+ above-mentioned line-breaking types.
+
+2005-11-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in, examples/argcontext.c examples/cairoview.c,
+ examples/renderdemo.c, examples/renderdemo.h examples/xftview.c,
+ modules/basic/basic-x.c, modules/hangul/hangul-fc.c,
+ modules/hebrew/hebrew-shaper.c, modules/hebrew/hebrew-shaper.h,
+ modules/indic/indic-fc.c, modules/indic/mprefixups.c,
+ modules/syriac/syriac-fc.c, pango/break.c pango/fonts.c,
+ pango/modules.c, pango/pango-coverage.c pango/pango-engine.c,
+ pango/pango-engine.h, pango/pango-fontmap.c,
+ pango/pango-fontset.c, pango/pango-impl-utils.h,
+ pango/pango-layout.c, pango/pango-layout.h,
+ pango/pango-renderer.c, pango/pango-script.c,
+ pango/pango-utils.c, pango/pangocairo-fc.h,
+ pango/pangocairo-font.c, pango/pangocairo-fontmap.c,
+ pango/pangocairo-private.h, pango/pangofc-decoder.c,
+ pango/pangofc-font.c, pango/pangofc-fontmap.c pango/pangoft2.c,
+ pango/pangox-fontcache.c, pango/pangox-fontmap.c pango/pangox.c,
+ pango/pangoxft-font.c, pango/querymodules.c,
+ pango/opentype/ftglue.c, pango/opentype/ftxgpos.c,
+ pango/opentype/ftxopen.c, pango/opentype/pango-ot-buffer.c,
+ pango/opentype/pango-ot-info.c,
+ pango/opentype/pango-ot-ruleset.c, tests/dump-boundaries.c,
+ tests/testboundaries.c, tests/testcolor.c tests/testiter.c,
+ tests/testscript.c: Turn various gcc warnings off. Adding const,
+ adding static, fully initializing structs, match signedness in
+ comparisons. (#317804)
+
+ * tests/testscript.c, tools/gen-script-for-lang.c:
+ (scripts_for_file): Pass error->message instead of error to fail(),
+ which was wrong.
+ (compare_lang): Fix typo comparing a and a instead of a and b.
+
+2005-11-04 Federico Mena Quintero <federico@ximian.com>
+
+ Fixes #320665:
+
+ * pango/pangocairo-fcfont.c: Use a simple, fixed-size cache to map
+ gunichars to glyph indices within the font. The cache is
+ described in detail here:
+ http://primates.ximian.com/~federico/news-2005-10.html#gtkfilechooser-profile-5
+ (GlyphCacheEntry): new structure to hold a gunichar and a PangoGlyph.
+ (struct _PangoCairoFcFont): Add a char_to_glyph_cache field.
+ (pango_cairo_fc_font_get_glyph): Allocate the char_to_glyph_cache
+ if needed. We do it on demand because while many fonts will be
+ alive at any one time (in order to cover the whole Unicode space),
+ only very few of them will be actually accessed for glyph lookups.
+ (pango_cairo_fc_font_get_glyph): Look up the gunichar in the
+ cache, and replace the cache entry if necessary.
+ (pango_cairo_fc_font_finalize): Free the char_to_glyph_cache.
+
+2005-11-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fontmap.c: Use quarks for GObject data to improve
+ performance. (Patch from Federico Mena Quintero)
+
+ * pango/modules.c (pango_module_load), pango/querymodules.c: Pass
+ G_MODULE_BIND_LAZY to g_module_open. (Pointed by John Rice)
+
+2005-11-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-font.c: Use macros for locking and unlocking fonts
+ we know are valid to avoid redundant PANGO_IS_FC_FONT checks.
+ (Review by Matthias Clasen)
+
+2005-11-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/tmpl/main.sgml, pango/Makefile.am, pango/pango-context.c
+ (itemize_state_init), pango/pango-utils.c, pango/pango-utils.h,
+ pango/pangox.c (itemize_string_foreach), pango/mini-fribidi/*:
+ Updated to FriBidi version 0.10.7 patched to handle UTF-8 directly.
+ Moved pango_log2vis_get_embedding_levels to pango-utils.c instead
+ of mini-fribidi. (#317192, review by Matthias Clasen)
+
+2005-11-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/pangoft2pgm.c, renderdemo.c, renderdemo.h: Added a --runs
+ options, useful for profiling. Misc cleanup, freeing memory. (from
+ #170414)
+
+2005-11-03 Behdad Esfahbod <behdad@gnome.org>
+
+ Patches from #170414. Reviewed by Matthias Clasen.
+
+ * pango/opentype/ftxgpos.c, pango/opentype/ftxgsub.c: Use call table
+ to dispatch different lookup types.
+
+ * pango/opentype/pango-ot-buffer.c, pango/opentype/pango-ot-ruleset.c:
+ Small cleanup.
+
+2005-10-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-engine.h: Add const to gchar * members of structs.
+ Shuts up gcc warnings. (#317676)
+
+2005-09-09 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-render.c (pango_cairo_show_glyph_string): unset
+ all part colors, since when drawing just a glyph string,
+ prepare_run() isn't called. (#315599, Choe Hwanjin)
+
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line): NULL
+ out renderer->priv->line_state.
+
+2005-09-25 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/mini-fribidi/fribidi_get_type.c: Removed. Not needed since
+ 2003 or so!
+
+2005-09-22 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangocairo-win32font.c (_pango_cairo_win32_font_new): Move
+ the calculation of dpi and size earlier. Use the size variable
+ instad of isize when looking for a matching cached font. Isize was
+ supposed to be the same as size anyway. (Actually it was the same
+ only when LOGPIXELSY equalled 96 (which often is the default
+ value), see below.)
+
+ * pango/pangocairo-win32fontmap.c (pango_cairo_win32_font_map_init):
+ Set dpi to the LOGPIXELSY value instead of hardcoding 96.
+
+ * pango/Makefile.am (libpangocairo_1_0_la_LIBADD): Need WIN32_LIBS
+ now.
+
+2005-09-14 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangocairo-win32font.c: Use identical glyph extents
+ cacheing as in pangocairo-fcfont.c. Huge performance improvement.
+
+ * README.win32: Update.
+
+2005-09-14 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangocairo-win32font.c (struct _PangoCairoWin32Font): Have
+ a list of metrics by language instead of just one metrics.
+
+ (pango_cairo_win32_font_get_scaled_font): Use the name cwfont
+ instead of cffont.
+
+ (free_metrics_info, pango_cairo_win32_font_finalize): Free the
+ metrics by language list.
+
+ (create_metrics_for_context): New helper function. Approximate the
+ character and digit widths correctly. (#314114)
+
+ (pango_cairo_win32_font_get_metrics): Use the list of metrics by
+ language. Call create_metrics_for_context() to measure metrics.
+
+ (_pango_cairo_win32_font_new): Keep the PangoWin32Font objects in
+ the PangoWin32Face::cached_fonts, like the pangowin32 backend
+ does.
+
+ PangoWin32Face::cached_fonts isn't really a proper cache. It's a
+ list with unbound length, one PangoWin32Font per size. Once there
+ is cacheing in cairo this can be dropped presumably? What does the
+ pangofc backend do? There are too many levels of cacheing going
+ on: we have the stuff in pangowin32-fontcache.c (unused now with
+ cairo), the PangoWin32FontMap::freed_fonts cache, and the
+ PangoWin32::cached_fonts list.
+
+ * pango/pangowin32-fontmap.c (pango_win32_fontmap_cache_remove,
+ pango_win32_fontmap_cache_clear): Use GQueue API instead of
+ manipulating pointers manually.
+
+ * pango/pangowin32-private.h
+ * pango/pangowin32.c: Move PangoWin32MetricsInfo to the private
+ header file, as also pangocairo-win32font.c uses it.
+
+2005-09-13 Tor Lillqvist <tml@novell.com>
+
+ * modules/basic/basic-win32.c: Drop unused font_cache variable and
+ the call to pango_win32_font_map_for_display() used in its
+ initialization, which caused an extra instance of
+ PangoWin32FontMap to be created, and fonts enumerated an extra
+ time.
+
+2005-09-12 Jean Brefort <jean.brefort@normalesup.org>
+
+ * pango/pango-attributes.c: (pango_attr_list_splice): Fixed typo
+ (#316054).
+
+2005-09-11 Matthias Clasen <mclasen@redhat.com>
+
+ * pango/pangocairo-fontmap.c (free_context_info): Use g_free()
+ to free g_new()-allocated data, otherwise the GLib memory profiler
+ becomes very unhappy.
+
+2005-09-05 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/pango-layout.c (pango_layout_set_auto_dir): Fixed typo in
+ docs.
+
+2005-08-29 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/opentype/ottest.c, pango/opentype/disasm.c: Generate valid
+ XML output. Dump LookupFlag too.
+
+2005-08-29 Behdad Esfahbod <pango@behdad.org>
+
+ * examples/cairoview.c: Set cairo font resolution.
+
+ * tests/testboundaries.c: Remove unused Hangul Jamo macros.
+
+2005-08-29 Behdad Esfahbod <pango@behdad.org>
+
+ * examples/HELLO.utf8: Add a few Arabic non-spacing marks to the
+ example. Put the line with Pango in Greek-Japanese back in.
+
+2005-08-26 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/break.c: Protect against future line-break type additions in
+ glib Unicode module.
+
+2005-08-25 Tor Lillqvist <tml@novell.com>
+
+ * pango/Makefile.am: Use pangocairo.def when linking libpangocairo
+ on Windows, instead of relying on GNU ld auto-exporting all public
+ symbols.
+
+ * pango/pangocairo.def: Add missing entries. (#314420, Kazuki
+ Iwamoto)
+
+2005-08-24 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangocairo-render.c (draw_error_underline): convert
+ from Pango units to doubles, fix some coordinate space problems
+ that had previously been fixed in GTK+. (#313015, Luis Villa)
+
+Local Variables:
+coding: utf-8
+End:
+vim: encoding=utf-8:
diff --git a/trunk/ChangeLog.pre-1-14 b/trunk/ChangeLog.pre-1-14
new file mode 100644
index 00000000..ca8916de
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-14
@@ -0,0 +1,928 @@
+2006-08-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.14.0 ===
+
+ * configure.in: Version 1.14.0
+ * configure.in: Require cairo-1.2.2 for the bugfixes it has
+
+ * NEWS: Updated.
+
+2006-08-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/renderdemo.c (parse_options): Don't ignore all trailing
+ whitespace in input text. Only chop one newline.
+
+ * examples/viewer-main.c (main): setlocale(LC_ALL, "") to get GOption
+ work for UTF-8 text on the command line.
+
+2006-07-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.13.5 ===
+
+ * configure.in: Version 1.13.5
+
+ * NEWS: Updated.
+
+2006-07-31 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 121672 – Ra (vattu) not rendered properly in Malayalam
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot.c (shiftCharsLeft3), (indic_ot_reorder):
+ Reorder combinations of some three chars!
+
+2006-07-31 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 335811 – Some conjugates of Malayalam are wrong.
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot-class-tables.c: Update consonant tags to
+ fix conjugates.
+
+2006-07-25 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/basic-fc.c: Add Cuneiform and Phoenician in the list
+ of supported scripts by this backend. Phoenician is a simple RTL
+ script.
+
+ * pango/pango-script.c (pango_script_get_sample_language): Add
+ language code "nqo" for script N'Ko.
+
+2006-07-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.13.4 ===
+
+ * configure.in: Version 1.13.4
+
+ * NEWS: Updated.
+
+2006-07-24 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 336282 – Update to Unicode Character Database 5.0.0
+
+ * pango/mini-fribidi/fribidi_tab_char_type_2.i: Update to UCD 5.0.0.
+
+ * pango/mini-fribidi/README: Note the about update.
+
+ * pango/pango-script.h: Add new values for PangoScript.
+
+ * pango/pango-script.c (pango_script_for_unichar_bsearch): Default
+ to PANGO_SCRIPT_UNKNOWN.
+
+ * pango/pango-script.c (pango_script_get_sample_language): Add empty
+ entries for new script values.
+
+ * tools/gen-script-table.pl: Default to PANGO_SCRIPT_UNKNOWN as is
+ now the default value of Scripts.txt in UCD 5.0.0.
+
+ * pango/pango-script-table.h: Regenerated against UCD 5.0.0.
+
+ * docs/tmpl/scripts.sgml: Document new script types.
+
+ * tools/gen-script-for-lang.c (scripts_for_line): Ignore data at the
+ end of lines as many .orth files in fontconfig now list the character
+ name there.
+
+ * pango/pango-script-lang-table.h: Regenerate against newer
+ fontconfig 2.3.9x.
+
+2006-07-24 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 347073 – Allow empty GPOS table
+
+ * pango/opentype/harfbuzz-open.c (_HB_OPEN_Load_ScriptList): Don't
+ err on empty GPOS/GSUB tables.
+
+2006-07-19 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (pango_layout_get_extents): Improve docs.
+
+2006-07-17 Richard Hult <richard@imendio.com>
+
+ Bug 347021 – atsui crash when a matching font cannot be found.
+ Patch from Brian Tarricone.
+
+ * pango/pangoatsui-fontmap.c (pango_atsui_font_map_load_font):
+ Bail out if best desc or best face isn't found.
+
+2006-07-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.13.3 ===
+
+ * configure.in: Version 1.13.3
+
+ * NEWS: Updated.
+
+2006-07-10 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 330603 – pango_scan_int invokes undefined behaviour
+
+ * pango/pango-utils.c (pango_scan_int): Use strtol.
+
+2006-07-10 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 315599 – PangoAttribute remains in wrong context.
+
+ * pango/pangocairo-render.c (_pango_cairo_do_glyph_string): Rever my
+ commit that removed Owen's fix from last year!
+
+2006-07-10 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 163677 – pango_attr_list_splice: inconsistent docs
+ Patch from Morten Welinder
+
+ * pango/pango-attributes.c (pango_attr_list_splice): Improve docs.
+
+2006-07-10 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 345070 – [ml_IN] not render for combination with ZWJ
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot-class-tables.c: Process ZWJ for Malayalam.
+
+2006-07-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 345274 – list of new symbols for each version is missing in docs
+ Patch from Priit Laes
+
+ * docs/pango-docs.sgml: Generate index of deprecated, and new symbols
+ per version.
+
+2006-07-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 346297 – autogen doesn't work with automake-1.6
+ Patch from Priit Laes
+
+ * autogen.sh, configure.in: Require automake 1.7.
+
+2006-07-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/glyphstring.c (pango_glyph_string_get_width):
+ * pango/pango-glyph.h:
+ * pango/pango-layout.c (pango_layout_line_index_to_x),
+ (pango_layout_line_x_to_index), (pango_layout_line_get_x_ranges):
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line): Fix silly
+ error in implementation of pango_glyph_string_get_width(), and also
+ remove unused font parameter from its signature.
+
+2006-07-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Remove obsolete checks for varargs that were
+ preivously used by the OpenType code, but are not needed with
+ HarfBuzz anymore.
+
+2006-07-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 135683 – Cache glyphstring extents
+
+ * pango/pango-layout.c (pango_layout_line_index_to_x),
+ (pango_layout_line_x_to_index), (pango_layout_line_get_x_ranges):
+ Use pango_glyph_string_get_width in most places in PangoLayout.
+
+2006-07-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 135683 – Cache glyphstring extents
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/glyphs.sgml:
+ * pango/pango.def:
+ * pango/pango-glyph.h:
+ * pango/glyphstring.c (pango_glyph_string_get_width): New function.
+ Much faster than calling pango_glyph_string_extents and using
+ logical_rect.width.
+
+ * pango/pango-renderer.c (add_underline), (add_strikethrough),
+ (pango_renderer_draw_layout_line): Use the new function for
+ optimization.
+
+2006-07-07 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 344766 – Memory leak in get_ruleset() in modules/basic/basic-fc.c
+
+ * pango/pango-ot-private.h: Rename PANGO_OT_IS_RULESET is
+ PANGO_IS_OT_RULESET.
+
+ * pango/pango-ot-ruleset.c (pango_ot_ruleset_finalize),
+ (pango_ot_ruleset_new), (pango_ot_ruleset_add_feature),
+ (pango_ot_ruleset_substitute), (pango_ot_ruleset_position):
+ Use weak pointers to reference ruleset->info, to avoid circular
+ dependency.
+
+2006-07-07 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-matrix.c: New file.
+ * pango/pango-utils.c: Move all pango_matrix_* stuff into a separate
+ file.
+
+2006-06-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 345600 – cvs build error in pango/opentype/Makefile
+
+ * pango/opentype/Makefile.am: Rename variable SOURCES to MAINSOURCES.
+ Some automake versions seem to use it or something.
+
+2006-06-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 345511 – -no-undefined problem with new libtool
+
+ * configure.in: Remove -no-undefined on non-Win32 systems. That
+ doesn't make any sense, and makes latest libtool not create shared
+ libraries.
+
+2006-06-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * autogen.sh: Just call gnome-autogen.sh. The old autogen.sh had
+ poor version checking and was borking with libtool 2.x.
+
+ * Makefile.am:
+ * configure.in:
+ * pango-zip.sh.in:
+ * pango/Makefile.am:
+ * pango/pango.rc.in:
+ * pango/pangoft2.rc.in:
+ * pango/pangowin32.rc.in: Rename LT_* variables such that autoconf
+ doesn't err on "possibly undefined macros".
+
+2006-06-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.13.2 ===
+
+ * configure.in: Version 1.13.2
+
+ * NEWS: Updated.
+
+2006-06-07 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info):
+ Set matrix on the context we create to load minifont.
+
+2006-06-07 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 326960 – hex box drawing for win32 and atsui backends of cairo
+
+ Hans already fixed win32.
+
+ * pango/pangocairo-atsuifont.c (compute_glyph_extents): Handle
+ PANGO_GLYPH_UNKNOWN_FLAG.
+
+2006-06-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 343717 – License information in unclear.
+
+ * modules/arabic/arabic-ot.c, modules/syriac/syriac-ot.c: Fix
+ dual-license information and refer to pango/opentype/COPYING.
+
+2006-06-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Followup on previous change.
+
+ * pango/pango-renderer.c: Note that pango_renderer_draw_rectangle
+ and pango_renderer_draw_error_underline should be called with
+ active renderer.
+
+ * pango/pangocairo-render.c (pango_cairo_renderer_draw_glyphs),
+ (_pango_cairo_do_glyph_string), (_pango_cairo_do_layout_line),
+ (_pango_cairo_do_layout): Remove excess cairo_save/restore() calls.
+
+ * pango/pangocairo-render.c (_pango_cairo_do_error_underline): Don't
+ go through renderer.
+
+2006-06-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 343355 – Add pango_cairo_show_error_underline &
+ pango_cairo_error_underline_path
+ Based on patch by LingNing Zhang.
+
+ * docs/pango-sections.txt, docs/tmpl/pangocairo.sgml,
+ pango/pangocairo.def, pango/pangocairo.h, pango/pangocairo-render.c:
+ New functions pango_cairo_show_error_underline and
+ pango_cairo_error_underline_path.
+
+ * pango/pangocairo-render.c (_pango_cairo_do_glyph_string),
+ (_pango_cairo_do_layout_line), (_pango_cairo_do_layout),
+ (_pango_cairo_do_error_underline), (pango_cairo_show_glyph_string),
+ (pango_cairo_show_layout_line), (pango_cairo_show_layout),
+ (pango_cairo_show_error_underline),
+ (pango_cairo_glyph_string_path), (pango_cairo_layout_line_path),
+ (pango_cairo_layout_path), (pango_cairo_error_underline_path): Merge
+ similar code for pango_cairo_show_* and pango_cairo_*_path functions.
+
+2006-06-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 343966 – pango Cygwin build fixes
+ Patch from Cygwin Ports maintainer.
+
+ * configure.in: Add missing space.
+ * tests/Makefile.am: Add $(EXEEXT) where appropriate.
+
+2006-06-05 Hans Breuer <hans@breuer.org>
+
+ * pango/pangowin32-fontmap.c(pango_win32_font_map_init) : synthesize
+ some italic variants for fonts no having them already. This fixes
+ bug #343796 and for the italic case also bug #110521.
+
+ * pango/pangocairo-win32font.c(compute_glyph_extents) : not only
+ handle PANGO_GLYPH_EMPTY but also PANGO_GLYPH_UNKNOWN_FLAG.
+ The latter is needed to have proper sizing of the "hex box" for
+ missing glyphs. It also stops cairo complaining about unknown glyphs.
+ Fixes part of bug #343796.
+
+ * pango/makefile.msc : create $(PRJ_TOP)\config.h.win32. (Not
+ changing in years does not necessarily mean it is not used)
+
+ * pango/testfonts.c : make family_name survive
+ pango_font_description_free(), it is used later on
+
+2006-06-02 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.c (pango_find_base_dir): Don't g_return if text ==
+ NULL and length == 0.
+
+2006-05-31 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 341138 – Using TTC font, Gtk2 programs begin to eating big memory
+ and have many cpu usage.
+ Patch from Yong Li.
+
+ * pango/opentype/ftglue.c (_hb_ftglue_face_goto_table): TrueType table
+ offsets are absolute, not relative.
+
+2006-05-31 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 336153 – Mark to mark positioning (Lookup Type 6) isn't correct
+ when using MarkAttchmentType
+ Patch from Tin Myo Htet.
+
+ * pango/opentype/harfbuzz-gpos.c (Lookup_MarkMarkPos): Ignore marks
+ of non-matchin attachment type.
+
+2006-05-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info): Set
+ absolute_size, since we are using describe_with_absolute_size now...
+
+2006-05-30 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 333984 – pango_language_from_string improvements
+
+ * pango/pango-utils.c (lang_equal), (lang_hash),
+ (pango_language_from_string): Allow digits in language tags as per
+ RFC-3066, and stop on first invalid char. Previous
+ pango_language_from_string ("en_US.UTF-8") was returning "en-usutf-",
+ now it returns "en-us".
+
+ * pango/pango-utils.c (pango_language_matches): Allow other common
+ separators in the language list (colon, comma, and space).
+
+2006-05-30 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 125378 – Better underline thickness handling
+
+ * pango/pango-layout.c (pango_layout_run_get_extents): Include
+ underline in ink extents.
+
+2006-05-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-render.c (draw_error_underline): Fix offset to
+ center the underline in requested rectangle.
+
+ * pango/pangocairo-render.c (pango_cairo_show_glyph_string): Remove
+ unncessary renderer activation and cleanup.
+
+2006-05-23 Tor Lillqvist <tml@novell.com>
+
+ * pango/pangowin32.c (pango_win32_font_class_init): Initialize the
+ describe_absolute method pointer correctly.
+ (pango_win32_font_describe): Scale size to points which is what
+ pango_font_description_set_size() wants. There has been several
+ bugs opened around this issue, with more or less misleading
+ guesses. See for instance #314114. Thanks to Behdad for finally
+ noticing the real problem here.
+
+2006-05-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 342525 – With PangoFc and PangoWin32, approximate digit width is
+ not what it says
+
+ * pango/pangocairo-win32font.c (max_glyph_width),
+ (create_metrics_for_context): Use max digit width instead of average.
+
+ Reverted the following changes:
+
+ * pango/pangofc-font.c (pango_fc_font_create_metrics_for_context):
+ Likewise for PangoFc. Compute average instead of max.
+ (max_glpyh_with): Now unused, drop.
+
+ * pango/pangowin32.c (pango_win32_font_get_metrics): Calculate
+ average digit width correctly, not as max of the digit
+ widths. (#342525) Note that this code doesn't really get much used
+ currently (instead the code in pangocairo-win32font.c is used),
+ fixed only for completeness.
+ (max_glpyh_with): Now unused, drop.
+
+2006-05-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-font.h, pango/fonts.c: New function
+ pango_font_describe_with_absolute_size().
+
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info):
+ * pango/pangocairo-win32font.c (create_metrics_for_context):
+ * pango/pangofc-font.c (pango_fc_font_class_init),
+ (pango_fc_font_describe_absolute),
+ (pango_fc_font_create_metrics_for_context):
+ * pango/pangowin32.c (pango_win32_font_class_init),
+ (pango_win32_font_get_metrics), (pango_win32_font_describe),
+ (pango_win32_font_describe_absolute): Implement and use
+ PangoFontClass->describe_absolute.
+
+2006-05-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 339730 – Pango needlessly falls back away from a Type 1 font into
+ a TTF font
+
+ * pango/fonts.c (find_field): Fix strncmp usage.
+
+2006-05-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 342562 – Support absolute sizes in
+ pango_font_description_to/from_string
+
+ * pango/fonts.c (parse_size), (pango_font_description_from_string),
+ (pango_font_description_to_string): Accept and generate a "px" suffix
+ to identify absolute font sizes.
+
+2006-05-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 341922 – pango should handle more characters as zero width
+ Patch from Roozbeh Pournader
+
+ * pango/pango-utils.c (pango_is_zero_width): Handle the following too:
+
+ U+00AD SOFT HYPHEN
+ U+034F COMBINING GRAPHEME JOINER
+ U+2060 WORD JOINER
+ U+2061 FUNCTION APPLICATION
+ U+2062 INVISIBLE TIMES
+ U+2063 INVISIBLE SEPARATOR
+
+2006-05-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 342525 – With PangoFc and PangoWin32, approximate digit width is
+ not what it says
+
+ * pango/pangofc-font.c (pango_fc_font_create_metrics_for_context):
+ Likewise for PangoFc. Compute average instead of max.
+ (max_glpyh_with): Now unused, drop.
+
+2006-05-22 Tor Lillqvist <tml@novell.com>
+
+ Bug 342525 – With PangoFc and PangoWin32, approximate digit width is
+ not what it says
+
+ * pango/pangowin32.c (pango_win32_font_get_metrics): Calculate
+ average digit width correctly, not as max of the digit
+ widths. (#342525) Note that this code doesn't really get much used
+ currently (instead the code in pangocairo-win32font.c is used),
+ fixed only for completeness.
+ (max_glpyh_with): Now unused, drop.
+
+2006-05-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fontmap.c: Remove unused struct
+ _cairo_font_options.
+
+2006-05-17 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 342079 – pangoatsui-private.h missing from release
+
+ * pango/Makefile.am (libpangocairo_1_0_la_SOURCES):
+ Include pangoatsui-private.h.
+
+2006-05-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.13.1 ===
+
+ * configure.in: Version 1.13.1
+
+ * NEWS: Updated.
+
+2006-05-15 Richard Hult <richard@imendio.com>
+
+ Bug 322374 – Examples does not build on MacOS X
+
+ * pango/Makefile.am (libpangocairo_1_0_la_LDFLAGS): Add the necessary
+ frameworks to make this build with -no-undefined.
+
+2006-05-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-item.c (pango_item_split): Don't copy item before
+ g_return_if_fail'ing it for NULL. (Coverity issue id=18509&runid=43)
+
+2006-05-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (pango_font_face_list_sizes): Fix possible NULL
+ dereference. (Coverity issues id=17770&runid=43)
+
+2006-05-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 71033 – make size 0 fonts work
+
+ * pango/fonts.c (pango_font_description_set_size): Update docs to note
+ a size value of zero may have been set explicitly.
+
+ * pango/pango-context.c (pango_context_load_font): Don't warn if font
+ size if zero.
+
+ * pango/pangoatsui-fontmap.c (pango_atsui_font_map_load_font):
+ * pango/pangox-fontmap.c (pango_x_font_map_load_font): Don't return if
+ size is zero (probably will fail with no fonts found.)
+
+ * pango/pangoxft-fontmap.c (pango_xft_font_map_default_substitute): Xft
+ chokes on size zero. Reassing PIXEL_SIZE to 1.0 if it's zero.
+
+2006-05-01 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 340229 – pango_font_description_from_string does not do bound
+ checking
+
+ * pango/fonts.c (pango_font_description_set_size),
+ (pango_font_description_set_absolute_size), (parse_size):
+ * pango/pango-markup.c (span_parse_func): Don't accept negative font
+ sizes, and make sure sizes don't overflow.
+
+2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 329483 – hinting hexbox in cairo backend doesn't handle absolute
+ font size
+ Bug 340040 – pangocairo hex box hinting falls apart with PS/PDF
+ backends
+
+ * configure.in: Require cairo >= 1.1.2. Also pass -no-undefined on all
+ systems.
+
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info): Fix
+ hexbox info to respect absolute sizes and no metrics hinting settings.
+
+2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 329664 – Move gunichar_to_glyph cache from PangoCairoFcFont to
+ PangoFcFont
+ Patch from LingNing Zhang.
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_finalize),
+ (pango_cairo_fc_font_glyph_extents_cache_init),
+ (pango_cairo_fc_font_get_glyph_extents_cache_entry),
+ (pango_cairo_fc_font_class_init), (pango_cairo_fc_font_init):
+ * pango/pangofc-font.c (pango_fc_font_finalize),
+ (pango_fc_font_real_get_glyph): Move gunichar->glyph cache to
+ pangofc-font.c
+
+2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 329547 – pango_layout_get_pixel_extents and
+ pango_layout_get_pixel_size cause off-by-one metrics
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/glyphs.sgml:
+ * pango/pango-types.h: Define PANGO_PIXELS_FLOOR and PANGO_PIXELS_CEIL.
+
+ * pango/pango-layout.c (pango_layout_get_pixel_extents),
+ (pango_layout_get_pixel_size): Make sure logical rects are
+ consistent and ink rects are inclusive.
+
+2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/tmpl/atsui-fonts.sgml:
+ * docs/tmpl/coverage-maps.sgml:
+ * docs/tmpl/engines.sgml:
+ * docs/tmpl/fonts.sgml:
+ * docs/tmpl/freetype-fonts.sgml:
+ * docs/tmpl/glyphs.sgml:
+ * docs/tmpl/layout.sgml:
+ * docs/tmpl/main.sgml:
+ * docs/tmpl/modules.sgml:
+ * docs/tmpl/opentype.sgml:
+ * docs/tmpl/pango-engine-lang.sgml:
+ * docs/tmpl/pango-engine-shape.sgml:
+ * docs/tmpl/pango-renderer.sgml:
+ * docs/tmpl/pangocairo.sgml:
+ * docs/tmpl/pangofc-decoder.sgml:
+ * docs/tmpl/pangofc-font.sgml:
+ * docs/tmpl/pangofc-fontmap.sgml:
+ * docs/tmpl/scripts.sgml:
+ * docs/tmpl/tab-stops.sgml:
+ * docs/tmpl/text-attributes.sgml:
+ * docs/tmpl/utils.sgml:
+ * docs/tmpl/win32-fonts.sgml:
+ * docs/tmpl/x-fonts.sgml:
+ * docs/tmpl/xft-fonts.sgml:
+ * pango/modules.c:
+ * pango/pango-coverage.c: Doc updates.
+
+2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 337594 – pango_glyph_string_extents_range possible bug
+
+ * pango/glyphstring.c (pango_glyph_string_extents_range): Add offset
+ for first glyph too.
+
+2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 333771 – Use gmodule-no-export-2.0 instead of gmodule-2.0 in
+ pango-uninstalled.pc.in
+
+ * pango-uninstalled.pc.in: Require gmodule-no-export-2.0, like
+ pango.pc.in does.
+
+2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 307196 – Unhinted fonts are measured incorrectly and drawing
+ problems occur as a result
+
+ * pango/pangofc-font.c (get_face_metrics),
+ (pango_fc_font_get_raw_extents):
+ * pango/pangoxft-font.c (_pango_xft_font_new): Rollback previous
+ change that forced metrics hinting always on.
+
+ * pango/pangocairo-fcfont.c (_pango_cairo_fc_font_new): Set fcfont
+ metrics hinting based on cairo font options.
+
+2006-04-28 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 339749 – pango_language_from_string issues
+ Patch from Morten Welinder.
+
+ * pango/pango-utils.c (lang_equal): Make the equal function symmetric.
+
+2006-04-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-font.c (get_face_metrics),
+ (pango_fc_font_get_raw_extents): Don't use is_hinted. Metrics are
+ always hinted now.
+
+ * pango/pangoxft-font.c (_pango_xft_font_new): Remove hack that forced
+ is_hinted to TRUE.
+
+2006-04-27 Behdad Esfahbod <behdad@gnome.org>
+
+ * pangocairo.pc.in, pangocairo-uninstalled.pc.in: Remove CAIRO_CFLAGS
+ from Cflags, as we Require cairo already.
+
+2006-04-27 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-impl-utils.h:
+ * pango/fonts.c (pango_font_get_glyph_extents),
+ (pango_font_get_metrics), (pango_font_get_font_map):
+ * pango/pangocairo-render.c (pango_cairo_show_glyph_string),
+ (pango_cairo_glyph_string_path): Add more warning_history items and
+ handle more font failures, to make sure that instead of crashing,
+ gedit runs and draws empty boxes when pango.modules is not set
+ properly.
+
+2006-04-26 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 339747 – pango_font_metrics_get_approximate_digit_width docs
+
+ * pango/fonts.c: Fix typo in docs.
+
+2006-04-26 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 339749 – pango_language_from_string issues
+
+ * pango/pango-utils.c (pango_language_from_string): Avoid lookup that
+ we know fails...
+
+2006-04-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.13.0 ===
+
+ * configure.in: Version 1.13.0
+
+ * NEWS: Updated.
+
+2006-04-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/HELLO.utf8: Add Sinhala. (patch from Harshula)
+
+2006-04-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 338343 – Bad cast
+
+ * pango/pango-layout.c (pango_layout_set_text): Fix cast.
+
+2006-04-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangox.c (get_font_metrics_from_subfonts): Check for nullity
+ somewhere else.
+
+2006-04-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/harfbuzz-gpos.c: Fix loop variables. (coverity
+ found bug.)
+
+2006-04-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 337924 – cleanups for issues reported by various compilers
+ Patch from Kjartan Maraas.
+
+ * examples/viewer-x.c (update):
+ * modules/arabic/arabic-fc.c (fallback_shape),
+ (arabic_engine_shape):
+ * modules/basic/basic-fc.c (fallback_shape), (basic_engine_shape):
+ * modules/basic/basic-x.c:
+ * modules/hangul/hangul-fc.c:
+ * modules/hebrew/hebrew-fc.c (hebrew_engine_shape):
+ * modules/indic/indic-fc.c:
+ * modules/khmer/khmer-fc.c:
+ * modules/syriac/syriac-fc.c:
+ * modules/thai/thai-fc.c:
+ * modules/tibetan/tibetan-fc.c:
+ * pango/break.c:
+ * pango/modules.c:
+ * pango/opentype/ftglue.c (_hb_ftglue_face_goto_table):
+ * pango/pango-attributes.c (pango_attr_list_filter):
+ * pango/pango-engine.c:
+ * pango/pango-fontset.c:
+ * pango/pango-layout.c (pango_layout_set_text),
+ (pango_layout_xy_to_index), (pango_layout_get_cursor_pos):
+ * pango/pango-markup.c (text_handler):
+ * pango/pango-utils.c (read_alias_file):
+ * pango/pangocairo-fcfont.c (G_DEFINE_TYPE_WITH_CODE):
+ * pango/pangocairo-fcfontmap.c (G_DEFINE_TYPE_WITH_CODE):
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info):
+ * pango/pangox-fontmap.c (pango_x_make_matching_xlfd):
+ * tests/dump-boundaries.c (fail):
+ Remove unused variables. Remove excess semicolon after DEFINE_TYPE
+ macros.
+
+2006-04-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * config.h.win32, examples/makefile.msc: Removed. Have not been
+ updated since Feb 2001.
+
+2006-04-10 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c: Fix broken changes I made :).
+
+2006-04-10 Behdad Esfahbod <behdad@gnome.org>
+
+ Fix minor bugs reported by the Coverity scan report.
+
+ * pango/opentype/harfbuzz-gdef.c (HB_GDEF_Build_ClassDefinition):
+ * pango/opentype/harfbuzz-gpos.c (HB_GPOS_Query_Scripts),
+ (HB_GPOS_Query_Languages), (HB_GPOS_Query_Features): Do not access
+ structs before we check them for nullity.
+
+ * pango/pango-layout.c (pango_layout_index_to_line),
+ (pango_layout_index_to_line_and_extents),
+ (pango_layout_index_to_pos): Check for invalid iterators outside the
+ loop, so we don't crash.
+
+ * pango/pango-layout.c (pango_layout_line_x_to_index): Set
+ char_trailing instead of trailing in one of too many paths. Should
+ have been a typo.
+
+ * pango/pangox.c (get_font_metrics_from_subfonts): Check for nullity
+ somewhere.
+
+2006-04-09 Tor Lillqvist <tml@novell.com>
+
+ * pango/pango-utils.c (pango_quantize_line_geometry): Fix typo in
+ doc comment.
+
+2006-04-09 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 337821 – invisible unicode chars are visible next to hebrew chars
+
+ * modules/hebrew/hebrew-fc.c: Handle zero_width chars in fallback
+ shaper too.
+
+ * modules/hebrew/hebrew-shaper.c: Remove unused Unicode<->ISO8859
+ tables.
+
+2006-04-07 Behdad Esfahbod <behdad@gnome.org>
+
+ Incorrect text rendering when in x86 64-bit precision mode
+ https://bugs.freedesktop.org/show_bug.cgi?id=5200
+
+ * pango/pangocairo-fcfont.c:Round metrics when converting
+ to Pango units.
+
+2006-04-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 337502 – Win32 build fix
+ Patch from Alexander Larsson.
+
+ * pango/pangocairo-fontmap.c: Fix order of checking for freetype and
+ win32 cairo backends to match the constructor.
+
+ * pango/pangoft2.def: Add missing symbol
+
+2006-04-06 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype: Update from HarfBuzz. Lars Knoll fixed all the
+ warnings.
+
+2006-04-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.c, pango/querymodules.c: Fix a few warnings.
+
+2006-04-03 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/harfbuzz-impl.h: Make sure TTAG_GDEF and frineds are
+ defined, needed for FreeType <= 2.1.7 (pointed by Tim Janik).
+
+2006-04-03 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 337029 – pango/fonts.c: Illegal structure initialization
+
+ * pango/fonts.c: Change NULL's to ""'s after previous change, and fix
+ code to follow.
+
+2006-03-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c:
+ * pango/pango-utils.c:
+ * pango/pangox-fontmap.c:
+ * pango/pangoft2.c (_pango_ft2_ft_strerror): Change char* to
+ char[] in the ft error table, to avoid relocations.
+
+2006-03-31 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 336026 – Make fallback shaper in modules work
+ Patch from Denis Jacquerye.
+
+ * pango/pango-ot-buffer.c (pango_ot_buffer_output): Call
+ pango_fc_font_kern_glyphs if GPOS not applied.
+
+2006-03-31 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 334802 – Using plain integer as NULL pointer
+
+ * pango/mapping.c (pango_glyph_string_x_to_index): Fix type assigining
+ trailing instead of *trailing.
+
+ * pango/pango-layout.c (pango_layout_line_new): Use NULL instead of 0.
+
+2006-03-31 Behdad Esfahbod <behdad@gnome.org>
+
+ Convert pango/opentype to the new project called HarfBuzz.
+
+ * pango/opentype/*: Restructured.
+
+ * pango/pango-ot-*: Updated to use HarfBuzz symbol names.
+
+2006-03-30 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 335840 – Typo in including Xft.
+
+ * pangoxft-render.h: Define _XFT_NO_COMPAT_ instead of _XFT_NO_COMPAT.
+
+2006-03-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/*.[ch]: Make #include syntax in sources and headers more
+ consistent. We are using the "..." syntax for all Pango headers
+ in source files, and <...> syntax in all header files, except for
+ including private headers, that we use "...".
+
+2006-03-30 Behdad Esfahbod <behdad@gnome.org>
+
+ Hook up pango-utils.h into the documentation, as we are installing
+ it anyway. Move some internal stuff to pango-impl-utils.h and make
+ source files include that instead.
+
+2006-03-30 Tor Lillqvist <tml@novell.com>
+
+ Fix blurred underlines on Win32 (#332656):
+
+ * pango/pango-utils.c (pango_quantize_line_geometry):
+ New public function. Used to be the static quantize_position() in
+ pangofc-font.c
+
+ * pango/pango-utils.h: Declare it.
+
+ * pango/pango.def: Here, too.
+
+ * pango/pangofc-font.c (quantize_position): Remove.
+ (get_face_metrics): Use pango_quantize_line_geometry() instead.
+
+ * pango/pangocairo-win32font.c (create_metrics_for_context): Call
+ pango_quantize_line_geometry() for underline and strikethrough
+ geometries.
+
+2006-03-25 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/opentype/ottest.c: Don't err on Table_Missing.
+
+2006-03-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Create pango-1-12 stable branch.
+
+ * ChangeLog.pre-1-12: Created.
+
+ * Makefile.am: Updated to dist above.
+
+Local Variables:
+coding: utf-8
+End:
+vim: encoding=utf-8:
diff --git a/trunk/ChangeLog.pre-1-16 b/trunk/ChangeLog.pre-1-16
new file mode 100644
index 00000000..47559ee9
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-16
@@ -0,0 +1,1827 @@
+2007-02-26 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.16.0 ===
+
+ * configure.in: Version 1.16.0
+
+ * configure.in: Require cairo 1.2.6 because of its important fixes.
+
+ * NEWS: Updated.
+
+ * README: Updated.
+
+2007-02-20 Stefan Kost <ensonic@users.sf.net>
+
+ Xrefs for glib and cairo in the docs. Add object hierarchy to the docs.
+
+ * configure.in:
+ * docs/Makefile.am:
+ * docs/pango-docs.sgml:
+
+2007-02-18 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 409212 – Missing link flag prevents build with "-z defs" ld flags
+ Patch from Loïc Minier
+
+ * configure.in: Add xrender to pkg-config requirements for pangoxft.
+
+2007-02-18 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 409212 – Missing link flag prevents build with "-z defs" ld flags
+ Patch from Loïc Minier
+
+ * pango/Makefile.am: Add $(X_LIBS) to pangoxft_LDADD.
+
+2007-02-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 355987 – choosing font/shaper for spaces breaks Arabic runs on
+ spaces
+
+ * pango/pango-context.c (itemize_state_process_run): Don't choose
+ shaper for ASCII space char.
+
+2007-02-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 407087 – autogen.sh wants automake-1.7
+
+ * autogen.sh: Require automake 1.9, like configure.in does.
+
+2007-02-12 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.15.6 ===
+
+ * configure.in: Version 1.15.6
+
+ * NEWS: Updated.
+
+2007-02-13 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangowin32-fontmap.c (pango_win32_insert_font): If
+ something has gone wrong in setting the family of the font
+ description, don't bother with the font as it isn't usable and
+ will cause crashes later anyway. (#404295)
+
+2007-01-31 Tor Lillqvist <tml@novell.com>
+
+ * pango/Makefile.am: Use pangocairo.def only on Win32, not
+ Cygwin. (#402373, "paul")
+
+2007-01-30 Tor Lillqvist <tml@novell.com>
+
+ * pango-zip.sh.in: Include also the COPYING file in the zipfiles.
+
+ * Makefile.am (EXTRA_DIST): Include just pango-zip.sh.in in the
+ tarball, not pango-zip.sh.
+
+2007-01-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (pango_font_get_metrics),
+ (pango_font_get_font_map): Remove PANGO_IS_FONT() check. Just
+ do NULL-checking.
+
+2007-01-23 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 399738 – pango 1.15.5 won't compile on Mac OS X: 'FC_HINT_STYLE'
+ undeclared (first use in this function)
+
+ * pango/pangoft2.c (pango_ft2_font_get_face): Don't use FC_HINT_STYLE
+ if it's not defined (old fontconfig versions).
+
+2007-01-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.15.5 ===
+
+ * configure.in: Version 1.15.5
+
+ * NEWS: Updated.
+
+2007-01-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-glyph-item.c (_pango_glyph_item_iter_next_cluster):
+ Fix the "menu accels are two chars wide" bug that was introduced
+ by the recent changes in this function, in 1.15.4. Apparently
+ glyph_index means separate things in next_cluster and prev_cluster.
+
+2007-01-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (pango_font_get_metrics): Populate metrics for
+ NULL/broken fonts. Now our glyph boxes have underlines too. Yay!
+
+2007-01-21 Tor Lillqvist <tml@novell.com>
+
+ * configure.in: Add AC_MSG_RESULT([no]) to the failed branch of
+ PKG_CHECK_MODULES tests to make the output from configure
+ cleaner.
+
+2007-01-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 398238 – pangorc file missing from tests directory
+
+ * pango-view/Makefile.am:
+ * tests/Makefile.am:
+ Don't use $<. Doesn't work with Sun's make.
+
+2007-01-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Require automake 1.9.
+
+2007-01-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoft2.c (pango_ft2_font_get_face): Respect FC_HINT_STYLE.
+ Patch has been in Fedora for ages.
+
+2007-01-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.15.4 ===
+
+ * configure.in: Version 1.15.4
+
+ * NEWS: Updated.
+
+2007-01-17 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 395328 – Map kATSDeletedGlyphcode to PANGO_GLYPH_EMPTY
+
+ * modules/basic/basic-atsui.c (set_glyph): Handle
+ kATSDeletedGlyphcode.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/viewer-render.c (make_layout): Fix typo when rounding
+ to points.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 397337 – Use is_ellipsized and is_wrapped to optimize property
+ changes
+
+ * pango/pango-layout.c (pango_layout_set_wrap),
+ (pango_layout_set_ellipsize): Using is_ellipsized and is_wrapped,
+ only clear lines if wrap/ellipsize change has any effect on the lines.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ *.c, *.h: Removed spaces followed b tabs.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ *.c, *.h: Replace preceding sequences of 8 spaces with tabs.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/pangowin32tobmp.c (SaveBitmap):
+ * modules/tibetan/tibetan-fc.c:
+ Replace C++-style // comments with C-style /* */ ones.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ *.c, *.h: Drop trailing whitespace.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 328585 – Need to know if a layout has unknown glyphs
+ Patch from LingNing Zhang
+
+ * pango/pango-layout-private.h:
+ * pango/pango-layout.c (pango_layout_init), (pango_layout_copy),
+ (pango_layout_get_unknown_glyphs_count),
+ (pango_layout_clear_lines):
+ * pango/pango-layout.h:
+ New public function:
+
+ pango_layout_get_unknown_glyphs_count()
+
+ * pango/pango.def:
+ * docs/tmpl/layout.sgml:
+ * docs/pango-sections.txt:
+ Update.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 326693 – PangoLayouts should be query-able about their
+ effective properties (width / wrapped / ellipsized / etc)
+
+ * pango/pango-layout-private.h:
+ * pango/pango-layout.c (pango_layout_init), (pango_layout_copy),
+ (pango_layout_is_wrapped), (pango_layout_clear_lines),
+ (process_line):
+ * pango/pango-layout.h:
+ New public function:
+
+ pango_layout_is_wrapped()
+
+ * pango/pango.def:
+ * docs/tmpl/layout.sgml:
+ * docs/pango-sections.txt:
+ Update.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 397327 – pango-layout.c: 'pango_layout_is_ellipsized' must return
+ a value
+
+ * pango/pango-layout.c (pango_layout_is_ellipsized): Use
+ g_return_val_if_fail() instead of g_return_if_fail().
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/ellipsize.c (get_cluster_width): Fix width calculation.
+ Was causing ellipsization to stop at a zero-width glyph that was
+ part of a bigger cluster.
+
+ * pango/ellipsize.c (remove_one_span): Skip over zero-width clusters,
+ otherwise ellipsization will stop at a zero-width cluster.
+
+ * pango/pango-glyph-item.c (_pango_glyph_item_iter_next_cluster),
+ (_pango_glyph_item_iter_prev_cluster): Fix yet another bug with
+ in prev_cluster that was making it not work for any interesting
+ cluster.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/cairotwisted.c (point_on_path), (draw_text),
+ (draw_twisted), (draw_dream), (draw_wow), (main):
+ Improve text-on-path example.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Generate .bz2 tarball instead of .gz.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/Makefile.am:
+ * pango-view/renderdemo.c:
+ * pango-view/renderdemo.h:
+ * pango-view/viewer-main.c:
+ * pango-view/viewer-pangocairo.c:
+ * pango-view/viewer-pangoft2.c:
+ * pango-view/viewer-pangox.c:
+ * pango-view/viewer-pangoxft.c:
+ * pango-view/viewer-render.c:
+ * pango-view/viewer-render.h:
+ * pango-view/viewer-x.c:
+ Rename renderdemo.[ch] to viewer-render.[ch].
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango-view/Makefile.am: Rename HELLO.utf8 and GLASS.utf8 to
+ HELLO.txt and GLASS.txt.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/pango-view.c:
+ * examples/pangocairo-view.c:
+ * examples/pangoft2-view.c:
+ * examples/pangox-view.c:
+ * examples/pangoxft-view.c:
+ * examples/renderdemo.c:
+ * examples/renderdemo.h:
+ * examples/test-arabic.txt:
+ * examples/test-chinese.txt:
+ * examples/test-devanagari.txt:
+ * examples/test-gurmukhi.txt:
+ * examples/test-hebrew.txt:
+ * examples/test-ipa.txt:
+ * examples/test-lao.txt:
+ * examples/test-latin.txt:
+ * examples/test-mixed.txt:
+ * examples/test-syriac.txt:
+ * examples/test-tamil.txt:
+ * examples/test-thai.txt:
+ * examples/test-tibetan.txt:
+ * examples/viewer-cairo.c:
+ * examples/viewer-cairo.h:
+ * examples/viewer-main.c:
+ * examples/viewer-pangocairo.c:
+ * examples/viewer-pangoft2.c:
+ * examples/viewer-pangox.c:
+ * examples/viewer-pangoxft.c:
+ * examples/viewer-win32.c:
+ * examples/viewer-x.c:
+ * examples/viewer-x.h:
+ * examples/viewer.h:
+ Move into pango-view/
+
+ * Makefile.am:
+ * configure.in:
+ * examples/Makefile.am:
+ * pango-view/Makefile.am:
+ Update.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/renderdemo.c (parse_enum): Oops. Replace GType* with GType.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 363510 – Ability to query whether a PangoLayout is effectively
+ ellipsized (as opposed to the set_ellpisize()/get_ellipsize() methods
+ which only set a request, or return the set request respectively)
+ Patch from Milosz Derezynski
+
+ * pango/pango-layout.h:
+ * pango/ellipsize.c (_pango_layout_line_ellipsize):
+ * pango/pango-layout-private.h:
+ * pango/pango-layout.c (pango_layout_init), (pango_layout_copy),
+ (pango_layout_is_ellipsized), (pango_layout_clear_lines),
+ (pango_layout_line_postprocess):
+ New public function:
+
+ pango_layout_is_ellipsized()
+
+ * pango/pango.def:
+ * docs/tmpl/layout.sgml:
+ * docs/pango-sections.txt:
+ Update.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line): Fix
+ background rendering being off in presence of rise attributes.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-context.c (itemize_state_init),
+ (itemize_state_update_for_new_run): Update centered_baseline in
+ presence of gravity attributes.
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/cairotwisted.c (draw_text):
+ * pango/pangocairo-win32font.c (max_glyph_width):
+ * pango/pangofc-font.c (max_glyph_width):
+ * pango/pangowin32.c (max_glyph_width),
+ (pango_win32_render_layout):
+ * pango/pangox.c (pango_x_render_layout):
+ Use pango_layout(_iter)?_get_line_readonly() instead of
+ pango_layout(_iter)?_get_line().
+
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-attributes.h:
+ * pango/pango-attributes.c:
+ New attribute types PANGO_ATTR_GRAVITY and PANGO_ATTR_GRAVITY_HINT.
+ New public functions:
+
+ pango_attr_gravity_new()
+ pango_attr_gravity_hint_new()
+
+ * pango/pango-context.c (update_attr_iterator),
+ (itemize_state_init), (itemize_state_add_character),
+ (get_shaper_and_font), (itemize_state_update_for_new_run):
+ Handle gravity and gravity_hint attributes.
+
+ * pango/pango-utils.h:
+ * pango/pango-utils.c:
+ New public function:
+
+ pango_parse_enum()
+
+ * pango/pango-markup.c (span_parse_func): Parse gravity and
+ gravity_hint attributes for <span>. Optimize a bit.
+
+ * pango/pango-markup.c (parse_absolute_size), (attr_strcmp),
+ (span_parse_int), (span_parse_boolean), (span_parse_color),
+ (span_parse_enum), (span_parse_func): Use pango_scan_int(),
+ pango_color_parse(), and pango_parse_enum(). Also, ignore '-' and
+ '_' differences when matching attribute names for <span>.
+
+ * examples/renderdemo.c (parse_enum), (parse_ellipsis),
+ (parse_gravity), (parse_gravity_hint), (parse_hinting),
+ (parse_wrap): Use a generic parse_enum() that uses pango_parse_enum().
+
+ * modules/basic/basic-fc.c (basic_engine_shape):
+ * pango/pangofc-fontmap.c (pango_fc_make_pattern):
+ Use PANGO_GRAVITY_IS_VERTICAL().
+
+ * pango/pango.def:
+ * docs/pango-sections.txt:
+ * docs/tmpl/text-attributes.sgml:
+ * docs/tmpl/utils.sgml:
+ Update.
+
+2007-01-15 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 323173 – Add layout of mixed direction text for vertical layout
+
+ * pango/pango-gravity.h:
+ * pango/pango-gravity.c:
+ Moved gravity stuff here. New public API:
+
+ PangoGravityHint
+ pango_gravity_get_for_matrix()
+ pango_gravity_get_for_script()
+
+ * pango/pango-context.h:
+ * pango/pango-context.c (pango_context_init),
+ (update_resolved_gravity), (itemize_state_update_for_new_run):
+ Support gravity hint. New public API:
+
+ pango_context_set_gravity_hint()
+ pango_context_get_gravity_hint()
+
+ * pango/pango-utils.c:
+ * pango/pango-matrix.c:
+ * pango/pango-matrix.h:
+ * pango/pango-types.h:
+ Moved gravity and matrix stuff into its own header. pango-types.h
+ includes both pango-matrix.h and pango-gravity.h
+
+ * pango/pango.h:
+ Include new headers.
+
+ * pango/pango.def:
+ * pango/Makefile.am:
+ Update.
+
+ * docs/pango-docs.sgml:
+ * docs/pango-sections.txt:
+ * docs/tmpl/glyphs.sgml:
+ * docs/tmpl/main.sgml:
+ * docs/tmpl/vertical.sgml:
+ Add a section for Vertical Text.
+
+ * examples/renderdemo.c (do_output), (parse_gravity_hint),
+ (parse_options):
+ Support gravity hint.
+
+ * examples/test-mixed.txt:
+ New test, mixed Latin, Arabic, Chinese text.
+
+2007-01-15 Tor Lillqvist <tml@novell.com>
+
+ * configure.in: Don't check for X and don't warn about missing
+ fontconfig on Win32. (#392628, Yevgen Muntyan)
+
+2007-01-15 Tor Lillqvist <tml@novell.com>
+
+ * configure.in: Automatically use -mms-bitfields on Windows when
+ building with gcc. (#394453)
+
+2007-01-13 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc pango/opentype/makefile.msc : updated
+
+2007-01-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.15.3 ===
+
+ * configure.in: Version 1.15.3
+
+ * NEWS: Updated.
+
+2007-01-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 351496 – PangoAnalysis::gravity breaks binary compatibility
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/glyphs.sgml:
+ * docs/tmpl/main.sgml:
+ * pango/pango-context.c (itemize_state_add_character):
+ * pango/pango-item.h:
+ * pango/pango-layout.c (pango_layout_run_get_extents):
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line):
+ Don't introduce bitfields in public struct and rename PangoAnalysis.
+ centered_baseline to PangoAnalysis.flags and introduce
+ PANGO_ANALYSIS_FLAGS_CENTERED_BASELINE.
+
+2007-01-07 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/tmpl/engines.sgml:
+ * docs/tmpl/fonts.sgml:
+ * docs/tmpl/freetype-fonts.sgml:
+ * docs/tmpl/layout.sgml:
+ * docs/tmpl/main.sgml:
+ * docs/tmpl/modules.sgml:
+ * docs/tmpl/opentype.sgml:
+ * docs/tmpl/pango-renderer.sgml:
+ * docs/tmpl/pango-version.sgml:
+ * docs/tmpl/pangofc-font.sgml:
+ * docs/tmpl/pangofc-fontmap.sgml:
+ * docs/tmpl/text-attributes.sgml:
+ * docs/tmpl/win32-fonts.sgml:
+ * docs/tmpl/x-fonts.sgml:
+ * docs/tmpl/xft-fonts.sgml:
+ * pango/ellipsize.c:
+ * pango/fonts.c:
+ * pango/glyphstring.c:
+ * pango/modules.c:
+ * pango/pango-attributes.c:
+ * pango/pango-context.c:
+ * pango/pango-context.h:
+ * pango/pango-coverage.c:
+ * pango/pango-glyph-item.c:
+ * pango/pango-layout.c:
+ * pango/pango-layout.h:
+ * pango/pango-markup.c:
+ * pango/pango-matrix.c:
+ * pango/pango-ot-buffer.c:
+ * pango/pango-ot-info.c:
+ * pango/pango-ot-ruleset.c:
+ * pango/pango-renderer.c:
+ * pango/pango-script.c:
+ * pango/pango-utils.c:
+ * pango/pangoatsui-fontmap.c:
+ * pango/pangocairo-fontmap.c:
+ * pango/pangofc-font.c:
+ * pango/pangofc-font.h:
+ * pango/pangofc-fontmap.c:
+ * pango/pangofc-fontmap.h:
+ * pango/pangoft2-fontmap.c:
+ * pango/pangoft2-render.c:
+ * pango/pangoft2.c:
+ * pango/pangowin32-fontcache.c:
+ * pango/pangowin32-fontmap.c:
+ * pango/pangowin32.c:
+ * pango/pangox-fontmap.c:
+ * pango/pangox.c:
+ * pango/pangoxft-font.c:
+ * pango/pangoxft-fontmap.c:
+ * pango/pangoxft-render.c:
+ * pango/reorder-items.c:
+ Spell-check the docs.
+
+2007-01-07 Tor Lillqvist <tml@novell.com>
+
+ * modules/basic/Makefile.am: Fix build on Win32 outside
+ srcdir. (#392789, J. Ali Harlow)
+
+2007-01-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.c: Improve docs, and mention
+ g_unichar_iszerowidth().
+
+2007-01-04 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 332266 – gdk_draw_layout fails for coordinates >= 2^21
+
+ * pango/pango-types.h:
+ * pango/pango-matrix.c: New public API:
+ pango_matrix_transform_distance()
+ pango_matrix_transform_point()
+ pango_matrix_transform_rectangle()
+ pango_matrix_transform_pixel_rectangle()
+
+ * pango/pango-utils.h:
+ * pango/pango-utils.c: New public API:
+ pango_units_from_double()
+ pango_units_to_double()
+ pango_extents_to_pixels()
+
+ * pango/pango-layout.c (pango_layout_get_pixel_extents),
+ (pango_layout_line_get_pixel_extents): Use pango_extents_to_pixels().
+
+ * pango/pangocairo-fcfont.c:
+ (pango_cairo_fc_font_glyph_extents_cache_init),
+ (compute_glyph_extents): Use pango_units_from_double().
+
+ * examples/renderdemo.c (do_output): Use
+ pango_matrix_transform_pixel_rectangle();
+
+ * pango/pango.def:
+ * docs/pango-sections.txt:
+ * docs/tmpl/glyphs.sgml: Update.
+
+2007-01-03 Changwoo Ryu <cwryu@debian.org>
+
+ Bug 388702 – Crash when there's no Hangul glyph in the font.
+
+ * modules/hangul/hangul-fc.c (render_syllable): Do not try to
+ render unknown syllable glyphs as jamos.
+
+ * modules/hangul/hangul-fc.c (hangul_engine_shape): Check if the
+ remaining string is a syllable.
+
+ Bug 388581 - Every last Hangul syllable is decomposed to jamos.
+
+ * modules/hangul/hangul-fc.c (hangul_engine_shape): Check if the
+ remaining string is a syllable.
+
+2007-01-03 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 390877 – Don't feed pango-features.h to glib-mkenums
+ Patch from Yevgen Muntyan
+
+ * pango/Makefile.am: Move pango-features.h to pangoinclude_HEADERS.
+
+2006-12-23 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 384543 – FcFontMatch misuse
+
+ * pango/pangofc-fontmap.c (pango_fc_face_describe):
+ Call FcConfigSubstitute and FcDefaultSubstitute before calling
+ FcFontMatch.
+
+ * pango/pangoft2.c (load_fallback_face):
+ Call _pango_ft2_font_map_default_substitute().
+
+ * pango/pangocairo-fcfontmap.c
+ (pango_cairo_fc_font_map_context_substitute):
+ Handle the case of context == NULL.
+
+2006-12-23 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-utils.c (pango_language_get_default): Improve docs.
+
+2006-12-20 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.15.2 ===
+
+ * configure.in: Version 1.15.2
+
+ * NEWS: Updated.
+
+2006-12-19 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 326099 – Setting width, indentation and ellipsizing doesn't work
+ as I would expect
+
+ * pango/ellipsize.c (_pango_layout_line_ellipsize): Account for
+ indentation when deciding what width to ellipsize for.
+
+ * pango/pango-layout.c (get_alignment): Don't bother about
+ conditioning on the line direction for center alignment.
+
+2006-12-20 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-defs.h:
+ * modules/hangul/hangul-fc.c
+ (hangul_engine_shape): Optimizing for non-old Hangul users; no
+ more waste of decompose and compose.
+ (render_syllable): The string argument is now in UTF-8. Normalization
+ is now done only when the entire sequence is equivalent to a
+ precomposed syllable.
+ (render_isolated_tone): Conditioned out tone mark's dummy base
+ character drawing.
+
+2006-12-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-render.c (pango_cairo_renderer_draw_glyphs):
+ Avoid some floating-point operations by caching the y value for the
+ baseline, using it for glyphs having y_offset of 0.
+
+2006-12-15 Frederic Crozat <fcrozat@mandriva.com>
+
+ Bug 385478 – Fix tests on OPD platform
+
+ * pango/check.defs: Fix tests on OPD platform to report correct
+ symbols name.
+
+2006-12-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 319808 – Patch to let pango support artifical italic, bold and
+ bold italic styles for the fonts which don't have these styles.
+ Patch from James Su
+
+ * pango/pangofc-fontmap.c (pango_fc_face_describe), (create_face),
+ (pango_fc_family_list_faces): Create fake Bold, Italic, and Bold
+ Italic faces for fonts that do not have one.
+
+2006-12-13 Gwenole Beauchesne <gbeauchesne@mandriva.com>
+
+ Bug 385478 – Fix tests on OPD platform
+
+ * pango/check.defs: Improve symbols extraction for OPD-based
+ platforms (e.g. ppc64, ia64).
+
+2006-12-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 385321 – Worst case expansion for Sinhala
+ Patch from Harshula
+
+ * modules/indic/indic-ot-class-tables.c: Change worst case expansion
+ for Sinhala from 3 to 4. This is only superficial because Pango
+ doesn't appear to ever use the worst case expansion value.
+
+2006-12-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Red Hat Bug 211574: [hi/ml/si_LK] cursor naviation is wrong when
+ using ZWJ (200d)
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-lang.c (indic_engine_break): Handle cursor
+ movement around ZWJ and ZWNJ.
+
+2006-12-07 Behdad Esfahbod <behdad@gnome.org>
+
+ Red Hat Bug 216424: [te_IN] pango - consonant + dependent vowel (ai)
+ Composed char is not rendering properly
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot.c (indic_ot_reorder): Fix it!
+
+2006-12-07 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout-private.h:
+ * pango/pango-layout.c (pango_layout_get_extents_internal),
+ (pango_layout_get_extents), (pango_layout_clear_lines),
+ (pango_layout_line_leaked), (pango_layout_line_get_extents),
+ (pango_layout_iter_copy), (pango_layout_get_iter),
+ (pango_layout_iter_get_layout_extents):
+ Cache layout ink and logical extents.
+
+2006-12-06 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in:
+ * pango/Makefile.am:
+ New generated public header file pango-features.h. Currently contains
+ the version information. In the future, can be expanded to define
+ which backends have been enabled, etc.
+
+ * pango/pango.def:
+ * pango/pango-utils.h:
+ * pango/pango-utils.c:
+ New public macros and functions: PANGO_VERSION_ENCODE(),
+ PANGO_VERSION_MAJOR, PANGO_VERSION_MINOR, PANGO_VERSION_MICRO,
+ PANGO_VERSION, PANGO_VERSION_STRING, PANGO_VERSION_CHECK(),
+ pango_version(), pango_version_string(), pango_version_check().
+
+ * docs/pango-docs.sgml:
+ * docs/pango-sections.txt:
+ * docs/tmpl/pango-version.sgml:
+ Docs for new symbols, in a new section.
+
+ * examples/renderdemo.c (show_version):
+ If run-time Pango lib version is different than the compile-time one,
+ show that one too.
+
+ * pango/pango.h:
+ #include <pango-utils.h> as well as almost all other public pango-*.h
+ headers (though, the other ones were already included indirectly).
+ The only public pango-*.h header pango.h shouldn't include are
+ pango-ot.h (which is really misnamed) and pango-modules.h (that should
+ not be needed by 99.99% users anyway).
+
+ * docs/Makefile.am:
+ * docs/check.docs: Test to check that all symbols are documented and
+ properly hooked into documentation tree.
+
+ * pango/pango.rc.in:
+ * pango/pangoft2.rc.in:
+ * pango/pangowin32.rc.in:
+ Update, reflecting some internal symbol changes.
+
+ * pango/check.defs: Improve.
+
+2006-12-06 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/renderdemo.c (do_output): Set context language to
+ pango_language_get_default() instead of hardcoding "en-US".
+
+ * pango/pango-utils.c (pango_language_get_default): Improve docs.
+
+2006-12-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 333982 – Fallback to $LANG whenever NULL PangoLanguage is used
+ Patch from LingNing Zhang
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/utils.sgml:
+ * pango/pango-context.c:
+ * pango/pango-types.h:
+ * pango/pango-utils.c (_pango_get_lc_ctype),
+ (pango_language_get_default):
+ * pango/pango.def:
+ New public function pango_language_get_default(). Note that, this
+ does not make Pango fallback to the default language automatically,
+ but the user can use this function to set the default language of the
+ locale on a context:
+
+ pango_context_set_language (context, pango_language_get_default());
+
+2006-12-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 373856 – Wish: Function to convert a GdkColor to a string
+ Patch from Matthew Barnes
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/text-attributes.sgml:
+ * pango/pango-attributes.h:
+ * pango/pango.def:
+ * pango/pango-color.c (pango_color_to_string):
+ New public function pango_color_to_string().
+
+2006-12-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Red Hat Bug 216850: Issue in combination with vowels (ml_IN)
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot.c (indic_ot_reorder): Fix it!
+
+2006-12-06 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 382437 – tests/testboundaries fails
+
+ * configure.in: Require libthai >= 0.1.7
+
+2006-12-06 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/Makefile.am:
+ * examples/test-gurmukhi.txt:
+ Gurmukhi test text from supreet sethi.
+
+2006-12-05 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/layout.sgml:
+ * pango/pango-layout.c (pango_layout_get_lines_readonly),
+ (pango_layout_get_line_readonly),
+ (pango_layout_iter_get_run_readonly),
+ (_pango_layout_iter_get_line), (pango_layout_iter_get_line),
+ (pango_layout_iter_get_line_readonly):
+ * pango/pango-layout.h:
+ * pango/pango-renderer.c (pango_renderer_draw_layout):
+ * pango/pango.def:
+ Add new functions:
+ pango_layout_get_line_readonly()
+ pango_layout_get_lines_readonly()
+ pango_layout_iter_get_line_readonly()
+ pango_layout_iter_get_run_readonly()
+ These should be used when you do not intend to modify the run/line,
+ which is more than most of the time. So, update your app, benefit
+ from more optimizations (in this case, line extents caching)!
+
+2006-12-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.15.1 ===
+
+ * configure.in: Version 1.15.1
+
+ * NEWS: Updated.
+
+2006-12-04 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 135683 – Cache glyphstring extents
+
+ Cache line extents. This avoids the final pango_font_get_glyph_extents()
+ call per glyph per layout rendering. Now we don't make any
+ pango_font_get_glyph_extents() calls when rendering a layout (some
+ conditions apply).
+
+ * pango/pango-layout.c (pango_layout_get_lines),
+ (pango_layout_get_line), (pango_layout_line_leaked),
+ (pango_layout_line_get_extents), (pango_layout_line_new),
+ (pango_layout_iter_get_run), (pango_layout_iter_get_line):
+ Cache line extents. Line extents are cached only if the user doesn't
+ have a pointer to the line or any of its runs. Functions that give
+ away such pointers mark the line as "leak"ed.
+
+ * pango/pango-layout.c (pango_layout_index_to_line_and_extents),
+ (pango_layout_xy_to_index), (pango_layout_index_to_pos):
+ Use _pango_layout_iter_get_line() which is like
+ pango_layout_iter_get_line() but doesn't leak the line.
+
+ * pango/pango-layout-private.h: Add pango_layout_iter_get_line()
+ duplicate _pango_layout_iter_get_line_readonly() that doesn't leak
+ the line.
+
+ * pango/pango-renderer.c (pango_renderer_draw_layout): Use
+ _pango_layout_iter_get_line_readonly().
+
+2006-12-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-render.c (_pango_cairo_renderer_draw_frame):
+ Improve upon last change. Suggested by Carl Worth: use
+ cairo_rectangle(x + width, y, -width, height) to do a rectangle with
+ the other orientation.
+
+2006-12-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-render.c (_pango_cairo_renderer_draw_frame),
+ (_pango_cairo_renderer_draw_box_glyph),
+ (_pango_cairo_renderer_draw_unknown_glyph):
+ Fix handling of boxes drawn in do_path mode. Previously we were
+ doing one rectangle and stroke it if in show mode, and leave it alone
+ if in path mode. That doesn't really work. Now we do two rectangles,
+ for the outer and inner rects of the box border, but with different
+ orientations, such that pango_cairo_layout_path(); cairo_fill(); works
+ for hexboxes now.
+
+2006-12-04 Behdad Esfahbod <behdad@gnome.org>
+
+ Red Hat Bug 211964: [ta] Rendering issue with Tamil
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot-class-tables.c (indic_ot_find_syllable):
+ Handle 2 split matra.
+
+2006-12-04 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line),
+ (pango_renderer_draw_glyphs), (pango_renderer_draw_rectangle),
+ (pango_renderer_draw_error_underline),
+ (pango_renderer_draw_trapezoid), (pango_renderer_draw_glyph),
+ (pango_renderer_activate), (pango_renderer_deactivate),
+ (pango_renderer_set_color), (pango_renderer_get_color),
+ (pango_renderer_part_changed), (pango_renderer_prepare_run),
+ (pango_renderer_set_matrix): Replace PANGO_IS_RENDERER with
+ PANGO_IS_RENDERER_FAST that is just a NULL-check.
+
+2006-12-01 Behdad Esfahbod <behdad@gnome.org>
+
+ Red Hat Bug 213632: ZWJ (200d) and ZWNJ (200c) showing same output
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot.c (indic_ot_reorder): Handle ZWNJ.
+
+2006-12-01 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (pango_layout_run_get_width), (update_run),
+ (pango_layout_iter_copy), (pango_layout_iter_get_run_extents):
+ Don't cache run_logical_rect in PangoLayoutIter. Just cache run_width
+ that can be fastly computed using pango_glyph_string_get_width().
+ Avoids one pango_font_get_glyph_extents() call per glyph per layout
+ rendering. We are down to 1 now.
+
+2006-11-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (pango_layout_get_extents_internal): Rework
+ the way we compute the real_width to avoid calling
+ pango_layout_get_extents(), and so, avoid one
+ pango_font_get_glyph_extents() call per glyph per layout rendering.
+ We now make 2 such calls.
+
+2006-11-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line):
+ Don't call into pango_glyph_string_extents() if we don't need anything
+ out of it! (Ok, that function returns immediately in that case, but
+ still, avoiding the call overhead.)
+
+2006-11-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-render.c (acquire_renderer), (release_renderer):
+ Use G_LOCK_* wrappers for GStaticMutex.
+
+2006-11-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-font.c (_pango_cairo_font_install),
+ (_pango_cairo_font_get_font_face),
+ (_pango_cairo_font_get_scaled_font):
+ * pango/pangocairo-private.h:
+ * pango/pangocairo-render.c (pango_cairo_renderer_draw_glyphs):
+ Revert two of the cast changes from last commit, to make sure the
+ test-pangocairo-fontmap-mismatch test doesn't crash.
+
+2006-11-28 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_font_face),
+ (pango_cairo_fc_font_install), (pango_cairo_fc_font_finalize),
+ (pango_cairo_fc_font_get_metrics), (pango_cairo_fc_font_shutdown),
+ (_pango_cairo_fc_font_new):
+ * pango/pangocairo-fcfontmap.c
+ (pango_cairo_fc_font_map_set_resolution),
+ (pango_cairo_fc_font_map_get_resolution_cairo),
+ (pango_cairo_fc_font_map_get_renderer),
+ (pango_cairo_fc_font_map_finalize),
+ (pango_cairo_fc_font_map_get_resolution_fc),
+ (pango_cairo_fc_font_map_create_font):
+ * pango/pangocairo-font.c (_pango_cairo_font_install),
+ (_pango_cairo_font_get_font_face),
+ (_pango_cairo_font_get_scaled_font),
+ (_pango_cairo_font_get_hex_box_info):
+ * pango/pangocairo-fontmap.c (pango_cairo_create_layout):
+ * pango/pangocairo-render.c (set_color),
+ (_pango_cairo_renderer_draw_unknown_glyph),
+ (pango_cairo_renderer_draw_glyphs),
+ (pango_cairo_renderer_draw_rectangle),
+ (pango_cairo_renderer_draw_error_underline):
+ Use simple, fast, casts instead of PANGO_CAIRO_*() macros where the
+ object cannot have reached us if it wasn't of the right type.
+
+2006-11-27 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 371388 – Add Thai langauage engine
+ Patch from Theppitak Karoonboonyanan
+
+ * configure.in: Look for libthai and enable thai-lang module.
+ * modules/thai/Makefile.am: Hook thai-lang module.
+
+ * modules/thai/thai-lang.c: New Thai language engine that uses libthai
+ to do dictionary-based Thai line-breaking.
+
+ * examples/test-thai.txt: Improved.
+
+2006-11-25 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-render.c (acquire_renderer), (release_renderer),
+ (_pango_cairo_do_glyph_string), (_pango_cairo_do_layout_line),
+ (_pango_cairo_do_layout): Make renderer-cache really thread-safe this
+ time. Last try was not quite thread-safe theoretically, because
+ pointer assignments are not necessarily atomic on some archs. Anyway,
+ this one should do it.
+
+2006-11-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/HELLO.utf8:
+ * examples/Makefile.am:
+ * examples/test-lao.txt:
+ Add Lao text samples from Anousak Souphavanh.
+
+2006-11-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 377975 – bug in _pango_glyph_item_iter_next_cluster
+
+ * pango/pango-glyph-item.c (_pango_glyph_item_iter_next_cluster),
+ (_pango_glyph_item_iter_prev_cluster): Fix condition for ending a
+ cluster.
+
+2006-11-21 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-glyph-item.c: Fix typo in private docs.
+
+2006-11-20 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 356666 – pango is not thread-safe, nautilus does not honour that
+
+ * pango/pangocairo-render.c (acquire_renderer), (release_renderer),
+ (_pango_cairo_do_glyph_string), (_pango_cairo_do_layout_line),
+ (_pango_cairo_do_layout): Instead of using a per-fontmap renderer, use
+ a locally cached one, but make sure only one thread uses the cached
+ renderer. Fixes the raciest point in pangocairo.
+
+2006-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 352795 – configure.in: Bug in "checking Whether to write
+ dependencies into .pc files"
+
+ * configure.in: Make libtool magic robust.
+
+2006-11-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-context.c (itemize_state_process_run): Choose
+ shaper/font for unassigned Unicode codepoints too. This is needed to
+ be able to render scripts being encoded before next version of Unicode
+ is out.
+
+2006-11-08 Roozbeh Pournader <roozbeh@farsiweb.info>
+
+ Bug 350132 – backspacing doesn't work properly for Arabic
+
+ * modules/arabic/arabic-lang.c: Add more backspace_deletes_character
+ cases.
+
+2006-11-08 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 369670 – Crash when selecting text using the keyboard
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually): Don't
+ index vis2log_map[] with a negative value.
+
+2006-11-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 369670 – Checked g_free calls
+
+ * pango/pango-coverage.c (pango_coverage_unref):
+ * pango/pango-layout.c (pango_layout_finalize),
+ (pango_layout_set_text):
+ * pango/pangofc-font.c (pango_fc_font_finalize):
+ * pango/pangox-fontmap.c (pango_x_font_map_read_alias_file):
+ Remove redundant checks before g_free() calls.
+
+2006-10-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/Makefile.am (cairosimple_LDADD): Do not require pangoft2
+ unconditionally.
+
+2006-10-24 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_class_init),
+ (pango_ft2_font_map_get_resolution): Implement get_resolution for FT2
+ fontmaps.
+
+2006-10-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/arabic/arabic-lang.c: Do not include arabic-ot.h.
+
+2006-10-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/test-thai.txt: Replace by a better one.
+
+2006-10-17 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/Makefile.am:
+ * examples/test-thai.txt: Added.
+
+2006-10-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * === Released 1.15.0 ===
+
+ * configure.in: Version 1.15.0
+
+ * NEWS: Updated.
+
+2006-10-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 330407 – Multiple dependant vowel signs (indic) displayed as one
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot-class-tables.c: Change state transition for
+ cn to dv.
+
+2006-10-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-ot-info.c (pango_ot_info_get_type):
+ * pango/pango-ot-ruleset.c (pango_ot_ruleset_get_type):
+ * pango/pangoatsui-fontmap.c (pango_atsui_family_get_type),
+ (pango_atsui_face_get_type):
+ * pango/pangocairo-font.c (pango_cairo_font_get_type):
+ * pango/pangocairo-fontmap.c (pango_cairo_font_map_get_type):
+ * pango/pangofc-fontmap.c (pango_fc_face_get_type),
+ (pango_fc_family_get_type):
+ * pango/pangowin32-fontmap.c (pango_win32_family_get_type),
+ (pango_win32_face_get_type):
+ * pango/pangox-fontmap.c (pango_x_font_map_get_type),
+ (pango_x_face_get_type), (pango_x_family_get_type):
+ * pango/pangox.c (pango_x_font_get_type):
+ Make TypeInfo structs not static. Reduces relocations.
+
+2006-10-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 361938 – Can't include *-lang modules (./configure
+ --with-included-modules fails)
+
+ * configure.in:
+ * modules/Makefile.am:
+ * pango/.cvsignore:
+ * pango/Makefile.am:
+ * pango/modules.c (init_modules):
+ * pango/modules.h:
+ Make included language engines work.
+
+2006-10-12 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 353877 – Sinhala is_cursor_position and
+ backspace_deletes_character issues
+ Patch from Akira TAGOH
+
+ * configure.in:
+ * modules/indic/Makefile.am:
+ * modules/indic/indic-lang.c: Add a simple Indic language engine.
+
+2006-10-12 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 358224 – Telugu Character U+0C31 does not render its below-base
+ form.
+ Patch from Rahul Bhalerao
+
+ * modules/indic/indic-ot-class-tables.c: Change the class of U+0C31
+ from '_ct' to '_bb'.
+
+2006-10-12 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 358174 – Reph and Vattu forms of Assamese character RA(U+09F0) are
+ not rendered.
+ Patch from Rahul Bhalerao
+
+ * modules/indic/indic-ot-class-tables.c: Change the class bit of
+ U+09F0 from '_ct' to '_rv'.
+
+2006-10-07 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/Makefile.am:
+ * examples/test-latin.txt: Add part of Jabberwocky as Latin test text.
+
+2006-10-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 356685 – [or_IN] Rendering of consonant+0x0B4D+0x0B2F is wrong
+ Patch from Rahul Bhalerao
+
+ * modules/indic/indic-ot-class-tables.c: Change _ct to _bb for
+ various Orya characters.
+
+2006-10-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 357790 – Rendering problem for malayalam consonant RA (U+0D30)
+ Patch from Rahul Bhalerao
+
+ * modules/indic/indic-ot-class-tables.c:
+ * modules/indic/indic-ot.c (indic_ot_reorder):
+ Fix.
+
+2006-10-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 359043 – PangoRenderer does not show in API docs
+
+ * docs/pango-docs.sgml: Hook PangoRenderer docs.
+
+2006-10-02 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 359046 – renderdemo.c unconditionally use GLib 2.12
+
+ * configure.in: Require glib 2.12, for Unicode 5.0 data files.
+
+2006-09-25 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 357686 – pangocairo-font.c: illegal g_object_unref in
+ pango_cairo_font_get_hex_box_info
+
+ * pango/pangocairo-font.c (_pango_cairo_font_get_hex_box_info): Remove
+ wrong g_object_unref (fontmap).
+
+2006-09-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 357228 – Remove aix specific hack from configure.in
+
+ * configure.in: Remove hack added back 2002 that is not required
+ anymore.
+
+2006-09-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * configure.in: Step module interface version to 1.6.0 because of the
+ script_break() slight change of behavior and anticipated changes to
+ the module interface this cycle.
+
+2006-09-18 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 350132 – backspacing doesn't work properly for Arabic
+
+ * configure.in:
+ * modules/arabic/Makefile.am:
+ * modules/arabic/arabic-lang.c:
+ Add a simple Arabic language engine. Currently it just makes sure
+ that backspace_deletes_character is not set on ALEF-MADDA
+ combinations.
+
+2006-09-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * tools/gen-script-table.pl:
+ * pango/pango-script-table.h:
+ * pango/pango-script.c (pango_script_for_unichar): Minor
+ simplification.
+
+ * tests/testscript.c (test_script_lookup): Update to pass.
+
+2006-09-18 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangoft2-render.c (pango_ft2_font_render_glyph): Remove a
+ couple of unnecessary static variables.
+
+2006-09-18 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 356194 – more pango_get_log_attrs problems
+
+ * pango/break.c (tailor_break): New function. Simply calls the
+ script_break() function of the language engine, if any.
+
+ * pango/break.c (pango_break): Call pango_default_break()
+ unconditionally. Call tailor_break() on top of the result to tailor
+ it using the language engines, if any.
+
+ * pango/break.c (tailor_segment): Call tailor_break() on the segment,
+ and make sure the log_attrs for the first position are not corrupted.
+
+ * pango/break.c (pango_get_log_attrs): Call pango_default_break() on
+ the entire paragraph, and call tailor_segment on each segment.
+
+ * pango/pango-engine.h: Update docs about *script_break()'s behavior.
+
+2006-09-15 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 355820 – pango_get_log_attrs broken
+
+ * pango/break.c (break_it), (pango_get_log_attrs): Use PangoScriptIter
+ to itemize text, instead of pango_script_for_unichar().
+
+2006-09-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangofc-fontmap.c (pango_fc_face_describe): Unset gravity on
+ the resulting font description. We want gravity to be set on all
+ fonts described, but not font faces.
+
+2006-09-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/indic/indic-ot-class-tables.c: Change enums to macros, to
+ get in synch with ICU shaper. No functional changes.
+
+2006-09-14 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/indic/indic-ot.h: Change some enums to macros, to get in
+ synch with ICU shaper. No functional changes.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 351223 – the conjuction of Con + 0x0d4d +0x0d31 of Malayalam is
+ wrong
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot.c (swapChars), (indic_ot_reorder): Special
+ case the above case.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 355750 – The glyphs of the conjuctions about Cons+0x0d4d+0x0d32 of
+ Malayalm are wrong.
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot-class-tables.c (mlymCharClasses): Change
+ U+0D32 from _bb to _ct.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 349876 – U+0x0904 of Devanagari need be "independent vowel", but
+ it is "reserved" in Pango
+ Patch from LingNing Zhang
+
+ * modules/indic/indic-ot-class-tables.c (devaCharClasses): Change
+ U+0904 from _xx to _iv.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 355550 – Miscalculation of logical attributes in
+ pango_get_log_attrs()
+ Patch from Theppitak Karoonboonyanan
+
+ * pango/break.c (pango_get_log_attrs): Pass the correct lang_engine to
+ pango_break().
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/modules.c (pango_engine_pair_get_engine): Err about failing to
+ load engine only once per module.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 355697 – The IndicOTClassTable of Oriya has a error.
+
+ * modules/indic/indic-ot-class-tables.c: Compute lastChar from
+ charClasses table size to avoid out-of-synch.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 355782 – Misaligned extents in pango
+
+ * pango/pango-layout.c (pango_layout_get_extents_internal),
+ (pango_layout_get_extents), (pango_layout_iter_copy),
+ (pango_layout_get_iter), (pango_layout_iter_get_line_extents):
+ Add a new internal member layout_width to PangoLayoutIter. Set it up
+ in pango_layout_get_extents_internal and use in
+ pango_layout_iter_get_line_extents to fix misalignment of ink link
+ extents.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ "Thou shalt not touch code that does not fit in thy brain."
+
+ * pango/pango-layout.c (update_cluster): Add cluster_start_index
+ parameter back in.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-engine.h: Remove unnecessary 'static' in type definition
+ that causes a relocation.
+
+ * pango/shape.c (pango_shape): Make sure last_cluster is invalid.
+
+2006-09-13 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 355782 – Misaligned extents in pango
+
+ * pango/pango-layout.c (cluster_width): Rewrite based on
+ is_cluster_start instead of accessing log_clusters directly. This is
+ more robust as next_cluster uses that, so the two match now.
+
+ * pango/pango-layout.c (update_cluster): Remove the
+ cluster_start_index parameter and use iter->cluster_start instead.
+
+ * pango/pango-layout.c (pango_layout_iter_copy): Fix typo in copying
+ iter->cluster_width.
+
+ * pango/pango-layout.c (pango_layout_iter_get_cluster_extents): Add
+ an assert to make sure iter->cluster_width is correctly set.
+
+ * pango/pango-layout.c (pango_layout_iter_get_char_extents): Remove
+ assert that was readded above to check more cases.
+
+2006-09-12 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 355605 – hexbox with 0000 in it
+
+ * modules/hangul/hangul-fc.c (render_syllable): If decomposition
+ fails, backup and add a single hexbox glyph for the original
+ character.
+
+2006-09-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 355435 – Invalid calls to pango_map_get_engine()
+ Patch from Theppitak Karoonboonyanan
+
+ * pango/break.c (pango_get_log_attrs):
+ * pango/pango-renderer.c (add_underline):
+ * pango/pangofc-font.c (pango_fc_font_find_shaper):
+ * pango/pangowin32.c (pango_win32_font_find_shaper):
+ * pango/pangox.c (pango_x_font_find_shaper):
+ Pass a PangoScript to pango_map_get_engine, not a gunichar!
+
+2006-09-11 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 347146 – underline/overstrike spaces
+
+ * pango/pango-renderer.c (add_underline), (add_strikethrough),
+ (pango_renderer_draw_layout_line): Use logical extents for
+ x and width of underline/strikethrough, such that trailing spaces are
+ correctly handled.
+
+ * pango/pango-layout.c (pango_layout_run_get_extents): Use logical
+ rect for underline/strikethrough, and reflect that in run ink extents.
+
+ * pango/pango-layout.c (pango_layout_line_get_extents): Don't
+ let runs with empty ink extents affect total ink extents.
+
+2006-09-10 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 352535 – Ink extents of empty glyph
+
+ * pango/pangocairo-fcfont.c
+ (pango_cairo_fc_font_get_glyph_extents): Return zero ink_rect for
+ PANGO_GLYPH_EMPTY.
+
+2006-09-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/cairotwisted.c: A simple text-on-path example using
+ pangocairo.
+
+ * examples/Makefile.am: Update.
+
+2006-09-08 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (find_field_any): Parse style. It was dropped when
+ I was adding support for gravity.
+
+2006-08-31 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c, pango/pangox-fontmap.c, pango/pangox.c:
+ Minor doc syntax update.
+
+2006-08-30 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 148732 – cursor movenmet is not correct in gedit when I type
+ Arabic text.
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually): Update
+ locally cached line properties upon line change.
+
+2006-08-30 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/Makefile.am (pango.modules): Improve the conditional to
+ ignore included modules.
+
+2006-08-30 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 352811 – SIGSEGV with pango(cairo)-view on HP-UX
+
+ * modules/Makefile.am (pango.modules): Don't hardcode .so extension.
+ Look for .la instead.
+
+2006-08-30 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 353525 – libpangoft2-1.0.so.0: undefined reference to
+ `pango_font_description_get_gravity'
+
+ * examples/Makefile.am: Explicitly link to the just built pangoft2 for
+ pangocairo uses, like we already do for pangoxft.
+
+2006-08-28 Tor Lillqvist <tml@novell.com>
+
+ * modules/basic/Makefile.am: Have basic-win32.c instead of
+ basic-win32.lo depend on usp10.h so things work out also in case
+ the basic-win32 module is compiled in.
+
+2006-08-26 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 349813 – typo in docs for pango_layout_move_cursor_visually
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually): Fix typo.
+
+2006-08-23 Tor Lillqvist <tml@novell.com>
+
+ * pango/Makefile.am
+ * examples/Makefile.am
+ * pango/testfonts.c
+ * examples/pangowin32tobmp.c: Rename pango/testfonts.c to
+ examples/pangowin32tobmp.c. (#104151)
+
+2006-08-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-context.c (itemize_state_process_run): Replace (!isgraph
+ && !isspace) with (!isprint) which is equivalent. Also, update
+ comments.
+
+2006-08-22 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 145275 – Font selection for space characters
+
+ * pango/pango-context.c (itemize_state_process_run): Find shaper/font
+ for Private Use and space characters too. Finding shaper for Private
+ Use is needed for any practical use of those areas. Ideally, spaces
+ should be synthesized if they are not available in the font, but
+ falling back to other fonts is far easier, and should give pretty good
+ results with the current set of common fonts. These fixes allow
+ Firefox+Pango to render MathML like Firefox+Xft does.
+
+2006-08-22 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/fonts.c (gravity_map): Rename "Upright" to "Not-Rotated".
+ Also, reorder the user-friendly names (Not-Rotated, Rotated-Left, ...)
+ before the enum names (South, East, ...) such that they are used to
+ describe fonts.
+
+2006-08-21 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 352114 – pango-1.14: generated docs still contain old example code
+
+ * docs/tmpl/pangocairo.sgml: Update cairo example code to that of
+ examples/cairosimple.c.
+
+2006-08-20 Behdad Esfahbod <behdad@gnome.org>
+
+ Support per-item gravity.
+
+ * pango/pango-context.c (update_attr_iterator),
+ (itemize_state_init), (itemize_state_update_for_new_run),
+ (itemize_state_process_run): Make per-item gravity work, by setting
+ gravity into font description before loading fonts. Also, allow
+ the context font description to override the gravity (but not
+ centered_baseline.)
+
+ * pango/pangocairo-fcfont.c (_pango_cairo_fc_font_new): Get gravity
+ from font description, not context.
+
+ * pango/pangofc-fontmap.c (fontset_hash_key_equal),
+ (fontset_hash_key_hash), (fontset_hash_key_copy),
+ (pango_fc_make_pattern), (pango_fc_font_map_get_patterns),
+ (pango_fc_font_map_load_fontset),
+ (pango_fc_font_description_from_pattern): Get gravity from font
+ description, not context. Moreover, put it into pattern, and
+ reconstruct it out of font patterns.
+
+ * pango/pangofc-private.h: Define PANGO_FC_GRAVITY, which is the key
+ we put PangoGravity into an FcPattern under.
+
+2006-08-20 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/fonts.sgml:
+ * pango/fonts.c (pango_font_description_set_gravity),
+ (pango_font_description_get_gravity),
+ (pango_font_description_merge_static),
+ (pango_font_description_better_match),
+ (pango_font_description_equal), (pango_font_description_hash),
+ (find_field_any), (pango_font_description_from_string),
+ (pango_font_description_to_string):
+ * pango/pango-font.h:
+ * pango/pango.def:
+ Add gravity in PangoFontDescription.
+
+2006-08-20 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-matrix.c (pango_matrix_to_gravity): Correct switched
+ return value of EAST/WEST.
+
+ * pango/pango-types.h (PangoGravity): Add PANGO_GRAVITY_AUTO.
+ * pango/pango-context.h: Add pango_context_get_gravity().
+
+ * examples/renderdemo.c (parse_gravity), (parse_options):
+ * pango/pango-context.c (pango_context_init),
+ (update_resolved_gravity), (pango_context_set_matrix),
+ (pango_context_set_base_gravity), (pango_context_get_gravity),
+ (itemize_state_init), (get_shaper_and_font):
+ * pango/pango-layout.c (line_set_resolved_dir):
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_metrics),
+ (pango_cairo_fc_font_glyph_extents_cache_init),
+ (_pango_cairo_fc_font_new):
+ * pango/pangofc-fontmap.c (pango_fc_make_pattern),
+ (pango_fc_font_map_load_fontset):
+ * pango/pango.def:
+ * docs/pango-sections.txt:
+ * docs/tmpl/main.sgml:
+ Update to above.
+
+2006-08-20 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/renderdemo.c (parse_options):
+ * examples/renderdemo.h: Change the --rotate parameter to double now
+ that we depend on a recent-enough glib.
+
+2006-08-20 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 351496 – PangoAnalysis::gravity breaks binary compatibility
+
+ * pango/pango-item.h (PangoAnalysis): Use bitfields for level.
+
+2006-08-17 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc pango/pango.def : updated
+ * pango/break.c(1630) : error C2059: syntax error : '}' Intializing a
+ struct with empty braces is not supported with MSVC, instead use 0.
+ * pango/pangocairo.def : removed pango_fc_font_(map_)get_type
+ pangocairo has either win32 fonts or freetype. The former is more usual.
+ * pango/pango-utils.c : replaced M_PI by G_PI (from glib/gtypes.h).
+
+2006-08-17 Behdad Esfahbod <behdad@gnome.org>
+
+ Part of Bug 348825 – pango should optimize away calls to FcFontSort as
+ much as possible
+
+ * pango/pangofc-fontmap.c: Increase FONTSET_CACHE_SIZE from 16 to 64.
+
+2006-08-17 Tor Lillqvist <tml@novell.com>
+
+ * pangowin32.pc.in: Drop @WIN32_LIBS@, no need to search -lgdi32
+ when linking apps that link with libcairowin32.
+
+ * pango/pango.def: Add two symbols.
+
+2006-08-16 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 351585 – API documentation issues with 2.15 release
+
+ * pango/fonts.c (pango_font_describe_with_absolute_size): Add Since
+ tag to docs.
+
+2006-08-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (line_set_resolved_dir): Adjust line
+ resolved_dir according to context base_gravity, like we do
+ in itemize_state_add_character().
+
+2006-08-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/viewer-pangocairo.c (render_callback): Render block
+ progression and line direction arrows, and a base gravity roof-top.
+
+ * pango/pango-matrix.c (pango_matrix_to_gravity): New function.
+
+ * pango/pango-utils.c (pango_gravity_to_rotation): New function.
+
+ * pango/pangocairo-fcfont.c (_pango_cairo_fc_font_new): Use
+ pango_gravity_to_rotation().
+
+ * pango/pango-utils.h:
+ * pango/pango-types.h:
+ Reorder a bit.
+
+ * examples/Makefile.am:
+ * examples/test-chinese.txt: New test text for Chinese.
+
+ * pango/check.defs: New script that checks that all the exported
+ symbols are listed in the respective .def file. (only checks the
+ libraries actually built. No win32 for example.)
+
+ * pango/Makefile.am: Hook check.defs as a 'make check' test.
+
+ * pango/pango.def:
+ * pango/pangoft2.def:
+ * pango/pangocairo.def:
+ Update.
+
+ * docs/tmpl/glyphs.sgml:
+ * docs/tmpl/main.sgml:
+ * docs/pango-sections.txt:
+ Update.
+
+2006-08-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/basic-fc.c (fallback_shape): Remove redundant
+ positioning block!
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-layout.c (pango_layout_run_get_extents):
+ * pango/glyphstring.c (pango_glyph_string_extents_range):
+ Return if none of logical_rect or ink_rect is non-NULL.
+
+ * pango/pango-item.h (PangoAnalysis): Add new member centered_baseline
+ which if set, makes item rendered such that ascent == descent.
+
+ * pango/pango-context.c (itemize_state_init),
+ (itemize_state_add_character):
+ * pango/pango-renderer.c (pango_renderer_draw_layout_line):
+ Implement centered_baseline.
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_metrics): When
+ adjusting ascent/descent for vertical fonts, adjust strikethrough and
+ underline position too.
+
+ * docs/tmpl/main.sgml: Document new struct member.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/basic-fc.c (basic_engine_shape): Use analysis->gravity
+ to detect vertical fonts, instead of poking into the font_pattern.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * modules/basic/basic-fc.c (basic_engine_shape): Always use
+ fallback shaping for vertical fonts.
+
+ * pango/pango-context.c (get_shaper_and_font): Always use basic
+ shaper for vertical items (east/west gravity).
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/renderdemo.c (do_output): Render the header with SOUTH
+ gravity.
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_metrics),
+ (pango_cairo_fc_font_glyph_extents_cache_init): Center baseline
+ for east/west gravity in pango_font_metrics too.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/HELLO.utf8: Remove excess LRM.
+
+ * examples/viewer-pangocairo.c (render_callback): Draw baselines in
+ border-drawing mode.
+
+ * pango/pango-layout.c (pango_layout_line_get_extents): Make sure
+ we set logical_rect.y on empty lines. Previously empty lines had
+ wrong baseline. The code apparently was written like that
+ intentionally, but I cannot find out why.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/break.c (pango_get_log_attrs): Remove initliazer members
+ for analysis, let compiler zero them all. Fixes compile break after
+ adding the gravity member inside there.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-context.c (itemize_state_add_character):
+ Fix handling of WEST and EAST gravity effect on bidi level.
+
+ * pango/pangocairo-fcfont.c
+ (pango_cairo_fc_font_glyph_extents_cache_init):
+ For NORTH gravity (upside down text), swap ascent and descent,
+ and for EAST/WEST, center baseline between ascent/descent.
+
+ * pango/shape.c (pango_shape): If glyph width is negative, negate
+ it and shift glyph by that amount. This allows having font matrices
+ that essentially move the glyph origin to the right of the glyph to
+ still work.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_scaled_font),
+ (_pango_cairo_fc_font_new): Move font_matrix rotation into font_new
+ as we use only rotation and no translation anymore.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * docs/pango-sections.txt:
+ * docs/tmpl/main.sgml:
+ * examples/renderdemo.c (parse_gravity), (parse_options):
+ * pango/pango-context.c (pango_context_init),
+ (pango_context_get_base_gravity), (itemize_state_add_character):
+ * pango/pango-types.h:
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_scaled_font):
+ * pango/pangofc-fontmap.c (pango_fc_make_pattern):
+ Oops. Exchange west<->east and north<->south gravities. The gravity
+ is the side that the glyph sits on. So, for normal Latin text for
+ example, gravity is south, not north.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * examples/renderdemo.c (do_output), (parse_gravity),
+ (parse_options): Support --gravity.
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_get_scaled_font),
+ (compute_glyph_extents), (_pango_cairo_fc_font_new): Load rotated
+ scaled_fonts to handle gravity.
+
+ * pango/pangofc-fontmap.c (pango_fc_make_pattern),
+ (pango_fc_font_map_get_patterns), (pango_fc_font_map_load_fontset):
+ Set FC_VERTICAL_LAYOUT on West and East gravity.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-context.c (itemize_state_process_run):
+ Add FIXME note about handling item gravity.
+
+ * pango/pangofc-fontmap.c (fontset_hash_key_equal),
+ (fontset_hash_key_hash), (fontset_hash_key_copy),
+ (pango_fc_font_map_get_patterns): Add gravity into the hask key.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-item.h: Add a gravity member to PangoItem, and
+
+ * pango/pango-context.c (itemize_state_init),
+ (itemize_state_add_character): Propagate context base_gravity
+ into items.
+
+2006-08-15 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-types.h: Add enum PangoGravity.
+
+ * pango/pango-context.h:
+ * pango/pango-context.c (pango_context_set_base_gravity),
+ (pango_context_get_base_gravity): New functions.
+
+ * pango/pango.def:
+ * docs/pango-sections.txt: Hook new API.
+
+Local Variables:
+coding: utf-8
+End:
+vim: encoding=utf-8:
diff --git a/trunk/ChangeLog.pre-1-2 b/trunk/ChangeLog.pre-1-2
new file mode 100644
index 00000000..537b3a7c
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-2
@@ -0,0 +1,1570 @@
+Fri Dec 20 12:18:43 2002 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.2.0 ===
+
+ * configure.in: Version 1.2.0, interface age 0.
+
+ * NEWS: Updated
+
+Fri Dec 20 11:59:22 2002 Owen Taylor <otaylor@redhat.com>
+
+ Some unit fixups (#96335)
+
+ * pango/pango-layout.c pango/pango-mapping.c:
+ Fix occurrences of "in thousandths of a device
+ unit" to say "in #PangoGlyphUnit" which will
+ give a link to the PangoGlyphUnit docs.
+
+ * docs/tmpl/text-attributes.sgml: Change 1000 to PANGO_SCALE.
+
+ * docs/tmpl/glyphs.sgml: Fix docs for PangoGlyphUnit,
+ fix mention of value of PANGO_SCALE from 1000 to 1024.
+
+ * pango/pango-layout.c (pango_layout_line_get_x_ranges):
+ Fix the docs for @ranges so it doesn't sound like the
+ coordinates are in pixels.
+
+Fri Dec 20 11:49:33 2002 Owen Taylor <otaylor@redhat.com>
+
+ * README: Add a note about fonts.conf.
+
+Mon Dec 16 21:16:31 2002 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.1.6 ===
+
+ * NEWS: Updated.
+
+ * configure.in: Version 1.1.6, interface age 2.
+
+ * configure.in: Bump PANGO_MODULE_VERSION to 1.2.0.
+
+Mon Dec 16 19:28:18 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/hangul-xft.c (render_isolated_tone):
+ When we get an isolated tone in isolation, do something
+ reasonable rather than just return no glyphs and
+ causing an assertion failure. (#100625)
+
+ * pango/pangofc-fontmap.cI (_pango_fc_font_map_get_coverage):
+ Add a hack to force Hangul marks to be be rendered
+ in the same font as base Hangul glyphs.
+
+Mon Dec 16 18:10:46 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-xft.c: Add some extra ranges
+ as "*" to match basic-x.c. (#101083, Jungshik Shin)
+ Remove some extraneous "" ranges since we have
+ { 0x0000, 0xffff, "" } anyways.
+
+Thu Dec 12 13:59:43 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Require autoconf-2.53.
+
+2002-12-11 Matthias Clasen <maclas@gmx.de>
+
+ * docs/tmpl/text-attributes.sgml:
+ * docs/tmpl/glyphs.sgml:
+ * docs/tmpl/engines.sgml:
+ * docs/tmpl/main.sgml:
+ * docs/tmpl/pango-indic.sgml:
+ * docs/tmpl/coverage-maps.sgml:
+ * docs/tmpl/fonts.sgml:
+ * docs/pango_markup.sgml: Cosmetic changes to short descriptions.
+
+ * docs/tmpl/tab-stops.sgml:
+ * docs/tmpl/modules.sgml:
+ * docs/tmpl/opentype.sgml:
+ * docs/tmpl/xft-fonts.sgml:
+ * docs/tmpl/freetype-fonts.sgml:
+ * docs/tmpl/win32-fonts.sgml: Add short descriptions.
+
+ * docs/pango-docs.sgml: Move "OpenType Font Handling" to
+ "Low Level Functionality".
+
+ * docs/pango-sections.txt: Combine the "X Fonts" and
+ "X Rendering" sections.
+
+Tue Dec 10 18:37:19 2002 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.1.5 ===
+
+ * pango/pango-attributes.h pango/pango-font.h
+ pango/pango-fontset.h pango/pango-fontmap.h: Add
+ explicit /*< public >*/ /*< private *>/ guards.
+ (See #95398 for gtk-doc changes making this necessary)
+
+Tue Dec 10 14:51:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 1.1.5, interface age 1.
+
+ * NEWS: Update.
+
+Sun Dec 8 22:57:55 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c: Draw the unknown glyph box with
+ X primitives rather than hoping that some font has an
+ actualpainting unknown glyph... that code was
+ apparently still working badly. Use "en" not
+ NULL as the language tags for getting the metrics
+ for the return glyph and the unknown character
+ glyph... NULL gives too large results. (#98245,
+ Based on a patch from Morten Welinder.)
+
+Sun Dec 8 15:22:10 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-glyph-item.c (pango_glyph_item_apply_attrs):
+ Free the iter. (Fix from Kjartan Maraas, #100672)
+
+2002-12-08 Matthias Clasen <maclas@gmx.de>
+
+ * docs/tmpl/pango-indic.sgml: Document PangoIndicScript.
+
+2002-12-07 Matthias Clasen <maclas@gmx.de>
+
+ * pango/pangowin32.c (pango_win32_get_dc): Document.
+
+Sat Dec 7 01:05:25 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI (pango_fc_font_map_get_patterns):
+ Print out an informative error message and exit(1) if
+ no fonts are found. (#98672)
+
+ * pango/pangoft2.c (pango_ft2_font_get_face): Fix some
+ bugs in the last commit.
+
+Sat Dec 7 00:10:02 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2.c (pango_ft2_font_get_face): Don't
+ use face->generic.data to hold the size the face is
+ currently set to; we don't need it currently and
+ it interferes with the use of face->generic.data for
+ OpenType data. (#93822, frequently reported bug)
+
+Fri Dec 6 23:07:58 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_real_render)
+ pango/pangox.c (pango_x_render): Roughly clip glyphs
+ into the X coordinate area to avoid wrap-around. (#73119)
+
+Fri Dec 6 19:42:33 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules.c (map_get_submap): Dynamically allocate
+ submap arrays so we aren't constrained to the BMP.
+ (#100307, Federic Zhang)
+
+Fri Dec 6 18:58:25 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.lo: Use octal escapes rather than
+ hex to avoid the problem over having hex digits
+ immediately after the hex escape.
+
+Fri Dec 6 18:30:36 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c: Convert literal UTF-8 to octal
+ escapes. (#92050, Arnaud Charlet)
+
+ * pango/testfonts.c: Convert literal ISO-8859-1
+ to UTF-8 hex escapes. (Don't know how passing
+ ISO-8859-1 to pango_shape() was working...)
+
+Fri Dec 6 18:07:48 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/devanagari-x.c, pango/modules.c
+ pango/pango-utils.c pango/pangoft2.c pango/querymodules.c:
+ Convert [sf]printf to g_[sf]printf, or, where
+ appropriate g_printerr(). (Based on patch from
+ Matthias Clasen, #99321)
+
+ * configure.in: Require glib-2.1.3.
+
+Fri Dec 6 17:56:32 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Add missing thai-xft to thai-modules.
+ (#99883, Tony Graham)
+
+Mon Dec 2 17:22:34 2002 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.1.4 ===
+
+ * configure.in: Up version to 1.1.4, interface age 0.
+
+ * NEWS: Updated.
+
+ * pango/pangoxft-fontmap.c (pango_fc_do_finalize)
+ * pango/pangoft2-fontmap.c (pango_fc_do_finalize): Fix
+ leaks of fontmap->substitute_data. (#99850)
+
+ * pango/Makefile.am (INCLUDES): Fix accidental reference
+ to pango-script-table.h.
+
+Sun Nov 17 23:28:26 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-glyph-item.[ch] pango/pango-layout.h:
+ Rename PangoLayoutRun to PangoGlyphItem (with a
+ typedef for compat), add pango_glyph_item_split(),
+ pango_glyph_item_apply_attrs().
+
+ * pango/pango-attributes.[ch]: Add
+ pango_attr_list_filter(), pango_attr_iterator_get_attrs().
+
+ * pango/pango-layout.c: Remove attributes that don't
+ affect shaping before shaping, shape and then add
+ them back. Fixes the infamous "underscores break
+ arabic shaping" bug (#83058)
+
+ * pango/pango-item.h: Remove an extraneous include.
+
+ * pango/pango-layout.c (imposed_shape): Fix bytes/chars
+ problem for glyph->log_clusters.
+
+ * pango/pango-layout.c (cluster_end_index)
+ * pango/pango-layout.c (pango_layout_iter_next_cluster): Fix
+ confusion between global indices and run-relative indices.
+
+ * docs/tmpl/glyphs.sgml: Improve docs for log_clusters.
+
+ * docs/*: Document new API and PangoOTRuleset
+
+2002-11-29 Matthias Clasen <maclas@gmx.de>
+
+ * docs/tmpl/xft-fonts.sgml:
+ * docs/tmpl/freetype-fonts.sgml: Add docs.
+
+ * pango/pangoxft-fontmap.c (pango_xft_substitute_changed):
+ * pango/pangoft2-fontmap.c
+ (pango_ft2_font_map_set_default_substitute):
+ Fix doc typos.
+
+2002-11-28 Matthias Clasen <maclas@gmx.de>
+
+ * pango/pangoxft-fontmap.c:
+ * pango/pangoxft-font.c:
+ * pango/pangowin32.c:
+ * pango/pangoft2-fontmap.c: Mark 1.2 API additions, fix some
+ doc comments.
+
+ * pango/pangoft2-fontmap.c
+ (pango_ft2_font_map_set_default_substitute): Implement this
+ function. (#99850)
+
+2002-11-26 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Do not add GLIB_CFLAGS to CFLAGS.
+
+ * docs/Makefile.am, examples/Makefile.am,
+ modules/arabic/Makefile.am, modules/basic/Makefile.am,
+ modules/hangul/Makefile.am, modules/hebrew/Makefile.am,
+ modules/indic/Makefile.am, modules/tamil/Makefile.am,
+ modules/thai/Makefile.am, pango/Makefile.am,
+ pango/mini-fribidi/Makefile.am, pango/opentype/Makefile.am:
+ Instead add $(GLIB_CFLAGS) directly to INCLUDES (GTKDOC_CFLAGS for
+ docs/Makefile.am). Also some cosmetic line wrapping and
+ reindentation. (#77981)
+
+Mon Nov 25 20:25:23 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/glyphstring.c (pango_glyph_string_extents_range):
+ Clarify the meaning of the @end parameter. (#96843,
+ Jungshik Shin)
+
+Mon Nov 25 19:57:02 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_free): Remove
+ some confusing left over verbiage in API docs about what
+ font descriptions could be freed. (#96558,
+ Michael R. Walton.)
+
+Mon Nov 25 19:24:29 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mini-fribidi/fribidi_get_type.c (_pango_fribidi_get_type):
+ Fix off-by-one in check for non-BMP characters.
+ (#91834, He Qiangqiang)
+
+Mon Nov 25 11:58:30 2002 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer-qt.cc (readFile): Fix missing argument
+ (#99380, Dagfinn I. Mannsåker)
+
+2002-11-23 Matthias Clasen <maclas@gmx.de>
+
+ * docs/version.xml.in: New file to let configure dump the version in.
+
+ * docs/pango-docs.sgml: Add version information.
+
+ * docs/Makefile.am (extra_files): Add version.xml.in.
+ (content_files): Add version.xml.
+
+ * configure.in: Generate docs/version.xml.
+
+Thu Nov 21 17:35:08 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-ft2.c: Remove duplicate
+ include of basic-common.h (#97667, Tony Graham)
+
+Thu Nov 21 00:26:40 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Use some shell magic rather than
+ perl to check for the right gtk-doc version to
+ avoid having to worry about finding Perl.
+ Make checks handle 0.10 > 0.9. (#99120, Dan Mills)
+ Check for 0.10, since we need that for
+ --output-format=xml.
+
+2002-11-12 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-fontcache.c (free_cache_entry,
+ cache_entry_unref, pango_win32_font_cache_load): Add more
+ debugging output.
+
+ * modules/basic/basic-win32.c (uniscribe_shape): Plug memory leak:
+ Free return value from pango_win32_font_logfont(). Call
+ pango_win32_font_cache_unload() for the hfont returned from
+ pango_win32_font_cache_load() after using it.
+
+Fri Nov 8 20:02:09 2002 Soeren Sandmann <sandmann@daimi.au.dk>
+
+ * docs/tmpl/coverage-maps.sgml:
+ * docs/tmpl/glyphs.sgml:
+ * docs/tmpl/layout.sgml:
+ * docs/tmpl/x-fonts.sgml:
+ * pango/mapping.c:
+ * pango/pango-coverage.c:
+ * pango/pango-coverage.h:
+ * pango/pango-glyph.h:
+ * pango/pango-layout.c:
+ * pango/pango-layout.h:
+ * pango/pangox.h:
+
+ Trivial s/foo/foo_/ fixes to make pango.h includable with -Wshadow
+ (#91680).
+
+2002-11-09 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-x.c (render_syllable_with_ksx1001johab):
+ Renamed from render_syllable_with_ksx1005 (#95800).
+
+Thu Nov 7 10:05:28 2002 HideToshi Tajima <hidetoshi.tajima@sun.com>
+
+ * modules/basic/basic-x.c:
+ Fix #96781: changes for basic X shaper's code range for
+ compatibility Ideographs characters (0xFA0C - 0xFA2D)
+ (by federic.zhang@sun.com)
+
+2002-11-06 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-x.c (hangul_engine_shape): Applied some of
+ the hangul-xft changes into hangul-x; it takes precomposed
+ syllables as same as L+V or L+V+S jamo sequences.
+
+2002-11-04 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-defs.h (IS_S): Fixed wrong syllable
+ check.
+
+ * modules/hangul/hangul-defs.h:
+ * modules/hangul/hangul-x.c: No more use of TFILL, the internal
+ trailing consonant filler.
+ (render_syllable_with_*): Appended empty syllable
+ (ex. LFILL+VFILL) rendering case (#96175).
+ (render_syllable_with_ksx1005): Fixed wrong fallback glyphs
+ indices (from #95800 by Jungshik Shin).
+
+Fri Nov 1 21:08:42 2002 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.1.3 ===
+
+ * configure.in: Version 1.1.3
+
+ * NEWS: Updated.
+
+ * pango/pangofc-fontmap.cI (pango_fc_font_set_free):
+ Free font_set->patterns. (Found by Sven Neumann,
+ #91698)
+
+2002-11-03 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/basic/basic-xft.c: Removed hangul syllables and hangul
+ tonemarks ranges. Now hangul-xft is responsible for these ranges.
+
+2002-11-01 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-defs.h modules/hangul/hangul-xft.c:
+ Added Hangul Tone Marks rendering by Jungshik Shin (#96299).
+
+2002-10-31 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-xft.c (hangul_engine_get_coverage):
+ Added U+AC00- coverage
+ (hangul_engine_shape): Renders U+AC00 Hangul Syllables.
+
+2002-10-24 Tor Lillqvist <tml@iki.fi>
+
+ * modules/basic/basic-win32.c: Update the non-Uniscribe ranges to
+ cover some more simple scripts.
+
+ (itemize_shape_and_place): Handle unknown glyphs.
+
+ (script_engine_list): Only return the "everything" range if
+ Uniscribe is available. It would be nice to build up a more
+ specific range list based on the information ScriptGetProperties()
+ returns. That function lists information about each script the
+ Uniscribe version used can handle. Unfortunately, though, the
+ information is severely limited. It doesn't tell what Unicode
+ blocks a script covers. It only gives one language that uses
+ that script, and sometimes an charset number, but for most scripts
+ just the totally useless DEFAULT_CHARSET.
+
+2002-10-23 Alexander Larsson <alexl@redhat.com>
+
+ * pango/pango-layout.c (can_break_in):
+ Don't break at the first char in the first item on a line.
+ Fixes regression in linebreaking (#95900).
+
+2002-10-22 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Add --with-usp10 flag to indicate where to find
+ the usp10.h header, for using Uniscribe on Win32. Set USP10_H
+ autoconf variable, HAVE_USP10_H config.h macro and HAVE_USP10_H
+ automake conditional.
+
+ * acconfig.h: Add HAVE_USP10_H.
+
+ * pango/pangowin32-private.h (PANGO_WIN32_DEBUGGING): Change
+ semantics of this flag. If defined, also need to set env var
+ PANGO_WIN32_DEBUG to get the copious debugging output.
+ Change PING() macro accordingly. Add variable pango_win32_debug.
+
+ * pango/pangowin32.c (pango_win32_get_dc): New function. Code
+ factored out from pango_win32_font_class_init() and
+ pango_win32_font_map_class_init().
+ (pango_win32_get_debug_flag): New function.
+ (pango_win32_render): Handle y offsets, too. Potentially need to
+ call ExtTextOutW several times, one for each run of sequential
+ glyphs with the same y offset.
+
+ * pango/pangowin32.h: Declare above new functions, in the part
+ only for shaper engine use.
+
+ * pango/pangowin32.def: Export above new functions.
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init):
+ Call pango_win32_get_dc() as mentioned above.
+
+ * modules/basic/Makefile.am: If HAVE_USP10_H, let basic-win32.lo
+ depend on usp10.h.
+
+ * modules/basic/basic-win32.c: If HAVE_USP10_H, and the Uniscribe
+ DLL usp10.dll is present, use Uniscribe.
+ (uniscribe_shape, itemize_shape_and_place,
+ set_up_pango_log_clusters, convert_log_clusters_to_byte_offsets,
+ make_langid, init_uniscribe): New functions.
+ (dump_glyphs_and_log_clusters, lang_name, charset_name): Debugging
+ functions.
+
+2002-10-20 Matthias Clasen <maclas@gmx.de>
+
+ * docs/Makefile.am (SCANOBJ_FILES): Add $(DOC_MODULE).prerequisites.
+
+2002-10-15 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-xft.c (hangul_engine_shape):
+ * modules/hangul/hangul-x.c (hangul_engine_shape): Added missing
+ memcpy() from the static jamo buffer to allocated jamo buffer
+ (#95569). Thanks to Jungshik Shin.
+
+Mon Oct 14 15:39:41 2002 Manish Singh <yosh@gimp.org>
+
+ * pango/pango-context.c pango/pango-layout.c pango/pangoft2.c
+ pango/pangowin32-fontmap.c pango/pangowin32.c pango/pangox-fontmap.c
+ pango/pangox.c pango/pangoxft-font.c pango/pangoxft-fontmap.c
+ pango/testfonts.c pango/opentype/pango-ot-ruleset.c:
+ Get rid of unnecessary casts for g_object_{ref,unref}
+
+2002-10-15 Matthias Clasen <maclas@gmx.de>
+
+ * docs/Makefile.am: Dist the xml/*.xml, not
+ sgml/*.sgml. (#95678, Owen Taylor)
+
+2002-10-14 Matthias Clasen <maclas@gmx.de>
+
+ * docs/Makefile.am (SCANOBJ_FILES): Add $(DOC_MODULE).interfaces.
+
+Sun Oct 13 12:35:14 2002 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.1.2 ===
+
+ * configure.in: Version 1.1.2, interface age 0.
+
+ * NEWS: Updates.
+
+2002-10-04 Alexander Larsson <alexl@redhat.com>
+
+ * pango/pango-layout.[ch]:
+ * docs/tmpl/layout.sgml:
+ Add, implement and document PANGO_WRAP_WORD_CHAR
+
+Sun Sep 29 14:55:36 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgpos.c: ligatures can be also used in
+ MarkBasePos lookups. (2001-03-17 Werner Lemberg)
+
+Sun Sep 29 14:51:25 2002 Owen Taylor <otaylor@redhat.com>
+
+ Start of merges from freetype1 of OpenType fixes.
+
+ * pango/opentype/ftxgdef.c pango/opentype/ftxgpos.c pango/opentype/ftxgsub.c:
+ More fixes for special marks. (2001-03-17 Werner Lemberg)
+
+2002-09-28 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-fontmap.c (pango_win32_insert_font): Revert
+ change from 2002-09-21: Don't bypass the code that automatically
+ adds fonts to the families "monospace", "serif" and "sans". I
+ thought it would be unnecessary if you have a pango.aliases that
+ sets up aliases for these family names, but apparently
+ not. Without this code, pango_layout_line_get_empty_extents()
+ thinks empty lines have zero height, as it tries to use a font
+ called "sans" for instance, and no aliases get used.
+
+Fri Sep 27 17:50:51 2002 Owen Taylor <otaylor@redhat.com>
+
+ (Based on GTK+ patch by J. Ali Harlow in #87774)
+
+ * configure.in: Add CROSS_COMPILING conditional.
+
+ * modules/Makefile.am (install-data-local): Don't
+ generate pango.modules when installing into a DESTDIR
+ or cross-compiling.
+
+ * examples/Makefile.am (all-local): Don't generate
+ pango.modules when cross-compiling.
+
+Fri Sep 27 13:10:25 2002 HideToshi Tajima <hidetoshi.tajima@sun.com>
+
+ * modules/basic/tables-big.i: make charset ordering of
+ chinese character sets differently for chinese locales -
+ e.g., GB18030 is used first in zh-cn locales.
+ (#89937 James Su, Brian Yuan.)
+
+2002-09-25 Tor Lillqvist <tml@iki.fi>
+
+ * pango/Makefile.am: INCLUDED_WIN32_MODULES was missing from a
+ couple of places. (#93372)
+
+2002-09-24 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.c: Use PANGO_PIXELS macro throughout instead of
+ dividing by PANGO_SCALE.
+ (pango_win32_render): New try. This time handle both glyphs at
+ code point 0, specifically put there by PangoLayout to indicate
+ spacing (for tab handling), and actual invalid glyphs noticed by
+ the shaper. Invalid glyphs are indicated by the flag
+ PANGO_WIN32_UNKNOWN_FLAG. (Idea taken frompangoxft-font.c)
+ (pango_win32_get_unknown_glyph): Take also the char as parameter,
+ return the same char with the above flag ORed in.
+ (pango_win32_font_get_glyph_extents): If the glyph is flagged as
+ invalid, look for glyph 0 instead. Use g_win32_error_message() in
+ warning message instead of numeric error code.
+
+ * pango/pangowin32.h: Add the new parameter to the
+ pango_win32_get_unknown_glyph() declaration. Surround the API used
+ by shape engines with #ifdef PANGO_ENABLE_ENGINE.
+
+ * modules/basic/basic-win32.c: Change call accordingly.
+
+2002-09-24 Tor Lillqvist <tml@iki.fi>
+
+ * pango/opentype/pango-ot.def: Remove. Not used. (A static library
+ is built here. Exported entries are in ../pangoft2.def.)
+
+ * pango/opentype/Makefile.am (EXTRA_DIST): Remove from here, too.
+
+2002-09-23 Matthias Clasen <maclas@gmx.de>
+
+ * pango/pango-color.c (pango_color_parse): Make color parsing
+ more robust and correct. (#93804)
+
+ * tests/testcolor.c: Tests for pango_color_parse.
+
+ * tests/Makefile.am: Build testcolor.
+
+ * tests/runtests.sh: Run testcolor.
+
+2002-09-23 Tor Lillqvist <tml@iki.fi>
+
+ * pango/makefile.mingw.in
+ * pango/mini-fribidi/makefile.mingw
+ * pango/opentype/makefile.mingw.in
+ * examples/makefile.mingw.in
+ * modules/basic/makefile.mingw.in: Remove. Not maintained.
+
+ * pango/Makefile.am (EXTRA_DIST)
+ * pango/mini-fribidi/Makefile.am (EXTRA_DIST)
+ * pango/opentype/Makefile.am (EXTRA_DIST)
+ * examples/Makefile.am (EXTRA_DIST)
+ * modules/basic/Makefile.am (EXTRA_DIST): Remove
+ makefile.mingw(.in) from here, too.
+
+ * configure.in (AC_OUTPUT): Don't try to output above removed
+ files.
+
+ * examples/pangowin32.aliases: Remove. Not used.
+
+ * modules/basic/basic-win32.c: Minor spacing fixes, comment the
+ Unicode ranges covered.
+
+ * pango/makefile.msc
+ * pango/module-defs-win32.c.win32: Change according to change
+ below so that build also with the manually written makefile for
+ MSVC, which always uses included modules, still works.
+
+ * pango-zip.sh.in: Distribute specifically pango.aliases and
+ pango.modules, not the whole etc/pango which might contain editor
+ backup files.
+
+Mon Sep 16 12:03:54 2002 Arnaud Charlet <charlet@gnat.com>
+
+ * modules/basic/basic-win32.c: Check for correct macro, use
+ correct module entry name, so that --with-included-modules works
+ with autoconfiscated build for Windows. (#93372)
+
+2002-09-21 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-private.h
+ * pango/pangowin32*.c: Rename DEBUGGING to PANGO_WIN32_DEBUGGING.
+ Use plain printf instrad of g_print in the PING macro for
+ debugging output (to avoid UTF-8 requirement).
+
+ * pango/pangowin32.h: Guard against redefinition of _WIN32_WINNT.
+
+ * pango/pangowin32-private.h: Remove the FS_VIETNAMESE define, not
+ needed. Rename PangoWin32Font::face to win32face. Add enum
+ PangoWin32CoverageLanguageClass, used to classify PangoLanguages
+ that might have locale-specific coverage of fonts (i.e. CJKV).
+ Change PangoWin32Face::coverage into an array, coverages. Move
+ some TrueType macro and struct defines from pangowin32.c
+ here. Rename them a bit to match the names used in the specs
+ better. Add declarations for new functions (see below).
+
+ * pango/pangowin32.c (pango_win32_get_hfont): Convert
+ LOGFONT::lfFaceName to UTF-8 before printing.
+
+ (pango_win32_render): Revert the change from
+ 2002-09-05. Characters not in a font are supposed to show up at
+ this stage as invalid glyphs (usually a box). It's up to the
+ higher layers to filter out TABs and other characters that
+ shouldn't be visible.
+
+ (pango_win32_get_name_header, pango_win32_get_name_record): New
+ functions, to read the name table header and records from a
+ TrueType font.
+
+ (font_name_in): New function, checks if a font has a name in one
+ of the spoecial-case languages, or actually locales (zh_TW, zh_CN,
+ ja, ko, vi). Checks the TrueType name table.
+
+ (pango_win32_font_calc_coverage): Take a PangoLanguage parameter,
+ too. Use it to decide whether to hide the Unified CJKV Ideographs
+ block in case the font is not for the specified locale. If so, the
+ coverage for these characters is set to PANGO_COVERAGE_APPROXIMATE.
+
+ * pango/pangowin32-fontmap.c: Remove PangoWin32FontMap::faces,
+ unused. Remove dead _WE_WANT_GLOBAL_ALIASES_ code. Rename
+ parent_class to font_map_parent_class to match pangox-fontmap.c.
+
+ (get_family_name, get_family_name_lowercase): New functions.
+ Search for an English name for a TrueType font, in case the font
+ name in LOGFONT::lfFaceName is non-ASCII. (Can one assume that if
+ it is ASCII, it is the English name? Do some TrueType fonts have
+ different names in French, German, etc, and does the system return
+ these if the locale is set to use French, German, etc?)
+
+ (pango_win32_insert_font): Don't store LOGFONTs that differ only
+ in charset. What charset we specify when calling
+ CreateFontIndirect() is irrelevant, as we are going to use
+ ExtTextOutW() anyway, i.e. Unicode. Use the English family name
+ from get_family_name_lowercase(), not the one returned in the
+ LOGFONT from font enumeration.
+
+ Bypass the code that sets up the mapping for monospace, serif and
+ sans, and the recignition of plain "courier" for "courier new". We
+ need a pango.aliases anyhow, so let it handle that.
+
+ (pango_win32_coverage_language_classify): New function.
+
+ (pango_win32_font_entry_set_coverage,
+ pango_win32_font_entry_get_coverage): Take also a PangoLanguage
+ parameter, use the corresponding entry in the
+ PangoWin32Face::coverages array.
+
+ * pango/pango-utils.c (pango_get_lib_subdirectory,
+ pango_get_sysconf_subdirectory): Fix doc comment on Win32
+ behaviour.
+
+Thu Sep 19 15:12:21 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c (pango_scan_int): Fix problem
+ where position wasn't updated properly.
+
+Mon Sep 9 11:09:18 Eric Mader <mader@jtcsv.com>
+
+ * pango/pango/opentype/pango-to-ruleset.c: correctly handle back,
+ new_advance.
+
+Fri Sep 6 15:41:28 Eric Mader <mader@jtcsv.com>
+
+ * pango/pango/opentype/ftxopen.c:
+ * pango/pango/opentype/ftxopen.h: don't fail on an empty script
+
+2002-09-05 jacob berkman <jacob@ximian.com>
+
+ * autogen.sh: copy version with automake-1.4 fixes from -1-0 branch
+
+2002-09-05 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.c (pango_win32_render): Render only valid
+ glyphs. Fix by Florent Duguet. Don't know if this is quite the
+ correct way to fix the problem of default glyphs (ugly boxes)
+ showing up, maybe invalid glyphs never should get this far, but be
+ noticed earlier?
+
+2002-09-04 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango-utils.c: G_WIN32_DLLMAIN_FOR_DLL_NAME not needed on
+ Cygwin, surround with #ifdef G_OS_WIN32. (91785, Masahiro Sakai)
+
+Wed Aug 28 15:22:14 2002 Eric Mader <mader@jtcsv.com>
+
+ * pango/modules/indic/indic-ot.h:
+ * pango/modules/indic/indic-ot.c:
+ * pango/modules/indic/indic-ot-class-tables.c:
+ Change Punjabi script ('punj') to Gurmukhi ('guru')
+
+Tue Aug 20 17:31:39 2002 Owen Taylor <otaylor@redhat.com>
+
+ * Released 1.1.1.
+
+ * configure.in: Update versions numbers.
+
+ * NEWS: Updated.
+
+ * docs/pango-sections.txt: Updated.
+
+ * pango/pangoxft-font.c (pango_xft_font_[un]lock_face):
+ Fix docs.
+
+Tue Aug 20 17:14:13 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI: conditionalize
+ FC_PATTERN usage on #ifdef FC_PATTERN, since
+ it only existed in fontconfig for a brief amount
+ of time.
+
+Tue Aug 20 16:06:36 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Make the test for VARARGS macros
+ more robust, fixing problem with misbehaving
+ IRIX compiler that doesn't error on #error.
+ (#90267)
+
+Tue Aug 20 15:42:33 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-xft.c (maybe_add_SUB_feature):
+ modules/indic/indic-xft.c (maybe_add_GPOS_feature):
+ modules/indic/indic-ot.c (getOutputIndex)
+ modules/hebrew/hebrew-x.c (get_glyph_num)
+ modules/basic/basic-x.c (find_char): Fix missing
+ statics.
+
+ * modules/thai/{thai-shaper.[ch] thai-xft.c thai-x.c}:
+ Namespace the "abstract functions" that thai-xft/thai-x.c
+ export to thai-shaper.c.
+
+ * modules/arabic/arabic-{ot.[ch],ft2.c,xft.c}:
+ Rename Assign_Arabic_Properties to Arabic_Assign_Properties.
+
+Tue Aug 20 15:06:50 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/arabic-xft.c modules/arabic/arabic-ft2.c
+ modules/basic/tables-big.i modules/basic/tables-small.i
+ modules/hebrew/hebrew-ft2.c modules/hebrew/hebrew-xft.c:
+ Patch from Nils Nordman to add various missing 'static'
+ (#90353)
+
+Mon Aug 19 14:07:02 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI (pango_fc_font_map_get_patterns):
+ Delete the FC_PATTERN out of the result of FcFontRenderPrepare(),
+ because it makes identical fonts look like not identical fonts.
+
+ * pango/pangofc-fontmap.cI (uniquify_pattern): pango/pangoft-fontmap.c
+ pango/pangoxft-fontmap.c: Use a hash table to uniquify the patterns
+ we cache to save memory and speed lookups.
+
+ * pango/pangoxft-font.c (pango_xft_font_get_font): Split into
+ a public wrappper (with g_return_if_fail()) around a static
+ internal function (without check).
+
+ * pango/pangoxft-fontmap.c (_pango_xft_font_map_get_info): Remove
+ checked cast, since it was showing up high on profiles.
+
+Fri Aug 16 17:49:38 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI pango/pangoxft-fontmap.c
+ pango/pangoft2-fontmap.c pango/pangoxft-private.h
+ pango/pangoft2-private.h pango/pangoxft-font.c
+ pango/pangoft2.h: Move the common code between PangoXftFontmap
+ and PangoFT2Fontmap into a new file that is included from both
+ with appropriate #defines. This provides most of the
+ recent Xft backend improvements for the FT2 backend
+ as well.
+
+Tue Aug 13 16:38:19 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c (pango_xft_font_map_get_patterns):
+ Keep a separate description => fontset hash for each
+ language tag. Pass language tags through to Xft.
+
+Tue Aug 13 00:20:14 2002 Owen Taylor <otaylor@redhat.com>
+
+ * Released 1.1.0
+
+Thu Aug 8 23:14:27 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox-fontmap.c pango/pangoxft-fontmap.c:
+ use XAddExtension() magic to automatically clean
+ up our information when XCloseDisplay() is called.
+
+ * NEWS: Some updates for 1.1.x features.
+
+ * README: Update a bit.
+
+ * configure.in: Print Xft for the Xft backend, not Xft2
+ when printing summary.
+
+Thu Aug 8 21:37:48 2002 Owen Taylor <otaylor@redhat.com>
+
+ Some fixes from #90267
+
+ * configure.in: Fix case where freetype2 is not in
+ default include path. Quiet some warnings if
+ /usr/lib/qt* doesn't exist.
+
+ * examples/Makefile.am: Fix problem where if no
+ Qt was found, -I /include was in the CFLAGS.
+
+Thu Aug 8 19:34:03 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Remove the HAVE_FONTCONFIG conditional;
+ instead make the HAVE_FREETYPE conditional
+ be $have_freetype && $have_fontconfig.
+
+ * pango/Makefile.am: Use the HAVE_FREETYPE conditional
+ for checking whether we are building the FT2 backend,
+ as we do everywhere else.
+
+Thu Aug 8 19:14:09 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (load_fallback_font): Fix
+ accidentally exported set_unicode_charmap() and
+ load_fallback_face/font(). (Jacob Berkman, #90245)
+
+ * configure.in: Up PANGO_MODULE_VERSION to 1.1.0.
+
+Thu Aug 8 19:00:49 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c: Up MAX_FREED_FONTS to 128
+
+ * pango/pangoxft-fontmap.c (pango_xft_pattern_equal):
+ Short-circuit pattern1 == pattern2.
+
+ * pango/pangoxft-fontmap.c (pango_xft_font_map_get_patterns):
+ Patch from Keith Packard to use PangoFontSetSort rather
+ than our previous substitute-and-split-the-substitution
+ hack; this means that if any font on the system has the
+ character, it will be used.
+
+ * pango/pangoxft-fontmap.c (_pango_xft_font_map_cache_add):
+ Reorder so that it works with MAX_FREED_FONTS == 0.
+
+Thu Aug 8 18:55:21 2002 Owen Taylor <otaylor@redhat.com>
+
+ * examples/Makefile.am (INCLUDES): Add FONTCONFIG_CFLAGS
+ to INCLUDES. (Joe Yandle.)
+
+2002-08-08 jacob berkman <jacob@ximian.com>
+
+ * modules/hangul/Makefile.am (EXTRA_DIST): add tables-jamos.i
+ (xft_sources): add hangul-defs.h so it gets disted
+
+Wed Aug 7 14:35:13 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Fix missing trailing newline in file.
+
+Wed Aug 7 09:14:00 2002 Michael Meeks <michael@ximian.com>
+
+ * configure.in: echo status at end.
+
+Wed Aug 7 12:32:39 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (TT_Load_GSUB_Table):
+ Offset to MarkAttachClassDef is offset to table,
+ not offset to offset to table.
+
+ * pango/opentype/ftxopen.c (Get_Device): Handle
+ NULL device tables which we represent with
+ d->DeltaValue == NULL.
+
+Wed Aug 7 11:07:10 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/hangul-xft.c (hangul_engine_shape): Get
+ rid of direct access to FT_Face.
+
+Wed Aug 7 10:57:49 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/Makefile.am modules/thai/Makefile.am:
+ Add missing XFT_CFLAGS to INCLUDES. (Joe Yandle)
+
+Mon Aug 5 23:57:59 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c (pango_xft_pattern_hash): Use
+ FcPatternHash instead of rolling our own. (Slight speed
+ decrease) (Keith Packard)
+
+ * pango/pangoxft-fontmap.c (pango_xft_get_font_map):
+ Remove accidentally deleted call to init_fontset_hash().
+
+Mon Aug 5 23:12:13 2002 Owen Taylor <otaylor@redhat.com>
+
+ Patch from Keith Packard:
+
+ * pango/pangoxft-private.h (struct _PangoXftFont): Add
+ some comments.
+
+ * pango/pangoxft-private.h pango/pangoxft-font.c
+ pango/pangoxft-fontmap.c: Identify coverage by a
+ pair of filename and index within the filename instead
+ of just a filename, to handle TrueType Collection (TTC)
+ fonts.
+
+ * pango/pangoxft-fontmap.c (pango_xft_make_pattern):
+ Remove some leftover comments.
+
+Mon Aug 5 21:54:21 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c (pango_xft_get_font_map): Export.
+
+ * pango/pango-context.[ch]: Add pango_context_get_fontmap(),
+ allow fontmap = NULL for pango_context_set_fontmap().
+
+ * pango/pangoxft-font.c pango/pangoxft-fontmap.c
+ (pango_xft_font_get_metrics): More work on allowing
+ displays to be shut down, while leaving basically
+ working fonts behind.
+
+Fri Aug 2 12:12:34 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft.h pango/pangoxft-fontmap.c
+ (pango_xft_shutdown_display): New function allowing us to shut
+ down a display.
+
+Thu Aug 1 10:41:26 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Fix check for having any backend
+ HAVE_XFT => have_xft, etc. (Problem reported
+ by Andreas J Guelzow)
+
+2002-08-01 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-x.c (render_syllable_with_ksx1005):
+ Renders the prefix of uncomposable Hangul syllable in the way of
+ other font encoding code.
+
+Wed Jul 31 16:00:20 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/thai/thai-xft.c (make_glyph): Minor tweak
+ to last patch to clarify index passed to unknown_glyph().
+
+Wed Jul 31 15:43:39 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/thai/{thai-shaper.h,thai-x.c,thai-xft.c}:
+ Argument to make_glyph() shouldn't have been
+ unsigned char, since we pass unicode through it.
+
+ * modules/thai/thai-xft.c (make_glyph): Handle
+ THAI_FONT_ISO10646 correctly. If a character isn't
+ found, return the correct unknown glyph.
+
+Sat Jul 27 18:18:20 2002 Owen Taylor <otaylor@redhat.com>
+
+ Patch from Changwoo Ryu <cwryu@debian.org> (#86591)
+
+ * configure.in, modules/hangul/Makefile.am: : Added hangul-xft
+ module.
+
+ * modules/hangul/hangul-xft.c: New file, shaping Hangul Jamos
+ (U+1100-U+11FF) with Xft.
+
+ * modules/hangul/hangul-x.c (JOHAB_COMMON): Render any prefix of
+ uncommposable Hangul syllable as a syllable, and render remains as
+ uncomposed form. This looks better than completely uncomposed
+ jamo glyphs.
+ (render_syllable_with_iso10646): Likewise.
+ (render_syllable_with_ksc5601): Likewise.
+ (hangul_engine_shape): Fixed memory leak on shaping a syllable
+ with >= 6 jamos.
+
+ * modules/hangul/tables-jamos.i, modules/hangul/tables-ksc5601.i:
+ Separated Hangul Jamo mapping table from ksx1001 <=> unicode
+ table.
+
+ * modules/hangul/hangul-defs.h: New file with some common defines
+ and macros.
+
+ * modules/hangul/hangul-x.c (render_syllable_with_johabs): Fixed
+ wrong font index around fallback display with johabs.
+ (find_subfont): Uses "johabsh-1" (johabs-1 font with Hanja) in the
+ same way with "johabs-1".
+
+Wed Jul 31 14:41:07 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c (pango_x_list_subfonts): Make charset
+ ordering more important than ordering in the font
+ specfication, and document the previously undocumented
+ ordering. (#88562, Brian Yuan.)
+
+Wed Jul 31 12:38:36 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/querymodules.c (string_needs_escape): Avoid
+ using g_strescape(), since it mangles UTF-8.
+ (#89479, Yao Zhang)
+
+Tue Jul 30 23:10:14 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/shape.c (pango_shape): Set is_cluster_start
+ attributes based on the log_clusters[] set by the shape
+ engine. (Fix for #84307, Reported by Alex Larsson, others.)
+
+Sat Jul 27 09:46:51 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/thai/{thai-shaper.[ch],thai-x.c,thai-xft.c}
+ (make_unknown_glyph): Fix problem where
+ pango_xft_get_unknown_glyph() was being used for X
+ fonts. (reported by Jacob Berkman)
+
+Fri Jul 26 19:46:45 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-x.c modules/basic/tables-big.i:
+ Patch fromm Qingjiang (Brian) Yuan adding support
+ for GB-18030, BIG5-HKSCS, CNS-11643 and GBK encodings.
+ Also fix wrong encoding for Big5 fonts and look
+ for big5-1 as well as big5-0 for the encoding name.
+
+Fri Jul 26 19:23:58 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/hangul-x.c modules/hangul/tables-ksc5601.1:
+ Patch from Qingjiang (Brian) Yuan and Changwoo Ryu
+ to add support for ksc5601.1992-3 fonts.
+
+Fri Jul 26 18:48:49 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in modules/thai/Makefile.am
+ modules/thai/thai-shaper.[ch]
+ modules/thai/thai-xft.c modules/thai/thai-x.c:
+ Patch from Theppitak Karoonboonyanan that factors
+ out common code from thai-x.c and adds a new
+ Xft shaper for Thai. (#78346)
+
+ * pango/pangoxft.h pango/pangoxft-font.c: Add
+ pango_xft_font_has_char()
+ to optimize for cases where we don't actually need
+ to load the font.
+
+ * pango/pangoxft.h: Document pango_xft_font_get_glyph().
+
+ * modules/basic/basic-xft.c (basic_engine_shape): Clean
+ up an unused variable warning.
+
+Fri Jul 26 18:11:56 2002 Owen Taylor <otaylor@redhat.com>
+
+ * Add back non-spurious \$ removed in last commit.
+
+Fri Jul 26 18:11:56 2002 Owen Taylor <otaylor@redhat.com>
+
+ * Fix a leftover spurious \$ from the last commit.
+
+Fri Jul 26 17:59:06 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Replace uses of grep \(A\|B\) ... with
+ egrep (A|B). (#84872, Arnaud Charlet)
+
+Thu Jul 25 11:42:17 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_shutdown_display)
+ * pango/pangowin32-fontmap.c (pango_win32_shutdown_display):
+ Handle checking for fontmap == NULL and setting
+ it to NULL after unrefing properly. (#87915,
+ Sven Neumann)
+
+Wed Jul 24 23:07:43 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c: Fix wrong assertion that was
+ dying on lines separated by PS (U+2029). (#88824,
+ Choe Hwangjin)
+
+2002-07-22 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c (pango_ft2_font_get_face): don't access the old
+ (invalid) face pointer after loading a fallback face because we
+ couldn't set the unicode charmap.
+
+Mon Jul 15 20:22:46 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c: Fix trivial typo that was
+ causing the charcode hex boxes to be misrendered.
+
+Mon Jul 15 14:56:34 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2.c (pango_ft2_font_get_face): Move
+ setting of load_flags before we do any checks for the
+ font so they apply to the fallback font as well.
+
+ * pango/pangoft2.c (pango_ft2_font_get_face): Supply
+ FT_LOAD_NO_BITMAP as temporary workaround for problems
+ with embedded bitmaps, since we can't render bitmap fonts
+ at the moment.
+
+Wed Jul 3 18:54:14 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2.c: Fix some typos.
+
+Wed Jul 3 18:39:45 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2.c pango/pangoxft-font.c: Be more
+ robust when trying to set the unicode character
+ map on the font.
+
+ * pango/pangoft2.c pango/pangoft2-private.h:
+ Obey FC_HINTING, FC_AUTOHINT.
+
+Mon Jul 1 19:45:10 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c (pango_xft_set_default_substitute):
+ New function to allow tweaking of FcPattern default
+ substitution (for XSETTINGS support.)
+
+ * pango/pangoft2-fontmap.c pango/pangoft2.[ch]
+ pango/pangoft2-private.h: Rationalize DPI and
+ context creation by adding:
+
+ pango_ft2_font_map_new()
+ pango_ft2_font_map_set_resolution()
+ pango_ft2_font_map_set_default_substitute()
+ pango_ft2_font_map_create_context()
+
+2002-07-02 Matthias Warkus <mawarkus@gnome.org>
+
+ * pango/pango-markup.c (span_parse_func): Fixed typo that was
+ causing markup with <span rise="..."> attributes to
+ segfault. Permission to commit to HEAD and stable branch granted
+ by Owen Taylor.
+
+Sat Jun 15 23:26:41 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/arabic-ot.c: Support new Arabic
+ characters in Unicode 3.2. (Patch from Roozbeh
+ Pournader.)
+
+Thu Jun 13 16:39:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-markup.c (pango_parse_markup):
+ Fix problem with attr_list == NULL. (#85079,
+ Andreas J. Guelzow)
+
+Wed Jun 12 11:19:08 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/tamil/tamil-x.c: Use unsigned char for
+ bitfield array. (#83257, David L. Cooper II)
+
+ * tests/gen-all-unicode.c (main): Used char,
+ not guchar for array of characters. (#83258,
+ David L. Cooper II.)
+
+-Wed Jun 12 11:08:35 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/langboxfont.[ch] modules/arabic/naqshfont.[ch]:
+ Change @glyph2 parameter of arabic_*_recode() to be a gunichar*
+ like @glyph. (Fixes warning with Solaris 8 compiler;
+ #83256, David L. Cooper II)
+
+Wed Jun 12 11:02:04 2002 Owen Taylor <otaylor@redhat.com>
+
+ * examples/Makefile.am (EXTRA_DIST) examples/pangoft2.aliases:
+ Remove pangoft2.aliases from CVS/distribution; it is
+ no longer used. (#82736, Sven Neumann.)
+
+2002-06-10 Matthias Clasen <maclas@gmx.de>
+
+ * pango/pango-fontset.c (pango_fontset_real_get_metrics): Don't
+ leak raw_metrics and don't copy refcounts. (#84533)
+
+Thu Jun 6 15:01:48 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pangoft2.pc.in (Cflags): Add @FREETYPE_CFLAGS@
+
+ * tests/Makefile.am (INCLUDES): Add XFT_CFLAGS.
+ gtk/Makefile.am (INCLUDES): Add back FREETYPE_CFLAGS.
+
+Thu Jun 6 08:54:26 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Update the versioning to reflect '1.1.x'
+ (Use the 100 * minor + micro convention.)
+
+Thu Jun 6 08:42:32 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Provide : as the fourth argument
+ whne checking for fontconfig, xft, so we don't error out
+ if they aren't found. (#84333, HideToshi Tajima)
+
+Tue Jun 4 11:52:10 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pangoxft.pc.in (Cflags): Fix to have @XFT_CFLAGS@
+
+Mon Jun 3 22:16:35 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_get_coverage):
+ Don't open the font unecessarily, we already have
+ the FcCharSet.
+
+Mon Jun 3 18:56:09 2002 Owen Taylor <otaylor@redhat.com>
+
+ Xft2 and fontconfig conversion, based largely on a patch
+ from Keith Packard.
+
+ * configure.in acconfig.h: Add checks for fontconfig, switch
+ Xft checks to switch for Xft2 using pkg-config.
+
+ * pangoxft.pc.in pangoxft.pc.in
+ modules/{arabic,basic,hebrew,indic,tamil}/Makefile.am
+ pango/Makefile.am: Reflect new Xft/fontconfig dependencies.
+
+ * pango/pangoxft-private.h pango/pangoxft-fontmap.c
+ modules/arabic/arabic-xft.c modules/indic/indic-xft.c:
+ Switch over to using Xft2 and fontconfig.
+
+ * pango/pangoft2.c pango/pangoft2-fontmap.c pango/pangoft2-private.h
+ pango/pango/Makefile.am: Remove usage of mini-xft in
+ favor of fontconfig.
+
+ * pango/pango-ot.h pango/opentype/pango-ot-info.c pango/pangoxft.h
+ modules/arabic/arabic-{xft,ft2}.c modules/indic/indic-xft.c:
+ Attach OpenType information directly to the FT_Face
+ structure using FT_Generic.
+
+ * modules/tamil/Makefile.am modules/tamil/tamil-xft.c
+ configure.in: Remove this module, no longer needed.
+
+ * pango/pangoxft-font.c (pango_xft_real_render): Coalesce
+ calls to Xft rendering functions.
+
+2002-06-03 Matthias Clasen <maclas@gmx.de>
+
+ * pango/fonts.c (pango_font_description_better_match): Typo fix.
+
+ * pango/pango-color.c (pango_color_parse):
+ * docs/pango-docs.sgml: Replace homegrown "nbsp", "hash"
+ and "mdash" entities by standard ISO entities "nbsp", "num" and
+ "mdash".
+
+2002-06-03 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_list_families): set
+ n_families, fixes bug #83746.
+
+2002-05-28 Matthias Clasen <maclas@gmx.de>
+
+ * docs/*: Produce XML, not SGML.
+
+ * pango/fonts.c (pango_font_family_list_faces): Docs typo fix.
+
+ * pango/pango-color.c (pango_color_parse): Fix markup to reduce
+ spurious <link>s.
+
+2002-05-26 Tor Lillqvist <tml@iki.fi>
+
+ * pango-zip.sh.in: Use complete PANGO_VERSION in zip file
+ names.
+
+ * pango/Makefile.am: (Win32) Compile resource files and link with
+ them.
+
+ * pango/pango.rc.in
+ * pango/pangoft2.rc.in
+ * pango/pangowin32.rc.in: Include also the micro version number.
+
+ * pango/pangowin32-fontcache.c (logfont_hash): Use absolute value
+ of lfHeight.
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_for_display):
+ Instead of HORZSIZE which is Windows idea of physical monitor
+ width (but which can be *very* wrong), use LOGPIXELSY (the
+ "logical" dpi). This can be set by the user by choosing "small
+ fonts", "large fonts", or a custom dpi in the Display Settings.
+ Thanks to Joaquin Cuenca Abela.
+
+ (pango_win32_make_matching_logfont): Set lfHeight to the negative
+ of the requested size. Positive lfHeight indicates "cell height",
+ negative "character height" (?), which is closer to what we want,
+ says Joaquin Cuenca Abela.
+
+Tue May 21 15:27:41 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/tables-big.i: Fix C++ comment.
+ (#82035, David L. Cooper II)
+
+Tue May 14 12:02:13 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c pango/pangoft2-fontmap.c:
+ Report standard aliases as uppercase, fix
+ pango_*_face_describe() for aliases.
+
+Mon May 13 15:56:29 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-fontmap.c: Fake sans,serif,monospace
+ in the list of fonts.
+
+ * pango/pangoft2-fontmap.c: Fake aliases here as well.
+
+ (#78714, Xavier Cho.)
+
+Mon May 13 14:58:12 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c configure.in: Add a implementation
+ of strtok_r (copied from glibc) for machines that don't
+ have it. (#79472, Jacob Berkman.)
+
+ * pango/querymodules.c: Use printf() rather than
+ g_print, since we don't want encoding conversion.
+ (#77341)
+
+Fri May 10 14:41:27 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgdef.c (TT_Load_GDEF_Table): Fix acess
+ outside of a loaded frame and some memory leaks
+ on failure.
+
+Tue May 7 19:20:05 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/tamil/Makefile.am (EXTRA_LTLIBRARIES): Temporarily
+ remove tamil-xft from the build until we figure out
+ what to do with it. (Obscures the OpenType Tamil engine.)
+
+ * examples/HELLO.utf8: Fix spelling of Punjabi, removing
+ stray vowel.
+
+Mon May 06 15:07:39 2002 Eric Mader <mader@jtcsv.com>
+ * Add modules modules/indic/indic-xft.c, indic-ot.c, indic-ot.h, indic-ot-class-tables.c
+
+ * pango/opentype/ftxgdef.c: Compute full offset for mark attachment class table
+
+ * pango/opentype/ftxgpos.c: Only return TTO_Err_Not_Covered if nothing matches
+
+ * pango/opentype/pango-ot-ruleset.c: enable GPOS processing
+
+2002-05-02 Matthias Clasen <maclas@gmx.de>
+
+ * docs/Makefile.am (GTKDOC_CFLAGS, GTKDOC_LIBS): Set these.
+
+ * docs/pango.types: Add some types here.
+
+Tue Apr 23 16:15:07 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/fterrcompat.h: Add compatibility
+ defines for changes in FreeType 2.1.0.
+
+Tue Apr 23 15:21:34 2002 Owen Taylor <otaylor@redhat.com>
+
+ * README: Fix typo. (#79574)
+
+Wed Mar 27 19:30:35 2002 Owen Taylor <otaylor@redhat.com>
+
+ * Released 1.0.1
+
+ * NEWS: Updates.
+
+ * configure.in: Version 1.0.1, interface, binary age 1.
+
+Tue Mar 26 18:22:07 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-*.c modules/basic/basic-common.h: Move
+ ZERO_WIDTH_CHAR() macro into a common header file, add
+ ZERO WIDTH-NO BREAK SPACE (U+FEFF)
+
+ * modules/basic/Makefile.am (EXTRA_DIST): Add basic-common.h.
+
+2002-03-26 Alex Larsson <alexl@redhat.com>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_load_font):
+ Free pattern after using it.
+
+2002-03-26 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2-private.h
+ * pango/pangoft2.c (pango_ft2_font_get_metrics): calculate
+ average_char_width and average_digit_width by measuring sample layouts
+ and cache font metrics per language just like PangoX does, #53425.
+
+ * pango/pangoxft-font.c
+ * pango/pangoxft-private.h: the same approach for average_char_width
+ and average_digit_width as in PangoFT2, #53425.
+
+Mon Mar 25 15:53:17 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules.c (read_modules): Remove warning about
+ opening modules file... in some cases (included modules)
+ it isn't needed, and the warning about no modules that
+ was added recently should let people know what is going
+ on. (#73834, Arnaud Charlet)
+
+Mon Mar 25 15:46:54 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-*.c: Convert U+00A0 (NON BREAK SPACE)
+ to U+0020 (SPACE). (#73279, Mikael Hallendal)
+
+ * modules/basic/basic-xft.c (basic_engine_shape): Remove
+ some dead code.
+
+Mon Mar 25 15:31:17 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangowin32.c (pango_win32_font_get_metrics): Set
+ the right font when computing the average digit width.
+
+Mon Mar 25 14:52:29 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c (pango_x_font_get_metrics): Rewrite
+ average_digit_width computation to go through the same
+ shaping hack as the average_char_width code.
+ (Part of #53425)
+
+ * pango/pangox.c (pango_x_font_describe): Implement
+ except for results of pango_x_font_load().
+
+ * pango/pangox.c (pango_x_load_font): Document as
+ "don't use".
+
+ * pango/pangox.[ch] (pango_x_load_font): Add missing const.
+
+2002-03-25 Sven Neumann <sven@gimp.org>
+
+ * pango/fonts.c (pango_font_description_from_string): this function
+ may never return NULL, so we shouldn't say so in the comment.
+
+Wed Mar 20 18:40:34 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules.c (build_map): Add an informative
+ warning if no modules at all were found. (#74982,
+ suggestion from Dan Winship.)
+
+Wed Mar 20 15:22:54 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Error out if no backends found. (#74880)
+
+Wed Mar 20 15:14:15 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-markup.c (text_handler): Dummy-initialize
+ gsize variable to 0, not -1. (#73899, Erwann Chenede)
+
+Wed Mar 20 14:57:48 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-x.c modules/basic/tables-{big,small}.i:
+ When loading an iconv converter fails, recover gracefully
+ and warn rather than aborting. (#73861, report about problems
+ on IRIX from Soeren Sandmann)
+
+2002-03-18 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/basic/tables-big.i: Enabled ksc5601 fonts for the Hangul
+ compatibility jamos, the CJK unified ideographs, and the CJK
+ compatibility ideographs areas.
+
+2002-03-17 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-private.h: Add pango_win32_os_version_info
+ variable, an OSVERSIONINFO struct.
+
+ * pango/pangowin32.c: Initialise it.
+
+ * pango/pangowin32.h: Set _WIN32_WINNT to 0x0501 before including
+ <windows.h> to get the ClearType-related macros defined (if recent
+ enough headers are used).
+
+ * pango/pangowin32-fontcache.c (pango_win32_font_cache_load): Set
+ desired font quality to CLEARTYPE_QUALITY if on XP (or later), and
+ the system settings ask for ClearType.
+
+2002-03-16 Sven Neumann <sven@gimp.org>
+
+ * configure.in (GLIB_CFLAGS): use CFLAGS from gthread-2.0 to assure
+ pango behaves correctly in a threaded environment.
+
+Fri Mar 15 12:25:26 2002 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/tables-big.i: Prefer ksc5601 fonts to
+ unicode fonts for "ko" locales.
+
+Fri Mar 15 01:35:56 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c pango/opentype/ftxopen.c
+ pango/opentype/ftxopenf.h: In Load_ChainContextSubst2,
+ handle the case where an empty class definition
+ is represented by an offset of 0.
+
+ * pango/opentype/ftxgpos.c: Same for Load_ChainContextPos2.
+
+ * pango/opentype/{ftxopen.c,ftxgpos.c,ftxgsub.c,ftgdef.c}:
+ Fix pervasive bug where on cleanups on failure of loading
+ an array element, all array elements were freed, not
+ just the ones that had been succesfully loaded.
+
+Thu Mar 14 23:05:18 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxopen.c: Uncomment GPOS parts.
+
+ * pango/opentype/disasm.c: Start adding some GPOS
+ dumping.
+
+Thu Mar 14 20:28:59 2002 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Check for FT_Get_First_Char from
+ FreeType-2.0.9.
+
+ * pango/pangoft2.c pango/pangoxft-font.c: Use
+ FT_Get_First_Char/Get_Next_Char to accelerate coverage calculation.
+
+Thu Mar 14 20:02:58 2002 Owen Taylor <otaylor@redhat.com>
+
+ * examples/Makefile.am (EXTRA_DIST): Remove moc_view-qt.cc. (#74725)
+
+Wed Mar 13 10:31:07 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-coverage.c (pango_coverage_max): Fix typo
+ when computing maximums of sub-byte fields. (Stefan Israelsson,
+ #74518)
+
+2002-03-12 Matthias Clasen <maclas@gmx.de>
+
+ * pango/pangowin32-fontcache.c, pango/pangox-fontcache.c: Minor doc edits.
+
+ * docs/tmpl/win32-fonts.sgml: Document PangoWin32FontCache.
+
+ * docs/tmpl/x-fonts.sgml: Document PangoXFontCache.
+
+ * docs/tmpl/glyphs.sgml: Document PangoGlyphInfo.
+
+ * docs/tmpl/opentype.sgml: Document PangoOTInfo, PangoOTTag,
+ PangoOTTableType.
+
+Local Variables:
+coding: utf-8
+End:
+vim: encoding=utf-8:
diff --git a/trunk/ChangeLog.pre-1-4 b/trunk/ChangeLog.pre-1-4
new file mode 100644
index 00000000..6a91b528
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-4
@@ -0,0 +1,1762 @@
+Tue Mar 16 11:24:46 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.4.0 ===
+
+ * configure.in: Version 1.4.0, interface ago 0. Require
+ glib-2.4.0.
+
+ * NEWS: Updates.
+
+ * README: Some updates; include details about the FreeType
+ license of the OpenType code.
+
+Thu Mar 11 17:28:06 2004 Manish Singh <yosh@gimp.org>
+
+ * pango/pangofc-fontmap.c: Convert PangoStretch to and from FC_WIDTH,
+ so we can actually get fontconfig to match on condensed and expanded
+ versions of fonts, and have the info survive a pango_fc_face_describe
+ roundtrip. Fixes #131561.
+
+ * pango/pangox-fontmap.c: Remove unused function
+ free_coverages_foreach.
+
+Tue Mar 9 09:21:07 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.3.6 ===
+
+ * configure.in: version 1.3.6, interface age 1
+
+ * NEWS: Updates.
+
+2004-03-05 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango.def
+ * pango/pangoft2.def: Add missing entries. (#136339, J. Ali Harlow)
+
+Fri Mar 5 14:56:57 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c (kndaCharClasses): Change
+ U+0CC3/U+0CC4/U+0CD5 to _lm (length mark) so that they get ordered
+ after the below base forms. (#118108, Kailash C. Chowksey)
+
+2004-03-04 Tor Lillqvist <tml@iki.fi>
+
+ * pango/module-defs-win32.c.win32: Clarify comment.
+
+2004-03-03 Hans Breuer <hans@breuer.org>
+
+ * pango/module-defs-win32.c.win32 : if PANGO_MODULE_PREFIX is
+ defined include the basic backend shaper (should have been
+ commited at 2003-12-12, too)
+
+ * pango/makefile.msc : generate correct type for PangoFontMask
+ (bug #135892, John Ehresman)
+ * pango/opentype/makefile.msc : updated
+
+ * pango/pango.def pango/pangoft2.def : more updatd externals
+
+Wed Mar 3 16:00:10 2004 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Strip out the "export-dynamic" libtool
+ option from library link lines. (#124687, James Henstridge)
+
+2004-03-03 Tor Lillqvist <tml@iki.fi>
+
+ * NEWS: Correct spelling of my name.
+
+ * pango/Makefile.am (libpango_1_0_la_DEPENDENCIES): Add
+ pango-win32res.lo. (135581, J. Ali Harlow)
+
+ * configure.in: Move check for native Win32 (mingw) a bit
+ earlier. If Win32, disable static builds (like GLib does).
+
+ * pango/pango.def
+ * pango/pangoft2.def: Add some missing symbols. (#135945, Cedric
+ Gustin; #135980, J. Ali Harlow)
+
+ * pango/pangowin32-fontmap.c (pango_win32_family_get_name): Can be
+ static.
+
+Mon Mar 1 19:24:09 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.3.5 ===
+
+ * configure.in: Version 1.3.5 (1.3.4 skipped), interface age 0.
+
+ * NEWS: Update
+
+ * modules/arabic/arabic-fc.c (arabic_engine_shape):
+ Fix a crash from left-over handling of clusters
+ for non-spacing marks.
+
+Mon Mar 1 20:32:06 2004 Tim Janik <timj@gtk.org>
+
+ * autogen.sh:
+ - exit with $? instead of 1 in case of failure
+ - exit with $? if ./configure failed
+ (that's so autogen.sh && make lines work)
+ - removed --enable-gtk-doc option
+ - added $AUTOGEN_CONFIGURE_ARGS
+
+Fri Feb 27 11:23:21 2004 Owen Taylor <otaylor@redhat.com>
+
+ Patch from Dov Grobgeld to add auto-direction to PangoLayout
+ (more of #70451)
+
+ * examples/pangofttopgm.c: Add --no-auto-dir argument.
+
+ * pango-layout.[ch]: Add pango_layout_set_auto_dir()
+ defaulting to TRUE; resolve paragraph direction within
+ a layout by propagating base direction downwards
+ from paragraph to paragraph.
+
+ * pango-context.[ch]: Add pango_itemize_with_base_dir()
+ which overrides the base direction from the PangoContext.
+
+Mon Mar 1 10:01:58 2004 Owen Taylor <otaylor@redhat.com>
+
+ * docs/tmpl/text-attributes.sgml: Document %PANGO_UNDERLINE_ERROR.
+
+ * pango/pangofc-fontmap.c: Pango*Fc*FontmapPrivate. Make compile.
+
+2004-03-01 Murray Cumming <murrayc@murrayc.com>
+
+ * pango/pango-attributes.h: Removed trailing commas from the
+ enums - which causes warnings that break warnings-as-errors builds.
+
+Mon Mar 1 09:43:38 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_finalize):
+ Remove the INSTANCE_PRIVATE_DATA_WORKS #ifdefs,
+ since it does work now.
+
+Sun Feb 29 15:54:51 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangowin32.c pango/pangox.c pango/pangoft2.c:
+ Fix up off-by-one for right bound when drawing
+ PANGO_UNDERLINE_ERROR.
+
+Sun Feb 29 15:31:09 2004 Owen Taylor <otaylor@redhat.com>
+
+ Patch from Nicolas Setton, #114237
+
+ * pango/pango-attributes.h pango/pango-markup.c: Add a
+ new underline type, PANGO_UNDERLINE_ERROR.
+
+ * pango/pangowin32.c pango/pangox.c pango/pangoft2.c:
+ Implement drawing of PANGO_UNDERLINE_ERROR.
+
+ * pango/pango-layout.c (pango_layout_run_get_extents):
+ Handle PANGO_UNDERLINE_ERROR.
+
+2003-02-29 Noah Levitt <nlevitt@columbia.edu>
+
+ * docs/pango_markup.sgml:
+ * docs/tmpl/text-attributes.sgml:
+ * pango/pango-attributes.c:
+ * pango/pango-attributes.h:
+ * pango/pango-context.c:
+ * pango/pango-markup.c: New attribute to turn font fallback on or off.
+ (#105553)
+
+Sun Feb 29 10:54:55 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/arabic-ot.c (arabic): Add joining
+ classes for new Unicode-4.0 characters U+06EE, U+06EF, U+06FF.
+ (Patch by Roozbeh Pournader from #117282)
+
+Sun Feb 29 09:25:13 2004 Owen Taylor <otaylor@redhat.com>
+
+ Rework opentype interfaces and other changes to make GPOS
+ work for Arabic. (Most of #117282, #121060)
+
+ * pango/opentype/otlbuffer.[ch]: OTL_Buffer that
+ acts as a replacement for the separate GSUB and
+ GPOS string structures and hides many of the internal
+ details.
+
+ * pango/opentype/ftxgsub.[ch] pango/opentype/ftxgpos.[ch]:
+ Adapt to OTL_Buffer.
+
+ * pango/opentype/ftxgpos.c: Redo handling of cursive
+ chains so that it actually works.
+
+ * pango/pango-ot.h pango/opentype/pango-ot-buffer.c:
+ Pango wrapper around OTL_Buffer.
+
+ * pango/pango-ot.h pango/pango-ot-ruleset.c pango/pango-ot-buffer.c:
+ Split pango_ot_ruleset_shape() into pango_ot_ruleset_substitute(),
+ pango_ot_ruleset_position(), make them act on
+ PangoOTBuffer, add a separate pango_ot_buffer_output()
+ which does the default positioning and writes to a
+ PangoGlyphString.
+
+ * modules/arabic/arabic-fc.c modules/indic/indic-fc.c
+ modules/indic/mprefixups.[ch]: Adapt to new OpenType
+ interfaces; add GPOS features for Arabic.
+
+ * pango/opentype/pango-ot-info.c: Don't derive class information
+ from Unicode properties for Arabic presentation forms,
+ let the shaping process derive the properties.
+
+2004-02-28 Hans Breuer <hans@breuer.org>
+
+ * pango/modules/basic/basic-win32.c : use uniscribe_scripts instead of
+ uniscribe_ranges (does show only with HAVE_USP10_H, which I don't)
+ patch from J. Ali Harlow <ali@juiblex.co.uk>, fixes bug #135504
+
+2004-02-28 Hans Breuer <hans@breuer.org>
+
+ * pango/pango.def : updated externals including
+ patch from J. Ali Harlow <ali@juiblex.co.uk>, fixes bug #135518
+
+ * pango/pangowin32-fontmap.c : implement list_sizes() and
+ is_monospace() members
+
+Fri Feb 27 14:26:34 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c (bengCharClasses):
+ Mark BENGALI LETTER A (U+0985) and BENGALI LETTER E (U+098F)
+ as consonants which gives better behavior when they
+ are combined with halant, though it isn't exactly right.
+ (#118299, Sayamindu Dasgupta)
+
+Fri Feb 27 11:24:50 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mini-fribidi/fribidi.c (pango_log2vis_get_embedding_levels):
+ Handle PANGO_DIRECTION_NEUTRAL.
+
+Fri Feb 27 09:30:10 2004 Owen Taylor <otaylor@redhat.com>
+
+ Add some new enum and values and utilities for supporting
+ automatically determined base direction. (#70451, based
+ on changes by Dov Grobgeld)
+
+ * pango/pango-types.h docs/tmpl/main.sgml: Add
+ PANGO_DIRECTION_WEAK_RTL/LTR, extend the docs for
+ PangoDirection.
+
+ * pango/pango-types.h pango/pango-utils.h: Move
+ pango_get_mirror_char() to pango-types.h.
+
+ * pango/mini-fribidi/fribidi.c (pango_log2vis_get_embedding_levels):
+ Handle new values of PangoDirection, handle
+ PANGO_DIRECTION_TTB_LTR/RTL as aliases for PANGO_DIRECTION_RTL/LTR.
+
+ * pango/mini-fribidi/fribidi.c pango/pango-types.h: Add
+ pango_unichar_direction().
+
+ * pango/pango-utils.c pango/pango-types.h: Add
+ pango_find_base_dir()
+
+2003-02-26 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/pangofc-fontmap.c: Use g_array_sort correctly.
+
+Tue Feb 24 14:29:26 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.3.3 ===
+
+ * configure.in: Version 1.3.3, interface age 3.
+
+ * NEWS: Updates
+
+2003-02-23 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/pangowin32-fontmap.c:
+ * pango/pangofc-fontmap.c:
+ * pango/pango-font.h:
+ * pango/fonts.c: New API pango_font_family_is_monospace. (#108728)
+
+2003-02-23 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/fonts.c (pango_font_face_list_sizes):
+ * pango/pangofc-fontmap.c (pango_fc_face_list_sizes): Handle
+ NULL for sizes and n_sizes.
+
+2003-02-22 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/pangofc-fontmap.c (pango_fc_face_list_sizes): Handle
+ possibility of FcPatternGetDouble(FC_DPI) failing.
+
+2003-02-22 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/pango-font.h:
+ * pango/pangofc-fontmap.c:
+ * pango/pangowin32-fontmap.c:
+ * pango/fonts.c (pango_font_face_list_sizes): New API for
+ getting available sizes for a bitmap font face. (#99235)
+
+Sat Feb 21 11:31:16 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_justify): Add
+ a docs note about non-implementedness. (#64538)
+
+Sat Feb 21 09:49:23 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/pango-ot-ruleset.c (pango_ot_ruleset_shape):
+ Sign convention for y offsets is opposite between
+ PangoGlyphString and FT code. (#132591)
+
+2003-02-19 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/pangofc-font.c (pango_fc_font_get_metrics):
+ * pango/pangowin32.c (pango_win32_font_get_metrics): Make
+ approximate_digit_width the width of the widest digit, rather than the
+ average.
+
+Thu Feb 19 10:44:17 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (compute_derived_language):
+ Use 'xx' as the language for cases where we
+ the language tag mismatches the script but we don't
+ have a good language tag for the script.
+ (#123581)
+
+Tue Feb 17 23:15:13 2004 Laszlo Peter <laca@sun.com>
+
+ * pango-uninstalled.pc.in: use @PANGO_API_VERSION@
+ * pangoft2-uninstalled.pc.in: use @PANGO_API_VERSION@
+ * pangox-uninstalled.pc.in: use @PANGO_API_VERSION@
+ * pangoxft-uninstalled.pc.in: use @PANGO_API_VERSION@
+
+Mon Jan 26 10:30:06 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules/thai/thai-shaper.c: Reapply the patch
+ from #124175 that somehow got reverted.
+
+Fri Feb 13 10:54:18 2004 Owen Taylor <otaylor@redhat.com>
+
+ Memory leak fixes from Masatake YAMATO, #130652
+
+ * pango/opentype/ftxgdef.c (TT_Done_GDEF_Table):
+ Free the gdef table as well as the contained data.
+
+ * pango/opentype/ftxgdef.c (TT_GDEF_Build_ClassDefinition):
+ Set gcd->loaded, so that the contents get freed later.
+
+Fri Feb 13 10:19:16 2004 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Skip the xslt and stylesheet checks
+ unless --enable-man is specified. (#134133,
+ Julio M. Merino Vidal)
+
+Tue Feb 10 19:03:44 2004 Manish Singh <yosh@gimp.org>
+
+ * pango/pango-context.c (itemize_state_init): initialize font_desc
+ to NULL.
+
+Tue Feb 10 14:33:54 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-markup.c: Handle 'tag' being NULL
+ in a bunch of places. (#122844, Noah Levitt)
+
+Tue Feb 10 14:28:41 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (update_attr_iterator): Fix
+ a leak of a font descriptor. (#131909, Kjartan Maraas,
+ Christian Persch)
+
+Tue Feb 10 14:13:04 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-tabs.c (pango_tab_array_resize): Fix
+ the amount of memory being allocated. (#132994,
+ Torsten Schoenfeld)
+
+Mon Feb 9 09:52:24 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_iterator_next): Fix
+ infinite loop introduced with last change. (#133749,
+ reported by Mariano Suárez-Alvarez)
+
+Thu Feb 5 16:30:46 2004 Owen Taylor <otaylor@redhat.com>
+
+ Fix problem with empty markup tags (#128102, Christian Persch)
+
+ * pango/pango-context.c (itemize_state_process_run): Assert
+ that the run is non-empty.
+
+ * pango/pango-attributes.c (pango_attr_list_change):
+ Just ignore empty attributes.
+
+ * pango/pango-attributes.c (pango_attr_iterator_next):
+ Skip empty attributes.
+
+Thu Feb 5 15:28:44 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_font_description):
+ Accept NULL for desc as documented. (#133001, Torsten Schoenfeld)
+
+Thu Feb 5 15:21:49 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_check_lines):
+ Redo the last commit once again.
+
+Thu Feb 5 15:16:04 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_check_lines): Fix
+ stupid cut-and-pasto from last commit.
+
+Thu Feb 5 15:09:58 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_check_lines):
+ Set is_paragraph_start here too. (#131356,
+ Morten Welinder)
+
+Wed Jan 28 17:47:52 2004 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Require GLib-2.3.1. (#132695,
+ Rodney Dawes.)
+
+Mon Jan 26 14:20:34 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/pango-ot-info.c (is_truetype): Support
+ CFF fonts as well. (#131202, Manjunath Sripadarao)
+
+Mon Jan 26 10:30:06 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules/thai/thai-shaper.c: Fix up glyph addition
+ code so that it works properly with the typical
+ TrueType fonts that have 0 width for combining
+ characters. (#124175, Theppitak Karoonboonyanan)
+
+Fri Jan 23 16:05:31 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-markup.c (open_tag_free): Fix some
+ more problems with NULL attribute lists.
+
+Thu Jan 22 12:36:10 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.3.2 ===
+
+ * configure.in: Version 1.3.2, interface age 2.
+
+ * NEWS: Tweak.
+
+Wed Jan 21 00:50:56 2004 Matthias Clasen <maclas@gmx.de>
+
+ * NEWS: Updates for 1.3.2.
+
+2004-01-06 Roozbeh Pournader <roozbeh@sharif.edu>
+
+ * modules/arabic/arabic-ot.c: Corrected a mistake between ZWJ and
+ ZWNJ. (#130517)
+
+Fri Dec 19 22:20:18 2003 Matthias Clasen <maclas@gmx.de>
+
+ * docs/tmpl/layout.sgml: Document all members of PangoLayoutLine.
+
+Thu Dec 18 01:20:31 2003 Matthias Clasen <maclas@gmx.de>
+
+ * pango/pango-attributes.c (pango_attr_size_new): Correct the
+ documentation. (#128431, Ross Burton)
+
+2003-12-13 Hans Breuer <hans@breuer.org>
+
+ * pango/pango.def pangoft2.def : moved pango_fc_*
+ to the latter where they live on *nix too.
+
+ * pango/makefile.msc : make it build again (including
+ the Ft2 backend)
+
+ * pango/module-defs-fc.c.win32 : if PANGO_MODULE_PREFIX is defined
+ include the basic backend shaper
+
+ * pango/pangowin32.c (pango_win32_render_layout) :
+ initialize iter before first usage to avoid immediate crashing
+
+ * pango/opentype/makefile.msc
+ pango/modules/makefile.msc : finally build with mscv, too.
+ [completely untested cause I'm not able to type, write or read
+ any of these languages]
+
+ * modules/modules.def : follow module function renaming/changes
+
+ * modules/basic/basic-win32.c : register the right engine, i.e.
+ make it compile
+
+2003-12-08 Tor Lillqvist <tml@iki.fi>
+
+ * modules/basic/basic-win32.c (convert_log_clusters_to_byte_offsets):
+ Simplify.
+
+ (itemize_shape_and_place): Fix problem with RTL scripts: If
+ ScriptItemize() returns several items, must handle them in reverse
+ order. (#128812, reported by Shoshannah Forbes)
+
+Mon Dec 8 12:57:03 2003 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.3.1 ===
+
+ * NEWS: Further updates for 1.3.1
+
+ * pango/pango-script.c (pango_script_iter_next): Put in
+ a hopefully-correct fix for a problem with invalid values of
+ start_sp causing out-of-bounds writes. (#125928,
+ Morten Welinder)
+
+2003-12-07 Tor Lillqvist <tml@iki.fi>
+
+ * pango/Makefile.am: Fix problems when building outside srcdir for
+ Win32. (#122167, Jeff Bonggren)
+
+2003-12-05 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2-fontmap.c: initialize the fontmap's resolution
+ to some sane default values. Fixes bug #123602.
+
+2003-12-04 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/pango-context.c:
+ * pango/pango-layout.c: Honor U+2028 LINE SEPARATOR. (#85745)
+
+2003-11-25 Noah Levitt <nlevitt@columbia.edu>
+
+ * examples/pangoft2topgm.c: Add --indent=n option.
+
+ * pango/pango-layout.[ch]: Indent the first line of every paragraph,
+ not just the first line in the layout. (#66626)
+
+2003-11-25 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango-utils.c (lang_texts[]): Italian is "it"; "iw" is deprecated
+ for Hebrew, should be "he".
+
+2003-11-20 Manish Singh <yosh@gimp.org>
+
+ * pango/pangoft2-private.h: #include <fontconfig/fcfreetype.h> for
+ FcFreeTypeCharIndex().
+
+2003-11-20 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2-fontmap.c: reverted the patch for bug #123602
+ since I only applied it accidentally. I still believe the patch
+ should go in though.
+
+ * pango/pangoft2.c: really applied the fix for #101856 as
+ described below.
+
+2003-11-20 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/pango-utils.c:
+ * pango/mini-fribidi/Makefile.am:
+ * pango/mini-fribidi/README:
+ * pango/mini-fribidi/fribidi.c:
+ * pango/mini-fribidi/fribidi.patch:
+ * pango/mini-fribidi/fribidi_char_type.c:
+ * pango/mini-fribidi/fribidi_tab_char_type_2.i:
+ * pango/mini-fribidi/fribidi_types.c:
+ * pango/mini-fribidi/fribidi_types.h:
+ * pango/mini-fribidi/fribidi_types.i: Update to latest fribidi.
+ (#68435)
+
+2003-11-18 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/pangxft-font.c (pango_xft_real_render): Draw 6-digit hex boxes
+ for > U+FFFF. (#101081)
+
+2003-11-18 Morten Welinder <terra@gnome.org>
+
+ * pango/pango-attributes.c (pango_attr_iterator_get_font): Fix
+ _SCALE semantics. Fixes bug 121543; patch from Owen.
+
+2003-11-18 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c: removed the set_unicode_charmap() call. Made
+ pango_ft2_font_real_get_glyph() use FcFreeTypeCharIndex() rather
+ than FT_Get_Char_Index(). Made pango_ft2_font_real_has_char() use
+ FcCharSetHasChar(). This allows to use PangoFT2 with all font
+ encodings supported by fontconfig and fixes bug #101856.
+
+Wed Nov 12 16:11:47 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Version 1.3.1, interface age 1.
+
+ * NEWS: Updates for 1.3.1
+
+2003-11-12 Padraig O'Briain <padraig.obriain@sun.com>
+
+ * pango/modules.c: Make parent_class variable static.
+
+Sat Nov 1 09:32:15 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-ot.h pango/pangofc-font.h modules/indic/indic-ot.h
+ pango/pangoft2.c pango/opentype/pango-ot-info.c
+ pango/opentype/pango-ot-ruleset.c pango/opentype/ottest.c
+ pango/opentype/ftxopen.[ch] pango/opentype/ftxgdef.c
+ pango/opentype/ftxgsub.c pango/opentype/ftxgpos.c:
+ Switch over to recommended Freetype system of
+ include ft2build.h then #include FT_FREETYPE_H.
+ Fixes ftmodule.h problem with current Freetype CVS.
+ (#125548)
+
+Fri Oct 31 13:01:25 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (libpangox_1_0_la_LDFLAGS): Fix some
+ leftover references to INCLUDE_XFT_MODULES,
+ INCLUDED_FC_MODULES. (#125588, Martin Kretzschmar)
+
+ * pango/pangox-fontmap.c (pango_x_face_get_coverage):
+ Fix some code that was never quite finished.
+
+Fri Oct 31 12:32:38 2003 Owen Taylor <otaylor@redhat.com>
+
+ Fix one problem with iteration by chars (Part of
+ #89541, Mariano Suárez-Alvarez)
+
+ * Pango/pango-layout.c (cluster_end_index): Fix to
+ be item relative, like iter->cluster_index.
+
+ * pango/pango-layout.c (pango_layout_iter_next_char):
+ Adapt.
+
+Fri Oct 24 00:09:17 2003 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.3.0 ===
+
+ * pango/module-defs-fc.c.win32 pango/module-defs-fc.c.win32:
+ Add the -fc version, remove the -ft2 version. Not sure this
+ file is actually needed any more.
+
+ * pango/Makefile.am (libpango_1_0_la_SOURCES): Add
+ pango-impl-utils.h, pango-script-lang-table.h.
+
+ * docs/Makefile.am (dist-hook-local): Distribute generated
+ manpage.
+
+ * tests/Makefile.am (CLEANFILES): Add pango.modules
+
+Wed Oct 15 17:18:37 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (itemize_state_init): Initialize
+ state->lang. (#124047, Morten Welinder)
+
+Tue Oct 14 19:00:17 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hebrew/hebrew-fc.c (hebrew_engine_shape):
+ Remove an unused variable. (#122680, Kjartan Maraas)
+
+Wed Oct 1 12:40:38 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-script.c (pango_script_get_sample_language):
+ Fix a c99-ism, include stdlib.h for bsearch.
+ (#123616, Kaushal Kumar)
+
+2003-09-30 Matthias Clasen <maclas@gmx.de>
+
+ * pango/pango-engine.h (struct _PangoEngineShapeClass): Replace
+ get_coverage by covers in the doc comment.
+
+ * pango/pango-script.c (pango_language_includes_script)
+ (pango_script_get_sample_language):
+ * pango/pango-fontset.c (pango_fontset_foreach):
+ * pango/pango-fontmap.c (pango_font_map_get_shape_engine_type):
+ * pango/modules.c (pango_map_get_engines):
+ * pango/pango-fontset.h (PangoFontsetForEachFunc): Fix typos and
+ add "Since: 1.4" tags.
+
+ * docs/pango-sections.txt: Add PangoFontsetForeachFunc,
+ pango_fontset_foreach(), pango_font_map_get_shape_engine_type(),
+ PangoScriptForLang, pango_script_get_sample_language() and
+ pango_language_includes_script(), remove pango_map_get_entry().
+
+Wed Sep 24 18:29:34 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hebrew/hebrew-shaper.c (hebrew_shaper_get_next_cluster):
+ Handle non-hebrew characters.
+
+2003-09-25 Matthias Clasen <maclas@gmx.de>
+
+ * pango/break.c (pango_default_break): Only reset the word
+ type to WordNone at a word end if it is not also a word
+ start. Otherwise both 't' and 'e' are classified as word
+ start in '123test'. (#122754, Hidetoshi Tajima)
+
+Tue Sep 23 19:43:05 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (itemize_state_add_character): Don't
+ break runs when we hit neutral characters.
+
+Tue Sep 23 18:03:57 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-engines.[ch] pango/pango-engines-private.h:
+ Modules now declare a list of scripts that they cover instead of a
+ list of code point ranges. Also, there is now a ->covers() virtual
+ function that allows a module to decide live whether the font
+ covers a particular codepoint; remove old get_coverage() method.
+
+ * pango/pango-fontset.[ch]: Add a foreach() function to
+ iterate over all the fonts in a fontset (with a true
+ return stopping iteration).
+
+ * pango/pango-context.c: Complete rewrite using script-run
+ information to improve language tags. Switch to an approach
+ where we handle one run at a time rather than computing
+ information for each character individually then later
+ breaking the result into runs.
+
+ * pango/pango-fontset.[ch]: Switch over to using
+ pango-impl-utils.h.
+
+ * modules/basic/basic-x.c pango/pangox-fontmap.c: Adapt to
+ the change from get_coverage => covers.
+
+ * pango/pango-modules.h pango/modules.c: Switch PangoMap
+ over to being based on script rather than being based
+ on codepoint. Remove the no longer needed pango_map_get_entry().
+
+ * pango/modules.c: Handle new script-based modules.
+
+ * pango/pango-fc-fontmap.c pango/pango-win32-fontmap.c
+ pango/pang-fontmap.[ch]: Add a shape_engine_type field
+ to PangoFontmapClass, pango_font_map_get_shape_engine_type();
+ this allows generic code to find a shaper for a particular
+ fontmap.
+
+ * pango/pango-script.[ch]: Add pango_script_get_sample_language(),
+ pango_language_includes_script(); functions for determining
+ the relationship between scripts and language.
+
+ * tools/gen-script-for-lang.c: Modify to spit out a
+ useful table.
+
+ * pango/pango-script-lang-table.h: Version of table
+ generated from current fontconfig data.
+
+ * pango/pangox.c: Remove complicated code to compute
+ coverages; no longer useful now that we just have
+ the basic shaper as a legacy thing.
+
+ * modules/*/*.c: Adapt to identifying shape engines
+ by language range.
+
+ * modules/thai/thai-fc.c modules/thai/thai-shaper.[ch]:
+ Remove now unused "has_glyph" function and XTIS support.
+
+ * modules/thai/thai-fc.c: Handle non-Thai characters
+ as well, since the Thai module now gets spaces,
+ punctuation, and so forth.
+
+Mon Sep 15 17:16:59 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/fterrcompat.h: Fix gcc-3.3 versions of
+ macros to have the right return value.
+
+Mon Sep 15 17:07:58 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am: Add property dependencies on mini-fribidi
+ and opentype convenience libraries.
+
+Tue Sep 9 12:21:02 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c (pango_fc_font_description_from_pattern):
+ Fix a g_assert() with a side-effect. (Maybe #121742?)
+
+Mon Sep 15 15:48:25 2003 Owen Taylor <otaylor@redhat.com>
+
+ * examples/Makefile.am examples/argcontext.c examples/argcontext.h:
+ Borrow argument parsing code from GDK.
+
+ * examples/pangoft2topgm.c: Use argcontext.[ch]. Add options
+ --header to display options in a header in the image, --text
+ to pass the text on the command line, --width to set a
+ wrap width. Add autoconversion to non-PGM output formats
+ via 'convert' for --output="foo.png" etc.
+
+2003-09-12 Matthias Clasen <maclas@gmx.de>
+
+ * pango/pango-context.c (pango_context_set_font_map)
+ (pango_context_new): Document these funcions as backends-only, and
+ explain how to obtain initialized contexts. (#121881, Martin Pool)
+
+Tue Sep 9 12:17:07 2003 Owen Taylor <otaylor@redhat.com>
+
+ * tools/Makefile.am (EXTRA_DIST): Remove reference
+ to now-gone make-table.sh (#121393, Josh Beam)
+
+2003-09-02 Noah Levitt <nlevitt@columbia.edu>
+
+ * tests/.cvsignore:
+ * tests/Makefile.am:
+ * tests/pangorc: Fix tests so that can be run before "make install"
+ has been. (#119831)
+
+Mon Aug 25 10:17:21 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (Lookup_ChainContextSubst3)
+ * pango/opentype/ftxgpos.c (Lookup_ChainContextPos3):
+ Fix problems where the coverage wasn't being checked
+ for the first input glyph. (#118639, Kailash C. Chowksey)
+
+Mon Aug 25 10:11:59 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (EXTRA_DIST): add testfonts.c to
+ EXTRA_DIST until bug #104151 is sorted out.
+
+Sun Aug 24 12:35:25 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/querymodules.c: Remove a stray ; (#120528,
+ Mehran Mehr)
+
+Fri Aug 22 18:09:52 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/fterrcompat.h: Add some macro definitions
+ for gcc-3.3 that suppress the bogus strict-aliasing
+ warnings.
+
+ * pango/pango-utils.c (read_config_file): Use
+ g_hash_table_new_full() to simplify code and fix
+ gcc-3.3 warnings.
+
+ * pango/pangox-fontmap.c (pango_x_real_get_coverage_win)
+ * pango/querymodules.c (query_module): Suppress gcc-3.3
+ warnings.
+
+ * pango/modules.c (pango_find_map): Fix warning from
+ missing declaration of pango_module_get_type().
+
+ * pango/pango-context.c/pango-engine.c: Fix name confusion
+ for pango_get_fallback_shaper().
+
+Fri Aug 22 17:29:42 2003 Owen Taylor <otaylor@redhat.com>
+
+ * examples/Makefile.am (pango.modules): Add a dependency
+ on pango-querymodules... Really needs to depend on the
+ modules too, but this at least will reduce the chances
+ of it not getting rebuild when necessary.
+
+Thu Aug 21 00:29:46 2003 Soeren Sandmann <sandmann@daimi.au.dk>
+
+ * pango/pangofc-fontmap.c (pango_fc_face_get_type): Remove
+ ABSTRACT from g_type_register_static() call
+
+2003-08-20 Noah Levitt <nlevitt@columbia.edu>
+
+ * configure.in: Bump version to 1.3.0.
+
+Fri Aug 15 16:34:14 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: get the cflags for gmodule-2.0 as
+ well as gthread-2.0. (#119953, Benedikt Spranger)
+
+2003-08-14 Noah Levitt <nlevitt@columbia.edu>
+
+ * docs/tmpl/main.sgml:
+ * pango/break.c:
+ * pango/pango-break.h: Add backspace_deletes_character to
+ PangoLogAttr. (#114483)
+
+Thu Aug 14 10:41:21 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/modules.c (init_modules): Call g_type_init()
+ (#119830, Noah Levitt)
+
+2003-08-11 Matthias Clasen <maclas@gmx.de>
+
+ * acinclude.m4: Copy newer versions of JH_CHECK_XML_CATALOG and
+ JH_PATH_XML_CATALOG from gtk-doc to enable configuring without
+ xmlcatalog in PATH. (#119115)
+
+Fri Aug 8 12:59:42 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_default_substitute):
+ Move DPI substitution before FcDefaultSubstitute so
+ it actually works.
+
+Fri Aug 8 11:45:15 2003 Owen Taylor <otaylor@redhat.com>
+
+ * examples/pangoft2topgm.c: Replace --family/--scale
+ options with a single --font
+
+Fri Aug 8 11:33:24 2003 Owen Taylor <otaylor@redhat.com>
+
+ * examples/pangoft2topgm.c: Add option to run 'display'
+ on the output as well as/instead of specifying output
+ file name.
+
+Fri Aug 8 10:33:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2.h: Deprecate pango_ft2_get_context(),
+ pango_ft2_font_map_for_display(), pango_ft2_shutdown_display();
+ the explicit
+
+ * pango/pangoft2-fontmap.c (pango_ft2_shutdown_display):
+ Add docs about deprecations.
+
+ * examples/Makefile.am (INCLUDES): Add -DPANGO_DISABLE_DEPRECATED
+
+ * examples/pangoft2topgm.c: Fix deprecated usages; add
+ --dpi and --markup options. Improve error handling.
+
+Fri Aug 8 10:03:03 2003 Owen Taylor <otaylor@redhat.com>
+
+ * examples/pangoft2topgm.c: Get rid of a bunch of
+ leftovers from the conversion from viewer; add
+ --waterfall to create a waterfall output at different
+ sizes, and --margin to set the margin.
+
+2003-08-05 Tor Lillqvist <tml@iki.fi>
+
+ * modules/basic/basic-win32.c (text_is_simple): New function. Uses
+ the Uniscribe ScriptIsSimple() function to check if Uniscribe
+ shaping is needed for a piece of text.
+
+ (basic_engine_shape): Use it, to avoid calling Uniscribe to shape
+ non-complex text. Produces dramatic speedup according to tests by
+ Hans Breuer.
+
+ (init_uniscribe): No need for the PANGO_WIN32_NO_UNISCRIBE
+ environment variable any longer.
+
+Mon Aug 4 01:12:35 2003 Soeren Sandmann <sandmann@daimi.au.dk>
+
+ * tools/gen-script-for-lang.c (get_script_name): Fix C99 variable
+ declaration.
+
+Sun Aug 3 18:37:46 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.c (get_face_metrics): Fix sign
+ of metrics->descent.
+
+ * pango/pango-engine-private.h: fix include (Noah Levitt)
+
+Sat Aug 2 23:19:16 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-engine.[ch] modules/*/*-{fc,win32,x}.c
+ pango/modules.c pango/break.c pango/pango-context.c
+ pango/pango-layout.c pango/pango-modules.h
+ pango/querymodules.c pango/shape.c: Make
+ PangoEngine{,Lang,Shape} GObjects, and use a
+ GTypeModule-based module-loading system closely based
+ on the one used for GtkIMContext and GtkThemeEngine.
+
+ * pango/pango-impl-utils.h: OK, I'm tired of typing
+ in get_type() functions.
+
+ * pango/pango-script.[ch] pango/pango-script-table.h
+ tests/testscript.c tools/gen-script-table.pl: Add port
+ of script-range code from ICU in preparation for future
+ use. (#91542)
+
+ * tools/gen-script-for-lang.c: Utility program to determine
+ the script for each fontconfig .orth file.
+
+ * docs/tmpl/{scripts.sgml,pango-engine-lang.sgml,
+ pango-engine-shape.sgml} docs/pango-sections.txt docs/pango-docs.sgml:
+ Redo to go along with the above changes.
+
+ * configure.in: chmod +x tests/runtests.sh
+
+2003-08-03 Noah Levitt <nlevitt@columbia.edu>
+
+ * pango/Makefile.am (libpangoxft_1_0_la_DEPENDENCIES): Really make
+ pangoxft depend on pangoft2. (#119024)
+
+Sat Aug 2 14:33:28 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (libpangoxft_1_0_la_LIBADD): Make
+ pangoxft depend on pangoft2.
+
+ * pango/pangofc-fontmap.[ch]: Make pangofc-fontmap.cI
+ into a real base class.
+
+ * pango/pangofc-font.[ch]: Move some of the pangoxft/
+ pangoft2 implementation here.
+
+ * pango/pangoft2.c pango/pangoft2-fontmap.c
+ pango/pangoft2-private.h pango/pangoxft-font.c
+ pango/pangoxft2-fontmap.c pango/pangoxft-private.h: Adapt
+ to the new scheme
+
+ * modules/*/Makefile.am Modules/*/*/*-fc.c: Don't build
+ separate FT2 and Xft shapers, just build one Fc shaper.
+
+ * docs/pango-sections.txt docs/pango-docs.sgml
+ docs/tmpl/pangofc-font{,map}.sgml: Basic docs for
+ the new stuff.
+
+ * configure.in: Up pango_module_version to 1.4.0.
+
+Sat Aug 2 14:18:20 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/Makefile.am (EXTRA_DIST): Remove some
+ leftovers.
+
+Sat Aug 2 14:10:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am pango/pango-intset.[ch] pango/pango-indic.[ch]:
+ Remove.
+
+ * pango/pangox.c (pango_x_apply_ligatures): Make a noop,
+ remove associated code.
+
+ * pango/pangox-fontmap.c pango/pangox.[ch]: Deprecate everything.
+
+Sat Aug 2 13:17:45 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in
+ modules/arabic/{Makefile.am arconv.[ch],langboxfont.[ch],
+ mulefont.[ch],naqshfont.[ch],arabic-x.c}
+ modules/hangul/{Makefile.am,hangul-x.c,tables-johabfont.i,
+ tables-ksc5601.i}
+ modules/hebrew/{Makefile.am,hebrew-x.c}
+ modules/indic/{Makefile.am,*-x.c}
+ modules/tamil
+ modules/thai/{Makefile.am,thai-x.c}:
+ Remove old X font shapers.
+
+Sat Aug 2 16:40:19 2003 Soeren Sandmann <sandmann@daimi.au.dk>
+
+ Add API to kern a complete glyph string. Remove API to kern
+ individual glyph pairs.
+
+ * modules/basic/basic-fc.c (basic_engine_shape): use
+ pango_fc_font_kern_glyphs() instead of pango_fc_font_get_kerning().
+
+ * pango/pangoft2.c (pango_ft2_font_real_kern_glyphs): add this
+ function, remove pango_ft2_font_real_get_kerning().
+
+ * pango/pangoxft-font.c (pango_xft_font_real_kern_glyphs): add
+ this function, remove pango_xft_font_real_get_kerning().
+
+ * pango/pangofc-font.c (pango_fc_font_kern_glyphs): new
+ function. Remove pango_fc_font_get_kerning().
+
+ * pango/pangofc-font.h: remove pango_fc_font_get_kerning(), add
+ pango_fc_font_kern_glyphs().
+
+Tue Jul 29 09:58:13 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgdef.c (Check_Property): Rewrite
+ handling of IGNORE_SPECIAL_MARKS to be properly
+ "ignore marks of attachment type different than
+ specified. (#118456, Kailash C. Chowksey)
+
+Sat Jul 26 09:41:22 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (Lookup_LigatureSubst):
+ Revert back out the FreeType patch preventing
+ ligatures of not-originally adjacent glyphs;
+ it doesn't work for all scripts. (#118472,
+ Kailash C. Chowksey)
+
+Sat Jul 26 22:30:59 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (Lookup_ChainContextSubst{1,2,3}):
+ Check for lookahead glyphs in the right place. (Patch
+ from Kailash C. Chowksey, #116860)
+
+ * pango/opentype/ftxgpos.c (Lookup_ChainContextPos{1,2,3}):
+ Same fix here.
+
+Sat Jul 26 22:12:46 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (Do_String_Lookup,
+ TT_GSUB_Apply_String): Fix return value to only
+ contain TTO_Err_Not_Covered if *no* lookups
+ matched. Fix memory leaks on error in Apply_String().
+
+Sat Jul 26 22:09:44 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot.c (indic_ot_reorder):
+ Fix problem where NULL mpreFixups wasn't getting
+ returned properly.
+
+Sat Jul 26 21:06:26 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (Load_EmptyOrClassDefinition):
+ Fix confusion between boolean and FT_Error return.
+ (GSUB equivalent of fix for #108358)
+
+Sat Jul 26 10:52:20 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgpos.c (Lookup_ContextPos2):
+ * pango/opentype/ftxgsub.c (Lookup_ContextSubst2): Move
+ allocation afer initial checks, fixing memory leak.
+
+ * pango/opentype/ftxgsub.c (Lookup_ChainContextSubst2):
+ Fix some more error return memory leaks that weren't
+ fixed in the Qt changes.
+
+Sat Jul 26 10:43:20 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c pango/opentype/ftxgpos.c:
+ Fix various memory leaks from error returns that should
+ have been jumps to cleanup blocks. (From Qt, Lars Knoll)
+
+Sat Jul 26 10:30:24 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgpos.c: Fix additional places where
+ TTO_Err_Not_Covered wasn't considered a successful return
+ from Get_Class. (From Qt, Lars Knoll)
+
+Sat Jul 26 09:41:22 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (Lookup_LigatureSubst):
+ If applying a ligature lookup makes adjacent two glyphs
+ that were not originally adjacent, avoid making
+ subsequent ligatures between those glyphs.
+ (From FreeType, Werner Lemberg, 2001-08-22, 2001-08-23)
+
+Sat Jul 26 09:16:57 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgpos.c pango/opentype/ftxopen.c:
+ Fix some FreeType1 variable declarations that snuck
+ in from the last commits (Christophe Fergeau,
+ #118363)
+
+Fri Jul 25 23:38:07 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgpos.c pango/opentype/ftxgsub.c:
+ OpenType-1.4 update: backtrack information is stored with the
+ item closest to the input first (From FreeType,
+ Werner Lemberg, 2002-09-26)
+
+Fri Jul 25 23:07:06 2003 Owen Taylor <otaylor@redhat.com>
+
+ Update of GPOS and GSUB support to OpenType 1.3
+ (From FreeType, Werner Lemberg, 2001-08-08)
+
+ * pango/opentype/ftxopen.h: Add RIGHT_TO_LEFT LookupFlag
+
+ * pango/opentype/ftxgpos.c (GPOS_Instance): Add 'first'
+ member to mark the beginning of a chain of cursive connections.
+
+ * pango/opentype/ftxgpos.c (Do_String_Lookup): If the
+ RIGHT_TO_FLAG flag is set, shift cursive chain up so
+ last glyph is on the baseline.
+
+Fri Jul 25 22:59:13 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftx{gpos,gsub}.h pango/opentype/ftxgdef.c:
+ Add GPOS_LOOKUP_EXTENSION, GSUB_LOOKUP_EXTENSION, which
+ allow lookup information to be stored at 32-bit offets
+ via a double indirection. (From FreeType, Werner Lemberg,
+ 2001-08-08)
+
+Fri Jul 25 22:25:48 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (Lookup_ContextSubst2,
+ Lookup_ChainContextSubst2): Fix a couple of
+ places where TTO_Err_Not_Covered wasn't considered
+ a successful return from Get_Class -- it means
+ use class index 0. (From FreeType, Werner Lemberg,
+ 2001-08-06)
+
+Fri Jul 25 20:12:00 2003 Owen Taylor <otaylor@redhat.com>
+
+ Improvements to OpenType-dumping code, based on
+ changes in Qt by Lars Knoll.
+
+ * pango/opentype/ottest.c: Tweak the debugging output,
+ suppress some warnings.
+
+ * pango/opentype/disasm.c: Add support for
+ GSUB Context/Chain GPOS MarkBase lookups, improve
+ output in various ways.
+
+Fri Jul 25 12:07:21 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/mprefixups.[ch] modules/indic/indic-ot.[ch]
+ modules/indic/indic-fc.c: Port pre-base-mantra
+ fixup code from ICU, as needed for Tamil and Malayalam.
+ (Based on patch from Sivaraj Doddannan, #111166)
+
+Fri Jul 25 11:06:14 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot.[ch]: Port of some fixes from
+ ICU.
+
+ "Fixed problems w/ backing off the front of a syllable if
+ all consonants have post-base form... Fix tag list for base
+ consonant so that it doesn't have 'pstf'""
+
+ Based on patch from Taneem Ahmed (#118297)
+
+2003-07-25 Noah Levitt <nlevitt@columbia.edu>
+
+ * docs/tmpl/engines.sgml:
+ * docs/tmpl/glyphs.sgml:
+ * docs/tmpl/main.sgml: Get rid of explicit tables detailing the
+ members of structs, use the automatic things instead. (#117857)
+
+2003-07-25 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c (pango_ft2_render_layout_line): removed
+ redundant call to pango_layout_line_get_extents() (#116822).
+
+ * pango/pangoft2.c (pango_ft2_render): fixed source bitmap offset
+ for the monochrome case; some code cleanup (#116837).
+
+Thu Jul 24 18:03:32 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/*/Makefile.am: Remove leftover FRIBIDI_LIBS
+ reference. (Pointed out by Sven Neumann)
+
+Thu Jul 24 17:06:38 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-item.c (pango_item_copy/free): Handle
+ NULL item->analysis.font. (#114576, Morten Welinder)
+
+Thu Jul 24 17:04:21 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/pango-ot-ruleset.c (pango_ot_ruleset_shape):
+ Fix uses of g_assert() around statements with side effects.
+ (#115498, patch from David Cuthbert)
+
+Thu Jul 24 16:40:12 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in tests/runtests.sh.in: Generate
+ runtest.sh so we can use ECHO_C, ECHO_N, SHELL
+ (#114944)
+
+Thu Jul 24 15:55:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Clean up checks for usp10.h
+
+ * configure.in: Remove configure option for XftConfig
+ location.
+
+ * acconfig.h: Remove, not needed with autoconf-2.5x.
+ (#114916, Tony Graham)
+
+Thu Jul 24 15:37:16 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in pango/Makefile.am pango.pc.in: Remove
+ vestiges of support for external fribidi library.
+
+Thu Jul 24 15:09:22 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in examples/Makefile.am examples/viewer-qt.{cc,h}:
+ Remove Qt-based example; it was only testing the obsolete
+ pango-x backend, and was causing more problems for people
+ trying to configure Pango then it was worth.
+
+ * examples/viewer.c: Remove obsolete test case from CVS.
+
+Thu Jul 24 15:02:56 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/glyphstring.c (pango_glyph_string_get_logical_widths):
+ Fix up right-to-left case. (Based on patch from
+ Damon Chaplin, #117325)
+
+Thu Jul 24 14:35:48 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c (pango_language_matches): Increment
+ past the ';' for a list with multiple elements. (#117180,
+ John Finlay)
+
+2003-07-20 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc : updated to generate libtool
+ compatible dll names, define the right PANGO_MODULE_PREFIX,
+ pangoft2 still not build with msvc
+
+ * module/basic-win32.c : some #ifdef's for missing
+ LANG_* constants to make it compile with msvc50
+
+ * pango/pango.def : updated externals
+
+2003-06-25 Matthias Clasen <maclas@gmx.de>
+
+
+ * pango/pango-layout.c:
+ * pango/pango-tabs.c:
+ * pango/pango-attributes.c:
+ * docs/tmpl/layout.sgml:
+ * docs/tmpl/text-attributes.sgml: Doc markup and typo fixes.
+
+2003-06-17 Matthias Clasen <maclas@gmx.de>
+
+ * docs/Makefile.am: Add rule to regenerate man pages from
+ Docbook.
+ (man_MANS): Add pango-querymodules.1.
+ (content_files): Add pangoe-querymodules.xml.
+
+ * docs/pango-querymodules.xml: New refentry.
+
+ * docs/pango-querymodules.1: Man page generated from the .xml source.
+
+ * docs/pango-docs.sgml: Include pango-querymodules.xml.
+
+ * acinclude.m4 (JH_PATH_XML_CATALOG, JH_CHECK_XML_CATALOG): New
+ macros to check for XML catalog contents and path, borrowed from
+ gtk-doc.
+
+ * configure.in: New option --enable-man to enable regeneration of
+ man pages from Docbook, if the necessary tools are found.
+
+ * docs/pango-docs.sgml: Add an autogenerated index.
+
+2003-06-13 Tor Lillqvist <tml@iki.fi>
+
+ * pango-zip.sh.in (DLLDIR): libtool 1.5 installs DLLs in the bin
+ directory, so look there, too. Include the gtk-doc directory.
+
+Thu Jun 5 14:53:40 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually):
+ Fix bug in determining when we cross line boundaries.
+ (#103421, Matthias Clasen)
+
+Wed Jun 4 14:32:47 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/glyphstring.c (pango_glyph_string_extents_range):
+ Improve handling of empty ink rectangles; rework for
+ simplicity. (#103662)
+
+2003-06-04 Tor Lillqvist <tml@iki.fi>
+
+ * modules/thai/thai-x.c: Need config.h here, too, for
+ HAVE_X. Thanks to Patrick Welche.
+
+Mon Jun 2 10:43:15 PDT 2003 Keith Packard <keithp@keithp.com
+
+ * pango/pangoxft-font.c (pango_xft_font_real_get_kerning):
+ was returning with FT_Face locked. (#114226)
+
+Mon Jun 2 12:10:11 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-glyph-item.c (pango_glyph_item_apply_attrs):
+ Don't put statements with side-effects inside g_assert()!
+ (#114137, Jeff Waugh)
+
+2003-05-30 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangoft2.def: Add pango_ft2_font_map_set_default_substitute.
+
+Thu May 29 20:05:45 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-glyph-item.c: Fix a stupid bug in the
+ shortcircuit case.
+
+Thu May 29 18:49:00 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-fc.c: Use the correct tags at
+ the GPOS stage, taking into account changes during
+ the GSUB stage. (#112433)
+
+Thu May 29 18:37:58 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-glyph-item.c (pango_glyph_item_apply_attrs):
+ When applying attribute to a glyph item, handle attributes
+ that split clusters by giving the cluster all the attributes
+ that apply to it. (Previously caused a crash, #104976
+ Taneem Ahmed, Sunil Mohan Adapa)
+
+2003-05-29 Tor Lillqvist <tml@iki.fi>
+
+ * acconfig.h: Add HAVE_X.
+
+ * configure.in: Set HAVE_X.
+
+ * modules/thai/thai-shaper.h: Don't include pangox.h unless
+ HAVE_X. Also leave out the PangoXSubfont field unless HAVE_X.
+
+ * modules/hangul/Makefile.am
+ * modules/indic/Makefile.am
+ * modules/thai/Makefile.am: Use -no-undefined on Windows.
+
+ * modules/thai/thai-shaper.c: Include config.h for HAVE_X.
+
+ * README.win32: Some minor edits.
+
+ * pango/pango.def: Add pango_fc_* entries.
+
+ * pango/pangoft2.def: Add some missing entries.
+
+Wed May 28 17:43:16 2003 Owen Taylor <otaylor@redhat.com>
+
+ (#107630, Federic Zhang)
+
+ * tools/compress-table.pl (convert): Make read the
+ maps directly.
+
+ * tools/make-table.pl: Remove.
+
+2003-05-28 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c (pango_ft2_render): added support for rise,
+ strikethru and shape attributes. (#109900).
+
+Tue May 27 18:37:44 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mini-fribidi/fribidi.c (fribidi_analyse_string):
+ Limit the size of the buffers we alloca(). (#104328)
+
+Tue May 27 16:51:32 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Clean up so that tests for Xft/FreeType
+ are only run when we find fontconfig. (#112027,
+ Tim Mooney)
+
+ * README: Rewrite the text about fontconfig dependencies
+ to be clearer and not to have stale links to
+ http://keithp.com/fonts/. (#112027, Tim Mooney)
+
+Tue May 27 16:06:34 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox.c (pango_x_render): Patch from Morten
+ Welinder to collect characters into runs of the
+ same font with natural offsets before drawing them.
+ (#106892, Morten Welinder)
+
+Tue May 27 15:01:24 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_get_metrics):
+ Get the fontnmap for the right screen (#113452,
+ Morten Welinder)
+
+Tue May 27 12:36:50 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Fix typo for FreeType dependencies
+ in the enable_explicit_deps case. (#113333, James Su)
+
+Tue May 27 12:32:43 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (pango_context_new)
+ pango/pango-layout.c (pango_context_new)
+ pango/pango-win32.c (pango_win32_font_map_for_display)
+ pango/pangox-fontmap.c (pango_x_font_map_for_display)
+ pango/pangox.c (pango_x_font_new): Use g_object_new()
+ rather than g_type_create_instance() (Patch from
+ Benjamin Otte, #112786)
+
+Tue May 27 12:19:53 2003 Owen Taylor <otaylor@redhat.com>
+
+ * examples/pangoft2topgm.c (main): Add code to check
+ for "./pangorc" so that it works uninstalled.
+
+Fri May 2 17:20:23 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/mapping.c (pango_glyph_string_x_to_index):
+ Fix some incorrect edge cases for RTL text.
+ (#102952, Padraig O'Briain)
+
+Fri May 2 14:21:20 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (update_run): Fix a harmless
+ uninitialized memory read. (#109625, Rich Burridge)
+
+Wed Apr 30 16:46:52 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_hash): Hash
+ case insensitively (#106942, Morten Welinder)
+
+Tue Apr 29 18:02:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Add the fonconfig cflags/libs to
+ FREETYPE_CFLAGS/LIBS. (#111326, Noah Levitt)
+
+ * {pango,tests,examples}/Makefile.am: Remove now
+ unnecessary references to FONTCONFIG_CFLAGS/LIBS.
+
+Thu Apr 24 19:12:05 2003 Owen Taylor <otaylor@redhat.com>
+
+ * autogen.sh (have_libtool): Accept libtool-1.5. (#111482)
+
+2003-04-23 Matthias Clasen <maclas@gmx.de>
+
+ * docs/tmpl/glyphs.sgml: Remove outdated information about PangoGlyph.
+
+Wed Apr 16 03:46:42 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/pango-ot-info.c (synthesize_class_def):
+ More careful handling of face->charmap; if is NULL,
+ try to set a unicode charmap, if that doesn't succeed,
+ return. (Hopefully fixes #106550)
+
+Tue Apr 15 11:49:39 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxg{sub/pos}.c: When loading
+ in Load_Chain{Sub,Pos}ClassRule, the limit we
+ have only applies to the input ClassDef table.
+ Fixes problem with Arial Unicode. Much help from
+ Noah Levitt in tracing this down.
+
+Tue Apr 15 09:19:21 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_set_family):
+ Free the right string.
+
+Tue Apr 15 07:03:19 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.h: Always include freetype.h
+ even when not ENABLE_ENGINE | ENABLE_BACKEND.
+
+Tue Apr 15 06:57:02 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgpos.c: Fix mispelled constant
+ from last commit.
+
+Tue Apr 15 06:03:39 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgpos.c: Fix confusion between
+ boolean and FT_Error return. (#108358, Noah Levitt)
+
+ * pango/opentype/ftxopen.c (Get_Class1): index is
+ allowed to be NULL. (#108358, Noah Levitt)
+
+Tue Apr 15 05:47:35 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Don't look for Xft unless we found
+ FreeType. (#109573)
+
+Tue Apr 15 05:34:05 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/fonts.c (pango_font_description_set_family):
+ Switch around the code so that
+ pango_font_description_set_family (desc,
+ pango_font_description_set_family (desc))
+ in the case where desc->static_family is TRUE.
+ (#106964, Morten Welinder)
+
+Tue Apr 15 05:13:56 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Avoid complex quoting mess that
+ didn't work with all shells. (#108001)
+
+Tue Apr 15 05:00:39 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/pango-ot-info.c (synthesize_class_def):
+ Fix infinite loop in the case where the charmap contains
+ a character > 65535. (#106550, Morten Welinder.)
+
+Tue Apr 15 04:53:56 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot.h (enum): Cast some enumeration
+ members that are bigger than signed integers to (int) to fix
+ warning on AIX. (#107924)
+
+Tue Apr 15 04:39:48 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-coverage.c (pango_coverage_set): Fix
+ off-by-one error. (#108620, Noah Levitt)
+
+Tue Apr 15 03:54:01 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/hangul-{x,fc}.c: Fix out-of-bounds read
+ where the value wasn't actually used. (#106744, Morten Welinder)
+
+Tue Apr 15 03:47:37 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_iterator_next): Return
+ FALSE, not -1 in g_return_val_if_fail(). (#107666, Morten
+ Welinder.)
+
+Tue Apr 15 00:07:21 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2.[ch]: Fix some stupid type registration/
+ class size problems from last commit.
+
+Mon Apr 14 06:02:34 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/thai/{thai-fc.c,thai-shaper.c,thai-x.c}:
+
+ * modules/*/*-{xft,x,win32.c} pango/pango-engine.h
+ modules/*/Makefile.am: Switch over the way that
+ module entry points work, taking advantage of the
+ new automake capability for per-target CFLAGS for
+ shared sources.
+
+ * pango/pangofc-font.[ch] pango/pangoxft-font.c
+ pango/pangoft2.c: Add a base class for
+ PangoXft and PangoFT2 font classes so code can
+ be shared between FT2 and Xft backends.
+
+ * configure.in modules/*/Makefile.am
+ modules/{arabic,basic,hangul,hebrew,indic,thai}: Move
+ *-xft.c to *-fc.c and share between Xft and FT2 backends;
+ adds FT2 backend capabilities for hangul/indic/thai.
+
+ * pango/pangoxft.h pango/pangoft2.h: Deprecate
+ APIs that moved into PangoFcFont
+
+ * modules/basic/basic-fc.c (set_glyph): Add kerning
+ handling from FT2 backend.
+
+2003-04-03 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c (pango_ft2_font_get_face)
+ (pango_ft2_font_render_glyph): disable antialiasing if requested.
+ Fixes bug #109370.
+
+ * pango/pangoft2.c (pango_ft2_render): fixed rendering of
+ monochrome bitmaps.
+
+2003-04-02 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2.c (pango_ft2_render_layout)
+ * pango/pangowin32.c (pango_win32_render_layout)
+ * pango/pangox.c (pango_x_render_layout): use a PangoLayoutIter to
+ iterate over the lines and let render_layout_line() do the actual
+ rendering. Fixes bug #105292.
+
+2003-03-28 Sven Neumann <sven@gimp.org>
+
+ * pango/pangoft2-fontmap.c
+ * pango/pangoxft-fontmap.c: fixed typos in inline docs.
+
+2003-03-09 James Henstridge <james@daa.com.au>
+
+ * autogen.sh: make similar changes to the ones on glib head (call
+ gtk-docize, etc).
+
+ * configure.in: move some calculations into M4 macros, rather than
+ calculating them when configure runs.
+ Use AC_HELP_STRING where appropriate.
+ Replace gtk-doc checks with a call to GTK_DOC_CHECK.
+ Replace AC_OUTPUT_COMMANDS() call with a number of calls to
+ AC_CONFIG_COMMANDS (once per created file).
+ Get rid of the "chmod +x pango-config" bit, because there is no
+ pango-config anymore.
+
+ * Makefile.am: get rid of custom distcheck rule, and set
+ DISTCHECK_CONFIGURE_FLAGS, which is equivalent.
+ Use += to select which .pc files to install.
+
+ * pango/Makefile.am: Add rules to rebuild module-defs* files, and
+ remove them on clean.
+ Reorder so that rules related to each individual library are next
+ to each other.
+ Use BUILT_SOURCES for built sources.
+
+ * pango/opentype/Makefile.am: don't use STRIP_BEGIN/STRIP_END.
+
+ * modules/*/Makefile.am: simplify module makefiles through use of
+ +=, and regularise them a bit (fixed a few bugs in the process).
+
+ * docs/Makefile.am: remove common rules, and instead include
+ gtk-doc.make.
+
+ * examples/Makefile.am: add pango.modules to CLEANFILES.
+
+ * tests/Makefile.am: remove temporary files on clean.
+
+Mon Feb 17 13:06:39 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in **/Makefile.am: Add an --enable-debug
+ configure argument defaulting to 'yes' for unstable
+ releases and 'minimum' for stable releases.
+ For minimum, -DG_DISABLE_CAST_CHECKS.
+
+ * pango/pangofc-fontmap.cI pango/pangoft2-fontmap.c
+ pango/pangoxft-fontmap.c: Add caching of fontsets
+ (#104495, initial patch and review by Soeren Sandmann)
+
+ * pango/pangofc-fontmap.cI pango/pangoft2-fontmap.c
+ pango/pangoxft-fontmap.c pango/pangoft2-private.h
+ pango/pangoxft-private.h: Remove cache of recently freed
+ fonts; not necessary now that we cache fontsets.
+
+ * pango/pangofc-fontmap.cI (pango_fc_pattern_set_free):
+ Rename from pango_fc_font_set_free to reflect
+ what it actually does.
+
+ * pango/pangofc-fontmap.cI pango/pangoft-fontmap.c
+ pango/pangoxft-fontmap.c: Combine clear-the-cache
+ functions; we didn't need separate clear-the-font-cache
+ and clear-the-pattern-cache functions.
+
+Sun Feb 16 09:10:12 2003 Chema Celorio <chema@celorio.com>
+
+ * pango/pangoft2.c (pango_ft2_render_layout): fix a typo
+ in the @bitmap argument description. s/line/layout
+
+Wed Feb 12 17:20:15 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Simplify 'test x$have_x != xfalse'
+ to $have_x.
+
+Wed Feb 12 17:17:12 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: If --without-x is specified, don't
+ try to build Xft backend either. (#105210, patch
+ from Akira Tagoh)
+
+Wed Feb 12 17:09:00 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c: Fix bug where language
+ tag changes were not causing the font to be
+ looked up again. (bugzilla.redhat.com #84034)
+
+Wed Feb 12 16:59:23 2003 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in pango/opentype/fterrcompat.h README:
+ Up the FreeType version requirement to 2.0.9.
+ (2.2.1 had a compilation failure with older versions,
+ this catches it more cleanly, and removes some unneeded
+ checks. #105302, problem reported by Will Partain.)
+
+Wed Feb 12 16:48:46 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_text):
+ Guard against
+ pango_layout_set_text (pango_layout_get_text (layout));
+ (#105612, Morten Welinder)
+
+Wed Feb 12 16:44:05 2003 Owen Taylor <otaylor@redhat.com>
+
+ * examples/viewer-qt.cc: Remove call to
+ QApplication::setStyle (new QCDEStyle())... didn't
+ make sense and caused problems if CDEStyle wasn't
+ compiled into Qt. (#105264, Andrey Panov)
+
+Wed Feb 12 16:41:03 2003 Owen Taylor <otaylor@redhat.com>
+
+ * modules/hangul/Makefile.am (libpango_hangul_x_la_SOURCES):
+ Fix typo where xft_sources was used again. (#105219,
+ Chris Ross)
+
+Thu Jan 30 16:41:46 2003 Owen Taylor <otaylor@redhat.com>
+
+ * Makefile.am (EXTRA_DIST): Remove spec.spec.in from
+ EXTRA_DIST, and from dist rules. (#102231)
+
+ * configure.in: Don't generate pango.spec.
+
+Tue Jan 28 18:20:45 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-coverage.c (pango_coverage_set/get): Fix
+ an off-by-one error when checking if are off the end
+ of the coverage array. (#102284, Morten Welinder.)
+
+ * pango/pango-coverage.c (pango_coverage_get/set): Add
+ g_return_if_fail for index >= 0.
+
+2003-01-29 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.c (pango_win32_font_calc_coverage): Break out
+ of loop if char is 0xFFFF. Some fonts have tables terminated like
+ this.
+
+Tue Jan 28 15:18:24 2003 Owen Taylor <otaylor@redhat.com>
+
+ * autogen.sh (have_automake): Fix version in complaint
+ message about automake. (#104366, Rich Burridge)
+
+2003-01-20 Sven Neumann <sven@gimp.org>
+
+ * configure.in: fixed configure output which was wrong in case
+ freetype is available but fontconfig isn't (bug #103917).
+
+2003-01-17 Padraig O'Briain <padraig.obriain@sun.com>
+
+ * pango/fonts.c (pango_font_description_from_string): Avoid crash
+ with string such as " 12" (bug #103674)
+
+Fri Jan 10 18:56:36 2003 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgdef.c: Export TT_New_GDEF_Table
+ to create an empty GDEF table.
+
+ * pango/opentype/pango-ot-info.c: If the font doesn't
+ have a class definition table, synthesize one using
+ the charmap and the unicode properties of characters
+ in the charmap. (Needed to make things work with various
+ old Arabic fonts, such as the KACST fonts)
+
+Local Variables:
+coding: utf-8
+End:
+vim: encoding=utf-8:
diff --git a/trunk/ChangeLog.pre-1-6 b/trunk/ChangeLog.pre-1-6
new file mode 100644
index 00000000..017ad509
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-6
@@ -0,0 +1,799 @@
+Mon Sep 13 17:38:58 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.6.0 ===
+
+ * configure.in: Update versions for 1.6.0
+
+ * NEWS: Update.
+
+ * README: Minor tweak.
+
+ * pango/fonts.c pango/pango-context.c pango/pango-types.h
+ pango/pango-utils.c pango/pangoft2.c pango/pango-layout.c
+ pango/opentype/pango-ot-buffer.c: Add a bunch of missing
+ Since: 1.6.
+
+Mon Aug 16 14:17:56 2004 Owen Taylor <otaylor@redhat.com>
+
+ * examples/renderdemo.c (fc_substitute_func): Fix reversed
+ auto-hint option.
+
+2004-08-26 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangoft2.def: Add pango_ot_buffer_set_zero_width_marks,
+ again.
+
+ * pango/Makefile.am: Don't use -lm on Windows.
+ (pangoinclude_HEADERS): Put them on one line, automake 1.8 (at
+ least on Windows) otherwise drops the backslashes but still
+ outputs separate lines.
+
+2004-08-26 Dov Grobgeld <dov.grobgeld@weizmann.ac.il>
+
+ * modules/hebrew/hebrew-fc.c (hebrew_engine_shape): Added
+ open-type support for Hebrew.
+
+2004-08-22 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-fontmap.c (pango_win32_inner_enum_proc): Ignore
+ synthetic vertical writing versions of East Asian fonts. (#145322,
+ John Ehresman)
+
+Mon Aug 16 13:58:04 2004 Owen Taylor <otaylor@redhat.com>
+
+ * examples/renderdemo.[ch] examples/pangoft2topgm.c:
+ add a --hinting command line flag.
+
+Mon Aug 16 13:42:38 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-ot.h (struct _PangoOTGlyph): Sync with
+ change to OTL_GlyphItemRec.
+ (https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=129982,
+ Jatin Nansi)
+
+Tue Aug 10 11:51:10 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/arabic/arabic-fc.c (arabic_engine_shape): Fix
+ bug where cluster was getting set to 0 for non-spacing
+ marks rather than to the cluster of the base character.
+ (#149126, Behdad Esfahbod)
+
+2004-08-06 Hans Breuer <hans@breuer.org>
+
+ * pango/pango.def pango/pangoft2.def pango/pangowin32.def
+ pango/makefile.msc : updated
+
+ * pango/pangofc-decoder.c : static the pango_fc_decoder_*init
+ implementations
+
+ * pango/pangowin32.c : remove the duplicated, empty implementation
+ of pango_win32_font_init(), also replace parent_class variable
+ with pango_win32_font_parent_class as defined by G_DEFINE_TYPE
+
+ * modules/basic/basic-win32.c : implement basic_engine_covers
+
+ * pango/testfonts.c : iterate three common font names as was
+ intended orginally and said in the comment for years
+
+2004-08-06 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-fontmap.c: Typedef PangoWin32FontMapClass.
+
+ (pango_win32_font_map_class_init): Match what G_DEFINE_TYPE
+ generates.
+
+2004-08-05 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangoft2.def: Add pango_ot_buffer_set_zero_width_marks.
+
+Mon Aug 2 17:09:47 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.5.2 ==
+
+ * configure.in: Version 1.5.2
+
+ * NEWS: Updates
+
+Mon Aug 2 17:00:19 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-fc.c modules/indic/indic-ot.[ch]:
+ Add support for 'init' feature for Bengali.
+ (#130966, Sayamindu Dasgupta)
+
+Fri Jul 30 17:17:05 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgpos.[ch] pango/opentype/ftxgsub.[ch]
+ pango/opentype/ftxopen.[ch]: Finish extending properties
+ flags from FT_UShort => FT_UInt. (OTLBuffer was already
+ using an FT_UInt)
+
+Fri Jul 30 14:05:25 2004 Owen Taylor <otaylor@redhat.com>
+
+ Improve handling of decomposed two-part vowels
+ (#121882, Jungshik Shin)
+
+ * modules/indic/indic-ot-class-tables.c (stateTable):
+ allow a dependent vowel to be followed by another
+ dependent vowel.
+
+ * modules/indic/indic-ot.c (indic_ot_reorder): Handle
+ multiple vowel matras.
+
+Fri Jul 30 13:33:49 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot.c (indic_ot_reorder): Suppress
+ blwf on the first consonant in a syllable. (#118301,
+ Taneem Ahmed)
+
+Thu Jul 29 16:10:06 2004 Owen Taylor <otaylor@redhat.com>
+
+ Fix Malayalam double-consonant conjuncts: #121671, Rajkumar S
+
+ * modules/indic/indic-ot.[ch]: Add a new feature
+ set pstf_p and use it for post-base consonants, since
+ the existing nukt_p suppressed the pstf feature.
+ (#121671, Rajkumar S)
+
+ * modules/indic/indic-ot-class-tables.c (mlymCharClasses):
+ make U+D2F (MALAYALAM LETTER YA) _pb not _ct.
+
+ * modules/indic/indic-ot-class-tables.c (mlymCharClasses):
+ Classify U/UU/VOCALIC R as _dr not _db since they should
+ be ordered after post-base consonants.
+
+Wed Jul 28 17:00:23 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/mprefixups.c (indic_mprefixups_apply):
+ Check glyphs[mpreLimit] not glyphs[mpreIndex]. (Found
+ by Chris Blizzard)
+
+Wed Jul 28 09:49:29 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_ellipsize): Fix
+ API docs. (#148627, Keith Sharp)
+
+Tue Jul 27 14:07:44 2004 Behdad Esfahbod <pango@behdad.org>
+
+ * modules/arabic/arabic-fc.c: Don't substitute FARSI YEH
+ with ARABIC YEH if the font does not have any ARABIC YEH.
+
+Tue Jul 27 12:38:05 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxopen.[ch] pango/opentype/ftxgsub.c
+ pango/opentype/ftxpos.c: Save the order in which
+ features were added and use that when applying features.
+ (Patch from Soheil Hassas Yeganeh, #122330)
+
+Tue Jul 27 09:11:40 2004 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/opentype/ftxgpos.c: Remove the unused parameter
+ from the IN_CURITEM() and IN_CURGLYPH macros.
+
+Tue Jul 27 06:35:25 2004 Behdad Esfahbod <pango@behdad.org>
+
+ * pango/opentype/otlbuffer.c (otl_buffer_copy_output_glyph):
+ Fix bug to copy glyph from in_string, not out_string.
+
+Mon Jul 26 19:11:46 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgdef.c: Fix allocation and indexing
+ in NewGlyphClasses array. (#130661, Masatake YAMATO)
+
+Mon Jul 26 15:55:03 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (get_glyph_extents_missing):
+ mini_width/height are still (before render patch) in
+ pixels, not Pango units.
+
+Mon Jul 26 15:24:11 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (ADD_Glyph): Remove the
+ unused parameter from the IN_CURITEM() and IN_CURGLYPH
+ macros.
+
+Mon Jul 26 15:21:23 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c: Add missing macro to make the
+ last change actually compile.
+
+Mon Jul 26 15:16:07 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c (Lookup_ChainContextSubst[123]):
+ Match backtrack context against the output glyphs not
+ the input glyphs (#145174, Aamir Wali)
+
+Mon Jul 26 14:49:22 2004 Owen Taylor <otaylor@redhat.com>
+
+ * ftxgdef.[ch] otlbuffer.[ch]: Make Check_Property() take a
+ OTL_GlyphItem, add a gproperties field to OTLGlyphItem,
+ and use that to cache the properties for a glyph.
+
+ * ftxgsub.c ftxgdef.c: Adapt to Check_Property() changes.
+
+ * otlbuffer.[ch] ftxgsub.c: Add otl_buffer_copy_output_glyph()
+ to use when we are copying an unmodified glyph from input
+ to output that preserves the cached properties.
+
+2004-07-23 Morten Welinder <terra@gnome.org>
+
+ * examples/renderdemo.c (parse_ellipsis): Fix C99ism. I am clearly
+ the last man stuck in the dark age of C.
+
+Tue Jul 20 12:10:42 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-script.c (pango_language_includes_script):
+ return TRUE for PANGO_SCRIPT_COMMON and PANGO_SCRIPT_INHERITED.
+
+Mon Jul 19 16:48:23 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.5.1 ===
+
+ * configure.in: Pango 1.5.1
+
+ * NEWS: Updates
+
+Mon Jul 19 17:09:11 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/disasm.c: Add support for
+ ChainContextSubstFormat3.
+
+Mon Jul 19 16:29:45 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/ftxgsub.c pango/opentype/ftxgpos.c:
+ Fix pervasive buffer overruns when skipping glyphs
+ when matching contexts. (#118592, Kailash C. Chowksey)
+
+Fri Jul 16 10:29:40 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.c pango/pangofc-private.h
+ (pango_fc_font_get_raw_extents): Need to export this
+ function as a symbol if not in the header file since
+ it is used by PangoXft.
+
+Fri Jul 16 07:43:04 2004 Owen Taylor <otaylor@redhat.com>
+
+ #143601: Felipe Heidrich
+
+ * pango/pango-layout.c (pango_layout_line_x_to_index):
+ Go into painful detail about the behavior for X positions
+ outside the line.
+
+ * pango/pango-layout.c (pango_layout_xy_to_index):
+ Add some more details about handling of positions
+ outside the layout, reference
+ pango_layout_line_x_to_index().
+
+Thu Jul 15 10:48:01 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.c (pango_fc_font_get_glyph): Replace
+ non-breaking-space with a normal space before looking it up.
+ (Inspired by http://bugzilla.ximian.com/show_bug.cgi?id=60549)
+
+Wed Jul 14 17:47:38 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.[ch] pango/ellipsize.c pango/Makefile.am:
+ Add PangoEllipsizeMode, pango_layout_set_ellipsize(), implement.
+ (#59071)
+
+ * pango/pango-layout-private.h pango/pango-layout.c:
+ Move PangoLayout structure into a separate header file.
+
+ * pango/pango-glyph-item.[ch]: Add pango_glyph_item_free().
+
+ * pango/pango-glyph-item-private.h pango/pango-glyph-item.c:
+ Internally export the PangoGlyphItemIter functionality.
+
+ * examples/renderdemo.[ch]: Add --ellipsize option.
+
+Wed Jul 14 17:42:49 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-script.c (pango_language_includes_script):
+ Fix problem when we only figured out latin script for 'en'
+ not for 'en-us'. Fix reversed arguments to bsearch.
+
+Tue Jul 13 16:23:15 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-types.h pango/pango-utils.c
+ docs/pango-sections.txt: Add a GType for PangoMatrix
+ (#145532, Torsten Schoenfeld)
+
+Tue Jul 13 14:12:06 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-render.c (compare_points): Make
+ static. (#147512, Morten Welinder)
+
+Tue Jul 13 10:07:44 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am: Reverse order of pangoft2/pangoxft
+ in Makefile; apparently automake doesn't figure out
+ the correct installation order. (#146472)
+
+Tue Jul 13 10:02:53 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c (pango_language_get_sample_string):
+ Make table constant. (#145515, Morten Welinder)
+
+2004-07-12 Morten Welinder <terra@gnome.org>
+
+ * pango/pangoxft-font.c (get_glyph_extents_xft): Fix C99ism.
+ (#147415, self.)
+
+2004-07-12 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-fc.c (render_basic): Render U+00A0
+ (non-break-space) as a space.
+
+Sat Jul 10 18:06:21 2004 Owen Taylor <otaylor@redhat.com>
+
+ * examples/renderdemo.[ch] examples/Makefile.am
+ examples/pangoft2topgm.c: Split most of the guts
+ of pangoft2topgm.c into separate source files
+ to allow creation of new rendering demos for
+ different backends.
+
+Sat Jul 10 18:03:58 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_new_font):
+ Const-ification fix.
+
+Sat Jul 10 17:55:03 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-types.h pango/pango-utils.c (pango_matrix_concat):
+ One more constification.
+
+Sat Jul 10 17:45:05 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-private.h: Add _pango prefix for
+ _pango_ft2_font_get_cache_glyph_data and friends
+ defined only in private header file.
+
+Sat Jul 10 17:33:38 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-private.h pango/pangoft2-render.c
+ pango/pango-context.[ch] pango/pangoft2.[ch] pango/pango-utils.
+ pango/pango-types.h pango/pangofc-fontmap.c: Make PangoMatrix
+ arguments const where appropriate.
+
+ * pango/pango-context.c pango/fonts.c pango/pangofc-font.c
+ pangofc-fontmap.c pango/pangoft2.c pango/pangoft2-fontmap.c
+ pango/pangoxft-font.c pango/pangoxft-fontmap.c
+ pango/pangowin32-fontmap.c: Use G_DEFINE_TYPE comprehensively.
+
+ * pango/pangoft2-private.h pangoft2.c: Un-staticify
+ pango_ft2_font_get_type.
+
+Sat Jul 10 16:55:46 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.h (struct _PangoFcFont):
+ s/hinted/is_hinted/ s/transform/is_transformed/.
+
+Sat Jul 10 16:39:44 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.[ch]: Add hinted/transform flags
+ to the font structure to allow efficient conditionalization
+ of behavior rather than repeatedly extracting the information
+ from the FcPattern.
+
+ * pango/pangofc-font.c pango/pangofc-private.h pango/pangoft2.c:
+ Move the glyph metrics computation into a
+ _pango_fc_font_get_raw_extents() function that can be
+ shared with the Xft backend.
+
+ * pango/pangoxft.c: When a transform is in effect, don't
+ get glyph extents from Xft ... they are device space
+ and not useful, use _pango_fc_font_get_raw_extents() instead.
+
+Fri Jul 9 15:23:39 2004 Manish Singh <yosh@gimp.org>
+
+ * pango/pango-ot.h: Add declaration for pango_ot_buffer_set_rtl.
+
+2004-07-08 Owen Taylor <otaylor@redhat.com>
+
+ * pango/break.c: Add missing row for the WORD_JOINER
+ class. (#145833, Billy Biggs)
+
+Thu Jul 8 15:25:29 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.[ch]: Add pango_context_get_font_map()
+
+ * pango/pango-fonts.c pango/pango-fontset.c pango/pango-context.c:
+ Some s/PangoMetrics/PangoFontMetrics/ in docs.
+
+ * pango/pango-context.c: Fix problem with unsetting
+ the matrix for a context.
+
+ * pango/pango-types.h: Switch to a much more efficient
+ implementation of PANGO_SCALE.
+
+2004-07-07 Morten Welinder <terra@gnome.org>
+
+ * pango/pango-layout.c (process_item): Add letter spacing
+ correction to the last character, not the one just beyond the
+ table. (#145517, self.)
+
+Thu Jun 24 14:07:10 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.5.0 ===
+
+ * NEWS: Updated
+
+Thu Jun 24 13:35:03 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-glyph-item.c (pango_glyph_item_apply_attrs):
+ Fix double cluster increment.
+
+Thu Jun 24 00:50:46 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_run_get_extents): Fix
+ bug with using wrong uline value.
+
+Wed Jun 23 17:26:50 2004 Owen Taylor <otaylor@redhat.com>
+
+ * tests/Makefile.am (pango.modules): Don't generate
+ all-unicode.txt when cross-compiling. (#135503,
+ J. Ali Harlow)
+
+Wed Jun 23 16:51:51 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.[ch]: Add PANGO_TYPE_LAYOUT_ITER.
+ (#138408, Johan Dahlin)
+
+Wed Jun 23 16:13:53 2004 Owen Taylor <otaylor@redhat.com>
+
+ #143693, Sayamindu Dasgupta
+
+ * pango/opentype/pango-ot-buffer.c (pango_ot_buffer_set_zero_width_marks) pango/opentype/pango-ot-private.h:
+ Allow setting for whether marks should be given zero width,
+ defaulting to FALSE.
+
+ * modules/arabic/arabic-fc.c (arabic_engine_shape): Turn
+ on zero-width-marks setting.
+
+Wed Jun 23 11:17:51 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.[ch]: Add new letter_spacing
+ attribute.
+
+ * pango/pango-attributes.c (pango_attr_rise_new): Correct
+ description; rise is in Pango units, not em-relative.
+
+ * pango/pango-glyph-item.c: Break out iteration-over-clusters
+ from ApplyAttrsState into a separate GlyphItemIter.
+
+ * pango/pango-glyph-item.[ch]: New function
+ pango_glyph_item_letter_space() to add add letter spacing
+ to a single glyph item.
+
+ * pango/pango-markup.c: Add a letter_spacing attribute.
+
+ * pango/pango-layout.c: Use G_DEFINE_TYPE().
+
+ * pango/pango-layout.c (pango_layout_get_item_properties):
+ Switch to use a structure rather than a pile of out
+ parameters.
+
+ * pango/pango-layout.c (pango_run_get_extents): Remove
+ the unused shape_set out parameter.
+
+ * pango/pangofc-decoder.[ch] pango/pangofc-fontmap.[ch]:
+ Doc fixes.
+
+ * pango/pango-types.h: Deprecate pango_get_mirror_char()
+
+ * pango/pango-utils.c (pango_get_mirror_char): Add docs.
+
+ * docs/pango-sections.txt docs/pango-docs.sgml: Add
+ PangoFcDecoder and letter spacing.
+
+Tue Jun 22 14:10:41 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/break.c: Handle new Unicode-4.0 WORD_JOINER
+ and NEXT_LINE classes. (#143436, Jeroen Zwartepoorte)
+
+ * pango/break.c (pango_default_break): Handle space
+ followed by a combining character as called for by
+ TR 14.
+
+ * tests/testboundaries.c (check_line_char): Fix up
+ for space+combining mark
+
+ * pango/break.c (pango_default_break): Change fixme
+ for G_UNICODE_BREAK_SURROGATE to g_assert_not_reached().
+
+Tue Jun 22 10:39:32 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-render.c (_pango_ft2_draw_error_underline,
+ _pango_ft2_draw_rect): Allow %NULL for @matrix.
+ (#144775, Diego González)
+
+Mon Jun 21 16:02:04 2004 Owen Taylor <otaylor@redhat.com>
+
+ #143556, Noah Misch
+
+ * pango/Makefile.am: Add $(no_undefined) when building libpangox,
+ libpangoxft for cygwin builds.
+
+ * modules/basic/Makefile.am (pango_basic_x_la_LDFLAGS):
+ Add $(no_undefined) for basic-x module.
+
+ * pango/Makefile.am: Add $(GLIB_LIBS) for pangox, pangoxft,
+ for benefit of cygwin, AIX, etc.
+
+Mon Jun 21 15:26:44 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (update_attr_iterator): Initialize
+ state->lang from context->language if not otherwise set.
+ Without doing this, the default language tag was, not
+ suprisingly, having no effect! (#137334, Frederic Zhang)
+
+ * pango/pango-attributes.c (pango_attr_iterator_get_font):
+ Fix typo in doc comment.
+
+Mon Jun 21 14:42:02 2004 Owen Taylor <otaylor@redhat.com>
+
+ * docs/pango_markup.sgml: use x-large instead of 100
+ in the markup example. (#142355, Doug Quale).
+ Fix the 'size' documentation to say 1024ths rather
+ than 1000ths. Document using font_desc='12.5' instead.
+
+Mon Jun 21 14:34:34 2004 Owen Taylor <otaylor@redhat.com>
+
+ #142355, Sven Neumann
+
+ * pango/pangoft2.c (pango_ft2_font_get_face): Mention
+ pango_fc_font_lock/unlock face as the correct
+ replacements.
+
+ * pango/pangofc-font.h: Move lock/unlock_face outside
+ of the #ifdef PANGO_ENABLE_ENGINE.
+
+Mon Jun 21 14:23:05 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (no_shape_filter_func)
+ pango/pango-script.c (get_pair_index):
+ pango/modules.c (append_engines): Fix
+ some missing statics. (#142237, Morten Welinder)
+
+ * pango/mini-fribidi/fribidi_types.c: Move
+ fribidi_type_name inside the #ifdef DEBUG.
+
+Mon Jun 21 13:55:17 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/otlbuffer.c: Use the gcc-3.3
+ strict-aliasing compatible macros from fterrcompat.h
+ (#140495, reported by Stanislav Brabec)
+
+Mon Jun 21 11:47:41 2004 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in pango.pc.in: Missed commit: add
+ -lm dependency to pkg-config files.
+
+ * docs/pango-sections.txt: Add PangoMatrix and rotated
+ rendering functions
+
+Mon Jun 21 11:41:18 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.c (pango_attr_list_change):
+ Fix leak when inserting an empty attributes. (#140771,
+ Morten Welinder)
+
+Mon Jun 21 11:38:22 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (pango_context_set_font_map):
+ Handle setting the same object back. (#143523,
+ Morten Welinder)
+
+Mon Jun 21 11:35:29 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_new):
+ Revert the last change, assert that initialization
+ succeeded.
+
+Mon Jun 21 11:29:39 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_new):
+ For cleanliness, unref the fontmap if we get an error
+ from FreeType. (#143524, Morten Welinder)
+
+ * pango/pangoft2-fontmap.c (pango_ft2_font_map_finalize):
+ Deal with NULL ft2fontmap->library.
+
+2004-06-17 Christopher Blizzard <blizzard@redhat.com>
+
+ * pango/pangofc-decoder.c (pango_fc_decoder_get_glyph,
+ pango_fc_decoder_get_charset): Changes to support extra arguments.
+
+ * pango/pangofc-decoder.h (struct _PangoFcDecoderClass): Add the
+ PangoFcDecoder * as the first argument to the callbacks for
+ get_glyph and get_charset.
+
+Wed Jun 9 17:32:59 2004 Christopher Blizzard <blizzard@redhat.com>
+
+ * pango/Makefile.am: Add export of pangofc-decoder.h. Build
+ pangofc-decoder.c.
+
+ * pango/pangofc-decoder.h pango/pangofc-decoder.c: New files.
+ Virtual base class for any custom font decoders.
+
+ * pango/pangofc-font.c: Add new PangoFcFontPrivate structure.
+
+ * pango/pangofc-font.c (pango_fc_font_class_init): Attach new
+ private structure using g_type_class_add_private().
+
+ * pango/pangofc-font.c (pango_fc_font_finalize): Make sure to
+ unset any decoders that are attached to the font.
+
+ * pango/pangofc-font.c (pango_fc_font_get_coverage): When
+ determining coverage, use a custom decoder if available.
+
+ * pango/pangofc-font.c (pango_fc_font_has_char): When determining
+ if a font has a character, use a custom decoder if available.
+
+ * pango/pangofc-font.c (pango_fc_font_get_glyph): When doing
+ single character to glyph convertions, use a custom decoder if
+ available.
+
+ * pango/pangofc-font.c (_pango_fc_font_get_decoder): New
+ function. Get the custom decoder for the given font.
+
+ * pango/pangofc-font.c (_pango_fc_font_set_decoder): New
+ function. Set a custom decoder for the given font.
+
+ * pango/pangofc-fontmap.c: Add structure PangoFcFindFuncInfo to
+ keep track of callbacks to create custom decoders. Modify
+ PangoFcFontMapPrivate by adding a list of PangoFcFontFuncInfo
+ callbacks that have been registered.
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_add_find_func): New
+ function. Add callbacks to the fontmap that will create custom
+ decoders when pango creates new fonts.
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_finalize): Clear out
+ any findfuncs that have been registered and notify them about
+ destruction.
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_new_font): When
+ creating new fonts, call back to any registered find functions so
+ they can create custom decoders for those fonts. Attach those
+ custom decoders to the newly created fonts.
+
+ * pango/pangofc-fontmap.c (_pango_fc_font_map_get_coverage):
+ Change the argument to take a PangoFcFont instead of an FcPattern.
+ Call _pango_fc_font_map_fc_to_coverage instead of doing the
+ conversion inline.
+
+ * pango/pangofc-fontmap.c (_pango_fc_font_map_fc_to_coverage): New
+ function. Convert an FcCharSet to a PangoCoverage object.
+
+ * pango/pangofc-fontmap.h: New declarations for
+ pango_fc_font_map_add_decoder_find_func and
+ PangoFcDecoderFindFunc.
+
+ * pango/pangofc-private.h: New declarations for
+ _pango_fc_font_map_fc_to_coverage, _pango_fc_font_get_decoder and
+ _pango_fc_font_set_decoder.
+
+Mon Jun 7 2004 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * modules/thai/Makefile.am modules/thai/thai-shaper.c
+ (thai_engine_shape) +modules/thai/thai-ot.c +modules/thai/thai-ot.h:
+ Add OpenType support in Thai module. (#141541)
+
+Wed Jun 2 10:07:06 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-types.h (PANGO_MATRIX_INIT): Remove
+ stray semi-colon. (#143516, Morten Welinder)
+
+Mon May 31 07:39:01 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-utils.c pango/pango-types.h (pango_matrix_concat):
+ Fix 'new' as parameter name (C++ compatibility issue).
+ (#143430, David Hawthorne)
+
+Fri May 28 11:39:39 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-types.h pango/pango-utils.c: Add PangoMatrix
+ type for affine transforms.
+
+ * configure.in pango.pc.in pango/Makefile.am: Add a -lm
+ dependency for PangoMatrix operations.
+
+ * pango/pango-context.[ch]: Add pango_context_set/get_matrix().
+
+ * pango/pangoft2-render.c pango/pangoft2-private.h: Add
+ code for drawing antialiased transformed rectangles and
+ squiggly error underlines.
+
+ * pango/pangoft2.[ch]: Add pango_ft2_render_transformed(),
+ pango_ft2_render_layout_subpixel(),
+ pango_ft2_render_layout_line_subpixel(), implement transformed
+ rendering.
+
+ * pango/pangofc-font.c: Pass any transformation matrix on to
+ fontconfig when creating the pattern for a PangoFcFont.
+
+Fri May 28 2004 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * pango/opentype/pango-ot-buffer.c (apply_gpos_ltr): Negate y offset
+ according to different conventions between PangoGlyphString and OTL
+ (#142544)
+
+Thu May 27 17:54:24 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/otlbuffer.c: Revert error return changes
+ from last commit.
+
+Thu May 27 16:57:30 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/otlbuffer.c: Free buffer->positions,
+ clean up error returns that were returning uninitialized
+ values. (#139239, Behdad Esfahbod)
+
+Thu May 27 15:42:20 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangox-fontmap.c pango/pangox.c: Add some missing
+ statics. (#142299, Morten Welinder)
+
+Thu May 27 15:32:03 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-font.h pango/fonts.c: Add underline and
+ strikethrough position and thickness metrics.
+
+ * pango/pangofc-font.c: Implement underline and strikethrough
+ position and thickness metrics.
+
+ * pango/pango-fontset.c (pango_fontset_real_get_metrics):
+ Initialize metrics from the metrics of the first font
+ in the fontset.
+
+Thu May 27 15:08:32 2004 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Increment version to 1.5 for devel branch.
+
+2004-05-06 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * pango/break.c (pango_break):
+ Fix incorrect casts to get the class object of lang engine. (#141931)
+
+2004-04-29 Jody Goldberg <jody@gnome.org>
+
+ * pango/pango-layout.c (get_alignment) : only invert if the layout and
+ the context really disagree, not if they are WEAK_LTR vs LTR
+
+2004-03-11 Jody Goldberg <jody@gnome.org>
+
+ * pango/pango-attributes.h : Add a comment clarifying that
+ PangoAttribute::end_index is _exclusive_. The range is [start..end)
+ Additionally clarify that that the indicies are in _bytes_ not
+ characters.
+
+2004-04-29 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_for_display):
+ Use floating-point math in resolution calculation. (#141229, John
+ Ehresman)
+
+ * pango/pangowin32-fontmap.c (pango_win32_insert_font): Don't leak
+ family_name. (#140772, John Ehresman)
+
+2004-04-20 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * modules/thai/thai-shaper.c (get_adjusted_glyphs_list):
+ * modules/thai/thai-fc.c (tis620_2):
+ Use dottedcircle as the base for individual combining characters.
+
+2004-04-18 Changwoo Ryu <cwryu@debian.org>
+
+ * modules/hangul/hangul-defs.h (IS_JAMO):
+ * modules/hangul/hangul-fc.c (hangul_engine_shape, render_basic):
+ handle non-Hangul unicode chars, fixes #129741, #137347.
+
+2004-04-05 Anders Carlsson <andersca@gnome.org>
+
+ * examples/argcontext.c (arg_context_parse):
+ Handle '--' correctly.
+
+Local Variables:
+coding: utf-8
+End:
+vim: encoding=utf-8:
diff --git a/trunk/ChangeLog.pre-1-8 b/trunk/ChangeLog.pre-1-8
new file mode 100644
index 00000000..341256f3
--- /dev/null
+++ b/trunk/ChangeLog.pre-1-8
@@ -0,0 +1,488 @@
+Wed Dec 15 23:49:14 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.8.0 ===
+
+ * configure.in: Version 1.8.0
+
+ * NEWS: Update.
+
+ * README: Updates.
+
+Wed Dec 15 23:13:57 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/basic/basic-win32.c (uniscribe_shape): Emergency
+ fix for #151068... if uniscribe shaping comes up with
+ no glyphs, fall back to non-uniscribe shaping.
+
+Wed Dec 15 22:09:42 2004 Owen Taylor <otaylor@redhat.com>
+
+ Add pixel sizes for fonts (#119081, patch from Chris Lahey)
+
+ * pango/fonts.c pango/pango-font.h:
+ Add pango_font_description_set_absolute_size(),
+ pango_font_description_get_size_is_absolute()
+
+ * pango/pango-attributes.[ch]: Add pango_attr_size_new_absolute(),
+ change PANGO_ATTR_SIZE from PangoAttrInt to PangoAttrSize
+ (preserves compat because first component is identical)
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_load_font):
+ For absolute sizes, convert pixels to points, before
+ calling pango_win32_font_new().
+
+ * pango/pangofc-fontmap.c pango/pangoft2.c pango/pangoxft-font.c:
+ Handle absolute sizes.
+
+Wed Dec 15 18:50:18 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-fc.c modules/indic/indic-ot.h:
+ Force zero-width marks to glyph index 0 so they
+ won't be drawn. (#145233, Aniruddha Shankar)
+
+Wed Dec 15 11:15:37 2004 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in modules/Makefile.am modules/tibetan/*:
+ Add simple tibetan module. (#148566, G Karunakar)
+
+Wed Dec 15 08:38:52 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c: Split
+ U+DDE as U+DD9, U+DDF.
+
+Tue Dec 14 20:44:53 2004 Owen Taylor <otaylor@redhat.com>
+
+ Sinhala support (#153517, Anuradha Ratnaweera)
+
+ * modules/indic/indic-ot.h modules/indic/indic-fc.c
+ modules/indic/indic-ot-class-tables.c: Add tables for Sinhala.
+
+ * modules/indic/indic-ot.c (indic_ot_reorder): Add handling
+ of Virama for two-part dependent vowels.
+
+Tue Dec 14 18:36:57 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_copy): Copy
+ layout->auto_dir. (#153547, Morten Welinder)
+
+Tue Dec 14 18:32:46 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/Makefile.am (libpangoft2_1_0_la_LIBADD): Add $(libm),
+ needed for no-undefined platforms like AIX. (#160773,
+ Vincent Berger)
+
+Tue Dec 14 18:08:36 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-font.h: Add PANGO_WEIGHT_SEMIBOLD.
+ (#86957, Lars Clausen)
+
+ * pango/fonts.c: s/600/PANGO_WEIGHT_SEMIBOLD.
+
+ * pango/pangofc-fontmap.c (pango_fc_convert_weight_to_fc)
+ * pango/pangofc-fontmap.c (pango_fc_convert_weight_to_pango):
+ Handle PANGO_WEIGHT_SEMIBOLD, use additional weights added
+ in fontconfig-2.2.
+
+2004-12-14 Dan Winship <danw@novell.com>
+
+ * examples/Makefile.am (INCLUDES): add XFT_CFLAGS
+
+Tue Dec 14 17:27:14 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/indic-ot-class-tables.c (guruCharClasses):
+ Add the correct char classes for Unicode-4.0 characters
+ U+A01, U+A03. (#158943, Sukhjinder Sidhu)
+
+2004-12-14 Matthias Clasen <mclasen@redhat.com>
+
+ * pango.pc.in: Require gmodule-no-export
+
+ * configure.in: Use gmodule-no-export-2.0.pc, require glib 2.5.7
+
+2004-12-14 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.c (pango_win32_font_get_metrics): Set also
+ underline and strikethrough position and thickness. (#161205)
+
+Mon Dec 13 14:44:40 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.[ch] pango/pango.def docs/pango-sections.txt:
+ Add pango_layout_get_font_description. (#153548, Morten Welinder)
+
+ * pango/pango-layout.c (pango_layout_set_font_description):
+ Guard against the same description being set back.
+
+2004-12-12 Tor Lillqvist <tml@iki.fi>
+
+ * pango/modules.c (read_modules)
+ * pango/pango-utils.c (read_alias_file,read_config_file): Use
+ gstdio wrappers. (#16111, Robert Ögren)
+
+ * pango/pangoft2-fontmap.c: Remove unneded includes of <dirent.h>
+ and <windows.h>.
+
+Fri Dec 10 16:30:40 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-render.c (draw_glyph): Fix problem
+ where the font would get unset after flushing at MAX_GLYPHS.
+ (#160978)
+
+Thu Dec 2 15:47:44 2004 Owen Taylor <otaylor@redhat.com>
+
+ * === Released 1.7.0 ===
+
+ * NEWS: Update.
+
+Thu Dec 2 15:31:33 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/break.c (pango_default_break): Ignore formatting
+ characters when determining word boundaries (Part of
+ #97545, Behdad Esfahbod)
+
+2004-11-30 Matthias Clasen <mclasen@redhat.com>
+
+ * pango/pango-renderer.c (pango_renderer_default_prepare_run): Set
+ the background color instead of setting underline twice.
+
+2004-11-28 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ Add Lao support to Thai module. (#156781)
+
+ * modules/thai/Makefile.am modules/thai/thai-shaper.[ch]
+ +modules/thai/thai-charprop.[ch]: Split WTT tables into a separate
+ source. Extend the tables for Lao. 3 new classes are added (AM for
+ SaraAm, AD4 for Nikkhahit, BCON for Lao semivowels). Now the range
+ 0x00-0x7f in TIS is used to store Lao characters. Rewrite ucs2tis()
+ et al macros accordingly.
+
+ * modules/thai/thai-shaper.c (get_next_cluster): Rewrite the
+ clusterization code, so it's not specific to Thai-English texts. (Note
+ that the special case of SaraAm is now handled by the new WTT character
+ class. So, the extra checks are now eliminated.)
+
+ * modules/thai/thai-shaper.c (get_glyphs_list, add_cluster):
+ Add glyph calculation for Lao clusters.
+
+ * modules/thai/thai-shaper.c (ThaiShapeTable structs,
+ get_adjusted_glyphs_list): Generalize the shaping maps according to
+ the new 8-bit internal encoding scheme. Now the character ranges are
+ relocatable rather than hard-coded. Add Lao shaping table.
+
+ * modules/thai/thai-shaper.c (get_adjusted_glyphs_list): Add special
+ case for Lao, where clusters can be longer than those of Thai.
+
+ * modules/thai/thai-fc.c (get_glyph_index_tis): Add Lao glyphs lookup.
+
+ * modules/thai/thai-ot.c (thai_ot_shape, +lao_ot_get_ruleset): Add Lao
+ OT rulesets retrieval.
+
+ * modules/thai/thai-fc.c (PangoEngineScriptInfo thai_scripts[]):
+ Add Lao script entry.
+
+Thu Nov 25 14:10:53 2004 Manish Singh <yosh@gimp.org>
+
+ * autogen.sh: rm autom4te.cache, since it might interfere with
+ differing autoconf versions.
+
+Tue Nov 23 10:23:43 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-attributes.[ch]: Add underline_color
+ and strikethrough_color attribute types. (#147616, Morten
+ Welinder)
+
+ * pango/pango-markup.c docs/pango_markup.sgml: Add
+ corresponding 'underline_color' and
+ 'strikethrough_color' attributes for <span>.
+
+ * pango/pango-renderer.c (pango_renderer_default_prepare_run):
+ Implement underline and strikethrough colors.
+
+ * pango/pango-renderer.c: Fix some bigs with updating
+ underlines/strikethrough state.
+
+ * pango/pango-renderer.c (get_total_matrix): Fix a const
+ warning.
+
+ * docs/pango-sections.txt: Update
+
+Mon Nov 22 15:53:37 2004 Manish Singh <yosh@gimp.org>
+
+ * modules/thai/Makefile.am: Remove stray 'x' character.
+
+Mon Nov 22 18:30:14 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/opentype/Makefile.am pango/Makefile.am
+ modules/*/Makefile.am: Set G_LOG_DOMAIN (#151923,
+ Hans Breuer)
+
+Mon Nov 22 15:21:11 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/syriac configure.in modules/Makefile.am
+ modules/makefile.msc: Add Syriac module by Emil
+ Soleyman-Zomalan. (#147779)
+
+ * examples/Makefile.am examples/syriac.utf: Syriac
+ example text.
+
+2004-11-21 Hans Breuer <hans@breuer.org>
+
+ * pango/makefile.msc : updated
+
+ * pango/pangowin32.[ch] pango/pangowin32.def : implement
+ pango_win32_render_transformed() by using the transformation
+ capabilities of GDI (not available on win9x)
+
+Sun Nov 21 11:43:00 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/break.c: Turn off backspace-deletes-character behavior
+ for Kana and Hangul. It's wrong for Kana, and for Hangul it's
+ theoretically right but interacts badly with current input
+ methods. (#155897, Leon Ho)
+
+Sun Nov 21 11:40:03 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_get_log_attrs): Return n+1
+ logical attributes not n logical attributes (#155912)
+
+Sun Nov 21 10:52:03 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c: Don't just call pango_fontset_get_metrics()
+ to implement pango_context_get_metrics(), since that skips our
+ normal font selection algorithm. Rather itemize the sample string
+ and get the metrics from that. (#149438, Felipe Heidrich)
+
+Sun Nov 21 10:46:34 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_set_text): Fix UTF8 => UTF-8
+ in warning and doc comment. (#153551, Morten Welinder)
+
+Sat Nov 20 23:50:40 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (get_glyph_extents_missing): Fix double
+ multiplication by PANGO_SCALE. (#157419, Matthias Clasen)
+
+ * pango/pangoxft-render.c (box_in_bounds): Fix sign typo.
+
+ * pango/pangoxft-render.c (pango_xft_renderer_draw_glyphs):
+ * pango/pangoxft-font.c (get_glyph_extents_missing):
+ Adjust vertical positioning so that we get integral positioning of
+ the box without a transform.
+
+Fri Nov 19 18:45:24 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-renderer.c (pango_renderer_default_draw_error_underline):
+ Fix crash when renderer->matrix is NULL.
+
+Fri Nov 19 17:44:33 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-renderer.[ch]: Remove color_set() virtual
+ function ... it's not absolutely necessary for chaining
+ renderers, and it's not clear that chaining renderers
+ is actually useful, anyways.
+
+ * pango/pango-renderer.[ch] (pango_renderer_set_color): Constify
+ color argument.
+
+ * pango/pango-render.c: Fix various bugs.
+
+ * pango/pango-attributes.[ch] (pango_attr_shape_new_with_data):
+ Add the ability to create a shape attribute with user data.
+
+ * pango/pango-renderer.[ch] (PangoRendererClass): Add a draw_shape
+ virtual function, to draw content for PangoAttrShape.
+
+ * pango/pangoxft-fontmap.c (pango_xft_shutdown_display):
+ Add note to docs that XCloseDisplay() will automatically take care
+ of releasing Pango's allocated resources for the display.
+
+ * docs/Makefile.am (SCAN_OPTIONS): Add the appropriate
+ --deprecated-guards option.
+
+ * docs/tmpl/xft-fonts.sgml: Add long description.
+
+ * docs/tmpl/x-fonts.sgml: Document as dead.
+
+2004-10-26 Matthias Clasen <mclasen@redhat.com>
+
+ * docs/tmpl/text-attributes.sgml: Document PANGO_UNDERLINE_ERROR
+ as a 1.4 addition. (#156533, Morten Welinder)
+
+2004-10-12 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * modules/thai/thai-shaper.h (thai_get_glyph_tis,
+ thai_make_glyph_tis): Use guchar instead of gchar as argument type.
+
+ * modules/thai/thai-fc.c (thai_get_glyph_tis, thai_make_glyph_tis):
+ Make *_tis functions wrappers to *_uni functions.
+
+2004-10-09 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ Explicitly handle dangling upper/lower marks by optionally using
+ dottedcircle as base, rather than requiring it.
+
+ * modules/thai/thai-shaper.h: Explicitly declare make_glyph and
+ get_glyph functions for 8-bit and Unicode chars as separate functions.
+
+ * modules/thai/thai-shaper.c (get_adjusted_glyphs_list): Rename
+ function calls to the new ones. Conditionally use dottedcircle glyph
+ as base for dangling upper/lower marks if available; simply expand
+ width to that of inkrect otherwise.
+
+ * modules/thai/thai-fc.c: Implement those new functions declared in
+ thai-shaper.h. Remove 0x25cc from tis620_2 glyph set.
+
+2004-10-08 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * modules/thai/thai-ot.c (thai_ot_get_ruleset): Return NULL if ruleset
+ is empty, to indicate the lack of OT features.
+
+ * modules/thai/thai-fc.c (tis620_1): Fix the PUA glyph table, after
+ actually checked with sample OSX (Jaguar) fonts. This actually turns
+ on PUA-based shaping with Thai OSX fonts in Pango.
+
+2004-10-07 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * modules/thai/thai-shaper.c (groups, group1_map, group2_map):
+ Remove unused data for XTIS.
+
+ * modules/thai/thai-shaper.[ch] (enum ThaiFontSet, get_glyphs_list),
+ modules/thai/thai-fc.c (thai_get_font_info, thai_make_glyph):
+ Remove THAI_FONT_ISO10646 font set, as it's already covered by
+ THAI_FONT_TIS.
+
+Sat Oct 2 10:08:13 2004 Manish Singh <yosh@gimp.org>
+
+ * modules/thai/thai-ot.c (thai_ot_get_ruleset): Use
+ g_return_val_if_fail() instead of g_return_if_fail() since this
+ function returns a value.
+
+2004-10-02 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ Make Thai module prefer OpenType tables, if available, to PUA
+ substitutions. (#153927)
+
+ * modules/thai/thai-ot.[ch]:
+ Merge get_gsub_ruleset() and get_gpos_ruleset() into an exported
+ function thai_ot_get_ruleset(). Rearrange thai_ot_shape() to call
+ it properly.
+
+ * modules/thai/thai-fc.c:
+ Try OT ruleset before PUA glyph sets.
+
+2004-09-25 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango.def: Add the new pango_renderer_* symbols.
+
+ * modules/basic/basic-win32.c (basic_engine_covers,
+ basic_engine_win32_class_init): Remove the implementation of the
+ covers method. It was wrong anyway, and unnecessary. No need to
+ override the default implementation. (#152997)
+
+Fri Sep 24 15:05:02 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-renderer.c (pango_renderer_draw_glyphs):
+ Activate the renderer.
+
+ * pango/pango-renderer.c (pango_renderer_get_color,
+ pango_renderer_draw_rectangle, pango_renderer_draw_trapezoid,
+ pango_renderer_draw_error_underline, pango_renderer_draw_glyph):
+ Require the renderer to be active.
+
+Fri Sep 24 12:59:22 2004 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Up version to 1.7.0.
+
+ * pango/pango-renderer.[ch] pango/pango.h pango/Makefile.am:
+ Add PangoRenderer, a base class that is subclassed to produce
+ rendering drivers for different backends and purposes.
+
+ * pango/pangoft2-private.h pango/pangoft2-render.c
+ pango/pangoft2.c: Move rendering into pangoft2-render.c,
+ use PangoRenderer.
+
+ * pango/pangoft2-fontmap.c pango/pangoft2-private.h: Add
+ _pango_ft2_font_map_get_renderer() to retrieve a singleton
+ fontmap for the fontmap.
+
+ * pango/pangoxft-render.[ch] pango/pangoxft.c pango/Makefile.am:
+ Make Xft rendering use PangoRenderer, add publically
+ visible, subclassable PangoXftRenderer.
+
+ * pango/pangoxft-fontmap.c pango/pangoxft-private.h: Add
+ _pango_xft_font_map_get_renderer() to retrieve a singleton
+ fontmap for the fontmap.
+
+ * examples/xftview.c examples/Makefile.am: Add a test program
+ using the Xft backend.
+
+ * docs/*: Update minimally for PangoRenderer.
+
+Wed Sep 22 16:15:40 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangoxft-font.c (pango_xft_font_get_glyph_extents): Use
+ get_glyph_extents_raw() when hinting is disabled as well
+ as when we are transforming. (#152529, Vincent Noel)
+
+ * pango/pangofc-font.c (pango_fc_font_get_raw_extents): Duplicate
+ the fix for non-scalable fonts from get_face_metrics() here as
+ well.
+
+Wed Sep 22 15:57:30 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-layout.c (pango_layout_get_ellipsize): Fix
+ typo in docs. (#153390, Paolo Borelli)
+
+Wed Sep 22 14:07:47 2004 Owen Taylor <otaylor@redhat.com>
+
+ Cleanups from 'sparse', #149922, Kjartan Maraas
+
+ * pango/pango-utils.c (read_config): () => (void) in
+ definition.
+
+ * pango/pangofc-fontmap.c (pango_fc_font_map_list_families):
+ Initialize *n_families, not n_families.
+
+ * pango/pangofc-fontmap.c pango/pangoft2.c opentype/ftxgdef.c
+ opentype/ftxgpos.c opentype/ftxgsub.c: : Fix various 0/NULL
+ confusion.
+
+Mon Sep 20 13:57:35 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/indic/mprefixups.c (indic_mprefixups_apply):
+ Fix various bugs, make more robust. (#151689, Arun M)
+
+Mon Sep 13 11:06:47 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/ellipsize.c (init_state): Initialize
+ ellipsis_is_cjk (#151901, Christian Persch)
+
+Mon Sep 13 10:18:51 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pango-context.c (itemize_state_process_run):
+ Except ideographic spaces from the !g_unichar_isgraph() test.
+ (#145275, Federic Zhang)
+
+Mon Sep 20 12:17:37 2004 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-font.c (get_face_metrics):
+ Don't use face->ascender/descender for non-scalable fonts,
+ since they aren't set. (#Enrico Scholz,
+ https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=129246)
+
+2004-09-18 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pango.def: Add pango_context_set_matrix. (#152883, Ivan
+ Wong)
+
+2004-09-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32-fontmap.c (pango_win32_insert_font): Ignore
+ fonts in SYMBOL_CHARSET. They don't have any Unicode mapping
+ table. (#149643)
+
+ * pango/querymodules.c (string_needs_escape, escape_string):
+ Escape also backslashes. (#152607, Kazuki Iwamoto)
+
+Local Variables:
+coding: utf-8
+End:
+vim: encoding=utf-8:
diff --git a/trunk/HACKING b/trunk/HACKING
new file mode 100644
index 00000000..dc02f5ee
--- /dev/null
+++ b/trunk/HACKING
@@ -0,0 +1,113 @@
+Formatting
+==========
+
+All parts of Pango other than modules should use the following formatting
+style; for modules, it is up to the discretion of the module
+author / maintainer, though they are encouraged to follow the following.
+
+The Pango formatting style is basically the GNU style of formatting
+(see http://www.gnu.org/prep/standards.html), with a few additions.
+In brief overview:
+
+ - Two character indents are used; braces go on a separate line, and
+ get a separate indentation level, so the total indent for an
+ enclosed block is 4 characters.
+
+ if (x < foo (y, z))
+ haha = bar[4] + 5;
+ else
+ {
+ while (z)
+ {
+ haha += foo (z, z);
+ z--;
+ }
+ return abc (haha);
+ }
+
+ - Spaces should be present between function name and argument block,
+ and after commas.
+
+ foo (z, z)
+
+ - In pointer types, the '*' is grouped with the variable name,
+ not with the base type.
+
+ int *a;
+
+ NOT: 'int* a'.
+
+ In cases where there is no variable name, for instance, return
+ values, there should be a single space between the base type
+ and the '*'.
+
+ - function and variable names are lower_case_with_underscores
+ type names are StudlyCaps, macro names are UPPER_CASE_WITH_UNDERSCORES
+
+
+Documentation comments
+======================
+
+All public API functions should have inline documentation headers
+in the gtk-doc / gnome-doc style. For instance:
+
+/**
+ * pango_layout_get_line:
+ * @layout: a #PangoLayout
+ * @line: the index of a line, which must be between 0 and
+ * pango_layout_get_line_count(layout) - 1, inclusive.
+ *
+ * Retrieves a particular line from a #PangoLayout (or @layout.)
+ *
+ * Return value: the requested #PangoLayoutLine, or %NULL if the
+ * index is out of range. This layout line can
+ * be ref'ed and retained, but will become invalid
+ * if changes are made to the #PangoLayout.
+ *
+ * Since: 1.6
+ **/
+PangoLayoutLine *
+pango_layout_get_line (PangoLayout *layout,
+ int line)
+[...]
+
+
+Choosing Function Names
+=======================
+
+- Don't abbreviate in unexpected ways:
+
+ pango_layout_get_line_count ()
+
+ Not:
+
+ pango_layout_ln_cnt ()
+
+- function that retrieve a value in a side-effect free fashion, should
+ include "get" in the name.
+
+ int pango_layout_get_line_count (PangoLayout *layout)
+
+ not
+
+ pango_layout_line_count ()
+
+
+- functions that set a single parameter in a side-effect free fashion
+ should include "set" in the name, for instance:
+
+ void pango_layout_set_width (PangoLayout *layout,
+ int width);
+
+Other comments
+==============
+
+- Avoid unsigned values for all but flags fields. This is because
+ the way C handles unsigned values generates bugs like crazy:
+
+ If width is unsigned and 10, then:
+
+ int new_width = MAX (width - 15, 1);
+
+ produces 4294967291, not 1.
+
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
new file mode 100644
index 00000000..3a8a2200
--- /dev/null
+++ b/trunk/MAINTAINERS
@@ -0,0 +1,4 @@
+Owen Taylor
+Email: otaylor@redhat.com
+Behdad Esfahbod
+Email: behdad@gnome.org
diff --git a/trunk/Makefile.am b/trunk/Makefile.am
new file mode 100644
index 00000000..cef144c9
--- /dev/null
+++ b/trunk/Makefile.am
@@ -0,0 +1,73 @@
+## Process this file with automake to create Makefile.in.
+
+SUBDIRS= pango modules pango-view examples docs tools tests
+
+EXTRA_DIST = \
+ autogen.sh \
+ pango.pc.in \
+ pangocairo.pc.in \
+ pangox.pc.in \
+ pangoxft.pc.in \
+ pangoft2.pc.in \
+ pangowin32.pc.in \
+ pango-uninstalled.pc.in \
+ pangocairo-uninstalled.pc.in \
+ pangox-uninstalled.pc.in \
+ pangoxft-uninstalled.pc.in \
+ pangoft2-uninstalled.pc.in \
+ pangowin32-uninstalled.pc.in \
+ ChangeLog.pre-1-0 \
+ ChangeLog.pre-1-2 \
+ ChangeLog.pre-1-4 \
+ ChangeLog.pre-1-6 \
+ ChangeLog.pre-1-8 \
+ ChangeLog.pre-1-10 \
+ ChangeLog.pre-1-12 \
+ ChangeLog.pre-1-14 \
+ MAINTAINERS \
+ HACKING \
+ README.win32 \
+ pango-zip.sh.in \
+ sanitize-la.sh
+MAINTAINERCLEANFILES = \
+ $(srcdir)/INSTALL \
+ $(srcdir)/aclocal.m4 \
+ $(srcdir)/autoscan.log \
+ $(srcdir)/compile \
+ $(srcdir)/config.guess \
+ $(srcdir)/config.h.in \
+ $(srcdir)/config.sub \
+ $(srcdir)/configure.scan \
+ $(srcdir)/depcomp \
+ $(srcdir)/install-sh \
+ $(srcdir)/ltmain.sh \
+ $(srcdir)/missing \
+ $(srcdir)/mkinstalldirs \
+ $(srcdir)/omf.make \
+ $(srcdir)/xmldocs.make \
+ `find "$(srcdir)" -type f -name Makefile.in -print`
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = pango.pc
+
+if HAVE_CAIRO
+pkgconfig_DATA += pangocairo.pc
+endif
+
+if HAVE_X
+pkgconfig_DATA += pangox.pc
+endif
+
+if HAVE_XFT
+pkgconfig_DATA += pangoxft.pc
+endif
+
+if HAVE_FREETYPE
+pkgconfig_DATA += pangoft2.pc
+endif
+
+if HAVE_WIN32
+pkgconfig_DATA += pangowin32.pc
+endif
+
+DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --disable-doc-cross-references
diff --git a/trunk/NEWS b/trunk/NEWS
new file mode 100644
index 00000000..6e3fb81d
--- /dev/null
+++ b/trunk/NEWS
@@ -0,0 +1,1636 @@
+Overview of changes between 1.17.4 and 1.17.5
+==============================================
+- Export PangoCairoFont and cleanup various standard macros.
+
+- Bugs fixed in this release:
+ Bug 150883 – Unicode LRO defect
+ Bug 449482 – Build error when xft not present
+ Part of Bug 347236 – provide pango_cairo_font_get_scaled_font
+
+Overview of changes between 1.17.3 and 1.17.4
+==============================================
+- Refactored the ATSUI font backend and install pangoatsui.h
+ that has a single function pango_atsui_font_get_atsu_font_id() and
+ a couple of types.
+
+- Bugs fixed in this release:
+ Bug 451547 – FAIL: runtests.sh
+ Bug 449543 - Ship pangoatsui.h
+
+Overview of changes between 1.17.2 and 1.17.3
+==============================================
+- Extensive pangocairo internal code refactoring and cleanup
+
+- New public API:
+
+ pango_font_face_is_synthesized()
+
+ pango_cairo_font_get_scaled_font()
+ pango_cairo_font_map_new_for_font_type()
+ pango_cairo_font_map_get_font_type()
+
+- New engine macros:
+
+ PANGO_OT_TAG_MAKE()
+ PANGO_OT_TAG_MAKE_FROM_STRING()
+
+- New PangoFontFace method is_synthesized.
+
+- Misc bug fixes
+- Bugs fixed in this release:
+ Bug 337593 – move glyph extents code (and cache) from
+ pangocairo-*font.c into pangocairo-font.c
+ Bug 347235 – Add pango_cairo_font_map_get_font_type
+ Bug 347236 – provide pango_cairo_font_get_scaled_font
+ Bug 353291 – Provide pango_cairo_font_map_new_for_font_type
+ Bug 438801 – underline should add "error" type.
+ Bug 440588 – Add pango_font_face_is_synthesized()
+ Bug 445832 – pango_cairo_update_layout() always invalidates layout
+ Bug 446018 – Bus error in the pango_ot_tag_from_language()
+ Bug 446355 – the parsing with pango_parse_markup is not coherent
+ Bug 447189 – fonts.c: pango_font_face_is_synthesized returns NULL
+ Bug 447568 – improve docs on what absolute size means
+ Bug 448342 – pango_layout_index_to_line_x() counts lines from 1
+
+Overview of changes between 1.17.1 and 1.17.2
+==============================================
+- Rename recently added pango_ot_ruleset_get_for() to
+ pango_ot_ruleset_get_for_description().
+
+- New engine API: pango_ot_ruleset_new_from_description().
+
+- Treat Unknown script like Common and other non-"real" scripts.
+ [Martin Hosken]
+
+- Misc typo fixes [Peter Moulder]
+
+- Bugs fixed in this release:
+
+ Bug 443206 – PANGO_SCRIPT_UNKNOWN should not cause a run break
+ Patch from Martin Hosken
+
+Overview of changes between 1.17.0 and 1.17.1
+==============================================
+
+- Ported the rest of OpenType shapers to the new OpenType APIs and
+ added standard features to them: Hebrew, Indic, Khmer, Thai, and Tibetan.
+
+- Added N'Ko support to the Arabic module. [Eugeniy Meshcheryakov]
+
+- Small Indic module fix for Malayalam.
+
+- Fixed font metrics returned by the ATSUI backend. [Richard Hult]
+
+- Make itemization use pango_language_get_default() if context has no
+ language set on it. Ditto for pango_context_get_metrics() if both
+ input language and context language are NULL.
+
+- Improved documentation on vertical text, also added stability note
+ to those parts of Pango API that are not indefinitely stable (shaper
+ and language engine APIs).
+
+- Misc bug fixes.
+
+- New OpenType engine API:
+
+ pango_ot_ruleset_get_feature_count()
+
+- Bugs fixed in this release:
+
+ Bug 357790 – Rendering problem for malayalam consonant RA (U+0D30)
+ Bug 385168 – indic, khmer, and tibetan modules don't apply ccmp
+ Bug 385477 – kern feature is not supported in OpenType layout for Tibetan.
+ Bug 433805 - [Atsui] Approximate char/digit width width often 0
+ Bug 436699 – N'Ko support
+ Bug 438705 – Test runs non-existent "/bin/bash" on HP-UX 11.11
+ Bug 438814 – synaptic crash with pango 1.17.0
+ Bug 440603 – Minor ABI change
+
+Overview of changes between 1.16.4 and 1.17.0
+==============================================
+
+General:
+
+- Text justification. A simple justification algorithm is implemented
+ that tries to justify by expanding spaces in the line, and if none
+ found, by adjust letter spacing. [Based on patch by Mathias
+ Hasselmann]
+
+- The pango_script_get_sample_language() function is modified to use
+ the value of environment variables PANGO_LANGUAGE or LANGUAGE
+ (checked in that order) to make guess better languages for scripts.
+ The env var should be a list of language tags, like "en:fa" for
+ example where in effect makes Pango choose Persian (fa) fonts
+ instead of Arabic (ar) fonts when a run of text in the Arabic script
+ is found in an otherwise non-Arabic layout.
+
+ This trick is also useful for East Asian languages. For example a
+ Japanese user that cannot set her primary language to Japanese can
+ still set PANGO_LANGUAGE="ja" and Pango will map CJK characters to
+ Japanese.
+
+ The LANGUAGE env var is a standard gettext variable listing
+ languages the user wants to receive UI translated messages in.
+ However, since most packages don't provide separate English
+ translations, setting LANGUAGE="en:ja" doesn't have the intended
+ effect and UI messages will be shown in Japanese. For these
+ situations one can use LANGUAGE="en:C:ja". Pango skips the special
+ language tag 'C'.
+
+- Simplified embedded-shape rendering with pangocairo backends do.
+ [Richard Hult]
+
+- New header file: Moved PangoLanguage APIs into its own header
+ pango-language.h, which is included from pango-types.h.
+
+- ATSUI backend now lists synthesized italic faces like other
+
+- Misc optimizations and fixes.
+
+OpenType Layout Engine Improvements:
+
+- Vertical glyph variants are not selected in vertical text if the
+ font supports them.
+
+- Instead of hardcoded OpenType script tag in each module, and using
+ Default Language System unconditionally, Pango will now find and use
+ the script/lang-sys pair that best matches the detected script and
+ language of a run of text. Moreover, it also applies the OpenType
+ 'locl' feature.
+
+ These, plus the PANGO_LANGUAGE env var, give font designers and
+ users lots of options to provide/choose language-specific glyph
+ variants.
+
+ Only basic, arabic, and syriac modules updated to take advantage of
+ the new support so far.
+
+New pango-view command line options:
+
+ --align
+ --justify
+ --language
+
+Public API Changes:
+
+- New public pangocairo API:
+
+ PangoCairoShapeRendererFunc
+ pango_cairo_context_set_shape_renderer()
+ pango_cairo_context_get_shape_renderer()
+
+ These are used by the default pangocairo renderer to render shape
+ attributes (see examples/cairoshape.c). Cairo-based PangoRenderer
+ implementations outside Pango may want to implement the draw_shape()
+ method similarly to provide compatibility with these new APIs. (See
+ bug #437533 for GdkPangoRenderer for example.)
+
+- Other public API changes:
+
+ New is_expandable_space member in PangoLogAttr
+ New macro PANGO_UNITS_ROUND()
+
+- New OpenType engine API. These are engine API, for use by Pango
+ modules, and typically need not to be bound by language bindings:
+
+ PANGO_OT_NO_FEATURE
+ PANGO_OT_NO_SCRIPT
+ PANGO_OT_TAG_DEFAULT_SCRIPT
+ PANGO_OT_TAG_DEFAULT_LANGUAGE
+ PangoOTFeatureMap
+ PangoOTRulesetDescription
+ pango_ot_ruleset_get_for()
+ pango_ot_ruleset_new_for()
+ pango_ot_ruleset_maybe_add_feature()
+ pango_ot_ruleset_maybe_add_features()
+ pango_ot_ruleset_description_hash()
+ pango_ot_ruleset_description_equal()
+ pango_ot_ruleset_description_copy()
+ pango_ot_ruleset_description_free()
+ pango_ot_tag_from_script()
+ pango_ot_tag_to_script()
+ pango_ot_tag_from_language()
+ pango_ot_tag_to_language()
+
+- Bugs fixed in this release:
+
+ Bug 64538 – pango_layout_set_justify() doesn't work
+ Bug 325714 – Pango should respect $LANGUAGE
+ Bug 414264 – Pango vertical writing support is different with real
+ CJK usage.
+ Bug 416515 – Time is not aligned with date on vertical panel
+ Bug 429397 – Updated MS Mincho/Gothic are not listed in font dialog
+ properly on Vista/
+ Bug 433805 – [Atsui] Approximate char/digit width width often 0
+ (worked around)
+ Bug 434160 - [atsui] Italic versions of some faces can't be created
+ Bug 435709 – pango_cairo_context_[sg]et_shape_renderer()
+ Bug 355789 – Pango misaligns word-wrapped text due to trailing
+ whitespace
+ Bug 436154 – Error building the pango.modules file while cross
+ compiling
+ Bug 436988 – Adding PangoScript to PangoAnalysis
+ Bug 437534 – pango_language_includes_script is buggy
+
+Overview of changes between 1.16.3 and 1.16.4
+==============================================
+- Add new configure option --disable-doc-cross-references and make
+ sure releases are made using it. Distributions are encouraged to
+ build with --enable-gtk-doc such that their Pango docs correctly
+ cross reference glib and cairo docs.
+- Bugs fixed in this release:
+ Bug 432991 – developer docs for libpango are broken
+
+Overview of changes between 1.16.2 and 1.16.3
+==============================================
+- Quantize kerning value if metrics hinting is on. This greatly improves
+ screen text rendering with certain fonts like DejaVu Sans.
+ See: http://behdad.org/blog/mces/image/metricshinting-kerning.png
+- Improved hex-box positioning in the cairo backend
+
+Overview of changes between 1.16.1 and 1.16.2
+==============================================
+- Fixed various bug in the OpenType Layout code (HarfBuzz)
+- Improved documentation
+- Improved ATSUI backend
+- Misc build system fixes
+- Bugs fixed in this release:
+ Bug 417946 – pangowin32-fontmap.c:using function without prototype
+ Bug 419262 - Don't create coverage every time it's asked for
+
+Overview of changes between 1.16.0 and 1.16.1
+==============================================
+- Improved Win32 backend: The Win32 backend has been
+ updated to always require Uniscribe at compile-time (it still
+ is optional at run-time), and to use the wide-character variants
+ of Windows APIs which improves the backend in many ways. The
+ 1.16.0 release is obsolete as far as the Win32 backend is
+ concerned, and official DLLs were not built for it.
+- Misc build system fixes
+- Bugs fixed in this release:
+ Bug 110521 – can't find bold and/or italic fonts on win32
+ Bug 120195 – there are some functions in pangowin32-fontmap.c that
+ might maybe should be static
+ Bug 407315 – Use wide character Win32 API in the pangowin32 code
+ Bug 412654 – SED variable undefined in the `libtool --config' output
+ used by configure
+ Bug 414297 – Fails to build with --enable-static
+ --with-included-modules in thai lang module
+ Patch from Loïc Minier
+
+Overview of changes between 1.15.6 and 1.16.0
+==============================================
+- Improved docs, with an object hierarchy and cross references to glib and
+ cairo docs now (may require rebuilding the docs to correctly detect glib
+ and cairo prefixes).
+- Improved font selection for space characters
+- Misc build system fixes
+- Bugs fixed in this release:
+ Bug 407087 – autogen.sh wants automake-1.7
+ Bug 409212 – Missing link flag prevents build with "-z defs" ld flags
+ Patch from Loïc Minier
+ Bug 355987 – choosing font/shaper for spaces breaks Arabic runs on
+ spaces
+
+Overview of changes between 1.15.5 and 1.15.6
+==============================================
+- Fix possible crasher in win32 font selection [Owen Taylor]
+- Misc build fixes.
+- Bugs fixed in this release:
+ Bug 399738 – pango 1.15.5 won't compile on Mac OS X: 'FC_HINT_STYLE'
+ undeclared (first use in this function)
+ Bug 404295 – Crash initializing pango-win32 fontmap
+
+Overview of changes between 1.15.4 and 1.15.5
+==============================================
+- Fix the "menu accels are two chars wide" bug that was introduced in 1.15.4
+- Respect FC_HINT_STYLE in the ft2 backend. Patch has been in Fedora for ages.
+- Require automake 1.9
+Bugs fixed in this release:
+ Bug 398238 – pangorc file missing from tests directory
+
+Overview of changes between 1.15.3 and 1.15.4
+==============================================
+General:
+- Finish vertical text support.
+- Fix various bugs that could cause ellipsization to stop prematurely.
+- Fix rendering of background color being off in presence of rise attribute.
+- Improved text-on-path example (examples/cairotwisted.c)
+
+Win32 Improvements:
+- Don't check for X and don't warn about missing fontconfig. [Tor Lillqvist]
+- Automatically use -mms-bitfields on Windows when building with gcc. [Tor]
+- Update makefile.msv. [Hans Breuer]
+
+Code base cleanups:
+- Whitespace cleanups. Hopefully patches still apply using patch -l
+- Replace C++-style // comments with C-style /* */ ones.
+- Move the pango-view tool from examples/ into pango-view/. The examples/
+ dir is still available and for simple examples only.
+
+Public API changes:
+
+- New PangoLayout query functions:
+
+ pango_layout_is_wrapped()
+ pango_layout_is_ellipsized()
+ pango_layout_get_unknown_glyphs_count()
+
+ The is_wrapped and is_ellipsized functions return whether the layout
+ had to wrap/ellipsize any paragraphs, as opposed to the get_wrap and
+ get_ellipsize that return the wrap/ellipsize mode set.
+
+- Misc new function:
+ pango_parse_enum()
+
+ This is more a convenience function for internal use, but set public
+ to go with other pango_parse_* functions. Bindings should feel free
+ to ignore this.
+
+
+- New header files:
+
+ Moved gravity and matrix stuff into their own header files pango-gravity.h
+ and pango-matrix.h. Both are included from pango-types.h.
+
+- Vertical text:
+
+ New attribute types:
+
+ PANGO_ATTR_GRAVITY
+ PANGO_ATTR_GRAVITY_HINT.
+
+ New enum type:
+
+ PangoGravityHint
+
+ New macro:
+
+ PANGO_GRAVITY_IS_VERTICAL()
+
+ New public functions:
+
+ pango_attr_gravity_new()
+ pango_attr_gravity_hint_new()
+ pango_gravity_hint_get_type
+ pango_context_set_gravity_hint()
+ pango_context_get_gravity_hint()
+ pango_gravity_get_for_matrix()
+ pango_gravity_get_for_script()
+
+ Removed:
+ pango_matrix_to_gravity()
+
+ replaced by pango_gravity_get_for_matrix()
+
+ Gravity API added in previous releases:
+
+ PangoGravity
+ pango_gravity_get_type
+ pango_context_get_base_gravity
+ pango_context_get_gravity
+ pango_context_set_base_gravity
+ pango_font_description_get_gravity
+ pango_font_description_set_gravity
+ pango_gravity_to_rotation
+
+ A tip on using the vertical text support: If you just want to get correct
+ behavior in rotated labels (say, vertical Chinese/Japanese, but rotated
+ Latin, etc), all you need to do is to set the context gravity to
+ PANGO_GRAVITY_AUTO. You can do this for example
+
+ #if defined(PANGO_VERSION_CHECK) && PANGO_VERSION_CHECK(1,15,4)
+ pango_context_set_gravity (context, PANGO_GRAVITY_AUTO);
+ #endif
+
+Bugs fixed in this release:
+ Bug 395328 – Map kATSDeletedGlyphcode to PANGO_GLYPH_EMPTY
+ Bug 397337 – Use is_ellipsized and is_wrapped to optimize property
+ changes
+ Bug 328585 – Need to know if a layout has unknown glyphs
+ Patch from LingNing Zhang
+ Bug 326693 – PangoLayouts should be query-able about their
+ effective properties (width / wrapped / ellipsized / etc)
+ Bug 397327 – pango-layout.c: 'pango_layout_is_ellipsized' must return
+ a value
+ Bug 323173 – Add layout of mixed direction text for vertical layout
+ Bug 394453 – Use -mms-bitfields
+ Bug 392628 – Don't check for X on win32
+
+
+Overview of changes between 1.15.2 and 1.15.3
+==============================================
+- Fix Hangul crasher and other Hangul bugs introduced in 1.15.2
+- Spell-checked docs
+- Build fixes
+- Don't introduce bitfields in public structs. This changes some public API
+ that was broken in the 1.15 series. The new struct is backward compatible
+ with the older Pango series, but not with earlier 1.15.x devel releases.
+
+- New Public API:
+
+ * PangoAnalysis.flags and PANGO_ANALYSIS_FLAGS_CENTERED_BASELINE. These are
+ mostly only useful for the vertical text support in Pango, but language
+ bindings probably want to update their bindings for PangoAnalysis to
+ include these.
+
+ * New PangoMatrix methods:
+
+ pango_matrix_transform_distance()
+ pango_matrix_transform_point()
+ pango_matrix_transform_rectangle()
+ pango_matrix_transform_pixel_rectangle()
+
+ The transform_rectangle methods are particularly useful when an
+ app/toolkit wants to know the extents of a rotated layout in device
+ coordinates. It will be used by Gtk+ for example, and is used by the
+ pango-view tool too. The _pixel_ variant takes a PangoRectangle in device
+ units instead of Pango units.
+
+ * Unit conversion helpers:
+
+ pango_units_from_double()
+ pango_units_to_double()
+ pango_extents_to_pixels()
+
+ The first two just convert between Pango units (fixed precision) and
+ double floating-point numbers. The current implementations are as simple
+ as "(int)floor (d * PANGO_SCALE + 0.5)" and "(double)i / PANGO_SCALE", but
+ the idea is to have optimized versions of these that do not use the FPU in
+ the future. That will be appreciated by embedded devices without FPU
+ units. Since the functionality can be generally useful, the API is made
+ public.
+
+ The pango_extents_to_pixels() function in conjunction with
+ pango_matrix_transform_rectangle() makes it possible to convert extents to
+ device space and round then, instead of having to transform rounded
+ user-space extents.
+
+- Bugs fixed in this release:
+ Bug 351496 – PangoAnalysis::gravity breaks binary compatibility
+ Bug 388702 – Crash when there's no Hangul glyph in the font.
+ Bug 384543 – FcFontMatch misuse
+ Bug 392789 – vpath build fails in basic module
+ Patch from J. Ali Harlow
+ Bug 390877 – Don't feed pango-features.h to glib-mkenums
+ Patch from Yevgen Muntyan
+
+
+Overview of changes between 1.15.1 and 1.15.2
+==============================================
+* Engines:
+ - Improved Hangul shaper engine
+ - Improved Indic shaper and language engines
+ - Require libthai >= 0.1.7 for the Thai language engine
+
+* Optimizations:
+ - Avoid some floating-point operations. Should cut the number of float
+ ops per expose event in pangocairo to a half.
+ - Cache ink and logical extents for PangoLayout
+
+* New Public API:
+
+ - New, generated, public header file pango-features.h. Included by
+ pango.h. Currently contains the version information. In the future,
+ can be expanded to define which backends have been enabled, etc.
+
+ - Public macros and functions for compile- and run-time version checking:
+
+ PANGO_VERSION_ENCODE()
+ PANGO_VERSION_MAJOR
+ PANGO_VERSION_MINOR
+ PANGO_VERSION_MICRO
+ PANGO_VERSION
+ PANGO_VERSION_STRING
+ PANGO_VERSION_CHECK()
+ pango_version()
+ pango_version_string()
+ pango_version_check()
+
+ The scheme chosen here is a mixture of approaches taken by glib and cairo.
+ The advantage over the glib model is that there are no public variables,
+ but it still gives access to a string and numerical representation of the
+ version number at compile- and run-time.
+
+ The macros enable conditional compilation of code depending on newer Pango
+ APIs, while the runtime functions allow refusing to run against old
+ versions of the library.
+
+ - New, readonly, version of methods that give read/write access to the
+ internals of PangoLayout:
+
+ pango_layout_get_line_readonly()
+ pango_layout_get_lines_readonly()
+ pango_layout_iter_get_line_readonly()
+ pango_layout_iter_get_run_readonly()
+
+ These should be used when you do not intend to modify the run/line,
+ which is most of the time the case. The only exception known to me
+ is Firefox that adjusts glyph widths to do justification. Most other
+ uses that do not write to the returned structs (or structs accessible from
+ them) should be ported to the new readonly API to benefit from major
+ optimizations (in this case, line extents caching). The list includes,
+ but is not limited to, Gtk+, SWT, ClassPath, gnome-applets, libgnomeprint,
+ xmlroff, GtkMathView, Conglomerate, Dia, Anjuta, wxWindows, The Gimp,
+ and various other applications/libraries:
+
+ http://www.google.com/codesearch?hl=en&q=+pango_layout_(iter_)%3Fget_(lines%3F%7Crun)%5B%5E_%5D&start=50&sa=N
+
+ Worth noting here is that, many uses of pango_layout_get_lines() can be
+ replaced by a pango_layout_get_iter() that works both more elegantly and
+ more efficiently. The versioning macros introduced in this release can be
+ used to make code use these new symbols without breaking compilation
+ against older Pango (though, such code compiled with the new Pango cannot
+ be run against an older Pango).
+
+ - pango_language_get_default(): Note that, this does not make Pango
+ fallback to the default language automatically (yet), but the user can
+ use this function to set the default language of the locale on a context:
+
+ pango_context_set_language (context, pango_language_get_default());
+
+ This essentially deprecates gtk_get_default_language(). The pango-view
+ tool has been updated to use this feature, so it now respects $LANG when
+ choosing fonts.
+
+ - pango_color_to_string().
+
+* Bugs fixed in this release:
+ Bug 326099 – Setting width, indentation and ellipsizing doesn't work
+ as I would expect
+ Bug 385478 – Fix tests on OPD platform
+ Bug 319808 – Patch to let pango support artifical italic, bold and
+ bold italic styles for the fonts which don't have these styles.
+ Patch from James Su
+ Bug 385321 – Worst case expansion for Sinhala
+ Patch from Harshula
+ Red Hat Bug 211574: [hi/ml/si_LK] cursor naviation is wrong when
+ using ZWJ (200d)
+ Patch from LingNing Zhang
+ Red Hat Bug 216424: [te_IN] pango - consonant + dependent vowel (ai)
+ Composed char is not rendering properly
+ Patch from LingNing Zhang
+ Bug 373856 – Wish: Function to convert a GdkColor to a string
+ Patch from Matthew Barnes
+ Red Hat Bug 216850: Issue in combination with vowels (ml_IN)
+ Patch from LingNing Zhang
+ Bug 382437 – tests/testboundaries fails
+ Bug 333982 – Fallback to $LANG whenever NULL PangoLanguage is used
+ Patch from LingNing Zhang
+
+Overview of changes between 1.15.0 and 1.15.1
+==============================================
+* Add Thai langauage engine. (currently makes tests/testboundary fail.)
+* Add Lao and improved Thai sample text.
+* Improved Indic module.
+* Output correct path for hexboxes in pango_cairo_layout_path().
+* Implement get_resolution method for the FT2 fontmap. Shouldn't make
+ any difference whatsoever. Open a bug if it does.
+* Misc small fixes.
+
+* Optimizations:
+ - Rework PangoLayout algorithms to avoid calling a recursive call to
+ pango_layout_get_extents(). Avoids one pango_font_get_glyph_extents()
+ call per glyph per layout rendering. We now make 2 such calls.
+ - Don't cache run_logical_rect in PangoLayoutIter.
+ Avoids one pango_font_get_glyph_extents() call per glyph per layout
+ rendering. We are down to 1 now.
+ - Cache line extents. This avoids the final pango_font_get_glyph_extents()
+ call per glyph per layout rendering. Now we don't make any
+ pango_font_get_glyph_extents() calls when rendering a layout (some
+ conditions apply)!
+ - Replace PANGO_IS_RENDERER with PANGO_IS_RENDERER_FAST for most
+ internal uses, that is, just a NULL-check.
+ - Use simple, fast, casts instead of PANGO_CAIRO_*() macros where the
+ object cannot have reached us if it wasn't of the right type.
+
+* Bugs fixed in this release:
+ Bug 135683 – Cache glyphstring extents
+ Red Hat Bug 211964: [ta] Rendering issue with Tamil
+ Patch from LingNing Zhang
+ Red Hat Bug 213632: ZWJ (200d) and ZWNJ (200c) showing same output
+ Patch from LingNing Zhang
+ Bug 371388 – Add Thai langauage engine
+ Patch from Theppitak Karoonboonyanan
+ Bug 377975 – bug in _pango_glyph_item_iter_next_cluster
+ Bug 369670 – Checked g_free calls
+
+Changes that also appeared between 1.14.7 and 1.14.8
+=====================================================
+* Improved thread-safety. Pango is still NOT thread-safe, but this fixes
+ lots of crashes using pangocairo from multiple threads.
+* Fix out-of-bounds array access.
+* Improved Indic shaper.
+* Improved Arabic language engine.
+* Choose shaper/font for unassigned Unicode codepoints.
+* Build fixes.
+* Bugs fixed in this release:
+ Bug 356666 – pango is not thread-safe, nautilus does not honour that
+ Bug 352795 – configure.in: Bug in "checking Whether to write
+ dependencies into .pc files"
+ Bug 350132 – backspacing doesn't work properly for Arabic
+ Bug 330407 – Multiple dependant vowel signs (indic) displayed as one
+ Patch from LingNing Zhang
+
+Overview of changes between 1.14.7 and 1.15.0
+==============================================
+* Add basic support for vertical text. (PangoGravity and related API)
+* New PangoCairo example (examples/cairotwisted) to lay text out on a path
+* Fix various bugs in the way language engines are used. Add simple Arabic
+ and Indic language engines. (Backported to 1.14.6)
+* Step module interface version up to 1.6.0
+* Misc small cleanups.
+* Bugs fixed in this release:
+ Bug 330407 – Multiple dependant vowel signs (indic) displayed as one
+ Bug 359043 – PangoRenderer does not show in API docs
+ Bug 359046 – renderdemo.c unconditionally use GLib 2.12
+ Bug 357228 – Remove aix specific hack from configure.in
+ Part of Bug 350132 – backspacing doesn't work properly for Arabic
+ Bug 356194 – more pango_get_log_attrs problems
+ Bug 355820 – pango_get_log_attrs broken
+ Bug 352811 – SIGSEGV with pango(cairo)-view on HP-UX
+ Bug 351496 – PangoAnalysis::gravity breaks binary compatibility
+ Bug 351585 – API documentation issues with 2.15 release
+
+Overview of changes between 1.14.6 and 1.14.7
+==============================================
+* Fixed broken build with included lang modules.
+* Bugs fixed in this release:
+ Bug 361938 – Can't include *-lang modules (./configure
+ --with-included-modules fails)
+
+Overview of changes between 1.14.5 and 1.14.6
+==============================================
+* Backport language-engine handling fixes from HEAD.
+* Add simple Arabic and Indic language engines.
+* Indic shaper fixes.
+* Bugs fixed in this release:
+ Bug 353877 – Sinhala is_cursor_position and
+ backspace_deletes_character issues
+ Patch from Akira TAGOH
+ Bug 358224 – Telugu Character U+0C31 does not render its below-base
+ form.
+ Patch from Rahul Bhalerao
+ Bug 358174 – Reph and Vattu forms of Assamese character RA(U+09F0)
+ are not rendered.
+ Patch from Rahul Bhalerao
+
+Overview of changes between 1.14.4 and 1.14.5
+==============================================
+* Indic shaper fixes.
+* Misc bug fixes.
+* Bugs fixed in this release:
+ Bug 356685 – [or_IN] Rendering of consonant+0x0B4D+0x0B2F is wrong
+ Patch from Rahul Bhalerao
+ Bug 357790 – Rendering problem for malayalam consonant RA (U+0D30)
+ Patch from Rahul Bhalerao
+ Bug 349813 – typo in docs for pango_layout_move_cursor_visually
+ Bug 357686 – pangocairo-font.c: illegal g_object_unref in
+ pango_cairo_font_get_hex_box_info
+
+Overview of changes between 1.14.3 and 1.14.4
+==============================================
+* Indic shaper fixes.
+* Misc bug fixes.
+* Bugs fixed in this release:
+ Bug 351223 – the conjuction of Con + 0x0d4d +0x0d31 of Malayalam is
+ wrong
+ Patch from LingNing Zhang
+ Bug 355750 – The glyphs of the conjuctions about Cons+0x0d4d+0x0d32 of
+ Malayalm are wrong.
+ Patch from LingNing Zhang
+ Bug 349876 – U+0x0904 of Devanagari need be "independent vowel", but
+ it is "reserved" in Pango
+ Patch from LingNing Zhang
+ Bug 355550 – Miscalculation of logical attributes in
+ pango_get_log_attrs()
+ Patch from Theppitak Karoonboonyanan
+ Bug 355697 – The IndicOTClassTable of Oriya has a error.
+ Bug 355782 – Misaligned extents in pango
+ Bug 355605 – hexbox with 0000 in it
+ Bug 355435 – Invalid calls to pango_map_get_engine()
+ Patch from Theppitak Karoonboonyanan
+ Bug 347146 – underline/overstrike spaces
+ Bug 352535 – Ink extents of empty glyph
+
+Overview of changes between 1.14.2 and 1.14.3
+==============================================
+* Win32 build improvement. [Tor Lillqist]
+* Bugs fixed in this release:
+ Bug 353525 – libpangoft2-1.0.so.0: undefined reference to
+ `pango_font_description_get_gravity'
+ Bug 349813 – typo in docs for pango_layout_move_cursor_visually
+
+Overview of changes between 1.14.1 and 1.14.2
+==============================================
+* Find shaper/font for Private Use and space characters.
+ Part of Bug 145275 – Font selection for space characters
+
+Overview of changes between 1.14.0 and 1.14.1
+==============================================
+* Increased fontset cache size from 16 to 64. This should make
+ firefox+pango A LOT faster.
+* Bugs fixed in this release:
+ Bug 352114 – pango-1.14: generated docs still contain old example code
+ Part of Bug 348825 – pango should optimize away calls to FcFontSort as
+ much as possible
+ Bug 351585 – API documentation issues with 2.15 release
+
+
+Overview of changes between 1.13.5 and 1.14.0
+==============================================
+* Make pango-view accept non-ASCII --text.
+* Require cairo-1.2.2 for the important bug fixes it has.
+
+Overview of changes between 1.13.4 and 1.13.5
+==============================================
+* Indic shaper improvements.
+* Misc fixes.
+* Bugs fixed in this release:
+ Bug 121672 – Ra (vattu) not rendered properly in Malayalam
+ Patch from LingNing Zhang
+ Bug 335811 – Some conjugates of Malayalam are wrong.
+ Patch from LingNing Zhang
+
+Overview of changes between 1.13.3 and 1.13.4
+==============================================
+* Update to Unicode Character Database 5.0.0.
+* Misc fixes.
+* Bugs fixed in this release:
+ Bug 336282 – Update to Unicode Character Database 5.0.0
+ Bug 347073 – Allow empty GPOS table
+ Bug 347021 – atsui crash when a matching font cannot be found.
+ Patch from Brian Tarricone.
+
+Overview of changes between 1.13.2 and 1.13.3
+==============================================
+* Improved build system. Using gnome-autogen.sh now.
+ (gnome-common needed for bootstrapping)
+* Improved documentation. Docs now include list of new API for
+ each stable version of Pango.
+* New public API:
+ - pango_glyph_string_get_width
+* Little performance improvement.
+* Misc fixes.
+* Bugs fixed in this release:
+ Bug 330603 – pango_scan_int invokes undefined behaviour
+ Bug 315599 – PangoAttribute remains in wrong context.
+ Bug 163677 – pango_attr_list_splice: inconsistent docs
+ Patch from Morten Welinder
+ Bug 345070 – [ml_IN] not render for combination with ZWJ
+ Patch from LingNing Zhang
+ Bug 345274 – list of new symbols for each version is missing in docs
+ Patch from Priit Laes
+ Bug 346297 – autogen doesn't work with automake-1.6
+ Patch from Priit Laes
+ Bug 135683 – Cache glyphstring extents
+ Bug 344766 – Memory leak in get_ruleset() in modules/basic/basic-fc.c
+ Bug 345600 – cvs build error in pango/opentype/Makefile
+ Bug 345511 – -no-undefined problem with new libtool
+
+Overview of changes between 1.13.1 and 1.13.2
+==============================================
+* Improved hexbox drawing, and font metrics calculations.
+* Synthesize italic variants on win32 [Hans Breuer]
+* New public API:
+ - pango_cairo_show_error_underline
+ - pango_cairo_error_underline_path
+ - pango_font_describe_with_absolute_size
+* Misc fixes.
+* Bugs fixed in this release:
+ Bug 326960 – hex box drawing for win32 and atsui backends of cairo
+ Bug 343717 – License information in unclear.
+ Bug 343355 – Add pango_cairo_show_error_underline &
+ pango_cairo_error_underline_path
+ Bug 343966 – pango Cygwin build fixes
+ Patch from Cygwin Ports maintainer.
+ Bug 343796 – Italic Chinese character can't be show correctly in
+ Win32.
+ Bug 314114 – max_x_advance not appropriate for
+ approximate_(char|digit)_width
+ Bug 341138 – Using TTC font, Gtk2 programs begin to eating big memory
+ and have many cpu usage.
+ Patch from Yong Li.
+ Bug 336153 – Mark to mark positioning (Lookup Type 6) isn't correct
+ when using MarkAttchmentType
+ Patch from Tin Myo Htet.
+ Bug 333984 – pango_language_from_string improvements
+ Bug 125378 – Better underline thickness handling
+ Bug 339730 – Pango needlessly falls back away from a Type 1 font into
+ a TTF font
+ Bug 342562 – Support absolute sizes in
+ pango_font_description_to/from_string
+ Bug 341922 – pango should handle more characters as zero width
+ Patch from Roozbeh Pournader
+ Bug 342525 – With PangoFc and PangoWin32, approximate digit width is
+ not what it says
+ Bug 342079 – pangoatsui-private.h missing from release
+
+Overview of changes between 1.13.0 and 1.13.1
+==============================================
+* Increased robustness against broken pango.modules
+* Improved build infrastructure:
+ - Remove CAIRO_CFLAGS from pangocairo.pc.in, as it Require's cairo already.
+ - Use -no-undefined on Unix too.
+* Improved documentation.
+* Misc fixes.
+* Bugs fixed in this release:
+ Bug 307196 – Unhinted fonts are measured incorrectly and drawing
+ problems occur as a result
+ Bug 329547 – pango_layout_get_pixel_extents and
+ pango_layout_get_pixel_size cause off-by-one metrics
+ Bug 339747 – pango_font_metrics_get_approximate_digit_width docs
+ Bug 339749 – pango_language_from_string issues
+ Patch from Morten Welinder.
+ Bug 333771 – Use gmodule-no-export-2.0 instead of gmodule-2.0 in
+ pango-uninstalled.pc.in
+ Bug 337594 – pango_glyph_string_extents_range possible bug
+ Bug 329664 – Move gunichar_to_glyph cache from PangoCairoFcFont to
+ PangoFcFont
+ Patch from LingNing Zhang.
+ Bug 322374 – Examples does not build on MacOS X
+ Bug 340229 – pango_font_description_from_string does not do bound
+ checking
+ Bug 329483 – hinting hexbox in cairo backend doesn't handle absolute
+ font size
+ Bug 340040 – pangocairo hex box hinting falls apart with PS/PDF
+ backends
+ Bug 71033 – make size 0 fonts work
+
+Overview of changes between 1.12.0 and 1.13.0
+==============================================
+* Fix incorrect rendering when in x86 64-bit precision mode
+ https://bugs.freedesktop.org/show_bug.cgi?id=5200
+* Fix non-OpenType fonts losing kerning in 1.12.0 [#336026, Denis Jacquerye]
+* Fix blurred underlines on Win32 [#332656, Tor Lillqvist]
+* Build fix when having both Win32 and FreeType cairo backends available
+ [#337502, Alexander Larsson]
+* Moved the OpenType Layout code into a new project called HarfBuzz:
+ http://www.freedesktop.org/wiki/Software/HarfBuzz
+* Improved documentation.
+* Misc bug fixes.
+* Fixed many compiler warnings.
+* Bugs fixed in this release:
+ 332656,335840,334802,337029,337821,338343
+
+Overview of changes between 1.11.99 and 1.12.0
+==============================================
+* Compilations fixes for MSVC. [#333115, Tor Lillqvist]
+* More NULL-check against unusable fonts, helps with Win32 fonts without
+ a Unicode cmap. [Tor]
+* Use g_print instead of printf for debugging output in Win32 backend.
+ [#332855, Tor]
+
+Overview of changes between 1.11.6 and 1.11.99
+==============================================
+* Fix problem recently introduced that made Win32 backend render boxes
+ only. [#332538, Hans Breuer]
+* Insert '?' chars instead of invalid UTF-8 sequences in
+ pango_layout_set_text [#33195]
+* Bugs fixed in this release:
+ 332167,332538,331995
+
+Overview of changes between 1.11.5 and 1.11.6
+=============================================
+* Do not export macros PANGO_GLYPH_EMPTY, PANGO_GLYPH_UNKNOWN_FLAG and
+ PANGO_GET_UNKNOWN_GLYPH publicly; just in the engine/backend interface.
+* Fix a few crashers, especially when a font cannot be read. [#314239]
+* Change some g_critical's to g_warning, where it's not application's
+ fault. [#331723]
+* Bugs fixed in this release:
+ 330795,331038,329148,331994,331995,331996,314239,331723
+
+Overview of changes between 1.11.4 and 1.11.5
+=============================================
+* Cleanup work on the win32 backend. Families are not listed all
+ in lower case anymore.
+* New public function: pango_win32_font_description_from_logfont.
+* pango-view accepts --wrap now, and lists backends in --help output.
+* A couple minor bug fixes.
+
+Overview of changes between 1.11.3 and 1.11.4
+=============================================
+* Major change in the low-level interface of Pango. The special value
+ PANGO_GLYPH_EMPTY is now defined to mean a "draw nothing" glyph. This
+ was what glyph 0 was used for previously. As a result, bumped up the
+ Pango module version, meaning that modules compiled against earlier
+ versions are probably not compatible with this release. [#73147]
+* New framework in examples for building a binary called pango-view,
+ that can be used to render a text file using any of the available
+ backends. This is installed into bindir now.
+* Enhancements to the FT2 backend, to draw boxes on missing glyphs.
+* Better hexbox drawing for cairo backend: Hinting hexbox, and
+ drawing a single-row hexbox for very small font sizes.
+* Improved documentation.
+
+Overview of changes between 1.11.2 and 1.11.3
+=============================================
+* Do not crash if the shapers fail.
+* Use g_slice for various struct allocations.
+* 100% symbol coverage in docs.
+* Misc bug fixes and documentation improvements.
+* Janitory works, like removing unneeded files.
+
+Overview of changes between 1.11.1 and 1.11.2
+=============================================
+* Draw hex box on missing glyphs for cairo-fc backend.
+* New --with-dynamic-modules option added to configure.
+* Use g_slice for various small memory allocations [Matthias Clasen]
+* Misc bug fixes, optimizations, and documentation improvements.
+
+Overview of changes between 1.11.0 and 1.11.1
+=============================================
+* ATSUI support for the cairo backend. [Anders Carlsson]
+* Fixed a couple of regressions with font size and scaling.
+* Draw a dashed empty box on missing glyphs for cairo-fc backend.
+* Support OpenType features for basic (Latin/Greek/...) module.
+* Support swash feature in Arabic module.
+* Misc bug fixes.
+* Misc documentation improvements.
+
+Optimizations:
+
+* Cache GObject private data in PangoFcFont.priv [Federico Mena Quintero]
+* Add a constant-sized light-weight cache for glyph extents.
+* Use g_slice_* instead of GMemChunk in mini-fribidi.
+
+
+Overview of changes between 1.10.1 and 1.11.0
+=============================================
+* Line-breaking algorithm updated to Unicode 4.1.
+* Code borrowed from GNU FriBidi resynched to version 1.0.7.
+* New improved Tibetan shaper module. [Pema Geyleg]
+* Bug fix in Khmer shaper module. [Jens Herden]
+* Respect fontconfig reassignment of font pixelsize. [Funda Wang]
+* Make OpenType GPOS handling more robust/correct. [Greg Aumann]
+* Various documentation fixes and improvements.
+* Various gcc warning fixes.
+* Misc bug fixes.
+
+Optimizations:
+
+* Add a lazy fixed-size per-font cache to map characters to glyphs,
+ in the cairo backend. [Federico Mena Quintero]
+* Optimize character to script mapping by adding a linear table for
+ characters < U+2000, and also caching the last mid point in
+ bsearch. [Federico, Matthias Clasen]
+* Enabled mini-fribidi's trashstack instead of direct mallocs.
+* Short circuit the bidi algorithm for provably unidirectional text.
+* Make mini-fribidi process UTF-8 directly.
+* Several strlen and g_utf8_strlen calls removed. [Owen Taylor, Billy Biggs]
+* Use call tables in the OpenType layout code.
+* Use quarks for accessing GObject data. [Federico]
+* Open Pango modules with lazy-bind flags. [John Rice]
+* Use new negative offsets in g_utf8_pointer_to_offset to avoid
+ scanning from the beginning of line on cursor movement.
+* Avoid redundant PANGO_IS_FC_FONT checks.
+
+Overview of changes between 1.10.0 and 1.10.1
+=============================================
+* Add various forms of caching to the Win32 backend, greatly
+ improving performance [Tor Lillqvist]
+* Fix problem with colors leaking from a Pango item to
+ subsequently drawn strings. [Choe Hwanjin]
+* Fix bug where error underlines would be drawn 1024 times
+ too big in the Cairo backend. [Luis Villa]
+* Misc bug and build fixes [Jean Brefort, Matthias Clasen,
+ Behdad Esfahbod, Kazuki Iwamoto]
+
+Overview of changes between 1.9.1 and 1.10.0
+============================================
+* Update script tables, bidi tables, and Arabic joining tables for Unicode 4.1
+ [Roozbeh Pournader, Behdad Esfahbod]
+* Misc bug and build fixes [Sebastien Bacher, Hans Breuer, Behdad,
+ J. Ali Harlow, Tor Lillqvist, Keith Packard, Vittorio Palmisano, Manish Singh]
+
+Overview of changes between 1.9.0 and 1.9.1
+==========================================
+* Support setting of font options and DPI on PangoContext for
+ the Cairo backend.
+* Adapt to recent Cairo API changes
+* Win32 build improvements [Tor Lillqvist]
+* Misc bug fixes [Hans Breuer, Thomas Fitzsimmons, Kazuki IWAMOTO]
+
+Overview of changes between 1.8.x and 1.9.x
+===========================================
+* Add Cairo support; PangoCairoFontmap is an interface with
+ implementations for Fontconfig fonts and Win32 fonts
+* Extend PangoFcFontmap to allow more customization by subclasses
+* Handle NULL language better for pango_context_get_metrics()
+* misc optimization [Paolo Borelli, Behdad Esfahbod]
+* Misc bug and build fixes [Hans Breuer, Damien Carbery,
+ Keith Packard, Manish Singh]
+* Doc fixes [Tim Janik]
+
+============================================================
+
+Overview of changes between 1.8.1 and 1.8.2
+===========================================
+* Add Khmer support [Jens Herden, Javier Sola]
+* Fix bugs and crashes in the operation of PangoLayoutIter [Amit Aronovitch]
+* Increase sharing of data between different copies of Pango
+ [Tommi Komulainen, Ross Burton]
+* Remove dependence of opentype code on FreeType internals [David Turner,
+ Behdad Esfahbod]
+* Cache metrics for the Win32 backend [Tor Lillqvist]
+* Improve handling of RTL text when passing it to Uniscribe [Tor]
+* Support for TrueType fonts on Win32 with characters outside the BMP [Tor]
+* Handle alpha in XftColors again. [Mikael Magnusson]
+* Better handling of MacThai encoded fonts [Theppitak Karoonboonyanan]
+* Handle zero width chars properly in Hangul backend
+ [Young-Ho Cha, Changwoo Ryu]
+* Fix Oriya character classification [Gora Mohanty, Gautam Sengupta]
+* PangoAttrIterator bug fixes [Morten Welinder]
+* Clean up copyright/licensing information [William N. Ray]
+* Misc bug and build fixes [Sebastien Bacher, Brandon Bergren,
+ Chris Blizzard, Paolo Borelli, Behdad, Harshula, Alex Jones, Aivars Kalvans,
+ Stepan Kasal, Karel Kulhavy, Ryan Lortie, Ben Maurer, Sukhjinder Sidhu,
+ Manish Singh, Emil Soleyman-Zomalan, Morten]
+
+Overview of changes between 1.8.0 and 1.8.1
+===========================================
+* Fix several problems with conjuct formation in Sinhala [Harshula]
+* Fix problems that were causing fonts to be missized and
+ not print in GtkHTML [Ross Burton]
+* Fix compilation with old fontconfig [Vincent Noel] and
+ old FreeType [Andrew P. Lentvorski, Jr]
+* Work around problem with glyphs in monospace fonts being truncated
+ by Xft [Billy Biggs]
+* Misc bug fixes [Damon Chaplin, Matthias Clasen, Kees Cook, Nick Lamb,
+ Adam Sampson,Manish Singh, Morten Welinder]
+* Misc build fixes [Sebastien Bacher, Matthias Clasen, Tor Lillquist]
+* Doc improvements [Torsten Schoenfeld, Billy Biggs, Morten Welinder]
+
+Overview of changes between 1.7.0 and 1.8.0
+===========================================
+* Add Sinhala support to the Indic module [Anuradha Ratnaweera]
+* Add Tibetan module [G Karunakar, Pema Geyleg]
+* Support pixel sizes for fonts [Chris Lahey]
+* Add pango_layout_get_font_description() [Morten Welinder]
+* Add PANGO_WEIGHT_SEMIBOLD [Lars Clausen]
+* Report underline metrics on Win32 [Tor]
+* Handle GLib-2.6.0 win32 filename encoding changes [Tor Lillqvist,
+ Robert Ögren]
+* Fix crash when drawing long strings
+* Misc fixes [Matthias Clasen, Dan Winship]
+
+Overview of changes between 1.6.x and 1.7.0
+===========================================
+
+* Add PangoRenderer, a subclassable driver object holding the
+ logic for rendering PangoLayout.
+* Support transformed rendering for the Xft backend
+* Add Lao support in Thai Module [Theppitak Karoonboonyanan]
+* Support Thai OpenType fonts [Theppitak]
+* Add Syriac module [Emil Soleyman-Zomalan]
+* Add underline-color and strikethrough-color attributes
+ [Morten Welinder]
+* Add pango_win32_render_transformed() [Hans Breuer]
+* Misc fixes [Hans Breuer, Matthias Clasen, Manish Singh,
+ Morten Welinder]
+* Documentation improvements
+
+============================================================
+
+Overview of changes since 1.6.0
+===============================
+* Fix several problem when computing font and selecting fonts
+ metrics for CJK [Felipe Heidrich, Federic Zhang]
+* Win32 bug fixes [Tor Lillqvist, Kazuki Iwamoto, Ivan Wong]
+* Misc bug fixes [Vincent Berger, Paolo Borelli, Behdad Esfahbod,
+ Leon Ho, Arun M, Kjartan Maraas, Vincent Noel, Christian Persch,
+ Enrico Scholz, Sukhjinder Sidhu, Morten Welinder]
+
+Overview of changes between 1.5.2 and 1.6.0
+===========================================
+* Add OpenType support for Hebrew [Dov Grobgeld]
+* Win32 bug and build fixes [Tor Lillqvist, Hans Breuer, John Ehresman]
+* Misc bug fixes [Behdad Esfahbod, Jatin Nansi]
+
+Overview of changes between 1.5.1 and 1.5.2
+===========================================
+* Support 'init' feature for Bengali [Sayamindu Dasgupta]
+* Allow 32-bit property fields in OpenType code
+* Optimize repeated property lookups in OpenType code
+* Misc bug fixes [Behdad, Keith Sharp, Morten Welinder]
+
+Overview of changes between 1.5.0 and 1.5.1
+===========================================
+* Add ellipsization support to PangoLayout
+* Add pango_context_get_font_map().
+* Fix metrics for the Xft backend when a transform is in effect
+* Separate out backend-independent parts of pangoft2topgm for
+ future rendering testbeds.
+* Code cleanups (use G_DEFINE_TYPE, make PangoMatrix parameters const)
+* Add a GType for PangoMatrix [Torsten Schoenfeld]
+* Misc bug fixes [Morten Welinder]
+
+Overview of changes between 1.4.x and 1.5.0
+===========================================
+* Allow applications to provide custom font decoders [Chris Blizzard]
+* Add support for setting a transformation matrix on a PangoContext
+* Add support for rotated rendering to the FT2 backend
+* Add metrics for underline and strikethrough position and thickness.
+* Add letter-spacing attribute and implement in PangoLayout
+* OpenType support in Thai Module [Theppitak Karoonboonyanan]
+* Add Add PANGO_TYPE_LAYOUT_ITER [Johan Dahlin]
+
+============================================================
+
+Overview of changes between 1.4.0 and 1.4.1
+===========================================
+* Win32 bug fixes [Tor Lillqvist, John Ehresman]
+* Thai rendering improvements including OpenType support
+ [Theppitak Karoonboonyanan]
+* Fix common crash in Hangul shaper [Changwoo Ryu]
+* Fix various problems with language tag selection [Frederic Zhang]
+* Documentation improvements [Felipe Heidrich, Doug Quale]
+* Fix crash in line break code [Jeroen Zwartepoorte, Billy Biggs]
+* Build fixes [J. Ali Harlow, Noah Misch]
+* OpenType engine fixes [Kailash C. Chowksey, Sayamindu Dasgupta, Aamir Wali,
+ Masatake YAMATO, Soheil Hassas Yeganeh]
+* Indic module bug fixes [Chris Blizzard, Rajkumar S, Taneem Ahmed,
+ Jungshik Shin]
+* Misc bug fixes [Stanislav Brabec, Anders Carlsson, Behdad Esfahbod,
+ Jody Goldberg, Theppitak, Sven Neumann, Manish Singh, Morten Welinder]
+
+Overview of changes between 1.3.6 and 1.4.0
+===========================================
+* Use FC_WIDTH when available so that multiple width fonts are
+ selected properly [Manish Singh]
+
+Overview of changes between 1.3.5 and 1.3.6
+===========================================
+* Improve handling of some Kannada vowels [Kailash C. Chowksey]
+* Fix problem with excess symbol exports on Linux [James Henstridge]
+* Win32 build fixes [Hans Breuer, John Ehresman, Tor Lillqvist, Cedric Gustin,
+ J. Ali Harlow]
+
+Overview of changes between 1.3.3 and 1.3.5
+===========================================
+* Add support for automatically determining the base direction for
+ PangoLayout from the contained text [Dov Grobgeld]
+* Major rework of internal opentype interfaces to fix
+ problems with GPOS. Turn on GPOS handling for Arabic.
+* Add a PangoAttribute to turn off font fallback [Noah Levitt]
+* Add wavy error-indication underlines [Nicolas Setton]
+* Improve handling of BENGALI LETTER A/E [Sayamindu Dasgupta]
+* Win32 bug fixes and improvements [J. Ali Harlow, Hans Breuer]
+* Misc bug fixes [Noah, Roozbeh Pournader]
+
+Overview of changes between 1.3.2 and 1.3.3
+===========================================
+* Add pango_font_face_list_sizes() [Noah Levitt]
+* Add pango_font_family_is_monospace [Noah]
+* Do OpenType processing for CFF fonts [Manjunath Sripadarao]
+* Fix wrong sign for GPOS vertical positioning
+* Fix up -uninstalled .pc files [Laszlo Peter]
+* Misc bug and build fixes fixes [Rodney Dawes, Theppitak Karoonboonyanan,
+ Noah, Kjartan Maraas, Julio M. Merino Vidal, Christian Persch,
+ Torsten Schoenfeld, Manish Singh, Mariano Suárez-Alvarez, Morten Welinder,
+ Masatake YAMATO]
+
+Overview of changes between 1.3.1 and 1.3.2
+===========================================
+* Correct a mixup between ZWJ and ZWNJ in the Arabic
+ engine [Roozbeh Pournader]
+* Build and bug fixes for Win32 [Hans Breuer]
+* Fix a problem with RTL scripts on Win32 [Tor Lillqvist, Shoshannah Forbes]
+* Documentation improvements [Ross Burton, Matthias Clasen]
+
+Overview of changes between 1.3.0 and 1.3.1
+===========================================
+* Support non-Unicode font encodings when supported by fontconfig
+ [Sven Neumann]
+* Draw 6-digit hex boxes for > U+FFFF [Noah Levitt]
+* Update to latest fribidi [Noah]
+* Honor U+2028 LINE SEPARATOR [Noah]
+* Fix a problem with iteration by chars [Mariano Suárez-Alvarez]
+* Misc bug and build fixes [Jeff Bonggren, Martin Kretzschmar,
+ Noah, Sven Neumann, Padraig O'Briain, Manish Singh,
+ Morten Welinder]
+* Fix header file includes to work with recent FreeType.
+
+Overview of changes between 1.2.x and 1.3.0
+===========================================
+* Share modules between the FT2 and Xft backend. Export PangoFcFont
+ and PangoFcFontMap base classes so that other fontconfig based
+ backends can be written and use these same modules.
+* Redo module system to use GTypeModule and work much like GTK+ theme
+ engines and input method modules.
+* Change modules to declare coverage by script, rather than by code
+ point. Add a ->covers callback so that modules can dynamically
+ decide whether they can cover a particular codepoint with a given
+ font. (This will allow multiple modules to handle a script for
+ different types fonts.)
+* Complete rewrite of itemization pass. Now uses script information to
+ improve language tags. This solves problems with incorrect language
+ tags resulting in drastically wrong fonts being selected by
+ fontconfig.
+* Add backspace-deletes-character PangoLogAttr; will allow proper
+ deletion behavior for non-Western scripts. [Noah Levitt]
+* Add pango_fc_font_kern_glyphs(), which speeds up kerning a lot over
+ doing it pair-by-pair. [Soeren Sandmann]. Kern in the Xft backend as
+ well as the FT2 backend.
+* Remove the X font backend, except a minimal set of stubs to maintain
+ binary compatibility.
+* Many improvements to pangoft2topgm to allow displaying PangoMarkup,
+ saving to different file formats, etc.
+* Convert build system to automake-1.7; many cleanups and
+ improvements. [James Henstridge]
+* Documentation additions and improvements [Matthias Clasen, Martin
+ Pool]; add man pages for the included binaries. [Matthias]
+* Misc bug and build fixes [Josh Beam, Tony Graham, Kaushal Kumar,
+ Noah, Mehran Mehr, Soeren, Morten Welinder]
+* Win32 build fixes [Tor Lillqvist, Hans Breuer]
+
+============================================================
+
+Overview of Changes in Pango 1.2.5
+==================================
+* Fix a problem where the indic-xft shaper didn't get linked
+ against all necessary files.
+
+Overview of Changes in Pango 1.2.4
+==================================
+* Win32 [Tor Lillqvist]
+ - Avoid calling Uniscribe when not necessary [Hans Breuer]
+ - Build fixes
+* Indic shaper
+ - Add pre-base-matra fixup code from ICU [Sivaraj Doddannan]
+ - Port of Bengali rendering fix from ICU [Taneem Ahmed]
+* OpenType
+ - Port various fixes by Werner Lemberg from FreeType version
+ - Port various fixes by Lars Knoll from Qt version
+ - Many other bug fixes [Kailash C. Chowksey, Me]
+* Fix bugs in FT2 rendering code [Sven Neumann]
+* Remove Qt-based example program; was causing compilation problems
+ for a lot of people.
+* Doc fixes [Noah Levitt]
+* Misc bug fixes [Dave Cuthbert, Damon Chaplin, Christophe Fergeau,
+ Tony Graham, Morten Welinder]
+* Build fixes [Sven Neumann, Benedikt Spranger]
+
+Overview of Changes in Pango 1.2.3
+==================================
+* Fix operation with --disable-debug [Jeff Waugh]
+* Improve handling of ink rectangle extents for empty runs
+* Fix problem with keynav at line boundaries for RTL text [Matthias Clasen]
+
+Overview of Changes in Pango 1.2.2
+==================================
+* Cache fontsets for the Xft and FT2 backends, a large speedup for short
+ strings [Owen Taylor, Soeren Sandmann]
+* Make built in rendering functions, especially the FT2 one,
+ work more like the GDK implementation [Sven Neumann]
+* Add an indic-ft2 module [Kapil Chowskey],
+ Add a thai-ft2 module [Theppitak Karoonboonyanan]
+* Optimize pango_x_render() by drawing multiple character with
+ a single request when possible [Morten Welinder]
+* Change the handling of attributes that cover only partial glyphs
+ [Owen, Taneem Ahmed, Sunil Mohan Adapa]
+* Fix problems with Arial Unicode and the Opentype code [Owen, Noah Levitt]
+* Fix common crash for fonts missing a GDEF table
+* Fix common portability problem with informative output at end
+ of configure.
+* Build cleanups and fixes [Tim Mooney, Chris Ross, Akira Tagoh,
+ Will Partain, James Su]
+* Miscellaneous bug fixes and cleanups [Simon Budig, Rick Jones,
+ Noah, Padraig O'Briain, Benjamin Otte, Andrey Panov, Federic Zhang]
+* Documentation fixes [Tim, Sven]
+
+Overview of Changes in Pango 1.2.1
+==================================
+* Handle older TrueType Open Arabic fonts.
+* Make Win32 backend handle a common TrueType font bug [Tor Lillqvist]
+* Fix crash with some non-BMP characters [Morten Welinder]
+* Avoid crashing on font descriptions like " 12" [Padraig O'Briain]
+* Minor build fixes [Rich Burridge, Sven Neumann]
+
+============================================================
+
+Changes between 1.1.6 and 1.2.0
+
+* Documentation fixes
+
+Changes between 1.1.5 and 1.1.6
+
+* Fix crash with isolated Hangul tone marks.
+* Improve font solection for Hangul tone marks
+* Improve range definitions for basic-xft [Jungshik Shin]
+* Docs improvements [Matthias Clasen]
+
+Changes between 1.1.4 and 1.1.5
+
+* Fix wrap-around coordinate problems for X, Xt.
+* Draw unknown character boxes with X primitives for the
+ X backend instead of hoping for a suitable glyph [Morten Welinder]
+* Fix crash with FT2 arabic shaper from using face->generic.data
+ for two things.
+* For Xft/FT2, give an informative error mesage when no fonts are found.
+* Support shape modules with ranges beyond the BMP [Federic Zhang]
+* Use octal escapes rather than literal UTF-8 [Arnaud Charlet]
+* Use g_[sf]printf where appropriate [Matthias Clasen]
+* Doc improvements [Matthias]
+* Misc build and bug fixes [Tony Graham, Kjartan Maraas]
+
+Changes between 1.1.3 and 1.1.4
+
+* Fix the Arabic-words-broken-by-underlines problem by
+ stripping out non-shape affecting attributes then adding them
+ back after shaping.
+* Hangul shaper fixes [Changwoo Ryu, Jungshik Shin]
+* Handle compatability ideographs in basic-x shaper [Federic Zhang]
+* Rename function parameters to avoid shadowing system headres
+ [Soeren Sandmann]
+* Fix memory leak in Win32 backend [Tor Lillqvist]
+* Fix crasher problem with non-BMP characters [He Qiangqiang]
+* Implement pango_ft2_font_map_set_default_substitute() [Matthias Clasen]
+* Doc improvements [Matthias Clasen, Michael R. Walton, Jungshik Shin]
+* Misc bug and build fixes [Dagfinn I. Mannsåker, Tony Graham,
+ Dan Mills, Sebastian Wilhelmi]
+
+Changes between 1.1.2 and 1.1.3
+
+* Hangul module bug fixes and improvements [Changwoo Ryu, Jungshik Shin]
+ - Move rendering of precomposed characters to hangul-xft shaper
+ - Handle Hangul tone marks
+* Win32 improvements [Tor Lillqvist]
+ - Use Uniscribe when present
+* Some doc build fixes [Matthias Clasen]
+* Code cleanup [Manish Singh]
+* Fix assertion failure in PangoLayout [Alex Larsson]
+* Fix memory leak when freeing fontmaps [Sven Neumann]
+
+Changes between 1.1.1 and 1.1.2
+
+* Add a new wrap mode for PangoLayout - PANGO_WRAP_WORD_CHAR [Alex Larsson]
+* Win32 work [Tor Lillqvist]
+ - Handle choosing the right font for CJK languages based on language tags.
+ - Fix boxes showing up for tabs [Florent Duguet]
+ - Better handling of finding ASCII font names.
+ - Cygwin compilation fix [Masahiro Sakai]
+ - Fix --with-included-modules on win32 [Arnaud Charlet]
+ - Various build fixes and cleanups
+* Indic module improvements [Eric Mader]
+* Fixes to generic OpenType handling [Eric]
+* Improve language specific charset ordering basic-x11 [James Su, Brian Yuan]
+* Some merges of fixes by Werner Lemberg to the original
+ FreeType OpenType code.
+* Robustify and otherwise improve pango_color_parse() [Matthias Clasen]
+* Some cross-compiling fixes [J. Ali Harlow]
+* Bug fix for pango_scan_int() needed for recent GTK+.
+
+Changes between 1.1.0 and 1.1.1
+
+* Merge a lot of the code between the Xft and FT2 backend,
+ so that the FT2 backend gets the recent improvements to Xft.
+* Add proper language tag support to the Xft/FT2 backends.
+* Various effienciency fixes for the Xft/FT2 backends.
+
+Changes between 1.0.x and 1.1.0
+
+* Support for version 2 of the Xft library. [Keith Packard]
+* Convert the freetype backend over to using fontconfig,
+ instead of MiniXft for font cataloging.
+* A port of the Indic OpenType code from ICU to Pango. [Eric Mader]
+* A new hangul-xft [Changwoo Ryu]
+* Bug-fixes to the OpenType handling code.
+* Various cleanups to the PangoXft and PangoFT2 public APIs.
+* Docs switched over to DocBook XML. [Matthias Clasen]
+
+============================================================
+
+Changes between 1.0.3 and 1.0.4
+
+* Add Thai shaper for Xft [Theppitak Karoonboonyanan]
+* Support GB-18030, BIG5-HKSCS, CNS-11643, GBK encodings for
+ basic-x shaper [Qingjiang (Brian) Yuan]
+* Support ksc5601.1992-3 fonts in hangul-x shpaer
+ [Qingjiang (Brian) Yuan, Changwoo Ryu]
+* Support new Arabic characters in Unicode 3.2 [Roozbeh Pournader]
+* Bug fixes [Jacob Berkman, Arnaud Charlet, David L. Cooper II,
+ Choe Hwangjin, Alex Larsson, Sven Neumann, Matthias Warkus, Yao Zhang]
+
+Changes between 1.0.2 and 1.0.3
+
+* Change algorithm for mapping points to pixels on
+ Windows to match the system method. [Joaquin Cuenca Abela,
+ Tor Lillqvist]
+* Fix family listing for the FT2 backend. [Sven Neumann]
+* Fix memory leak in pango_font_real_get_metrics() [Matthias Clasen]
+* Some compilation warning fixes. [David L. Cooper II]
+* Fix passing attr_list == NULL to pango_parse_markip [Andreas J. Guelzow]
+
+Changes between 1.0.1 and 1.0.2
+
+* Support building with FreeType 2.1.0
+* List Sans,Serif,Monospace when listing fonts for the
+ Xft and FT2 backends. (Xavier Cho)
+* Portability fixes. (David L. Cooper II, Jacob Berkman)
+* Fix problem with pango-querymodules using g_print().
+
+Changes between 1.0.0 and 1.0.1
+
+* Documentation improvements [Matthias Clasen]
+* Use new API in FreeType 2.0.9 to greatly speed up coverage
+ calculation for Xft and FT2 backends.
+* Some fixes for reading of OpenType tables.
+* Add -D_REENTRANT to compilation when necessary. [Sven Neumann]
+* Try and enable ClearType for Win32 backend. [Tor Lillqvist]
+* Fixes for Korean glyphs in the basic-x shaper [Changwoo Ryu]
+* Improvements for computation of average char/digit width [Sven Neumann]
+* Bug and error reporting fixes
+ [Arnaud Charlet, Erwann Chenede, Mikael Hallendal, Stefan Israelsson,
+ Alex Larsson, Soeren Sandmann, Dan Winship]
+
+============================================================
+
+Changes between 1.0.0 rc2 and 1.0.0
+
+* Updated README files.
+* Minor build fixes [Tor Lillqvist, Jacob Berkman]
+
+Changes between 1.0.0 rc1 and 1.0.0 rc2
+
+* Fix missing weight names when parsing font names [Arnaud Charlet]
+* Build fixes [Martin Gansser, Manish Singh]
+
+Changes between 0.26 and 1.0.0 rc1
+
+* Try to build libraries with only shared library dependencies
+ on Xft to deal with transition to Xft2.
+* Efficiency improvements for Xft backend
+* Bug, build and portability fixes
+
+Contributors: Jacob Berkman, Abel Cheung, David L. Cooper II,
+ Miroslaw Dobrzanski-Neumann, , Dov Grobgeld, Alex Larsson, Tor Lillqvist,
+ Sven Neumann, Gediminas Paulauskas, Manish Singh, Raymond Wan,
+ Richard Warren.
+
+Changes between 0.25 and 0.26
+
+* Fixes for AIX compilation [Miroslaw Dobrzanski-Neumann]
+* Fix zero-width characters being displayed [Sven Neumann]
+* Add some padding to class structures [Owen Taylor]
+
+Changes between 0.24 and 0.25
+
+* Win32 fixes [Tor Lillqvist, Hans Breuer]
+* Cleanup of <ctype.h> [Darin Adler]
+* Bug and build fixes [Anders Carlsson, Sven Neumann, Havoc Pennington,
+ Morten Welinder]
+
+Changes between 0.23 and 0.24
+
+* Win32 backend improvements [Tor Lillqvist]
+* Doc improvements [Havoc Pennington, Dennis Bjorklund]
+* Fix problem where "foo\n" was treated as one paragraph by pango-layout,
+ not two. [Arjan J. Molenaar, Owen Taylor]
+* Add glyph caching to FT2 backend [Alex Larsson]
+* Try to make configure checks for Qt-based example more robust [Owen]
+* New example program for FT2 backend [Dov Grobgeld]
+* Arabic shaper for FT2 backend [Andreas Bogk, Sven Neumann]
+* Bug fixes
+
+Other contributors: Mikael Hermansson, Darin Adler, Hidetoshi Tajima, Zack Rusin,
+ Jacob Berkman, Jason Tackaberry, Evan Martin, Matthias Clasen
+
+Changes between 0.22 and 0.23
+
+* Documentation improvements [Matthias Clasen]
+* Win32 fixes [Hans Breuer]
+* Improve search for XftConfig [Manish Singh]
+* Fixes for crashes in Hangul shaper [Owen Taylor]
+* Improvements to Arabic shapers for X and Xft [Roozbeh Pournader]
+* Add jisx0212, jisx0201, Big5 support to basic shaper [HideToshi Tajima]
+* Many bug fixes
+
+Other contributors: Darin Adler, Dennis Dementiev, Sebastian Klemke,
+ Alex Larsson, Sven Neumann, Joshua Pritikin, Padraig O'Briain,
+ Kristian Rietveld, Sebastian Wilhelmi
+
+Changes between 0.21 and 0.22
+
+* Documentation improvements [Matthias Clasen]
+* Win32 fixes [Tor Lillqvist, Hans Breuer]
+* Improve line-breaking algorithm to not be O(n^2) [Alex Larsson]
+* API addition to render to Xrender drawable
+* Restructure so that "font sets" are handled by the core
+ for all backends [Alex]
+* Use the Xft font configuration scheme for the FT2 backend as well [Alex]
+
+Other Contributors: Darin Alder, Sven Neumann, Raymond Wan
+
+Changes between 0.20 and 0.21
+
+* Documentation improvements. [Matthias Clasen, Sven Neumann]
+* pango_break() now reports n + 1 attributes for n characters, not n. [Havoc Pennington]
+* Win32 fixes, including support for configure.in on Win32. [Tor Lillqvist]
+* Bug fixes [Tony Graham, Eric Lemings, Manish Singh, Sven Neumann, Matt Wilson,
+ Frank Belew]
+
+Changes between 0.19 and 0.20
+
+* Change PangoFontDescription to save values for unset fields
+* Fix for compilation with FreeType 2.0.4 [Havoc Pennington]
+* Add PANGO_TYPE_FONT_METRICS [James Henstridge]
+* Win32 fixes and updates [Hans Breuer
+* PangoLayout bug fixes [Alex Larsson, Padraig O'Briain]
+* Misc fixes and cleanups.
+
+Other contributors: Matthias Clasen, Tony Graham, Mario Motta, Sven Neumann
+
+Changes between 0.18 and 0.19
+
+* Change font listing API to be more extensible. Instead of
+ using family names and
+* Make PangoMetrics and PangoFontDescription opaque heap-allocated
+ structures to allow extension going forward.
+* Allow for PangoFontDescription structures with unspecified
+ style/variant/stretch/weight.
+* Add PANGO_ENABLE_BACKEND and PANGO_ENABLE_ENGINE #defines to
+ protect parts of the API where we don't want to guarantee
+ source binary compatibility for 1.x.
+* Bug fixes.
+
+Changes between 0.17 and 0.18
+
+* Add PangoLanguage type for language tags, use consistently.
+* Add support for different font orderings for different lanuages to
+ basic shaper.
+* Win32 fixes [Alex,Hans]
+* Add pango_context_get_metrics() to get metrics for a font description
+* Add GTypes for various types [James]
+* Lots of warning fixes [Darin]
+* Fix to PangoLayout for lines with only tabs on them [Matthias]
+* Improve compositing of glyphs for pangoft2 backend [Sven]
+* Export pango_color_parse().
+* Adapt to changes in GLib.
+* Build and bug fixes.
+
+Changes between 0.16 and 0.17
+
+* Build/bug fixes
+* Cursor motion is now by graphemes (logical editing units) rather than
+ by characters
+* Optionally support jumping cursor instead of split cursor
+
+Changes between 0.15 and 0.16
+
+* Ability to make newlines in a PangoLayout display as regular characters
+ (useful for, e.g., having an entry widget with embedded newlines.)
+* Build fixes
+* Bug fixes
+
+Changes between 0.14 and 0.15
+
+* New version of Tamil shaper from Vikram Subramanian
+* Update mini-fribidi to correspond to the latest FriBidi CVS
+* Win32 fixes
+* More documentation
+* Various minor bug and build fixes.
+
+
+Changes between 0.13 and 0.14
+
+* Win32 improvements [Tor]
+* Much better boundary resolution using algorithms from the Unicode
+ standard [Havoc]
+* Initial support for anti-aliased TrueType and OpenType fonts
+ using the Xft and Xrender libraries from XFree86 4. [Owen]
+* Fix the FreeType support on Unix so it can be used for the frame-buffer
+ port of GTK+. [Alex]
+* Fix up module building [Alex]
+* Add average-character-width font metric [Havoc]
+* Bug fixes
+
+
+Changes between 0.12 and 0.13
+
+* Win32 Support [Tor]
+* Per-display caching of font coverage on the root window [Owen]
+* Handling of embedded non-characters in PangoLayout [Elliot]
+* Mapping table fixes and improvements [KUSANO Takayuki, Abigail, Owen]
+* Adjustable tab handling in PangoLayout [Havoc]
+* Add relative font-scaling attribute [Havoc]
+* Add function to convert XML/GMarkup description to a PangoAttrList [Havoc]
+* New version of Arabic shaper [Karl]
+* Enhanced Indic support with ligature tables from the font and
+ many more languages [Abigail]
+* Include FriBidi core that provides the features that Pango needs and
+ can be used instead of separately installed fribidi. [Owen]
+* Add PangoLayoutIterator that abstracts the geometry operations for
+ iterating over the lines/items/clusters/chars in a layout [Havoc]
+* Bug fixes, and more bug fixes
+
+
+What is new in GScript 0.1:
+
+* Initial release
+
+
+# Local Variables:
+# coding: utf-8
+# End:
+# vim: encoding=utf-8:
diff --git a/trunk/README b/trunk/README
new file mode 100644
index 00000000..6499767b
--- /dev/null
+++ b/trunk/README
@@ -0,0 +1,95 @@
+Pango is a library for layout and rendering of text, with an emphasis
+on internationalization. Pango can be used anywhere that text layout
+is needed; however, most of the work on Pango so far has been done using
+the GTK+ widget toolkit as a test platform. Pango forms the core of text
+and font handling for GTK+-2.x.
+
+Pango is designed to be modular; the core Pango layout can be used
+with different font backends. There are three basic backends, with
+multiple options for rendering with each.
+
+ - Client side fonts using the FreeType and fontconfig libraries.
+ Rendering can be with with Cairo or Xft libraries, or directly
+ to an in-memory buffer with no additional libraries.
+
+ - Native fonts on Microsoft Windows using Uniscribe if available for
+ complex script handling. Rendering can be done via Cairo or
+ directly using the native Win32 API.
+
+ - Native fonts on MacOS X, rendering via Cairo.
+
+The integration of Pango with Cairo (http://cairographics.org)
+provides a complete solution with high quality text handling
+and graphics rendering.
+
+Dynamically loaded modules then handle text layout for particular
+combinations of script and font backend.
+
+As well as the low level layout rendering routines, Pango includes
+PangoLayout, a high level driver for laying out entire blocks of text,
+and routines to assist in editing internationalized text.
+
+For more information about Pango, see:
+
+ http://www.pango.org/
+
+Dependencies
+============
+
+Pango depends on version 2.12.0 or newer of the GLib library; more
+information about GLib can be found at http://www.gtk.org/.
+
+When using client side fonts, the fontconfig library
+(http://www.fontconfig.org) to look up fonts. At least version 2.0.9
+of the FreeType font handling library (http://www.freetype.org) is
+also required.
+
+Cairo support depends on the Cairo library (http://cairographics.org).
+The Cairo backend is the preferred backend to use Pango with and is
+subject of most of the development in the future. It has the
+advantage that the same code can be used for display and printing.
+
+We suggest using Pango with Cairo as described above, but you can also
+do X-specific rendering using the Xft library. The Xft backend uses
+version 2 of the Xft library to manage client side fonts. Version 2 of
+Xft is available from http://xlibs.freedesktop.org/release/. You'll
+need the libXft package, and possibly the libXrender and renderext
+packages as well. You'll also need fontconfig (see below.)
+
+Installation of Pango on Win32 is possible, but is not documented
+here. See http://www.gimp.org/~tml/gimp/win32/downloads.html
+
+Notes
+=====
+
+ - By default, Pango tries to build itself so that no explicit
+ dependency on Xft or FreeType will be introduced in apps that
+ link to Pango. This is to avoid compatibility problems with
+ changes in the Xft or FreeType API's or ABI's. Specifying
+ --enable-explicit-deps or --enable-static when configuring Pango
+ will defeat this and should be avoided if possible.
+
+License
+=======
+
+Most of the code of Pango is licensed under the terms of the
+GNU Lesser Public License (LGPL) - see the file COPYING for details.
+
+The OpenType code in pango/opentype is derived from the FreeType
+project (http://www.freetype.org) and is dual-licensed under the
+GNU General Public License and the FreeType license. See see
+pango/opentype/FT-license.txt for full details of the FreeType
+license.
+
+Note that binary distributions of Pango must include a disclaimer
+that the software is based in part of the work of the FreeType Team,
+in the distribution documentation; for instance, by including this
+README file.
+
+Owen Taylor
+otaylor@redhat.com
+
+Behdad Esfahbod
+behdad@gnome.org
+
+26 February 2007
diff --git a/trunk/README.win32 b/trunk/README.win32
new file mode 100644
index 00000000..68fcd8ab
--- /dev/null
+++ b/trunk/README.win32
@@ -0,0 +1,50 @@
+The Pango backends written for Win32 is pangowin32. Pangowin32 uses
+the Win32 GDI font API. GTK+ 2.8 and later on Win32 however actually
+uses the pangocairo backend (which then uses only small parts of
+pangowin32). Much of the GDI font API calls are in cairo.
+
+The pangoft2 backend was originally written with Win32 in mind, but
+its main use nowadays is on other platforms than Win32.
+
+There are two ways to build Pango for Win32:
+
+1) Use gcc (mingw), libtool, make, like on Unix.
+
+If building from CVS, run the autogen.sh script that runs aclocal,
+automake, autoconf and configure to build makefiles etc. This is what
+tml@novell.com uses. Pass the same switches to autogen.sh that you
+would pass to the configure script.
+
+If building from a tarball, just running the configure script and then
+make should be enough. But, as always, you need to understand what is
+happening and follow the progress in case manual intervention is
+needed.
+
+If you want to support complex scripts (which you should!), you need
+the usp10.h header from the Platform SDK. Otherwise the basic-win32
+shaper module won' use Uniscribe and for instance Arabic and Indic
+scripts will look like crap. (Yes, complex script support *is*
+important. It is one of the main selling points of GTK+ and Pango.)
+Pass the --with-usp10 flag to the configure script to tell it where
+you have the Platform SDK (or other source of an "usp10.h" or
+"include/usp10.h" file).
+
+tml ran the configure script like this when building binaries for
+Pango 1.10.0:
+
+PATH=/devel/dist/glib-2.8.0/bin:$PATH ACLOCAL_FLAGS="-I /devel/dist/glib-2.8.0/share/aclocal" PKG_CONFIG_PATH=/devel/dist/glib-2.8.0/lib/pkgconfig:$PKG_CONFIG_PATH CC='gcc -mtune=pentium3' CPPFLAGS='-I/opt/gnu/include' LDFLAGS='-L/opt/gnu/lib' CFLAGS=-O ./configure --disable-gtk-doc --with-usp10=/opt/psdk --without-x --prefix=c:/devel/target/pango-1.10.0
+
+The pango.modules file tends not to get automatically set up correctly
+on Win32. Check that. Also make sure you set up a pango.aliases file
+if you want to support non-Latin scripts. pango.aliases file used by
+tml looks like this:
+
+tahoma = "tahoma,browallia new,mingliu,simhei,gulimche,ms gothic,latha,mangal"
+sans = "arial,browallia new,mingliu,simhei,gulimche,ms gothic,latha,mangal"
+serif = "times new roman,angsana new,mingliu,simsun,gulimche,ms gothic,latha,mangal"
+monospace = "courier new,courier monothai,mingliu,simsun,gulimche,ms gothic,latha,mangal"
+
+2) Use MSVC and nmake. Use the makefile.msc makefiles. These makefiles
+are supported by Hans Breuer. They requires manual editing. You need
+to have the source code to some suitable version of glib in a sibling
+directory. Ask Hans for advice.
diff --git a/trunk/THANKS b/trunk/THANKS
new file mode 100644
index 00000000..286f60e6
--- /dev/null
+++ b/trunk/THANKS
@@ -0,0 +1,13 @@
+Abigail Brady (Indic shapers)
+Hans Breuer (Windows backend)
+Matthias Clasen (Documentation)
+Sivaraj Doddannan (Tamil shaper)
+Behdad Esfahbod
+Dov Grobgeld (Hebrew shaper)
+Karl Koehler (Arabic shaper)
+Alex Larsson (FreeType and Windows backends)
+Tor Lillqvist (FreeType and Windows backends)
+Changwoo Ryu (Hangul shaper)
+Havoc Pennington
+Roozbeh Pournader (Arabic shaper)
+Chookij Vanatham (Hebrew shaper)
diff --git a/trunk/acinclude.m4 b/trunk/acinclude.m4
new file mode 100644
index 00000000..48fd5d8e
--- /dev/null
+++ b/trunk/acinclude.m4
@@ -0,0 +1,57 @@
+
+# Checks the location of the XML Catalog
+# Usage:
+# JH_PATH_XML_CATALOG([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# Defines XMLCATALOG and XML_CATALOG_FILE substitutions
+AC_DEFUN([JH_PATH_XML_CATALOG],
+[
+ # check for the presence of the XML catalog
+ AC_ARG_WITH([xml-catalog],
+ AC_HELP_STRING([--with-xml-catalog=CATALOG],
+ [path to xml catalog to use]),,
+ [with_xml_catalog=/etc/xml/catalog])
+ jh_found_xmlcatalog=true
+ XML_CATALOG_FILE="$with_xml_catalog"
+ AC_SUBST([XML_CATALOG_FILE])
+ AC_MSG_CHECKING([for XML catalog ($XML_CATALOG_FILE)])
+ if test -f "$XML_CATALOG_FILE"; then
+ AC_MSG_RESULT([found])
+ else
+ jh_found_xmlcatalog=false
+ AC_MSG_RESULT([not found])
+ fi
+
+ # check for the xmlcatalog program
+ AC_PATH_PROG(XMLCATALOG, xmlcatalog, no)
+ if test "x$XMLCATALOG" = xno; then
+ jh_found_xmlcatalog=false
+ fi
+
+ if $jh_found_xmlcatalog; then
+ ifelse([$1],,[:],[$1])
+ else
+ ifelse([$2],,[AC_MSG_ERROR([could not find XML catalog])],[$2])
+ fi
+])
+
+# Checks if a particular URI appears in the XML catalog
+# Usage:
+# JH_CHECK_XML_CATALOG(URI, [FRIENDLY-NAME], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+AC_DEFUN([JH_CHECK_XML_CATALOG],
+[
+ AC_REQUIRE([JH_PATH_XML_CATALOG],[JH_PATH_XML_CATALOG(,[:])])dnl
+ AC_MSG_CHECKING([for ifelse([$2],,[$1],[$2]) in XML catalog])
+ if $jh_found_xmlcatalog && \
+ AC_RUN_LOG([$XMLCATALOG --noout "$XML_CATALOG_FILE" "$1" >&2]); then
+ AC_MSG_RESULT([found])
+ ifelse([$3],,,[$3
+])dnl
+ else
+ AC_MSG_RESULT([not found])
+ ifelse([$4],,
+ [AC_MSG_ERROR([could not find ifelse([$2],,[$1],[$2]) in XML catalog])],
+ [$4])
+ fi
+])
+
+
diff --git a/trunk/autogen.sh b/trunk/autogen.sh
new file mode 100755
index 00000000..9c2921ae
--- /dev/null
+++ b/trunk/autogen.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+REQUIRED_AUTOMAKE_VERSION=1.9
+
+PKG_NAME="pango"
+
+(test -f $srcdir/configure.in \
+ && test -f $srcdir/README \
+ && test -d $srcdir/pango) || {
+ echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+ echo " top-level $PKG_NAME directory"
+ exit 1
+}
+
+which gnome-autogen.sh || {
+ echo "You need to install gnome-common from the GNOME CVS"
+ exit 1
+}
+USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh
diff --git a/trunk/configure.in b/trunk/configure.in
new file mode 100644
index 00000000..cc8162af
--- /dev/null
+++ b/trunk/configure.in
@@ -0,0 +1,971 @@
+dnl Process this file with autoconf to create configure.
+AC_PREREQ(2.56)
+
+dnl ==========================================================================
+dnl Versioning
+dnl ==========================================================================
+
+dnl Making releases:
+dnl PANGO_VERSION_MICRO += 1;
+dnl PANGO_INTERFACE_AGE += 1;
+dnl PANGO_BINARY_AGE += 1;
+dnl if any functions have been added, set PANGO_INTERFACE_AGE to 0.
+dnl if backwards compatibility has been broken,
+dnl set PANGO_BINARY_AGE _and_ PANGO_INTERFACE_AGE to 0.
+
+dnl
+dnl We do the version number components as m4 macros
+dnl so that we can base configure --help output off
+dnl of them.
+dnl
+
+dnl The triplet
+m4_define([pango_version_major], [1])
+m4_define([pango_version_minor], [17])
+m4_define([pango_version_micro], [5])
+m4_define([pango_version],
+ [pango_version_major.pango_version_minor.pango_version_micro])
+dnl The X.Y in -lpango-X.Y line. This is expected to stay 1.0 until Pango 2.
+m4_define([pango_api_version], [1.0])
+dnl Number of releases since we've added interfaces
+m4_define([pango_interface_age], [0])
+dnl Number of releases since we've broken binary compatibility.
+m4_define([pango_binary_age],
+ [m4_eval(100 * pango_version_minor + pango_version_micro)])
+dnl Module API version. This should be stepped up when a change causes
+dnl older modules to not work with new pango.
+m4_define([pango_module_version], [1.6.0])
+
+
+AC_INIT(pango, pango_version(),
+ [http://bugzilla.gnome.org/enter_bug.cgi?product=pango])
+
+AC_CONFIG_SRCDIR([ChangeLog])
+
+AM_INIT_AUTOMAKE(1.9 gnits dist-bzip2 no-dist-gzip)
+AM_CONFIG_HEADER([config.h])
+
+
+PANGO_VERSION_MAJOR=pango_version_major()
+PANGO_VERSION_MINOR=pango_version_minor()
+PANGO_VERSION_MICRO=pango_version_micro()
+PANGO_VERSION=pango_version()
+PANGO_API_VERSION=pango_api_version()
+PANGO_INTERFACE_AGE=pango_interface_age()
+PANGO_BINARY_AGE=pango_binary_age()
+PANGO_MODULE_VERSION=pango_module_version()
+
+AC_SUBST(PANGO_VERSION_MAJOR)
+AC_SUBST(PANGO_VERSION_MINOR)
+AC_SUBST(PANGO_VERSION_MICRO)
+AC_SUBST(PANGO_VERSION)
+AC_SUBST(PANGO_API_VERSION)
+AC_SUBST(PANGO_INTERFACE_AGE)
+AC_SUBST(PANGO_BINARY_AGE)
+AC_SUBST(PANGO_MODULE_VERSION)
+
+AC_DEFINE(MODULE_VERSION, "pango_module_version()", [Module interface version])
+AC_DEFINE(PANGO_BINARY_AGE, pango_binary_age(), [PANGO binary age])
+AC_DEFINE(PANGO_INTERFACE_AGE, pango_interface_age(), [PANGO interface age])
+AC_DEFINE(PANGO_VERSION_MAJOR, pango_version_major(), [PANGO major version])
+AC_DEFINE(PANGO_VERSION_MINOR, pango_version_minor(), [PANGO minor version])
+AC_DEFINE(PANGO_VERSION_MICRO, pango_version_micro(), [PANGO micro version])
+
+dnl libtool versioning
+m4_define([lt_current], [m4_eval(100 * pango_version_minor + pango_version_micro - pango_interface_age)])
+m4_define([lt_revision], [pango_interface_age])
+m4_define([lt_age], [m4_eval(pango_binary_age - pango_interface_age)])
+VERSION_INFO="lt_current():lt_revision():lt_age()"
+PANGO_CURRENT_MINUS_AGE=m4_eval(lt_current - lt_age)
+
+AC_SUBST(PANGO_CURRENT_MINUS_AGE)
+
+dnl ==========================================================================
+
+AC_CANONICAL_HOST
+
+AC_MSG_CHECKING([for native Win32])
+case "$host" in
+ *-*-mingw*)
+ pango_os_win32=yes
+ ;;
+ *)
+ pango_os_win32=no
+ ;;
+esac
+AC_MSG_RESULT([$pango_os_win32])
+AM_CONDITIONAL(OS_WIN32, test "$pango_os_win32" = "yes")
+
+AC_PROG_CC
+
+dnl
+dnl Check for a working C++ compiler, but do not bail out, if none is found.
+dnl We use this for an automated test for C++ header correctness.
+dnl
+AC_CHECK_PROGS(CXX, [$CCC c++ g++ gcc CC cxx cc++ cl], gcc)
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_TRY_COMPILE(,[class a { int b; } c;], ,CXX=)
+AM_CONDITIONAL(HAVE_CXX, test "$CXX" != "")
+AC_LANG_RESTORE
+
+AC_LIBTOOL_WIN32_DLL
+AM_DISABLE_STATIC
+
+if test "$pango_os_win32" = "yes"; then
+ if test x$enable_static = xyes -o x$enable_static = x; then
+ AC_MSG_WARN([Disabling static library build, must build as DLL on Windows.])
+ enable_static=no
+ fi
+ if test x$enable_shared = xno; then
+ AC_MSG_WARN([Enabling shared library build, must build as DLL on Windows.])
+ fi
+ enable_shared=yes
+fi
+
+AM_PROG_LIBTOOL
+
+AC_MSG_CHECKING([for some Win32 platform])
+case "$host" in
+ *-*-mingw*|*-*-cygwin*)
+ pango_platform_win32=yes
+ ;;
+ *)
+ pango_platform_win32=no
+ ;;
+esac
+AC_MSG_RESULT([$pango_platform_win32])
+AM_CONDITIONAL(PLATFORM_WIN32, test "$pango_platform_win32" = "yes")
+
+if test "$pango_os_win32" = "yes"; then
+ AC_CHECK_TOOL(WINDRES, windres, no)
+ if test "$WINDRES" = no; then
+ AC_MSG_ERROR([*** Could not find an implementation of windres in your PATH.])
+ fi
+ AC_CHECK_PROG(ms_librarian, lib.exe, yes, no)
+fi
+AM_CONDITIONAL(MS_LIB_AVAILABLE, test x$ms_librarian = xyes)
+
+changequote(,)dnl
+if test "x$GCC" = "xyes"; then
+ case " $CFLAGS " in
+ *[\ \ ]-Wall[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wall" ;;
+ esac
+fi
+changequote([,])dnl
+
+dnl declare --enable-* args and collect ac_help strings
+
+m4_define([debug_default],
+ m4_if(m4_eval(pango_version_minor() % 2), [1], [yes], [minimum]))
+
+AC_ARG_ENABLE(debug,
+ AC_HELP_STRING([--enable-debug=@<:@no/minimum/yes@:>@],
+ [turn on debugging @<:@default=debug_default()@:>@]),
+ ,
+ enable_debug=debug_default())
+
+if test "x$enable_debug" = "xyes"; then
+ PANGO_DEBUG_FLAGS="-DPANGO_ENABLE_DEBUG"
+else
+ PANGO_DEBUG_FLAGS="-DG_DISABLE_CAST_CHECKS"
+
+ if test "x$enable_debug" = "xno"; then
+ PANGO_DEBUG_FLAGS="$GLIB_DEBUG_FLAGS -DG_DISABLE_ASSERT -DG_DISABLE_CHECKS $PANGO_DEBUG_FLAGS"
+ fi
+fi
+
+AC_SUBST(PANGO_DEBUG_FLAGS)
+
+AC_ARG_ENABLE(rebuilds,
+ [AC_HELP_STRING([--disable-rebuilds],
+ [disable all source autogeneration rules])],,
+ [enable_rebuilds=yes])
+
+AM_CONDITIONAL(CROSS_COMPILING, [test $cross_compiling = yes])
+
+# define a MAINT-like variable REBUILD which is set if Perl
+# is found, so autogenerated sources can be rebuilt
+
+AC_CHECK_PROGS(PERL, perl5 perl)
+
+REBUILD=\#
+if test "x$enable_rebuilds" = "xyes" && \
+ test -n "$PERL" && \
+ $PERL -e 'exit !($] >= 5.002)' > /dev/null 2>&1 ; then
+ REBUILD=
+fi
+AC_SUBST(REBUILD)
+
+have_x=false
+if test "x$pango_os_win32" != xyes; then
+ AC_PATH_XTRA
+
+ if test x$no_x = xyes ; then
+ AC_MSG_WARN([X development libraries not found])
+ have_x=false
+ else
+ X_LIBS="$X_LIBS -lX11"
+ have_x=true
+ AC_DEFINE(HAVE_X, 1, [Have X libraries])
+ fi
+fi
+AM_CONDITIONAL(HAVE_X, $have_x)
+
+have_fontconfig=false
+have_freetype=false
+have_xft=false
+
+#
+# Check for fontconfig
+#
+PKG_CHECK_MODULES(FONTCONFIG, fontconfig >= 1.0.1, have_fontconfig=true, AC_MSG_RESULT([no]))
+
+if $have_fontconfig ; then
+ #
+ # Checks for FreeType
+ #
+ FREETYPE_LIBS=
+ FREETYPE_CFLAGS=
+ AC_PATH_PROG(FREETYPE_CONFIG, freetype-config, no)
+ if test "x$FREETYPE_CONFIG" != "xno" ; then
+ FREETYPE_CFLAGS=`$FREETYPE_CONFIG --cflags`
+ FREETYPE_LIBS=`$FREETYPE_CONFIG --libs`
+
+ pango_save_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $FREETYPE_LIBS"
+ AC_CHECK_LIB(freetype, FT_Get_Next_Char, have_freetype=true, :)
+ LDFLAGS=$pango_save_ldflags
+ fi
+
+ FREETYPE_LIBS="$FONTCONFIG_LIBS $FREETYPE_LIBS"
+ FREETYPE_CFLAGS="$FONTCONFIG_CFLAGS $FREETYPE_CFLAGS"
+
+ AC_SUBST(FREETYPE_LIBS)
+ AC_SUBST(FREETYPE_CFLAGS)
+ AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library])
+
+ #
+ # Checks for Xft/XRender
+ #
+ if $have_x && $have_freetype ; then
+ PKG_CHECK_MODULES(XFT, xft >= 2.0.0 xrender, have_xft=true, AC_MSG_RESULT([no]))
+ if $have_xft ; then
+ AC_DEFINE(HAVE_XFT, 1, [Have Xft library])
+ fi
+ fi
+elif test "x$pango_os_win32" != xyes; then
+ AC_MSG_WARN([No fontconfig found, skipping tests for FreeType and Xft])
+fi
+
+AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
+AM_CONDITIONAL(HAVE_XFT, $have_xft)
+
+#
+# Checks for Win32 GDI
+#
+have_win32=false
+WIN32_LIBS=""
+WIN32_CFLAGS=""
+# The following doesn't work with autoconf-2.13, so we check $host instead
+# AC_CHECK_LIB(gdi32, GetTextMetricsA@8, have_win32=true, : )
+case "$host" in
+ *-*-mingw*|*-*-cygwin*) have_win32=true ;;
+esac
+
+
+if test $have_win32 = true; then
+ WIN32_LIBS="-lgdi32"
+fi
+
+AC_SUBST(WIN32_LIBS)
+AM_CONDITIONAL(HAVE_WIN32, $have_win32)
+
+# Ensure MSVC-compatible struct packing convention is used when
+# compiling for Win32 with gcc.
+# What flag to depends on gcc version: gcc3 uses "-mms-bitfields", while
+# gcc2 uses "-fnative-struct".
+if test "$pango_os_win32" = "yes"; then
+ if test x"$GCC" = xyes; then
+ msnative_struct=''
+ AC_MSG_CHECKING([how to get MSVC-compatible struct packing])
+ if test -z "$ac_cv_prog_CC"; then
+ our_gcc="$CC"
+ else
+ our_gcc="$ac_cv_prog_CC"
+ fi
+ case `$our_gcc --version | sed -e 's,\..*,.,' -e q` in
+ 2.)
+ if $our_gcc -v --help 2>/dev/null | grep fnative-struct >/dev/null; then
+ msnative_struct='-fnative-struct'
+ fi
+ ;;
+ *)
+ if $our_gcc -v --help 2>/dev/null | grep ms-bitfields >/dev/null; then
+ msnative_struct='-mms-bitfields'
+ fi
+ ;;
+ esac
+ if test x"$msnative_struct" = x ; then
+ AC_MSG_RESULT([no way])
+ AC_MSG_WARN([produced libraries might be incompatible with MSVC-compiled code])
+ else
+ CFLAGS="$CFLAGS $msnative_struct"
+ AC_MSG_RESULT([${msnative_struct}])
+ fi
+ fi
+fi
+
+#
+# Checks for ATSUI
+#
+AC_CHECK_HEADER(Carbon/Carbon.h, [have_atsui=true], [have_atsui=true])
+
+#
+# Checks for Cairo
+#
+have_cairo=false
+have_cairo_png=false
+have_cairo_ps=false
+have_cairo_pdf=false
+have_cairo_xlib=false
+have_cairo_freetype=false
+have_cairo_win32=false
+have_cairo_atsui=false
+
+PKG_CHECK_MODULES(CAIRO, cairo >= 1.2.6, have_cairo=true, AC_MSG_RESULT([no]))
+
+if $have_cairo ; then
+ pango_save_ldflags=$LDFLAGS
+ m4_pattern_allow([PKG_CONFIG_DISABLE_UNINSTALLED])
+ INSTALLED_CAIRO_LIBS=`PKG_CONFIG_DISABLE_UNINSTALLED=yes $PKG_CONFIG --libs cairo`
+ LDFLAGS="$LDFLAGS $INSTALLED_CAIRO_LIBS"
+
+
+ AC_CHECK_LIB(cairo, cairo_surface_write_to_png, have_cairo_png=true, :)
+ if $have_cairo_png; then
+ AC_DEFINE(HAVE_CAIRO_PNG, 1, [Whether Cairo has PNG support])
+ fi
+
+ AC_CHECK_LIB(cairo, cairo_ps_surface_create, have_cairo_ps=true, :)
+ if $have_cairo_ps; then
+ AC_DEFINE(HAVE_CAIRO_PS, 1, [Whether Cairo has PS support])
+ fi
+
+ AC_CHECK_LIB(cairo, cairo_pdf_surface_create, have_cairo_pdf=true, :)
+ if $have_cairo_pdf; then
+ AC_DEFINE(HAVE_CAIRO_PDF, 1, [Whether Cairo has PDF support])
+ fi
+
+ AC_CHECK_LIB(cairo, cairo_xlib_surface_create, have_cairo_xlib=true, :)
+ if $have_cairo_xlib; then
+ AC_DEFINE(HAVE_CAIRO_XLIB, 1, [Whether Cairo has Xlib support])
+ fi
+
+ have_cairo=false
+
+ AC_CHECK_LIB(cairo, cairo_win32_scaled_font_select_font, have_cairo_win32=true, :)
+ if $have_cairo_win32 && $have_win32; then
+ AC_DEFINE(HAVE_CAIRO_WIN32, 1, [Whether Cairo uses the Win32 GDI for fonts])
+ have_cairo=true
+ fi
+
+ AC_CHECK_LIB(cairo, cairo_ft_scaled_font_lock_face, have_cairo_freetype=true, :)
+ if $have_cairo_freetype && $have_freetype ; then
+ AC_DEFINE(HAVE_CAIRO_FREETYPE, 1, [Whether Cairo uses FreeType for fonts])
+ have_cairo=true
+ fi
+
+ AC_CHECK_LIB(cairo, cairo_atsui_font_face_create_for_atsu_font_id, have_cairo_atsui=true, :)
+ if $have_cairo_atsui && $have_atsui ; then
+ AC_DEFINE(HAVE_CAIRO_ATSUI, 1, [Whether Cairo uses ATSUI for fonts])
+ have_cairo=true
+ fi
+
+ if $have_cairo ; then
+ AC_DEFINE(HAVE_CAIRO, 1, [Have usable Cairo library and font backend])
+ fi
+
+ LDFLAGS=$pango_save_ldflags
+fi
+
+AM_CONDITIONAL(HAVE_CAIRO, $have_cairo)
+AM_CONDITIONAL(HAVE_CAIRO_PNG, $have_cairo_png)
+AM_CONDITIONAL(HAVE_CAIRO_PS, $have_cairo_ps)
+AM_CONDITIONAL(HAVE_CAIRO_PDF, $have_cairo_pdf)
+AM_CONDITIONAL(HAVE_CAIRO_XLIB, $have_cairo_xlib)
+AM_CONDITIONAL(HAVE_CAIRO_WIN32, $have_cairo_win32 && $have_win32)
+AM_CONDITIONAL(HAVE_CAIRO_FREETYPE, $have_cairo_freetype && $have_freetype)
+AM_CONDITIONAL(HAVE_CAIRO_ATSUI, $have_cairo_atsui && $have_atsui)
+
+#
+# We must have some backend defined, in order for the pango-querymodules
+# rule in pango/Makefile.am to work correctly. If you are up to writing
+# a new Pango backend outside of Pango, you are up to sending the necessary
+# patch to fix that rule. :-)
+#
+if $have_freetype || $have_x || $have_xft || $have_win32 || $have_cairo_atsui ; then : ; else
+ AC_MSG_ERROR([*** Didn't find any of FreeType, X11, ATSUI, or Win32.
+*** Must have at least one backend to build Pango.])
+fi
+
+#
+# Checks for GLib
+#
+GLIB_REQUIRED_VERSION=2.12.0
+GLIB_MODULES="glib-2.0 >= $GLIB_REQUIRED_VERSION gobject-2.0 gmodule-no-export-2.0"
+
+PKG_CHECK_MODULES(GLIB, $GLIB_MODULES, :,
+ AC_MSG_ERROR([
+*** Glib $GLIB_REQUIRED_VERSION or better is required. The latest version of
+*** Glib is always available from ftp://ftp.gtk.org/.]))
+
+# Add in gthread-2.0 to CFLAGS but not to LIBS so we get any
+# necesary defines for thread-safety.
+GLIB_CFLAGS=`$PKG_CONFIG --cflags $GLIB_MODULES gthread-2.0`
+
+# See if it's safe to turn G_DISABLE_DEPRECATED on.
+GLIB_VERSION_MAJOR_MINOR=`$PKG_CONFIG --modversion glib-2.0 | sed "s/\.@<:@^.@:>@*\$//"`
+GLIB_REQUIRED_VERSION_MAJOR_MINOR=`echo $GLIB_REQUIRED_VERSION | sed "s/\.@<:@^.@:>@*\$//"`
+if test "x$GLIB_VERSION_MAJOR_MINOR" = "x$GLIB_REQUIRED_VERSION_MAJOR_MINOR"; then
+ GLIB_CFLAGS="-DG_DISABLE_DEPRECATED $GLIB_CFLAGS"
+fi
+
+#
+# Checks for LibThai
+#
+have_libthai=false
+LIBTHAI_REQUIRED_VERSION=0.1.7
+PKG_CHECK_MODULES(LIBTHAI, libthai >= $LIBTHAI_REQUIRED_VERSION, have_libthai=true, AC_MSG_RESULT([no]))
+
+#
+# Modules to build
+#
+arabic_modules="arabic-fc,arabic-lang"
+basic_modules="basic-fc,basic-win32,basic-x,basic-atsui"
+hangul_modules="hangul-fc"
+hebrew_modules="hebrew-fc"
+indic_modules="indic-fc,indic-lang"
+khmer_modules="khmer-fc"
+syriac_modules="syriac-fc"
+thai_modules="thai-fc"
+tibetan_modules="tibetan-fc"
+
+if $have_libthai ; then
+ thai_modules="$thai_modules,thai-lang"
+fi
+
+all_modules="$arabic_modules,$basic_modules,$hangul_modules,$hebrew_modules,$indic_modules,$khmer_modules,$syriac_modules,$thai_modules,$tibetan_modules"
+
+#
+# Allow building some or all modules included
+#
+AC_MSG_CHECKING(modules to link statically)
+
+AC_ARG_WITH(included_modules,
+ AC_HELP_STRING([--with-included-modules=no/yes/MODULE1 MODULE2 ...],
+ [build the given modules included @<:@default=no@:>@]))
+
+included_modules=""
+case x$with_included_modules in
+ xyes) included_modules=$all_modules ;;
+ xno|x) included_modules="" ;;
+ *) included_modules=$with_included_modules ;;
+esac
+AC_MSG_RESULT($included_modules)
+AM_CONDITIONAL(HAVE_INCLUDED_MODULES, test "x$included_modules" != x)
+
+#
+# Allow building only some or none of modules dynamic
+#
+AC_MSG_CHECKING(dynamic modules to build)
+
+AC_ARG_WITH(dynamic_modules,
+ AC_HELP_STRING([--with-dynamic-modules=no/yes/MODULE1 MODULE2 ...],
+ [build the given dynamic modules @<:@default=yes@:>@]))
+
+dynamic_modules=""
+case x$with_dynamic_modules in
+ xyes|x) dynamic_modules=$all_modules ;;
+ xno) dynamic_modules="" ;;
+ *) dynamic_modules=$with_dynamic_modules ;;
+esac
+AC_MSG_RESULT([$dynamic_modules (those built into Pango will be excluded)])
+AM_CONDITIONAL(HAVE_DYNAMIC_MODULES, test "x$dynamic_modules" != x)
+
+
+INCLUDED_X_MODULES=
+INCLUDED_FC_MODULES=
+INCLUDED_WIN32_MODULES=
+INCLUDED_ATSUI_MODULES=
+INCLUDED_LANG_MODULES=
+
+AC_SUBST(INCLUDED_X_MODULES)
+AC_SUBST(INCLUDED_FC_MODULES)
+AC_SUBST(INCLUDED_WIN32_MODULES)
+AC_SUBST(INCLUDED_ATSUI_MODULES)
+AC_SUBST(INCLUDED_LANG_MODULES)
+
+IFS="${IFS= }"; pango_save_ifs="$IFS"; IFS=", "
+for module in $included_modules; do
+ case $indic_modules in
+ *$module*) dir=indic ;;
+ *) dir=`echo $module | sed "s/-.*//"` ;;
+ esac
+ included_path="\$(top_builddir)/modules/$dir/libpango-$module.la"
+
+ case $module in
+ *-x) INCLUDED_X_MODULES="$INCLUDED_X_MODULES $included_path" ;;
+ *-fc) INCLUDED_FC_MODULES="$INCLUDED_FC_MODULES $included_path" ;;
+ *-win32) INCLUDED_WIN32_MODULES="$INCLUDED_WIN32_MODULES $included_path" ;;
+ *-atsui) INCLUDED_ATSUI_MODULES="$INCLUDED_ATSUI_MODULES $included_path" ;;
+ *-lang) INCLUDED_LANG_MODULES="$INCLUDED_LANG_MODULES $included_path" ;;
+ *) AC_MSG_ERROR([specified module $module not recognized]) ;;
+ esac
+done
+IFS="$pango_save_ifs"
+
+AM_CONDITIONAL(INCLUDE_ARABIC_FC, echo $included_modules | egrep '(^|,)arabic-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_ARABIC_LANG, echo $included_modules | egrep '(^|,)arabic-lang($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_BASIC_FC, echo $included_modules | egrep '(^|,)basic-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_BASIC_WIN32, echo $included_modules | egrep '(^|,)basic-win32($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_BASIC_X, echo $included_modules | egrep '(^|,)basic-x($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_BASIC_ATSUI, echo $included_modules | egrep '(^|,)basic-atsui($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_HANGUL_FC, echo $included_modules | egrep '(^|,)hangul-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_HEBREW_FC, echo $included_modules | egrep '(^|,)hebrew-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_INDIC_FC, echo $included_modules | egrep '(^|,)indic-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_INDIC_LANG, echo $included_modules | egrep '(^|,)indic-lang($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_KHMER_FC, echo $included_modules | egrep '(^|,)khmer-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_SYRIAC_FC, echo $included_modules | egrep '(^|,)syriac-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_THAI_FC, echo $included_modules | egrep '(^|,)thai-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_THAI_LANG, echo $included_modules | egrep '(^|,)thai-lang($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_TIBETAN_FC, echo $included_modules | egrep '(^|,)tibetan-fc($|,)' > /dev/null)
+
+AM_CONDITIONAL(DYNAMIC_ARABIC_FC, echo $dynamic_modules | egrep '(^|,)arabic-fc($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_ARABIC_LANG, echo $dynamic_modules | egrep '(^|,)arabic-lang($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_BASIC_FC, echo $dynamic_modules | egrep '(^|,)basic-fc($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_BASIC_WIN32, echo $dynamic_modules | egrep '(^|,)basic-win32($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_BASIC_X, echo $dynamic_modules | egrep '(^|,)basic-x($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_BASIC_ATSUI, echo $dynamic_modules | egrep '(^|,)basic-atsui($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_HANGUL_FC, echo $dynamic_modules | egrep '(^|,)hangul-fc($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_HEBREW_FC, echo $dynamic_modules | egrep '(^|,)hebrew-fc($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_INDIC_FC, echo $dynamic_modules | egrep '(^|,)indic-fc($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_INDIC_LANG, echo $dynamic_modules | egrep '(^|,)indic-lang($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_KHMER_FC, echo $dynamic_modules | egrep '(^|,)khmer-fc($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_SYRIAC_FC, echo $dynamic_modules | egrep '(^|,)syriac-fc($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_THAI_FC, echo $dynamic_modules | egrep '(^|,)thai-fc($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_THAI_LANG, echo $dynamic_modules | egrep '(^|,)thai-lang($|,)' > /dev/null)
+AM_CONDITIONAL(DYNAMIC_TIBETAN_FC, echo $dynamic_modules | egrep '(^|,)tibetan-fc($|,)' > /dev/null)
+
+#
+# We use flockfile to implement pango_getline() - should be moved to GLib
+# strtok_r isn't present on some systems
+#
+AC_CHECK_FUNCS(flockfile strtok_r)
+
+dnl **************************
+dnl *** Checks for gtk-doc ***
+dnl **************************
+
+if $have_cairo ; then : ; else
+ if test x$enable_gtk_doc = xyes ; then
+ AC_MSG_WARN([Cairo not present, disabling doc building])
+ enable_gtk_doc=no
+ fi
+fi
+
+GTK_DOC_CHECK([1.0])
+
+AC_ARG_ENABLE(man,
+ AC_HELP_STRING([--enable-man],
+ [regenerate man pages from Docbook @<:@default=no@:>@]),
+ enable_man=yes,
+ enable_man=no)
+
+if test "x$enable_man" != xno ; then
+ dnl
+ dnl Check for xsltproc
+ dnl
+ AC_PATH_PROG([XSLTPROC], [xsltproc])
+ if test -z "$XSLTPROC"; then
+ enable_man=no
+ fi
+fi
+
+if test "x$enable_man" != xno ; then
+ dnl check for DocBook DTD and stylesheets in the local catalog.
+ JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.1.2//EN],
+ [DocBook XML DTD V4.1.2],,enable_man=no)
+ JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
+ [DocBook XSL Stylesheets],,enable_man=no)
+fi
+
+AM_CONDITIONAL(ENABLE_MAN, test x$enable_man != xno)
+
+AC_ARG_ENABLE(doc-cross-references,
+ AC_HELP_STRING([--disable-doc-cross-references],
+ [cross reference glib and cairo symbols @<:@default=yes@:>@]),
+ enable_doc_cross_references=$enableval,
+ enable_doc_cross_references=yes)
+
+if test "x$enable_doc_cross_references" != xno ; then
+ GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
+ CAIRO_PREFIX="`pkg-config --variable=prefix cairo`"
+ AC_SUBST(GLIB_PREFIX)
+ AC_SUBST(CAIRO_PREFIX)
+fi
+AM_CONDITIONAL(ENABLE_DOC_CROSS_REFERENCES, test x$enable_doc_cross_references != xno)
+
+dnl ********************************************************
+dnl * Options to pass to libtool
+dnl ********************************************************
+
+# Note that -module isn't included here since automake needs to see it to know
+# that something like pango-arabic-fc.la is a valid libtool archive
+#
+LIBRARY_LIBTOOL_OPTIONS="-version-info $VERSION_INFO"
+MODULE_LIBTOOL_OPTIONS="-export-dynamic -avoid-version"
+if test "$pango_os_win32" = yes; then
+ # We currently use .def files on Windows
+ true
+ LIBRARY_LIBTOOL_OPTIONS="$LIBRARY_LIBTOOL_OPTIONS -no-undefined"
+ MODULE_LIBTOOL_OPTIONS="$MODULE_LIBTOOL_OPTIONS -no-undefined"
+else
+ # libtool option to control which symbols are exported
+ # right now, symbols starting with '_' are not exported
+ LIBRARY_LIBTOOL_OPTIONS="$LIBRARY_LIBTOOL_OPTIONS "'-export-symbols-regex "^pango_.*"'
+ MODULE_LIBTOOL_OPTIONS="$MODULE_LIBTOOL_OPTIONS "'-export-symbols-regex "^script_engine_.*"'
+fi
+AC_SUBST(LIBRARY_LIBTOOL_OPTIONS)
+AC_SUBST(MODULE_LIBTOOL_OPTIONS)
+
+dnl ********************************************************
+dnl * See whether we need to load our modules as .la files *
+dnl ********************************************************
+
+use_la_modules=false
+
+# is there any platform that we have to use .la files?
+
+if $use_la_modules ; then
+ AC_DEFINE(USE_LA_MODULES, 1, [Whether to load modules via .la files rather than directly])
+fi
+
+dnl ******************************************************
+dnl * See whether to include shared library dependencies *
+dnl ******************************************************
+
+AC_ARG_ENABLE(explicit-deps,
+ AC_HELP_STRING([--enable-explicit-deps=@<:@no/auto/yes@:>@],
+ [use explicit dependencies in .pc files @<:@default=auto@:>@]),
+ enable_explicit_deps="$enableval",
+ enable_explicit_deps=auto)
+
+AC_MSG_CHECKING([Whether to write dependencies into .pc files])
+case $enable_explicit_deps in
+ auto)
+ export SED
+ deplibs_check_method=`(./libtool --config; echo 'eval echo $deplibs_check_method') | sh`
+ if test "x$deplibs_check_method" '!=' xpass_all || test "x$enable_static" = xyes ; then
+ enable_explicit_deps=yes
+ else
+ enable_explicit_deps=no
+ fi
+ ;;
+ yes|no)
+ ;;
+ *) AC_MSG_ERROR([Value given to --enable-explicit-deps must be one of yes, no or auto])
+ ;;
+esac
+AC_MSG_RESULT($enable_explicit_deps)
+
+PKGCONFIG_X_LIBS=
+PKGCONFIG_XFT_LIBS=
+PKGCONFIG_FREETYPE_LIBS=
+PKGCONFIG_MATH_LIBS=
+PKGCONFIG_CAIRO_LIBS=
+
+if test $enable_explicit_deps = yes ; then
+ PKGCONFIG_X_LIBS="$X_LIBS $X_EXTRA_LIBS"
+ PKGCONFIG_XFT_LIBS=$XFT_LIBS
+ PKGCONFIG_FREETYPE_LIBS=$FREETYPE_LIBS
+ PKGCONFIG_MATH_LIBS=-lm
+ PKGCONFIG_CAIRO_LIBS=$FREETYPE_LIBS
+ if $have_cairo_freetype ; then
+ PKGCONFIG_CAIRO_REQUIRES=pangoft2
+ fi
+fi
+
+AC_SUBST(PKGCONFIG_X_LIBS)
+AC_SUBST(PKGCONFIG_XFT_LIBS)
+AC_SUBST(PKGCONFIG_FREETYPE_LIBS)
+AC_SUBST(PKGCONFIG_MATH_LIBS)
+AC_SUBST(PKGCONFIG_CAIRO_LIBS)
+AC_SUBST(PKGCONFIG_CAIRO_REQUIRES)
+AM_CONDITIONAL(DISABLE_EXPLICIT_DEPS, test $enable_explicit_deps = no)
+
+AC_CONFIG_COMMANDS([pango/module-defs.h],
+[
+cat > pango/module-defs.h <<EOTEXT
+/* Autogenerated by configure. Do not edit */
+
+#include "modules.h"
+
+EOTEXT
+
+IFS="${IFS= }"; pango_save_ifs="$IFS"; IFS=","
+for module in $included_modules; do
+ module_c=`echo $module | sed s/-/_/`
+ cat >> pango/module-defs.h <<EOTEXT
+extern void _pango_${module_c}_script_engine_list (PangoEngineInfo **engines, int *n_engines);
+extern PangoEngine *_pango_${module_c}_script_engine_init (GTypeModule *module);
+extern void _pango_${module_c}_script_engine_exit (void);
+extern void _pango_${module_c}_script_engine_create (const char *id);
+
+EOTEXT
+done
+
+IFS="$pango_save_ifs"
+],[
+included_modules=$included_modules
+])
+
+AC_CONFIG_COMMANDS([pango/module-defs-x.c],
+[
+### X modules
+cat > pango/module-defs-x.c <<EOTEXT
+/* Autogenerated by configure. Do not edit */
+
+#include "module-defs.h"
+
+PangoIncludedModule _pango_included_x_modules@<:@@:>@ = {
+EOTEXT
+
+IFS="${IFS= }"; pango_save_ifs="$IFS"; IFS=","
+for module in $included_modules; do
+ if echo $module | egrep -- "-x($|,)" > /dev/null; then
+ module_c=`echo $module | sed s/-/_/`
+ cat >> pango/module-defs-x.c <<EOTEXT
+ { _pango_${module_c}_script_engine_list, _pango_${module_c}_script_engine_init, _pango_${module_c}_script_engine_exit, _pango_${module_c}_script_engine_create },
+EOTEXT
+ fi
+done
+
+IFS="$pango_save_ifs"
+
+cat >> pango/module-defs-x.c <<EOTEXT
+ { NULL, NULL, NULL, NULL },
+};
+EOTEXT
+])
+
+AC_CONFIG_COMMANDS([pango/module-defs-fc.c],
+[
+### FC modules
+cat > pango/module-defs-fc.c <<EOTEXT
+/* Autogenerated by configure. Do not edit */
+
+#include "module-defs.h"
+
+PangoIncludedModule _pango_included_fc_modules@<:@@:>@ = {
+EOTEXT
+
+IFS="${IFS= }"; pango_save_ifs="$IFS"; IFS=","
+for module in $included_modules; do
+ if echo $module | egrep -- "-fc($|,)" > /dev/null; then
+ module_c=`echo $module | sed s/-/_/`
+ cat >> pango/module-defs-fc.c <<EOTEXT
+ { _pango_${module_c}_script_engine_list, _pango_${module_c}_script_engine_init, _pango_${module_c}_script_engine_exit, _pango_${module_c}_script_engine_create },
+EOTEXT
+ fi
+done
+
+IFS="$pango_save_ifs"
+
+cat >> pango/module-defs-fc.c <<EOTEXT
+ { NULL, NULL, NULL, NULL },
+};
+EOTEXT
+])
+
+AC_CONFIG_COMMANDS([pango/module-defs-win32.c],
+[
+### Win32 modules
+cat > pango/module-defs-win32.c <<EOTEXT
+/* Autogenerated by configure. Do not edit */
+
+#include "module-defs.h"
+
+PangoIncludedModule _pango_included_win32_modules@<:@@:>@ = {
+EOTEXT
+
+IFS="${IFS= }"; pango_save_ifs="$IFS"; IFS=","
+for module in $included_modules; do
+ if echo $module | egrep -- "-win32($|,)" > /dev/null; then
+ module_c=`echo $module | sed s/-/_/`
+ cat >> pango/module-defs-win32.c <<EOTEXT
+ { _pango_${module_c}_script_engine_list, _pango_${module_c}_script_engine_init, _pango_${module_c}_script_engine_exit, _pango_${module_c}_script_engine_create },
+EOTEXT
+ fi
+done
+
+IFS="$pango_save_ifs"
+
+cat >> pango/module-defs-win32.c <<EOTEXT
+ { NULL, NULL, NULL, NULL },
+};
+EOTEXT
+])
+
+AC_CONFIG_COMMANDS([pango/module-defs-atsui.c],
+[
+### ATSUI modules
+cat > pango/module-defs-atsui.c <<EOTEXT
+/* Autogenerated by configure. Do not edit */
+
+#include "module-defs.h"
+
+PangoIncludedModule _pango_included_atsui_modules@<:@@:>@ = {
+EOTEXT
+
+IFS="${IFS= }"; pango_save_ifs="$IFS"; IFS=","
+for module in $included_modules; do
+ if echo $module | egrep -- "-atsui($|,)" > /dev/null; then
+ module_c=`echo $module | sed s/-/_/`
+ cat >> pango/module-defs-atsui.c <<EOTEXT
+ { _pango_${module_c}_script_engine_list, _pango_${module_c}_script_engine_init, _pango_${module_c}_script_engine_exit, _pango_${module_c}_script_engine_create },
+EOTEXT
+ fi
+done
+
+IFS="$pango_save_ifs"
+
+cat >> pango/module-defs-atsui.c <<EOTEXT
+ { NULL, NULL, NULL, NULL },
+};
+EOTEXT
+])
+
+AC_CONFIG_COMMANDS([pango/module-defs-lang.c],
+[
+### lang modules
+cat > pango/module-defs-lang.c <<EOTEXT
+/* Autogenerated by configure. Do not edit */
+
+#include "module-defs.h"
+
+PangoIncludedModule _pango_included_lang_modules@<:@@:>@ = {
+EOTEXT
+
+IFS="${IFS= }"; pango_save_ifs="$IFS"; IFS=","
+for module in $included_modules; do
+ if echo $module | egrep -- "-lang($|,)" > /dev/null; then
+ module_c=`echo $module | sed s/-/_/`
+ cat >> pango/module-defs-lang.c <<EOTEXT
+ { _pango_${module_c}_script_engine_list, _pango_${module_c}_script_engine_init, _pango_${module_c}_script_engine_exit, _pango_${module_c}_script_engine_create },
+EOTEXT
+ fi
+done
+
+IFS="$pango_save_ifs"
+
+cat >> pango/module-defs-lang.c <<EOTEXT
+ { NULL, NULL, NULL, NULL },
+};
+EOTEXT
+])
+
+
+AC_HEADER_DIRENT
+AC_CHECK_HEADERS(unistd.h)
+
+# Honor aclocal flags
+ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS"
+dnl ===========================================================================
+AC_CONFIG_COMMANDS([pango/pango-features.h],
+ [featuresfile=pango/pango-features.h
+ outfile=$featuresfile.tmp
+ AC_MSG_NOTICE([creating $featuresfile])
+ cat >$outfile <<_EOF
+/* Generated by configure. Do not edit */
+#ifndef PANGO_FEATURES_H
+#define PANGO_FEATURES_H
+
+#define PANGO_VERSION_MAJOR $PANGO_VERSION_MAJOR
+#define PANGO_VERSION_MINOR $PANGO_VERSION_MINOR
+#define PANGO_VERSION_MICRO $PANGO_VERSION_MICRO
+
+#define PANGO_VERSION_STRING "$PANGO_VERSION_MAJOR.$PANGO_VERSION_MINOR.$PANGO_VERSION_MICRO"
+
+_EOF
+ # TODO: define macros for enabled features/backends here
+
+ echo '' >>$outfile
+ echo '#endif' >>$outfile
+
+ if cmp -s $outfile $featuresfile; then
+ AC_MSG_NOTICE([$featuresfile is unchanged])
+ rm -f $outfile
+ else
+ mv $outfile $featuresfile
+ fi
+],[
+ PANGO_VERSION_MAJOR=$PANGO_VERSION_MAJOR
+ PANGO_VERSION_MINOR=$PANGO_VERSION_MINOR
+ PANGO_VERSION_MICRO=$PANGO_VERSION_MICRO
+])
+
+AC_CONFIG_FILES([
+Makefile
+pango/Makefile
+pango/mini-fribidi/Makefile
+pango/opentype/Makefile
+pango/pango.rc
+pango/pangoft2.rc
+pango/pangowin32.rc
+pango-view/Makefile
+modules/Makefile
+modules/arabic/Makefile
+modules/basic/Makefile
+modules/hangul/Makefile
+modules/hebrew/Makefile
+modules/indic/Makefile
+modules/khmer/Makefile
+modules/syriac/Makefile
+modules/thai/Makefile
+modules/tibetan/Makefile
+examples/Makefile
+docs/Makefile
+docs/version.xml
+tools/Makefile
+tests/Makefile
+pango.pc
+pangox.pc
+pangowin32.pc
+pangoft2.pc
+pangoxft.pc
+pangocairo.pc
+pango-uninstalled.pc
+pangox-uninstalled.pc
+pangowin32-uninstalled.pc
+pangoft2-uninstalled.pc
+pangoxft-uninstalled.pc
+pangocairo-uninstalled.pc
+pango-zip.sh
+])
+
+AC_CONFIG_FILES([tests/runtests.sh],
+ [chmod +x tests/runtests.sh])
+
+AC_OUTPUT
+
+backends=""
+if $have_freetype && $have_fontconfig ; then backends="$backends FreeType"; fi
+if $have_x ; then backends="$backends X"; fi
+if $have_xft ; then backends="$backends Xft"; fi
+if $have_cairo ; then backends="$backends Cairo"; fi
+if $have_win32 ; then backends="$backends Win32"; fi
+
+echo "configuration:
+ backends:$backends"
diff --git a/trunk/docs/Makefile.am b/trunk/docs/Makefile.am
new file mode 100644
index 00000000..8ef306b5
--- /dev/null
+++ b/trunk/docs/Makefile.am
@@ -0,0 +1,140 @@
+## Process this file with automake to create Makefile.in.
+
+# The name of the module.
+DOC_MODULE=pango
+
+# The top-level SGML file.
+DOC_MAIN_SGML_FILE=pango-docs.sgml
+
+# Extra options to supply to gtkdoc-scan
+SCAN_OPTIONS=--deprecated-guards="PANGO_DISABLE_DEPRECATED"
+
+# The directory containing the source code. Relative to $(srcdir)
+DOC_SOURCE_DIR=../pango
+
+# Used for dependencies
+HFILE_GLOB=$(top_srcdir)/pango/*.h
+CFILE_GLOB=$(top_srcdir)/pango/*.c
+
+# Headers to ignore
+IGNORE_HFILES= \
+ ftglue.h \
+ mini-fribidi \
+ opentype \
+ module-defs.h \
+ modules.h \
+ pangoatsui-private.h \
+ pangocairo-private.h \
+ pangocairo-fc.h \
+ pangocairo-win32.h \
+ pangocairo-atsui.h \
+ pango-color-table.h \
+ pango-engine-private.h \
+ pango-impl-utils.h \
+ pango-glyph-item-private.h \
+ pango-layout-private.h \
+ pango-script-table.h \
+ pangofc-private.h \
+ pangoft2-private.h \
+ pangowin32-private.h \
+ pangoatsui-private.h \
+ pangox-private.h \
+ pangoxft-private.h \
+ pango-ot-private.h
+
+# CFLAGS and LDFLAGS for compiling scan program. Only needed
+# if $(DOC_MODULE).types is non-empty.
+INCLUDES = \
+ -DPANGO_ENABLE_BACKEND \
+ -DPANGO_ENABLE_ENGINE \
+ -I$(top_srcdir) \
+ $(GLIB_CFLAGS) \
+ $(XFT_CFLAGS) \
+ $(CAIRO_CFLAGS) \
+ $(FREETYPE_CFLAGS) \
+ $(X_CFLAGS)
+
+# libpangoxft.la and/or libpangocairo.la pull in libpango.la
+# and libpangoft2.la;
+# We're assuming here that we'll only regenerate the
+# HTML docs on Unix. We don't get introspection on Win32
+# specific types, but that isn't a big deal.
+
+GTKDOC_LIBS =
+
+if HAVE_XFT
+GTKDOC_LIBS += $(top_builddir)/pango/libpangoxft-1.0.la
+endif
+
+if HAVE_CAIRO
+GTKDOC_LIBS += $(top_builddir)/pango/libpangocairo-1.0.la
+endif
+
+# Extra options to supply to gtkdoc-mkdb
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+
+
+# Non-autogenerated SGML files to be included in $(DOC_MAIN_SGML_FILE)
+content_files = \
+ pango_markup.sgml \
+ version.xml \
+ pango-querymodules.xml
+
+# Images to copy into HTML directory
+HTML_IMAGES = \
+ layout.gif \
+ rotated-text.png
+
+if ENABLE_DOC_CROSS_REFERENCES
+# Extra options to supply to gtkdoc-fixref
+FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/glib \
+ --extra-dir=$(CAIRO_PREFIX)/share/gtk-doc/html/cairo
+endif
+
+include $(top_srcdir)/gtk-doc.make
+
+########################################################################
+
+man_MANS = pango-querymodules.1
+
+if ENABLE_MAN
+
+%.1 : %.xml
+ @XSLTPROC@ -nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+
+endif
+
+EXTRA_DIST += \
+ layout.fig \
+ layout.eps \
+ version.xml.in \
+ check.docs
+
+BUILT_EXTRA_DIST = $(man_MANS)
+
+# force doc rebulid after configure
+dist-hook-local: dist-local-check-no-cross-references maintainer-clean-local all-local
+ files='$(BUILT_EXTRA_DIST)'; \
+ for f in $$files; do \
+ if test -f $$f; then d=.; else d=$(srcdir); fi; \
+ cp $$d/$$f $(distdir) || exit 1; done; \
+ \
+ mkdir $(distdir)/TEXT; \
+ for f in $(srcdir)/TEXT/* ; do \
+ test -f $$f && cp -p $$f $(distdir)/TEXT; \
+ done
+
+#
+# Require gtk-doc when making dist
+#
+if ENABLE_DOC_CROSS_REFERENCES
+dist-local-check-no-cross-references:
+ @echo "*** --disable-doc-cross-references must be used in order to make dist"
+ @false
+else
+dist-local-check-no-cross-references:
+endif
+
+.PHONY: dist-local-check-no-cross-references
+
+TESTS = check.docs
diff --git a/trunk/docs/TEXT/glossary b/trunk/docs/TEXT/glossary
new file mode 100644
index 00000000..aa1d1f58
--- /dev/null
+++ b/trunk/docs/TEXT/glossary
@@ -0,0 +1,49 @@
+CFont: A font component. This is a rendering-specific entity
+ which is paired with a glyph index to uniquely indentify
+ a glyph. Each abstract Font maps to one or more CFonts;
+ the method for obtaining CFonts from Fonts is also
+ rendering system specific.
+
+Cluster: A cluster is a small portion of text that is rendered
+ as typographically intertwined glyphs.
+
+ A number of properties are associated with clusters
+ and cluster boundaries.
+
+ 1) Clusters are the smallest unit of text that is guaranteed to
+ progress in reading order. Within a cluster, reordering
+ of glyphs may occur.
+
+ 2) At the boundaries of clusters, character boundaries
+ and glyph boundaries are guaranteed to coincide.
+
+ 3) There will be a cursor position between every two clusters.
+ There may not be a cursor position at some positions
+ inside a cluster.
+
+ 4) The cluster boundary is the only place where information
+ about the correspondence between character position
+ and screen position is conveyed from the shape-engine
+ to the layers above.
+
+Engine: A script-specific object that is responsible for
+ converting Unicode text into glyphs or resolving
+ the properties of the text. Engines may be
+ rendering-system specific or independent of rendering
+ system.
+
+Font: An abstract font. The method in which a font is
+ created is dependent on the rendering system.
+
+Item: An item is a portion of text in a single script, handled
+ by a single shaping engine, and with a single directional
+ level. g_script_itemize() returns a list of items.
+
+Module: A dynamically loaded shared object containing one
+ or more Engines.
+
+Range: A subportion of an item. You pass a range into
+ g_script_shape() by passing in the analysis structure
+ for the item and some subportion of the text.
+
+
diff --git a/trunk/docs/check.docs b/trunk/docs/check.docs
new file mode 100755
index 00000000..9d092e8d
--- /dev/null
+++ b/trunk/docs/check.docs
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+LANG=C
+
+test -z "$srcdir" && srcdir=.
+status=0
+
+if ! test -f pango-undocumented.txt -a -f pango-unused.txt; then
+ echo At least one of pango-undocumented.txt and pango-unused.txt not found.
+ echo Skipping test.
+ exit 0
+fi
+
+status=0
+
+unused=`cat pango-unused.txt`
+if test -n "$unused"; then
+ echo Unused documentated symbols:
+ cat pango-unused.txt
+ status=1
+fi
+if ! grep '^0 symbols incomplete' pango-undocumented.txt >/dev/null ||
+ ! grep '^0 not documented' pango-undocumented.txt >/dev/null; then
+ echo Incomplete or undocumented symbols:
+ cat pango-unused.txt
+ status=1
+fi
+
+exit $status
diff --git a/trunk/docs/layout.eps b/trunk/docs/layout.eps
new file mode 100644
index 00000000..42c897ab
--- /dev/null
+++ b/trunk/docs/layout.eps
@@ -0,0 +1,231 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: layout.eps
+%%Creator: fig2dev Version 3.2 Patchlevel 1
+%%CreationDate: Thu Mar 9 16:51:04 2000
+%%For: otaylor@fresnel.labs.redhat.com (Owen Taylor,,547-0012 x249)
+%%Orientation: Portrait
+%%BoundingBox: 0 0 629 233
+%%Pages: 0
+%%BeginSetup
+%%EndSetup
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+/col32 {0.443 0.459 0.443 srgb} bind def
+
+end
+save
+-5.0 253.0 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+%%EndProlog
+
+$F2psBegin
+10 setmiterlimit
+n -1000 5215 m -1000 -1000 l 11561 -1000 l 11561 5215 l cp clip
+ 0.06000 0.06000 sc
+% Polyline
+15.000 slw
+gs clippath
+10200 3405 m 10350 3450 l 10200 3495 l 10380 3495 l 10380 3405 l cp
+6300 3495 m 6150 3450 l 6300 3405 l 6120 3405 l 6120 3495 l cp
+clip
+n 6150 3450 m 10350 3450 l gs col-1 s gr gr
+
+% arrowhead
+7.500 slw
+n 6300 3495 m 6150 3450 l 6300 3405 l 6300 3450 l 6300 3495 l cp gs 0.00 setgray ef gr col-1 s
+% arrowhead
+n 10200 3405 m 10350 3450 l 10200 3495 l 10200 3450 l 10200 3405 l cp gs 0.00 setgray ef gr col-1 s
+% Polyline
+n 1200 675 m 1200 3600 l gs col-1 s gr
+% Polyline
+15.000 slw
+gs clippath
+5250 3405 m 5400 3450 l 5250 3495 l 5430 3495 l 5430 3405 l cp
+1350 3495 m 1200 3450 l 1350 3405 l 1170 3405 l 1170 3495 l cp
+clip
+n 1200 3450 m 5400 3450 l gs col-1 s gr gr
+
+% arrowhead
+7.500 slw
+n 1350 3495 m 1200 3450 l 1350 3405 l 1350 3450 l 1350 3495 l cp gs 0.00 setgray ef gr col-1 s
+% arrowhead
+n 5250 3405 m 5400 3450 l 5250 3495 l 5250 3450 l 5250 3405 l cp gs 0.00 setgray ef gr col-1 s
+% Polyline
+n 1050 2175 m 1200 2175 l gs col-1 s gr
+% Polyline
+15.000 slw
+n 1125 2025 m 1125 2175 l gs col-1 s gr
+% Polyline
+7.500 slw
+n 6150 975 m 6150 3600 l gs col-1 s gr
+% Polyline
+n 5400 975 m 5400 3600 l gs col-1 s gr
+% Polyline
+n 1800 975 m 1800 675 l gs col-1 s gr
+% Polyline
+15.000 slw
+gs clippath
+1650 780 m 1800 825 l 1650 870 l 1830 870 l 1830 780 l cp
+1350 870 m 1200 825 l 1350 780 l 1170 780 l 1170 870 l cp
+clip
+n 1200 825 m 1800 825 l gs col-1 s gr gr
+
+% arrowhead
+7.500 slw
+n 1350 870 m 1200 825 l 1350 780 l 1350 825 l 1350 870 l cp gs 0.00 setgray ef gr col-1 s
+% arrowhead
+n 1650 780 m 1800 825 l 1650 870 l 1650 825 l 1650 780 l cp gs 0.00 setgray ef gr col-1 s
+% Polyline
+n 9750 975 m 9750 675 l gs col-1 s gr
+% Polyline
+15.000 slw
+gs clippath
+10200 780 m 10350 825 l 10200 870 l 10380 870 l 10380 780 l cp
+9900 870 m 9750 825 l 9900 780 l 9720 780 l 9720 870 l cp
+clip
+n 9750 825 m 10350 825 l gs col-1 s gr gr
+
+% arrowhead
+7.500 slw
+n 9900 870 m 9750 825 l 9900 780 l 9900 825 l 9900 870 l cp gs 0.00 setgray ef gr col-1 s
+% arrowhead
+n 10200 780 m 10350 825 l 10200 870 l 10200 825 l 10200 780 l cp gs 0.00 setgray ef gr col-1 s
+% Polyline
+n 10350 675 m 10350 3600 l gs col-1 s gr
+% Polyline
+15.000 slw
+n 4950 1425 m 1800 1425 l 1800 975 l 4950 975 l cp gs col32 s gr
+% Polyline
+n 4575 2025 m 1200 2025 l 1200 1575 l 4575 1575 l cp gs col32 s gr
+% Polyline
+n 5250 2625 m 1200 2625 l 1200 2175 l 5250 2175 l cp gs col32 s gr
+% Polyline
+n 2400 3225 m 1200 3225 l 1200 2775 l 2400 2775 l cp gs col32 s gr
+% Polyline
+n 9750 1425 m 6600 1425 l 6600 975 l 9750 975 l cp gs col32 s gr
+% Polyline
+n 10350 2025 m 6975 2025 l 6975 1575 l 10350 1575 l cp gs col32 s gr
+% Polyline
+n 10350 2625 m 6300 2625 l 6300 2175 l 10350 2175 l cp gs col32 s gr
+% Polyline
+n 10350 3225 m 9150 3225 l 9150 2775 l 10350 2775 l cp gs col32 s gr
+% Polyline
+7.500 slw
+n 1200 2025 m 1050 2025 l gs col-1 s gr
+/Times-Roman ff 360.00 scf sf
+1200 2475 m
+gs 1 -1 sc (demonstrate PangoLayout's) col0 sh gr
+/Times-Roman ff 360.00 scf sf
+1200 3075 m
+gs 1 -1 sc (features.) col0 sh gr
+/Times-Roman ff 360.00 scf sf
+1200 1875 m
+gs 1 -1 sc (should wrap suitably to) col0 sh gr
+/Helvetica ff 240.00 scf sf
+525 2175 m
+gs 1 -1 sc (spacing) dup sw pop 2 div neg 0 rm col-1 sh gr
+/Times-Roman ff 360.00 scf sf
+1800 1275 m
+gs 1 -1 sc (Here is some text that) col0 sh gr
+/Times-Roman ff 360.00 scf sf
+9150 3075 m
+gs 1 -1 sc (features.) col0 sh gr
+/Times-Roman ff 360.00 scf sf
+6600 1275 m
+gs 1 -1 sc (Here is some text that) col0 sh gr
+/Helvetica ff 240.00 scf sf
+1875 3825 m
+gs 1 -1 sc (width) dup sw pop 2 div neg 0 rm col-1 sh gr
+/Helvetica ff 240.00 scf sf
+6825 3825 m
+gs 1 -1 sc (width) dup sw pop 2 div neg 0 rm col-1 sh gr
+/Helvetica ff 240.00 scf sf
+10050 525 m
+gs 1 -1 sc (indent) dup sw pop 2 div neg 0 rm col-1 sh gr
+/Helvetica ff 240.00 scf sf
+1575 525 m
+gs 1 -1 sc (indent) dup sw pop 2 div neg 0 rm col-1 sh gr
+/Helvetica ff 300.00 scf sf
+9225 4125 m
+gs 1 -1 sc (Right Aligned) dup sw pop 2 div neg 0 rm col-1 sh gr
+/Helvetica ff 300.00 scf sf
+4350 4125 m
+gs 1 -1 sc (Left Aligned) dup sw pop 2 div neg 0 rm col-1 sh gr
+/Times-Roman ff 360.00 scf sf
+6975 1875 m
+gs 1 -1 sc (should wrap suitably to) col0 sh gr
+/Times-Roman ff 360.00 scf sf
+6300 2475 m
+gs 1 -1 sc (demonstrate PangoLayout's) col0 sh gr
+$F2psEnd
+rs
diff --git a/trunk/docs/layout.fig b/trunk/docs/layout.fig
new file mode 100644
index 00000000..7e43560b
--- /dev/null
+++ b/trunk/docs/layout.fig
@@ -0,0 +1,75 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+0 32 #717571
+2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 1 1 2
+ 1 1 1.00 90.00 150.00
+ 1 1 1.00 90.00 150.00
+ 6150 3450 10350 3450
+2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1200 675 1200 3600
+2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 1 1 2
+ 1 1 1.00 90.00 150.00
+ 1 1 1.00 90.00 150.00
+ 1200 3450 5400 3450
+2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1050 2175 1200 2175
+2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1125 2025 1125 2175
+2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 6150 975 6150 3600
+2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 5400 975 5400 3600
+2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1800 975 1800 675
+2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 1 1 2
+ 1 1 1.00 90.00 150.00
+ 1 1 1.00 90.00 150.00
+ 1200 825 1800 825
+2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 9750 975 9750 675
+2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 1 1 2
+ 1 1 1.00 90.00 150.00
+ 1 1 1.00 90.00 150.00
+ 9750 825 10350 825
+2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 10350 675 10350 3600
+2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4950 1425 1800 1425 1800 975 4950 975 4950 1425
+2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4575 2025 1200 2025 1200 1575 4575 1575 4575 2025
+2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 5250 2625 1200 2625 1200 2175 5250 2175 5250 2625
+2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 2400 3225 1200 3225 1200 2775 2400 2775 2400 3225
+2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 9750 1425 6600 1425 6600 975 9750 975 9750 1425
+2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 10350 2025 6975 2025 6975 1575 10350 1575 10350 2025
+2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 10350 2625 6300 2625 6300 2175 10350 2175 10350 2625
+2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 10350 3225 9150 3225 9150 2775 10350 2775 10350 3225
+2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1200 2025 1050 2025
+4 0 0 100 0 0 24 0.0000 4 330 4155 1200 2475 demonstrate PangoLayout's\001
+4 0 0 100 0 0 24 0.0000 4 255 1260 1200 3075 features.\001
+4 0 0 100 0 0 24 0.0000 4 330 3405 1200 1875 should wrap suitably to\001
+4 1 -1 100 0 16 16 0.0000 4 240 855 525 2175 spacing\001
+4 0 0 100 0 0 24 0.0000 4 255 3270 1800 1275 Here is some text that\001
+4 0 0 100 0 0 24 0.0000 4 255 1260 9150 3075 features.\001
+4 0 0 100 0 0 24 0.0000 4 255 3270 6600 1275 Here is some text that\001
+4 1 -1 100 0 16 16 0.0000 4 180 540 1875 3825 width\001
+4 1 -1 100 0 16 16 0.0000 4 180 540 6825 3825 width\001
+4 1 -1 100 0 16 16 0.0000 4 180 645 10050 525 indent\001
+4 1 -1 100 0 16 16 0.0000 4 180 645 1575 525 indent\001
+4 1 -1 100 0 16 20 0.0000 4 300 1770 9225 4125 Right Aligned\001
+4 1 -1 100 0 16 20 0.0000 4 300 1590 4350 4125 Left Aligned\001
+4 0 0 100 0 0 24 0.0000 4 330 3405 6975 1875 should wrap suitably to\001
+4 0 0 100 0 0 24 0.0000 4 330 4155 6300 2475 demonstrate PangoLayout's\001
diff --git a/trunk/docs/layout.gif b/trunk/docs/layout.gif
new file mode 100644
index 00000000..96bde1f2
--- /dev/null
+++ b/trunk/docs/layout.gif
Binary files differ
diff --git a/trunk/docs/pango-docs.sgml b/trunk/docs/pango-docs.sgml
new file mode 100644
index 00000000..3c82eeec
--- /dev/null
+++ b/trunk/docs/pango-docs.sgml
@@ -0,0 +1,124 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY pango-Text-Processing SYSTEM "xml/main.xml">
+<!ENTITY pango-Glyph-Storage SYSTEM "xml/glyphs.xml">
+<!ENTITY pango-Coverage-Maps SYSTEM "xml/coverage-maps.xml">
+<!ENTITY pango-Fonts SYSTEM "xml/fonts.xml">
+<!ENTITY pango-Text-Attributes SYSTEM "xml/text-attributes.xml">
+<!ENTITY pango-Tab-Stops SYSTEM "xml/tab-stops.xml">
+<!ENTITY pango-Layout-Objects SYSTEM "xml/layout.xml">
+<!ENTITY pango-Scripts SYSTEM "xml/scripts.xml">
+<!ENTITY pango-Engines SYSTEM "xml/engines.xml">
+<!ENTITY PangoEngineLang SYSTEM "xml/pango-engine-lang.xml">
+<!ENTITY PangoEngineShape SYSTEM "xml/pango-engine-shape.xml">
+<!ENTITY PangoRenderer SYSTEM "xml/pango-renderer.xml">
+<!ENTITY pango-Modules SYSTEM "xml/modules.xml">
+<!ENTITY pango-X-Fonts-and-Rendering SYSTEM "xml/x-fonts.xml">
+<!ENTITY pango-Win32-Fonts-and-Rendering SYSTEM "xml/win32-fonts.xml">
+<!ENTITY pango-FreeType-Fonts-and-Rendering SYSTEM "xml/freetype-fonts.xml">
+<!ENTITY pango-Xft-Fonts-and-Rendering SYSTEM "xml/xft-fonts.xml">
+<!ENTITY pango-ATSUI-Fonts SYSTEM "xml/atsui-fonts.xml">
+<!ENTITY pangocairo SYSTEM "xml/pangocairo.xml">
+<!ENTITY PangoFcFontMap SYSTEM "xml/pangofc-fontmap.xml">
+<!ENTITY PangoFcFont SYSTEM "xml/pangofc-font.xml">
+<!ENTITY PangoFcDecoder SYSTEM "xml/pangofc-decoder.xml">
+<!ENTITY pango-OpenType-Font-Handling SYSTEM "xml/opentype.xml">
+<!ENTITY pango-Misc-Utils SYSTEM "xml/utils.xml">
+<!ENTITY markup-format SYSTEM "pango_markup.sgml">
+<!ENTITY pango-querymodules SYSTEM "pango-querymodules.xml">
+<!ENTITY pango-Version SYSTEM "xml/pango-version.xml">
+<!ENTITY pango-Vertical-Text SYSTEM "xml/vertical.xml">
+<!ENTITY version SYSTEM "version.xml">
+<!ENTITY pango-tree-index SYSTEM "xml/tree_index.sgml">
+]>
+<book id="index">
+ <bookinfo>
+ <title>Pango Reference Manual</title>
+ <releaseinfo>for Pango &version;</releaseinfo>
+ </bookinfo>
+
+ <chapter id="pango">
+ <title>Basic Pango Interfaces</title>
+ &pango-Text-Processing;
+ &pango-Glyph-Storage;
+ &pango-Fonts;
+ &pango-Text-Attributes;
+ &pango-Tab-Stops;
+ &markup-format;
+ &pango-Layout-Objects;
+ &pango-Scripts;
+ &pango-Vertical-Text;
+ </chapter>
+
+ <chapter id="rendering">
+ <title>Rendering with Pango</title>
+ &pango-Win32-Fonts-and-Rendering;
+ &pango-FreeType-Fonts-and-Rendering;
+ &pango-Xft-Fonts-and-Rendering;
+ &pangocairo;
+ &pango-ATSUI-Fonts;
+ &pango-X-Fonts-and-Rendering;
+ </chapter>
+
+ <chapter id="lowlevel">
+ <title>Low Level Functionality</title>
+ &PangoRenderer;
+ &PangoFcFontMap;
+ &PangoFcFont;
+ &PangoFcDecoder;
+ &pango-OpenType-Font-Handling;
+ &pango-Coverage-Maps;
+ &pango-Engines;
+ &PangoEngineLang;
+ &PangoEngineShape;
+ &pango-Modules;
+ &pango-Misc-Utils;
+ &pango-Version;
+ </chapter>
+
+ <chapter id="tools">
+ <title>Pango Tools</title>
+
+ &pango-querymodules;
+ </chapter>
+
+ <chapter id="pango-hierarchy">
+ <title>Object Hierarchy</title>
+ &pango-tree-index;
+ </chapter>
+
+ <index id="index-all">
+ <title>Index</title>
+ </index>
+ <index id="index-deprecated" role="deprecated">
+ <title>Index of deprecated symbols</title>
+ </index>
+ <index id="index-1.2" role="1.2">
+ <title>Index of new symbols in 1.2</title>
+ </index>
+ <index id="index-1.4" role="1.4">
+ <title>Index of new symbols in 1.4</title>
+ </index>
+ <index id="index-1.6" role="1.6">
+ <title>Index of new symbols in 1.6</title>
+ </index>
+ <index id="index-1.8" role="1.8">
+ <title>Index of new symbols in 1.8</title>
+ </index>
+ <index id="index-1.10" role="1.10">
+ <title>Index of new symbols in 1.10</title>
+ </index>
+ <index id="index-1.12" role="1.12">
+ <title>Index of new symbols in 1.12</title>
+ </index>
+ <index id="index-1.14" role="1.14">
+ <title>Index of new symbols in 1.14</title>
+ </index>
+ <index id="index-1.16" role="1.16">
+ <title>Index of new symbols in 1.16</title>
+ </index>
+ <index id="index-1.18" role="1.18">
+ <title>Index of new symbols in 1.18</title>
+ </index>
+</book>
diff --git a/trunk/docs/pango-overrides.txt b/trunk/docs/pango-overrides.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/trunk/docs/pango-overrides.txt
diff --git a/trunk/docs/pango-querymodules.1 b/trunk/docs/pango-querymodules.1
new file mode 100644
index 00000000..c7c34901
--- /dev/null
+++ b/trunk/docs/pango-querymodules.1
@@ -0,0 +1,49 @@
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "PANGO-QUERYMODULES" 1 "" "" ""
+.SH NAME
+pango-querymodules \- Module registration utility
+.SH "SYNOPSIS"
+
+.nf
+\fBpango-querymodules\fR [module...]
+.fi
+
+.SH "DESCRIPTION"
+
+.PP
+ \fBpango-querymodules\fR collects information about loadable modules for Pango and writes it to \fIstdout\fR\&.
+
+.PP
+If called without arguments, it looks for modules in the Pango module path\&.
+
+.PP
+If called with arguments, it looks for the specified modules\&. The arguments may be absolute or relative paths\&.
+
+.SH "ENVIRONMENT"
+
+.PP
+The Pango module path is specified by the key Pango/ModulesPath in the Pango config database, which is read from \fI\fIsysconfdir\fR/pango/pangorc\fR, \fI~/\&.pangorc\fR and the file specified in the environment variable \fBPANGO_RC_FILE\fR\&.
+
+.SH "BUGS"
+
+.PP
+None known yet\&.
+
diff --git a/trunk/docs/pango-querymodules.xml b/trunk/docs/pango-querymodules.xml
new file mode 100644
index 00000000..1677d92e
--- /dev/null
+++ b/trunk/docs/pango-querymodules.xml
@@ -0,0 +1,53 @@
+<refentry id="pango-querymodules">
+
+<refmeta>
+<refentrytitle>pango-querymodules</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+
+<refnamediv>
+<refname>pango-querymodules</refname>
+<refpurpose>Module registration utility</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+<cmdsynopsis>
+<command>pango-querymodules</command>
+<arg choice="opt" rep="repeat">module</arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>
+<command>pango-querymodules</command> collects information about loadable
+modules for Pango and writes it to <filename>stdout</filename>.
+</para>
+<para>
+If called without arguments, it looks for modules in the Pango module path.
+</para>
+<para>
+If called with arguments, it looks for the specified modules. The arguments
+may be absolute or relative paths.
+</para>
+</refsect1>
+
+<refsect1><title>Environment</title>
+<para>
+The Pango module path is specified by the key
+<literal>Pango/ModulesPath</literal> in the Pango config database, which is
+read from
+ <filename><replaceable>sysconfdir</replaceable>/pango/pangorc</filename>,
+ <filename>~/.pangorc</filename> and the file specified in the environment
+ variable <envar>PANGO_RC_FILE</envar>.
+</para>
+</refsect1>
+
+<refsect1><title>Bugs</title>
+<para>
+None known yet.
+</para>
+</refsect1>
+
+</refentry>
+
+
diff --git a/trunk/docs/pango-sections.txt b/trunk/docs/pango-sections.txt
new file mode 100644
index 00000000..6b969db4
--- /dev/null
+++ b/trunk/docs/pango-sections.txt
@@ -0,0 +1,1062 @@
+<SECTION>
+<TITLE>Text Processing</TITLE>
+<FILE>main</FILE>
+<SUBSECTION>
+PangoContext
+PangoItem
+PangoAnalysis
+PANGO_ANALYSIS_FLAG_CENTERED_BASELINE
+PangoDirection
+PANGO_TYPE_DIRECTION
+<SUBSECTION>
+pango_itemize
+pango_itemize_with_base_dir
+pango_item_free
+pango_item_copy
+pango_item_new
+pango_item_split
+pango_reorder_items
+<SUBSECTION>
+pango_context_new
+pango_context_set_font_map
+pango_context_get_font_map
+pango_context_get_font_description
+pango_context_set_font_description
+pango_context_get_language
+pango_context_set_language
+pango_context_get_base_dir
+pango_context_set_base_dir
+pango_context_get_base_gravity
+pango_context_set_base_gravity
+pango_context_get_gravity
+pango_context_get_gravity_hint
+pango_context_set_gravity_hint
+pango_context_get_matrix
+pango_context_set_matrix
+pango_context_load_font
+pango_context_load_fontset
+pango_context_get_metrics
+pango_context_list_families
+<SUBSECTION>
+pango_get_mirror_char
+pango_unichar_direction
+pango_find_base_dir
+pango_gravity_to_rotation
+<SUBSECTION Standard>
+PANGO_TYPE_CONTEXT
+PangoContextClass
+PANGO_CONTEXT
+PANGO_CONTEXT_CLASS
+PANGO_IS_CONTEXT
+PANGO_IS_CONTEXT_CLASS
+PANGO_CONTEXT_GET_CLASS
+PANGO_TYPE_ITEM
+<SUBSECTION>
+pango_break
+pango_get_log_attrs
+pango_find_paragraph_boundary
+pango_default_break
+PangoLogAttr
+<SUBSECTION>
+pango_shape
+
+<SUBSECTION Private>
+pango_direction_get_type
+pango_context_get_type
+pango_item_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>Glyph Storage</TITLE>
+<FILE>glyphs</FILE>
+PANGO_SCALE
+PANGO_PIXELS
+PANGO_PIXELS_FLOOR
+PANGO_PIXELS_CEIL
+PANGO_UNITS_ROUND
+pango_units_to_double
+pango_units_from_double
+PangoRectangle
+PANGO_ASCENT
+PANGO_DESCENT
+PANGO_LBEARING
+PANGO_RBEARING
+pango_extents_to_pixels
+PangoMatrix
+PANGO_TYPE_MATRIX
+PANGO_MATRIX_INIT
+pango_matrix_copy
+pango_matrix_free
+pango_matrix_translate
+pango_matrix_scale
+pango_matrix_rotate
+pango_matrix_concat
+pango_matrix_transform_point
+pango_matrix_transform_distance
+pango_matrix_transform_rectangle
+pango_matrix_transform_pixel_rectangle
+pango_matrix_get_font_scale_factor
+PangoGlyph
+PANGO_GLYPH_EMPTY
+PANGO_GLYPH_UNKNOWN_FLAG
+PANGO_GET_UNKNOWN_GLYPH
+PangoGlyphInfo
+PangoGlyphGeometry
+PangoGlyphUnit
+PangoGlyphVisAttr
+PangoGlyphString
+PangoGlyphItem
+PANGO_TYPE_GLYPH_STRING
+pango_glyph_string_new
+pango_glyph_string_copy
+pango_glyph_string_set_size
+pango_glyph_string_free
+pango_glyph_string_extents
+pango_glyph_string_extents_range
+pango_glyph_string_get_width
+pango_glyph_string_index_to_x
+pango_glyph_string_x_to_index
+pango_glyph_string_get_logical_widths
+pango_glyph_item_split
+pango_glyph_item_apply_attrs
+pango_glyph_item_letter_space
+pango_glyph_item_free
+
+<SUBSECTION Private>
+pango_glyph_string_get_type
+pango_matrix_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>Coverage Maps</TITLE>
+<FILE>coverage-maps</FILE>
+PangoCoverageLevel
+PANGO_TYPE_COVERAGE_LEVEL
+PangoCoverage
+<SUBSECTION>
+pango_coverage_new
+pango_coverage_ref
+pango_coverage_unref
+pango_coverage_copy
+pango_coverage_get
+pango_coverage_max
+pango_coverage_set
+pango_coverage_to_bytes
+pango_coverage_from_bytes
+
+<SUBSECTION Private>
+pango_coverage_level_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>Fonts</TITLE>
+<FILE>fonts</FILE>
+PangoFontDescription
+PANGO_TYPE_FONT_DESCRIPTION
+PangoStyle
+PANGO_TYPE_STYLE
+PangoWeight
+PANGO_TYPE_WEIGHT
+PangoVariant
+PANGO_TYPE_VARIANT
+PangoStretch
+PANGO_TYPE_STRETCH
+PangoFontMask
+PANGO_TYPE_FONT_MASK
+pango_font_description_new
+pango_font_description_copy
+pango_font_description_copy_static
+pango_font_description_hash
+pango_font_description_equal
+pango_font_description_free
+pango_font_descriptions_free
+pango_font_description_set_family
+pango_font_description_set_family_static
+pango_font_description_get_family
+pango_font_description_set_style
+pango_font_description_get_style
+pango_font_description_set_variant
+pango_font_description_get_variant
+pango_font_description_set_weight
+pango_font_description_get_weight
+pango_font_description_set_stretch
+pango_font_description_get_stretch
+pango_font_description_set_size
+pango_font_description_get_size
+pango_font_description_set_absolute_size
+pango_font_description_get_size_is_absolute
+pango_font_description_set_gravity
+pango_font_description_get_gravity
+pango_font_description_get_set_fields
+pango_font_description_unset_fields
+pango_font_description_merge
+pango_font_description_merge_static
+pango_font_description_better_match
+pango_font_description_from_string
+pango_font_description_to_string
+pango_font_description_to_filename
+<SUBSECTION>
+PangoFontMetrics
+PANGO_TYPE_FONT_METRICS
+pango_font_metrics_ref
+pango_font_metrics_unref
+pango_font_metrics_get_ascent
+pango_font_metrics_get_descent
+pango_font_metrics_get_approximate_char_width
+pango_font_metrics_get_approximate_digit_width
+pango_font_metrics_get_underline_thickness
+pango_font_metrics_get_underline_position
+pango_font_metrics_get_strikethrough_thickness
+pango_font_metrics_get_strikethrough_position
+<SUBSECTION>
+PangoFont
+PANGO_TYPE_FONT
+PANGO_FONT
+PANGO_IS_FONT
+pango_font_find_shaper
+pango_font_describe
+pango_font_describe_with_absolute_size
+pango_font_get_coverage
+pango_font_get_glyph_extents
+pango_font_get_metrics
+pango_font_get_font_map
+<SUBSECTION>
+PangoFontFamily
+PANGO_TYPE_FONT_FAMILY
+PANGO_FONT_FAMILY
+PANGO_IS_FONT_FAMILY
+pango_font_family_get_name
+pango_font_family_is_monospace
+pango_font_family_list_faces
+<SUBSECTION>
+PangoFontFace
+PANGO_TYPE_FONT_FACE
+PANGO_FONT_FACE
+PANGO_IS_FONT_FACE
+pango_font_face_get_face_name
+pango_font_face_list_sizes
+pango_font_face_describe
+pango_font_face_is_synthesized
+<SUBSECTION>
+PangoFontMap
+PANGO_TYPE_FONT_MAP
+PANGO_FONT_MAP
+PANGO_IS_FONT_MAP
+PangoFontMapClass
+PANGO_FONT_MAP_CLASS
+PANGO_IS_FONT_MAP_CLASS
+PANGO_FONT_MAP_GET_CLASS
+pango_font_map_load_font
+pango_font_map_load_fontset
+pango_font_map_list_families
+pango_font_map_get_shape_engine_type
+<SUBSECTION>
+PangoFontset
+PANGO_TYPE_FONTSET
+PangoFontsetClass
+pango_fontset_get_font
+pango_fontset_get_metrics
+PangoFontsetForeachFunc
+pango_fontset_foreach
+PangoFontsetSimple
+PANGO_TYPE_FONTSET_SIMPLE
+pango_fontset_simple_new
+pango_fontset_simple_append
+pango_fontset_simple_size
+
+<SUBSECTION Standard>
+PANGO_FONT_FACE_CLASS
+PANGO_IS_FONT_CLASS
+PANGO_FONT_FACE_GET_CLASS
+PangoFontFamilyClass
+PangoFontFaceClass
+PANGO_FONT_GET_CLASS
+PANGO_FONT_CLASS
+PANGO_IS_FONT_FAMILY_CLASS
+PangoFontClass
+PANGO_FONT_FAMILY_GET_CLASS
+PANGO_FONT_FAMILY_CLASS
+PANGO_IS_FONT_FACE_CLASS
+PANGO_FONTSET
+PANGO_IS_FONTSET
+PANGO_FONTSET_CLASS
+PANGO_IS_FONTSET_CLASS
+PANGO_FONTSET_GET_CLASS
+PANGO_FONTSET_SIMPLE
+PANGO_IS_FONTSET_SIMPLE
+PangoFontsetSimpleClass
+
+<SUBSECTION Private>
+pango_font_metrics_new
+pango_font_get_type
+pango_stretch_get_type
+pango_style_get_type
+pango_variant_get_type
+pango_weight_get_type
+pango_font_mask_get_type
+pango_font_description_get_type
+pango_font_map_get_type
+pango_font_face_get_type
+pango_font_family_get_type
+pango_font_metrics_get_type
+pango_fontset_get_type
+pango_fontset_simple_get_type
+PANGO_UNKNOWN_GLYPH_WIDTH
+PANGO_UNKNOWN_GLYPH_HEIGHT
+</SECTION>
+
+<SECTION>
+<TITLE>Text Attributes</TITLE>
+<FILE>text-attributes</FILE>
+PangoAttrType
+PANGO_TYPE_ATTR_TYPE
+PangoAttrClass
+PangoAttribute
+PangoAttrString
+PangoAttrLanguage
+PangoAttrColor
+PangoAttrInt
+PangoAttrFloat
+PangoAttrFontDesc
+PangoAttrShape
+PangoAttrSize
+pango_parse_markup
+pango_attr_type_register
+pango_attribute_copy
+pango_attribute_equal
+pango_attribute_destroy
+<SUBSECTION>
+pango_attr_language_new
+pango_attr_family_new
+pango_attr_style_new
+pango_attr_variant_new
+pango_attr_stretch_new
+pango_attr_weight_new
+pango_attr_size_new
+pango_attr_size_new_absolute
+pango_attr_font_desc_new
+pango_attr_foreground_new
+pango_attr_background_new
+pango_attr_strikethrough_new
+pango_attr_strikethrough_color_new
+pango_attr_underline_new
+pango_attr_underline_color_new
+PangoUnderline
+PANGO_TYPE_UNDERLINE
+pango_attr_shape_new
+pango_attr_shape_new_with_data
+PangoAttrDataCopyFunc
+pango_attr_scale_new
+PANGO_SCALE_XX_SMALL
+PANGO_SCALE_X_SMALL
+PANGO_SCALE_SMALL
+PANGO_SCALE_MEDIUM
+PANGO_SCALE_LARGE
+PANGO_SCALE_X_LARGE
+PANGO_SCALE_XX_LARGE
+pango_attr_rise_new
+pango_attr_letter_spacing_new
+pango_attr_fallback_new
+pango_attr_gravity_new
+pango_attr_gravity_hint_new
+PangoColor
+PANGO_TYPE_COLOR
+pango_color_parse
+pango_color_copy
+pango_color_free
+pango_color_to_string
+PangoLanguage
+PANGO_TYPE_LANGUAGE
+pango_language_from_string
+pango_language_to_string
+pango_language_matches
+<SUBSECTION>
+PangoAttrList
+PANGO_TYPE_ATTR_LIST
+pango_attr_list_new
+pango_attr_list_ref
+pango_attr_list_unref
+pango_attr_list_copy
+pango_attr_list_insert
+pango_attr_list_insert_before
+pango_attr_list_change
+pango_attr_list_splice
+pango_attr_list_filter
+PangoAttrFilterFunc
+pango_attr_list_get_iterator
+PangoAttrIterator
+pango_attr_iterator_copy
+pango_attr_iterator_next
+pango_attr_iterator_range
+pango_attr_iterator_get
+pango_attr_iterator_get_font
+pango_attr_iterator_get_attrs
+pango_attr_iterator_destroy
+<SUBSECTION Private>
+pango_attr_type_get_type
+pango_attr_list_get_type
+pango_underline_get_type
+pango_color_get_type
+pango_language_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>Tab Stops</TITLE>
+<FILE>tab-stops</FILE>
+PangoTabArray
+PANGO_TYPE_TAB_ARRAY
+PangoTabAlign
+PANGO_TYPE_TAB_ALIGN
+pango_tab_array_new
+pango_tab_array_new_with_positions
+pango_tab_array_copy
+pango_tab_array_free
+pango_tab_array_get_size
+pango_tab_array_resize
+pango_tab_array_set_tab
+pango_tab_array_get_tab
+pango_tab_array_get_tabs
+pango_tab_array_get_positions_in_pixels
+
+<SUBSECTION Private>
+pango_tab_align_get_type
+pango_tab_array_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>Layout Objects</TITLE>
+<FILE>layout</FILE>
+PangoLayout
+PangoLayoutIter
+pango_layout_new
+pango_layout_copy
+
+pango_layout_get_context
+pango_layout_context_changed
+
+pango_layout_set_text
+pango_layout_get_text
+pango_layout_set_markup
+pango_layout_set_markup_with_accel
+pango_layout_set_attributes
+pango_layout_get_attributes
+pango_layout_set_font_description
+pango_layout_get_font_description
+pango_layout_set_width
+pango_layout_get_width
+pango_layout_set_wrap
+pango_layout_get_wrap
+pango_layout_is_wrapped
+PangoWrapMode
+PANGO_TYPE_WRAP_MODE
+pango_layout_set_ellipsize
+pango_layout_get_ellipsize
+pango_layout_is_ellipsized
+PangoEllipsizeMode
+PANGO_TYPE_ELLIPSIZE_MODE
+pango_layout_set_indent
+pango_layout_get_indent
+pango_layout_get_spacing
+pango_layout_set_spacing
+pango_layout_set_justify
+pango_layout_get_justify
+pango_layout_set_auto_dir
+pango_layout_get_auto_dir
+pango_layout_set_alignment
+pango_layout_get_alignment
+pango_layout_set_tabs
+pango_layout_get_tabs
+pango_layout_set_single_paragraph_mode
+pango_layout_get_single_paragraph_mode
+PangoAlignment
+PANGO_TYPE_ALIGNMENT
+
+pango_layout_get_unknown_glyphs_count
+pango_layout_get_log_attrs
+
+pango_layout_index_to_pos
+pango_layout_index_to_line_x
+pango_layout_xy_to_index
+pango_layout_get_cursor_pos
+pango_layout_move_cursor_visually
+
+pango_layout_get_extents
+pango_layout_get_pixel_extents
+pango_layout_get_size
+pango_layout_get_pixel_size
+pango_layout_get_line_count
+pango_layout_get_line
+pango_layout_get_line_readonly
+pango_layout_get_lines
+pango_layout_get_lines_readonly
+
+pango_layout_get_iter
+pango_layout_iter_free
+pango_layout_iter_next_run
+pango_layout_iter_next_char
+pango_layout_iter_next_cluster
+pango_layout_iter_next_line
+pango_layout_iter_at_last_line
+pango_layout_iter_get_index
+pango_layout_iter_get_baseline
+pango_layout_iter_get_run
+pango_layout_iter_get_run_readonly
+pango_layout_iter_get_line
+pango_layout_iter_get_line_readonly
+pango_layout_iter_get_char_extents
+pango_layout_iter_get_cluster_extents
+pango_layout_iter_get_run_extents
+pango_layout_iter_get_line_yrange
+pango_layout_iter_get_line_extents
+pango_layout_iter_get_layout_extents
+
+<SUBSECTION>
+PangoLayoutLine
+PangoLayoutRun
+
+pango_layout_line_ref
+pango_layout_line_unref
+pango_layout_line_get_extents
+pango_layout_line_get_pixel_extents
+pango_layout_line_index_to_x
+pango_layout_line_x_to_index
+pango_layout_line_get_x_ranges
+
+<SUBSECTION Standard>
+PANGO_TYPE_LAYOUT
+PangoLayoutClass
+PANGO_LAYOUT
+PANGO_IS_LAYOUT
+PANGO_LAYOUT_CLASS
+PANGO_IS_LAYOUT_CLASS
+PANGO_LAYOUT_GET_CLASS
+PANGO_TYPE_LAYOUT_ITER
+PANGO_TYPE_LAYOUT_LINE
+
+<SUBSECTION Private>
+pango_layout_get_type
+pango_layout_iter_get_type
+pango_layout_line_get_type
+pango_alignment_get_type
+pango_wrap_mode_get_type
+pango_ellipsize_mode_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>Scripts</TITLE>
+<FILE>scripts</FILE>
+PangoScriptIter
+PangoScript
+PANGO_TYPE_SCRIPT
+pango_script_for_unichar
+pango_script_get_sample_language
+pango_language_includes_script
+pango_script_iter_new
+pango_script_iter_get_range
+pango_script_iter_next
+pango_script_iter_free
+<SUBSECTION Private>
+pango_script_get_type
+PangoScriptForLang
+</SECTION>
+
+<SECTION>
+<TITLE>Engines</TITLE>
+<FILE>engines</FILE>
+PangoEngineInfo
+PangoEngineScriptInfo
+PangoEngine
+PangoEngineClass
+PANGO_RENDER_TYPE_NONE
+script_engine_list
+script_engine_init
+script_engine_exit
+script_engine_create
+<SUBSECTION Standard>
+PANGO_ENGINE
+PANGO_IS_ENGINE
+PANGO_TYPE_ENGINE
+PANGO_ENGINE_CLASS
+PANGO_IS_ENGINE_CLASS
+PANGO_ENGINE_GET_CLASS
+<SUBSECTION Private>
+pango_engine_get_type
+PANGO_MODULE_ENTRY
+PANGO_ENGINE_DEFINE_TYPE
+</SECTION>
+
+<SECTION>
+<TITLE>PangoEngineLang</TITLE>
+<FILE>pango-engine-lang</FILE>
+PangoEngineLang
+PangoEngineLangClass
+PANGO_ENGINE_TYPE_LANG
+PANGO_ENGINE_LANG_DEFINE_TYPE
+<SUBSECTION Standard>
+PANGO_ENGINE_LANG
+PANGO_IS_ENGINE_LANG
+PANGO_TYPE_ENGINE_LANG
+PANGO_ENGINE_LANG_CLASS
+PANGO_IS_ENGINE_LANG_CLASS
+PANGO_ENGINE_LANG_GET_CLASS
+<SUBSECTION Private>
+pango_engine_lang_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>PangoEngineShape</TITLE>
+<FILE>pango-engine-shape</FILE>
+PangoEngineShape
+PangoEngineShapeClass
+PANGO_ENGINE_TYPE_SHAPE
+PANGO_ENGINE_SHAPE_DEFINE_TYPE
+<SUBSECTION Standard>
+PANGO_ENGINE_SHAPE
+PANGO_IS_ENGINE_SHAPE
+PANGO_TYPE_ENGINE_SHAPE
+PANGO_ENGINE_SHAPE_CLASS
+PANGO_IS_ENGINE_SHAPE_CLASS
+PANGO_ENGINE_SHAPE_GET_CLASS
+<SUBSECTION Private>
+pango_engine_shape_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>Modules</TITLE>
+<FILE>modules</FILE>
+PangoIncludedModule
+PangoMap
+PangoMapEntry
+pango_find_map
+pango_map_get_engine
+pango_map_get_engines
+pango_module_register
+</SECTION>
+
+<SECTION>
+<FILE>pango-renderer</FILE>
+PangoRenderer
+PangoRenderPart
+PANGO_TYPE_RENDER_PART
+PangoRendererClass
+<TITLE>PangoRenderer</TITLE>
+pango_renderer_draw_layout
+pango_renderer_draw_layout_line
+pango_renderer_draw_glyphs
+pango_renderer_draw_rectangle
+pango_renderer_draw_error_underline
+pango_renderer_draw_trapezoid
+pango_renderer_draw_glyph
+pango_renderer_activate
+pango_renderer_deactivate
+pango_renderer_part_changed
+pango_renderer_set_color
+pango_renderer_get_color
+pango_renderer_set_matrix
+pango_renderer_get_matrix
+<SUBSECTION Standard>
+PANGO_RENDERER
+PANGO_IS_RENDERER
+PANGO_TYPE_RENDERER
+pango_renderer_get_type
+PANGO_RENDERER_CLASS
+PANGO_IS_RENDERER_CLASS
+PANGO_RENDERER_GET_CLASS
+<SUBSECTION Private>
+pango_render_part_get_type
+PangoRendererPrivate
+</SECTION>
+
+<SECTION>
+<TITLE>X Fonts and Rendering</TITLE>
+<FILE>x-fonts</FILE>
+PANGO_RENDER_TYPE_X
+pango_x_get_context
+pango_x_context_set_funcs
+PangoGetGCFunc
+PangoFreeGCFunc
+pango_x_render
+pango_x_render_layout_line
+pango_x_render_layout
+PangoXSubfont
+PANGO_X_MAKE_GLYPH
+PANGO_X_GLYPH_SUBFONT
+PANGO_X_GLYPH_INDEX
+pango_x_load_font
+pango_x_get_unknown_glyph
+pango_x_has_glyph
+pango_x_list_subfonts
+pango_x_font_map_for_display
+pango_x_shutdown_display
+pango_x_font_map_get_font_cache
+pango_x_font_subfont_xlfd
+pango_x_find_first_subfont
+pango_x_font_get_unknown_glyph
+pango_x_apply_ligatures
+pango_x_fallback_shape
+PangoXFontCache
+pango_x_font_cache_new
+pango_x_font_cache_free
+pango_x_font_cache_load
+pango_x_font_cache_unload
+</SECTION>
+
+<SECTION>
+<TITLE>Win32 Fonts and Rendering</TITLE>
+<FILE>win32-fonts</FILE>
+PANGO_RENDER_TYPE_WIN32
+pango_win32_get_context
+pango_win32_render
+pango_win32_render_transformed
+pango_win32_render_layout_line
+pango_win32_render_layout
+pango_win32_get_unknown_glyph
+pango_win32_font_get_glyph_index
+pango_win32_font_select_font
+pango_win32_font_done_font
+pango_win32_font_get_metrics_factor
+pango_win32_get_debug_flag
+pango_win32_get_dc
+PangoWin32FontCache
+pango_win32_font_cache_new
+pango_win32_font_cache_free
+pango_win32_font_cache_load
+pango_win32_font_cache_loadw
+pango_win32_font_cache_unload
+pango_win32_font_map_for_display
+pango_win32_shutdown_display
+pango_win32_font_map_get_font_cache
+pango_win32_font_logfont
+pango_win32_font_logfontw
+pango_win32_font_description_from_logfont
+pango_win32_font_description_from_logfontw
+
+<SUBSECTION Private>
+STRICT
+</SECTION>
+
+<SECTION>
+<TITLE>FreeType Fonts and Rendering</TITLE>
+<FILE>freetype-fonts</FILE>
+PangoFT2FontMap
+PANGO_RENDER_TYPE_FT2
+pango_ft2_font_map_new
+pango_ft2_font_map_set_resolution
+pango_ft2_font_map_create_context
+PangoFT2SubstituteFunc
+pango_ft2_font_map_set_default_substitute
+pango_ft2_font_map_substitute_changed
+pango_ft2_get_context
+pango_ft2_render
+pango_ft2_render_transformed
+pango_ft2_render_layout_line
+pango_ft2_render_layout_line_subpixel
+pango_ft2_render_layout
+pango_ft2_render_layout_subpixel
+pango_ft2_get_unknown_glyph
+pango_ft2_font_get_kerning
+pango_ft2_font_get_face
+pango_ft2_font_get_coverage
+pango_ft2_font_map_for_display
+pango_ft2_shutdown_display
+<SUBSECTION Standard>
+PANGO_TYPE_FT2_FONT_MAP
+PANGO_FT2_FONT_MAP
+PANGO_FT2_IS_FONT_MAP
+<SUBSECTION Private>
+pango_ft2_font_map_get_type
+STRICT
+</SECTION>
+
+<SECTION>
+<TITLE>Xft Fonts and Rendering</TITLE>
+<FILE>xft-fonts</FILE>
+PangoXftFont
+PangoXftFontMap
+PANGO_RENDER_TYPE_XFT
+pango_xft_get_context
+pango_xft_get_font_map
+pango_xft_set_default_substitute
+PangoXftSubstituteFunc
+pango_xft_substitute_changed
+pango_xft_shutdown_display
+pango_xft_font_get_font
+pango_xft_font_get_display
+pango_xft_font_has_char
+pango_xft_font_lock_face
+pango_xft_font_unlock_face
+pango_xft_font_get_glyph
+pango_xft_font_get_unknown_glyph
+PangoXftRenderer
+PangoXftRendererClass
+
+pango_xft_renderer_new
+pango_xft_renderer_set_draw
+pango_xft_renderer_set_default_color
+pango_xft_render
+pango_xft_picture_render
+pango_xft_render_transformed
+pango_xft_render_layout_line
+pango_xft_render_layout
+<SUBSECTION Standard>
+PANGO_TYPE_XFT_FONT
+PANGO_XFT_FONT
+PANGO_XFT_IS_FONT
+PANGO_TYPE_XFT_FONT_MAP
+PANGO_XFT_FONT_MAP
+PANGO_XFT_IS_FONT_MAP
+PANGO_XFT_RENDERER
+PANGO_IS_XFT_RENDERER
+PANGO_TYPE_XFT_RENDERER
+PANGO_XFT_RENDERER_CLASS
+PANGO_IS_XFT_RENDERER_CLASS
+PANGO_XFT_RENDERER_GET_CLASS
+
+<SUBSECTION Private>
+PangoXftRendererPrivate
+pango_xft_font_get_type
+pango_xft_font_map_get_type
+pango_xft_renderer_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>Cairo Rendering</TITLE>
+<FILE>pangocairo</FILE>
+PangoCairoFont
+PangoCairoFontMap
+pango_cairo_font_map_get_default
+pango_cairo_font_map_new
+pango_cairo_font_map_new_for_font_type
+pango_cairo_font_map_get_font_type
+pango_cairo_font_map_set_resolution
+pango_cairo_font_map_get_resolution
+pango_cairo_font_map_create_context
+pango_cairo_font_get_scaled_font
+pango_cairo_context_set_resolution
+pango_cairo_context_get_resolution
+pango_cairo_context_set_font_options
+pango_cairo_context_get_font_options
+PangoCairoShapeRendererFunc
+pango_cairo_context_set_shape_renderer
+pango_cairo_context_get_shape_renderer
+pango_cairo_update_context
+pango_cairo_create_layout
+pango_cairo_update_layout
+pango_cairo_show_glyph_string
+pango_cairo_show_layout_line
+pango_cairo_show_layout
+pango_cairo_show_error_underline
+pango_cairo_glyph_string_path
+pango_cairo_layout_line_path
+pango_cairo_layout_path
+pango_cairo_error_underline_path
+<SUBSECTION Standard>
+PANGO_CAIRO_FONT
+PANGO_CAIRO_FONT_MAP
+PANGO_IS_CAIRO_FONT
+PANGO_IS_CAIRO_FONT_MAP
+PANGO_TYPE_CAIRO_FONT
+PANGO_TYPE_CAIRO_FONT_MAP
+pango_cairo_font_get_type
+pango_cairo_font_map_get_type
+</SECTION>
+
+<SECTION>
+<TITLE>ATSUI Fonts</TITLE>
+<FILE>atsui-fonts</FILE>
+PANGO_RENDER_TYPE_ATSUI
+pango_atsui_font_get_atsu_font_id
+<SUBSECTION Standard>
+PANGO_ATSUI_FONT
+PANGO_ATSUI_FONT_CLASS
+PANGO_ATSUI_FONT_GET_CLASS
+PANGO_CAIRO_ATSUI_FONT
+PANGO_CAIRO_ATSUI_FONT_CLASS
+PANGO_CAIRO_ATSUI_FONT_GET_CLASS
+PANGO_IS_ATSUI_FONT
+PANGO_IS_ATSUI_FONT_CLASS
+PANGO_IS_CAIRO_ATSUI_FONT_CLASS
+PANGO_TYPE_ATSUI_FONT
+PANGO_TYPE_CAIRO_ATSUI_FONT
+PangoATSUIFont
+PangoATSUIFontClass
+PangoATSUIFontPrivate
+PangoCairoATSUIFont
+PangoCairoATSUIFontClass
+pango_atsui_font_get_type
+pango_cairo_atsui_font_get_type
+</SECTION>
+
+<SECTION>
+<FILE>pangofc-fontmap</FILE>
+<TITLE>PangoFcFontMap</TITLE>
+PangoFcFontMap
+PangoFcFontMapClass
+pango_fc_font_description_from_pattern
+pango_fc_font_map_cache_clear
+pango_fc_font_map_create_context
+pango_fc_font_map_shutdown
+pango_fc_font_map_add_decoder_find_func
+PangoFcDecoderFindFunc
+<SUBSECTION Standard>
+PANGO_FC_FONT_MAP
+PANGO_IS_FC_FONT_MAP
+PANGO_TYPE_FC_FONT_MAP
+PANGO_FC_FONT_MAP_CLASS
+PANGO_IS_FC_FONT_MAP_CLASS
+PANGO_FC_FONT_MAP_GET_CLASS
+
+<SUBSECTION Private>
+PangoFcFontMapPrivate
+pango_fc_font_map_get_type
+</SECTION>
+
+<SECTION>
+<FILE>pangofc-font</FILE>
+<TITLE>PangoFcFont</TITLE>
+PangoFcFont
+PangoFcFontClass
+PANGO_RENDER_TYPE_FC
+pango_fc_font_lock_face
+pango_fc_font_unlock_face
+pango_fc_font_has_char
+pango_fc_font_get_glyph
+pango_fc_font_get_unknown_glyph
+pango_fc_font_kern_glyphs
+<SUBSECTION Standard>
+PANGO_FC_FONT
+PANGO_IS_FC_FONT
+PANGO_TYPE_FC_FONT
+PANGO_FC_FONT_CLASS
+PANGO_IS_FC_FONT_CLASS
+PANGO_FC_FONT_GET_CLASS
+<SUBSECTION Private>
+pango_fc_font_get_type
+</SECTION>
+
+<SECTION>
+<FILE>pangofc-decoder</FILE>
+<TITLE>PangoFcDecoder</TITLE>
+PangoFcDecoder
+PangoFcDecoderClass
+pango_fc_decoder_get_charset
+pango_fc_decoder_get_glyph
+<SUBSECTION Standard>
+PANGO_FC_DECODER
+PANGO_IS_FC_DECODER
+PANGO_TYPE_FC_DECODER
+pango_fc_decoder_get_type
+PANGO_FC_DECODER_CLASS
+PANGO_IS_FC_DECODER_CLASS
+PANGO_FC_DECODER_GET_CLASS
+</SECTION>
+
+<SECTION>
+<TITLE>OpenType Font Handling</TITLE>
+<FILE>opentype</FILE>
+PangoOTTag
+PangoOTInfo
+PangoOTBuffer
+PangoOTGlyph
+PangoOTRuleset
+PangoOTRulesetDescription
+PangoOTTableType
+PangoOTFeatureMap
+PANGO_OT_TAG_MAKE
+PANGO_OT_TAG_MAKE_FROM_STRING
+PANGO_OT_ALL_GLYPHS
+PANGO_OT_NO_FEATURE
+PANGO_OT_NO_SCRIPT
+PANGO_OT_DEFAULT_LANGUAGE
+PANGO_OT_TAG_DEFAULT_LANGUAGE
+PANGO_OT_TAG_DEFAULT_SCRIPT
+pango_ot_info_get
+pango_ot_info_find_script
+pango_ot_info_find_language
+pango_ot_info_find_feature
+pango_ot_info_list_scripts
+pango_ot_info_list_languages
+pango_ot_info_list_features
+pango_ot_buffer_new
+pango_ot_buffer_destroy
+pango_ot_buffer_clear
+pango_ot_buffer_add_glyph
+pango_ot_buffer_set_rtl
+pango_ot_buffer_set_zero_width_marks
+pango_ot_buffer_get_glyphs
+pango_ot_buffer_output
+pango_ot_ruleset_get_for_description
+pango_ot_ruleset_new
+pango_ot_ruleset_new_for
+pango_ot_ruleset_new_from_description
+pango_ot_ruleset_add_feature
+pango_ot_ruleset_maybe_add_feature
+pango_ot_ruleset_maybe_add_features
+pango_ot_ruleset_get_feature_count
+pango_ot_ruleset_substitute
+pango_ot_ruleset_position
+pango_ot_ruleset_description_copy
+pango_ot_ruleset_description_equal
+pango_ot_ruleset_description_free
+pango_ot_ruleset_description_hash
+pango_ot_tag_from_language
+pango_ot_tag_from_script
+pango_ot_tag_to_language
+pango_ot_tag_to_script
+</SECTION>
+
+<SECTION>
+<TITLE>Miscellaneous Utilities</TITLE>
+<FILE>utils</FILE>
+pango_split_file_list
+pango_trim_string
+pango_read_line
+pango_skip_space
+pango_scan_word
+pango_scan_string
+pango_scan_int
+pango_config_key_get
+pango_lookup_aliases
+pango_parse_enum
+pango_parse_style
+pango_parse_variant
+pango_parse_weight
+pango_parse_stretch
+pango_get_sysconf_subdirectory
+pango_get_lib_subdirectory
+pango_log2vis_get_embedding_levels
+pango_language_get_default
+pango_language_get_sample_string
+pango_is_zero_width
+pango_quantize_line_geometry
+</SECTION>
+
+<SECTION>
+<TITLE>Version Checking</TITLE>
+<FILE>pango-version</FILE>
+PANGO_VERSION_ENCODE
+PANGO_VERSION
+PANGO_VERSION_MAJOR
+PANGO_VERSION_MINOR
+PANGO_VERSION_MICRO
+PANGO_VERSION_STRING
+PANGO_VERSION_CHECK
+pango_version
+pango_version_string
+pango_version_check
+</SECTION>
+
+<SECTION>
+<TITLE>Vertical Text</TITLE>
+<FILE>vertical</FILE>
+PangoGravity
+PANGO_TYPE_GRAVITY
+PangoGravityHint
+PANGO_TYPE_GRAVITY_HINT
+PANGO_GRAVITY_IS_VERTICAL
+pango_gravity_get_for_matrix
+pango_gravity_get_for_script
+<SUBSECTION Private>
+pango_gravity_get_type
+pango_gravity_hint_get_type
+</SECTION>
diff --git a/trunk/docs/pango.types b/trunk/docs/pango.types
new file mode 100644
index 00000000..96361269
--- /dev/null
+++ b/trunk/docs/pango.types
@@ -0,0 +1,30 @@
+#include <pango/pango.h>
+#include <pango/pangocairo.h>
+#include <pango/pangofc-font.h>
+#include <pango/pangofc-fontmap.h>
+#include <pango/pangoft2.h>
+#include <pango/pangoxft.h>
+#include <pango/pango-ot.h>
+
+pango_engine_get_type
+pango_engine_lang_get_type
+pango_engine_shape_get_type
+pango_font_get_type
+pango_font_family_get_type
+pango_font_face_get_type
+pango_font_map_get_type
+pango_fontset_get_type
+pango_fontset_simple_get_type
+pango_context_get_type
+pango_layout_get_type
+pango_renderer_get_type
+pango_fc_font_get_type
+pango_fc_font_map_get_type
+pango_fc_decoder_get_type
+pango_ft2_font_map_get_type
+pango_xft_font_get_type
+pango_xft_font_map_get_type
+pango_xft_renderer_get_type
+pango_cairo_font_map_get_type
+pango_ot_info_get_type
+pango_ot_ruleset_get_type
diff --git a/trunk/docs/pango_markup.sgml b/trunk/docs/pango_markup.sgml
new file mode 100644
index 00000000..5fc3ef48
--- /dev/null
+++ b/trunk/docs/pango_markup.sgml
@@ -0,0 +1,250 @@
+<refentry id="PangoMarkupFormat" revision="11 Dec 2002">
+<refmeta>
+<refentrytitle>Text Attribute Markup</refentrytitle>
+<manvolnum>3</manvolnum>
+<refmiscinfo>Pango Library</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>Text Attribute Markup</refname><refpurpose>Simple
+markup language to encode text with attributes</refpurpose>
+</refnamediv>
+
+<refsect1>
+<title>Pango Text Attribute Markup Language</title>
+
+<para>
+Frequently, you want to display some text to the user with attributes
+applied to part of the text (for example, you might want bold or
+italicized words). With the base Pango interfaces, you could create a
+<link linkend="PangoAttrList">PangoAttrList</link> and apply it to the
+text; the problem is that you'd need to apply attributes to some
+numeric range of characters, for example "characters 12-17." This is
+broken from an internationalization standpoint; once the text is
+translated, the word you wanted to italicize could be in a different
+position.
+</para>
+
+<para>
+The solution is to include the text attributes in the string to be
+translated. Pango provides this feature with a small markup language.
+You can parse a marked-up string into the string text plus a
+<link linkend="PangoAttrList">PangoAttrList</link> using the function
+<link linkend="pango-parse-markup">pango_parse_markup()</link>.
+</para>
+
+<para>
+A simple example of a marked-up string might be:
+<literal>"&lt;span foreground="blue" size="x-large"&gt;Blue text&lt;/span&gt; is &lt;i&gt;cool&lt;/i&gt;!"</literal>
+</para>
+
+<para>
+The root tag of a marked-up document is &lt;markup&gt;, but <link
+linkend="pango-parse-markup">pango_parse_markup()</link> allows you to
+omit this tag, so you will most likely never need to use it. The most
+general markup tag is &lt;span&gt;, then there are some convenience
+tags. &lt;span&gt; has the following attributes:
+<variablelist><title>&lt;span&gt; attributes</title>
+
+<varlistentry><term>font_desc</term>
+<listitem><para>
+A font description string, such as "Sans Italic 12"; note that any other
+span attributes will override this description. So if you have "Sans
+Italic" and also a style="normal" attribute, you will get Sans normal,
+not italic.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>font_family</term>
+<listitem><para>
+A font family name
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>face</term>
+<listitem><para>
+Synonym for font_family
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>size</term>
+<listitem><para>
+Font size in 1024ths of a point, or one of the absolute sizes
+'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',
+'xx-large', or one of the relative sizes 'smaller' or 'larger'.
+If you want to specify a absolute size, it's usually easier
+to take advantage of the ability to specify a partial
+font description using 'font_desc'; you can use
+<literal>font_desc='12.5'</literal> rather than
+<literal>size='12800'</literal>.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>style</term>
+<listitem><para>
+One of 'normal', 'oblique', 'italic'
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>weight</term>
+<listitem><para>
+One of 'ultralight', 'light', 'normal', 'bold', 'ultrabold', 'heavy',
+or a numeric weight
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>variant</term>
+<listitem><para>
+'normal' or 'smallcaps'
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>stretch</term>
+<listitem><para>
+One of 'ultracondensed', 'extracondensed', 'condensed',
+'semicondensed', 'normal', 'semiexpanded', 'expanded',
+'extraexpanded', 'ultraexpanded'
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>foreground</term>
+<listitem><para>
+An RGB color specification such as '#00FF00' or a color name such as
+'red'
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>background</term>
+<listitem><para>
+An RGB color specification such as '#00FF00' or a color name such as
+'red'
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>underline</term>
+<listitem><para>
+One of 'none', 'single', 'double', 'low', 'error'
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>underline_color</term>
+<listitem><para>
+The color of underlines; an RGB color specification such as '#00FF00'
+or a color name such as 'red'
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>rise</term>
+<listitem><para>
+Vertical displacement, in 10000ths of an em. Can be negative for
+subscript, positive for superscript.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>strikethrough</term>
+<listitem><para>
+'true' or 'false' whether to strike through the text
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>strikethrough_color</term>
+<listitem><para>
+The color of strikethrough lines; an RGB color specification such as
+'#00FF00' or a color name such as 'red'
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>fallback</term>
+<listitem><para>
+'true' or 'false' whether to enable fallback. If disabled, then characters
+will only be used from the closest matching font on the system. No fallback
+will be done to other fonts on the system that might contain the characters
+in the text. Fallback is enabled by default. Most applications should not
+disable fallback.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>lang</term>
+<listitem><para>
+A language code, indicating the text language
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>letter_spacing</term>
+<listitem><para>
+Inter-letter spacing in 1024ths of a point.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>gravity</term>
+<listitem><para>
+One of 'south', 'east', 'north', 'west', 'auto'.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>gravity_hint</term>
+<listitem><para>
+One of 'natural', 'strong', 'line'.
+</para></listitem>
+</varlistentry>
+
+</variablelist>
+
+</para>
+
+<para>
+The following convenience tags are provided:
+
+<variablelist><title>Convenience tags</title>
+<varlistentry><term>b</term>
+<listitem><para>
+Bold
+</para></listitem>
+</varlistentry>
+<varlistentry><term>big</term>
+<listitem><para>
+Makes font relatively larger, equivalent to &lt;span size="larger"&gt;
+</para></listitem>
+</varlistentry>
+<varlistentry><term>i</term>
+<listitem><para>
+Italic
+</para></listitem>
+</varlistentry>
+<varlistentry><term>s</term>
+<listitem><para>
+Strikethrough
+</para></listitem>
+</varlistentry>
+<varlistentry><term>sub</term>
+<listitem><para>
+Subscript
+</para></listitem>
+</varlistentry>
+<varlistentry><term>sup</term>
+<listitem><para>
+Superscript
+</para></listitem>
+</varlistentry>
+<varlistentry><term>small</term>
+<listitem><para>
+Makes font relatively smaller, equivalent to &lt;span size="smaller"&gt;
+</para></listitem>
+</varlistentry>
+<varlistentry><term>tt</term>
+<listitem><para>
+Monospace font
+</para></listitem>
+</varlistentry>
+<varlistentry><term>u</term>
+<listitem><para>
+Underline
+</para></listitem>
+</varlistentry>
+</variablelist>
+
+</para>
+
+</refsect1>
+
+</refentry>
diff --git a/trunk/docs/rotated-text.png b/trunk/docs/rotated-text.png
new file mode 100644
index 00000000..b29682e8
--- /dev/null
+++ b/trunk/docs/rotated-text.png
Binary files differ
diff --git a/trunk/docs/tmpl/atsui-fonts.sgml b/trunk/docs/tmpl/atsui-fonts.sgml
new file mode 100644
index 00000000..1a82afbf
--- /dev/null
+++ b/trunk/docs/tmpl/atsui-fonts.sgml
@@ -0,0 +1,37 @@
+<!-- ##### SECTION Title ##### -->
+ATSUI Fonts
+
+<!-- ##### SECTION Short_Description ##### -->
+Font handling with ATSUI fonts
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The macros and functions in this section are used to access fonts natively on
+MacOS systems using the ATSUI text rendering subsystem.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### MACRO PANGO_RENDER_TYPE_ATSUI ##### -->
+<para>
+A string constant identifying the ATSUI renderer. The associated quark (see
+g_quark_from_string()) is used to identify the renderer in pango_find_map().
+</para>
+
+
+
+<!-- ##### FUNCTION pango_atsui_font_get_atsu_font_id ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/coverage-maps.sgml b/trunk/docs/tmpl/coverage-maps.sgml
new file mode 100644
index 00000000..69c71626
--- /dev/null
+++ b/trunk/docs/tmpl/coverage-maps.sgml
@@ -0,0 +1,136 @@
+<!-- ##### SECTION Title ##### -->
+Coverage Maps
+
+<!-- ##### SECTION Short_Description ##### -->
+Unicode character range coverage storage
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+It is often necessary in Pango to determine if a particular font can
+represent a particular character, and also how well it can represent
+that character. The #PangoCoverage is a data structure that is used
+to represent that information.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### ENUM PangoCoverageLevel ##### -->
+<para>
+Used to indicate how well a font can represent a particular Unicode
+character point for a particular script.
+</para>
+
+@PANGO_COVERAGE_NONE: The character is not representable with the font.
+@PANGO_COVERAGE_FALLBACK: The character is represented in a way that may be
+ comprehensible but is not the correct graphical form.
+ For instance, a Hangul character represented as a
+ a sequence of Jamos, or a Latin transliteration of
+ a Cyrillic word.
+@PANGO_COVERAGE_APPROXIMATE: The character is represented as basically the correct
+ graphical form, but with a stylistic variant inappropriate for
+ the current script.
+@PANGO_COVERAGE_EXACT: The character is represented as the correct graphical form.
+
+<!-- ##### MACRO PANGO_TYPE_COVERAGE_LEVEL ##### -->
+<para>
+The #GObject type for #PangoCoverageLevel.
+</para>
+
+
+
+<!-- ##### STRUCT PangoCoverage ##### -->
+<para>
+The #PangoCoverage structure represents a map from Unicode characters
+to #PangoCoverageLevel. It is an opaque structure with no public fields.
+</para>
+
+
+<!-- ##### FUNCTION pango_coverage_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_coverage_ref ##### -->
+<para>
+
+</para>
+
+@coverage:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_coverage_unref ##### -->
+<para>
+
+</para>
+
+@coverage:
+
+
+<!-- ##### FUNCTION pango_coverage_copy ##### -->
+<para>
+
+</para>
+
+@coverage:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_coverage_get ##### -->
+<para>
+
+</para>
+
+@coverage:
+@index_:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_coverage_max ##### -->
+<para>
+
+</para>
+
+@coverage:
+@other:
+
+
+<!-- ##### FUNCTION pango_coverage_set ##### -->
+<para>
+
+</para>
+
+@coverage:
+@index_:
+@level:
+
+
+<!-- ##### FUNCTION pango_coverage_to_bytes ##### -->
+<para>
+
+</para>
+
+@coverage:
+@bytes:
+@n_bytes:
+
+
+<!-- ##### FUNCTION pango_coverage_from_bytes ##### -->
+<para>
+
+</para>
+
+@bytes:
+@n_bytes:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/engines.sgml b/trunk/docs/tmpl/engines.sgml
new file mode 100644
index 00000000..20de439f
--- /dev/null
+++ b/trunk/docs/tmpl/engines.sgml
@@ -0,0 +1,116 @@
+<!-- ##### SECTION Title ##### -->
+Engines
+
+<!-- ##### SECTION Short_Description ##### -->
+Language-specific and rendering-system-specific processing
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+Pango utilizes a module architecture in which the language-specific
+and render-system-specific components are provided by loadable
+modules. Each loadable module supplies one or more
+<firstterm>engines</firstterm>. Each <firstterm>engine</firstterm>
+has an associated <firstterm>engine type</firstterm> and
+<firstterm>render type</firstterm>. These two types are represented by
+strings.
+</para>
+<para>
+Each dynamically-loaded module exports several functions which provide
+the public API. These functions are script_engine_list(),
+script_engine_init() and script_engine_exit, and
+script_engine_create(). The latter three functions are used when
+creating engines from the module at run time, while the first
+function is used when building a catalog of all available modules.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoEngineInfo ##### -->
+<para>
+The #PangoEngineInfo structure contains information about a particular
+engine. It contains the following fields:
+</para>
+
+@id: a unique string ID for the engine.
+@engine_type: a string identifying the engine type.
+@render_type: a string identifying the render type.
+@scripts: array of scripts this engine supports.
+@n_scripts: number of items in @scripts.
+
+<!-- ##### STRUCT PangoEngineScriptInfo ##### -->
+<para>
+The #PangoEngineScriptInfo structure contains
+information about how the shaper covers a particular
+script.
+</para>
+
+@script: a #PangoScript. The value %PANGO_SCRIPT_COMMON has
+ the special meaning here of "all scripts"
+@langs: a semicolon separated list of languages that this
+ engine handles for this script. This may be empty,
+ in which case the engine is saying that it is a
+ fallback choice for all languages for this range,
+ but should not be used if another engine
+ indicates that it is specific for the language for
+ a given code point. An entry in this list of "*"
+ indicates that this engine is specific to all
+ languages for this range.
+
+<!-- ##### STRUCT PangoEngine ##### -->
+<para>
+</para>
+
+
+<!-- ##### STRUCT PangoEngineClass ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO PANGO_RENDER_TYPE_NONE ##### -->
+<para>
+A string constant defining the render type
+for engines that are not rendering-system
+specific.
+</para>
+
+
+
+<!-- ##### FUNCTION script_engine_list ##### -->
+<para>
+</para>
+
+@engines: location to store a pointer to an array of engines.
+@n_engines: location to store the number of elements in @engines.
+
+
+<!-- ##### FUNCTION script_engine_init ##### -->
+<para>
+
+</para>
+
+@module:
+
+
+<!-- ##### FUNCTION script_engine_exit ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION script_engine_create ##### -->
+<para>
+
+</para>
+
+@id:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/fonts.sgml b/trunk/docs/tmpl/fonts.sgml
new file mode 100644
index 00000000..0dff0479
--- /dev/null
+++ b/trunk/docs/tmpl/fonts.sgml
@@ -0,0 +1,1023 @@
+<!-- ##### SECTION Title ##### -->
+Fonts
+
+<!-- ##### SECTION Short_Description ##### -->
+Structures representing abstract fonts
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+Pango supports a flexible architecture where a
+particular rendering architecture can supply an
+implementation of fonts. The #PangoFont structure
+represents an abstract rendering-system-independent font.
+Pango provides routines to list available fonts, and
+to load a font of a given description.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoFontDescription ##### -->
+<para>
+The #PangoFontDescription structure represents the description
+of an ideal font. These structures are used both to list
+what fonts are available on the system and also for specifying
+the characteristics of a font to load.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_FONT_DESCRIPTION ##### -->
+<para>
+The #GObject type for #PangoFontDescription.
+</para>
+
+
+
+<!-- ##### ENUM PangoStyle ##### -->
+<para>
+</para>
+
+@PANGO_STYLE_NORMAL:
+@PANGO_STYLE_OBLIQUE:
+@PANGO_STYLE_ITALIC:
+
+<!-- ##### MACRO PANGO_TYPE_STYLE ##### -->
+<para>
+The #GObject type for #PangoStyle.
+</para>
+
+
+
+<!-- ##### ENUM PangoWeight ##### -->
+<para>
+An enumeration specifying the weight (boldness) of a font. This is a numerical
+value ranging from 100 to 900, but there are some predefined values:
+</para>
+
+@PANGO_WEIGHT_ULTRALIGHT: the ultralight weight (= 200)
+@PANGO_WEIGHT_LIGHT: the light weight (=300)
+@PANGO_WEIGHT_NORMAL: the default weight (= 400)
+@PANGO_WEIGHT_SEMIBOLD: a weight intermediate between normal and bold (=600)
+@PANGO_WEIGHT_BOLD: the bold weight (= 700)
+@PANGO_WEIGHT_ULTRABOLD: the ultrabold weight (= 800)
+@PANGO_WEIGHT_HEAVY: the heavy weight (= 900)
+
+<!-- ##### MACRO PANGO_TYPE_WEIGHT ##### -->
+<para>
+The #GObject type for #PangoWeight.
+</para>
+
+
+
+<!-- ##### ENUM PangoVariant ##### -->
+<para>
+An enumeration specifying capitalization variant of the font.
+</para>
+
+@PANGO_VARIANT_NORMAL: A normal font.
+@PANGO_VARIANT_SMALL_CAPS: A font with the lower case characters
+ replaced by smaller variants of the capital characters.
+
+<!-- ##### MACRO PANGO_TYPE_VARIANT ##### -->
+<para>
+The #GObject type for #PangoVariant.
+</para>
+
+
+
+<!-- ##### ENUM PangoStretch ##### -->
+<para>
+An enumeration specifying the width of the font relative to other designs
+within a family.
+</para>
+
+@PANGO_STRETCH_ULTRA_CONDENSED: ultra condensed width
+@PANGO_STRETCH_EXTRA_CONDENSED: extra condensed width
+@PANGO_STRETCH_CONDENSED: condensed width
+@PANGO_STRETCH_SEMI_CONDENSED: semi condensed width
+@PANGO_STRETCH_NORMAL: the normal width
+@PANGO_STRETCH_SEMI_EXPANDED: semi expanded width
+@PANGO_STRETCH_EXPANDED: expanded width
+@PANGO_STRETCH_EXTRA_EXPANDED: extra expanded width
+@PANGO_STRETCH_ULTRA_EXPANDED: ultra expanded width
+
+<!-- ##### MACRO PANGO_TYPE_STRETCH ##### -->
+<para>
+The #GObject type for #PangoStretch.
+</para>
+
+
+
+<!-- ##### ENUM PangoFontMask ##### -->
+<para>
+The bits in a #PangoFontMask correspond to fields in a
+#PangoFontDescription that have been set.
+</para>
+
+@PANGO_FONT_MASK_FAMILY: the font family is specified.
+@PANGO_FONT_MASK_STYLE: the font style is specified.
+@PANGO_FONT_MASK_VARIANT: the font variant is specified.
+@PANGO_FONT_MASK_WEIGHT: the font weight is specified.
+@PANGO_FONT_MASK_STRETCH: the font stretch is specified.
+@PANGO_FONT_MASK_SIZE: the font size is specified.
+@PANGO_FONT_MASK_GRAVITY: the font gravity is specified (Since: 1.16.)
+
+<!-- ##### MACRO PANGO_TYPE_FONT_MASK ##### -->
+<para>
+The #GObject type for #PangoFontMask.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_font_description_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_copy ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_copy_static ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_hash ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_equal ##### -->
+<para>
+
+</para>
+
+@desc1:
+@desc2:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_free ##### -->
+<para>
+
+</para>
+
+@desc:
+
+
+<!-- ##### FUNCTION pango_font_descriptions_free ##### -->
+<para>
+
+</para>
+
+@descs:
+@n_descs:
+
+
+<!-- ##### FUNCTION pango_font_description_set_family ##### -->
+<para>
+
+</para>
+
+@desc:
+@family:
+
+
+<!-- ##### FUNCTION pango_font_description_set_family_static ##### -->
+<para>
+
+</para>
+
+@desc:
+@family:
+
+
+<!-- ##### FUNCTION pango_font_description_get_family ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_set_style ##### -->
+<para>
+
+</para>
+
+@desc:
+@style:
+
+
+<!-- ##### FUNCTION pango_font_description_get_style ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_set_variant ##### -->
+<para>
+
+</para>
+
+@desc:
+@variant:
+
+
+<!-- ##### FUNCTION pango_font_description_get_variant ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_set_weight ##### -->
+<para>
+
+</para>
+
+@desc:
+@weight:
+
+
+<!-- ##### FUNCTION pango_font_description_get_weight ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_set_stretch ##### -->
+<para>
+
+</para>
+
+@desc:
+@stretch:
+
+
+<!-- ##### FUNCTION pango_font_description_get_stretch ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_set_size ##### -->
+<para>
+
+</para>
+
+@desc:
+@size:
+
+
+<!-- ##### FUNCTION pango_font_description_get_size ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_set_absolute_size ##### -->
+<para>
+
+</para>
+
+@desc:
+@size:
+
+
+<!-- ##### FUNCTION pango_font_description_get_size_is_absolute ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_set_gravity ##### -->
+<para>
+
+</para>
+
+@desc:
+@gravity:
+
+
+<!-- ##### FUNCTION pango_font_description_get_gravity ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_get_set_fields ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_unset_fields ##### -->
+<para>
+
+</para>
+
+@desc:
+@to_unset:
+
+
+<!-- ##### FUNCTION pango_font_description_merge ##### -->
+<para>
+
+</para>
+
+@desc:
+@desc_to_merge:
+@replace_existing:
+
+
+<!-- ##### FUNCTION pango_font_description_merge_static ##### -->
+<para>
+
+</para>
+
+@desc:
+@desc_to_merge:
+@replace_existing:
+
+
+<!-- ##### FUNCTION pango_font_description_better_match ##### -->
+<para>
+
+</para>
+
+@desc:
+@old_match:
+@new_match:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_from_string ##### -->
+<para>
+
+</para>
+
+@str:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_to_string ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_description_to_filename ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### STRUCT PangoFontMetrics ##### -->
+<para>
+A #PangoFontMetrics structure holds the overall metric information
+for a font (possibly restricted to a script). The fields of this
+structure are private to implementations of a font backend. See
+the documentation of the corresponding getters for documentation
+of their meaning.
+</para>
+
+@ref_count: reference count. Used internally. See pango_font_metrics_ref()
+ and pango_font_metrics_unref().
+@ascent: the distance from the baseline to the highest point of the glyphs of
+ the font. This is positive in practically all fonts.
+@descent: the distance from the baseline to the lowest point of the glyphs of
+ the font. This is positive in practically all fonts.
+@approximate_char_width: approximate average width of the regular glyphs of
+ the font.
+@approximate_digit_width: approximate average width of the glyphs for digits
+ of the font.
+@underline_position: position of the underline. This is normally negative.
+@underline_thickness: thickness of the underline.
+@strikethrough_position: position of the strikethrough line. This is
+ normally positive.
+@strikethrough_thickness: thickness of the strikethrough line.
+
+<!-- ##### MACRO PANGO_TYPE_FONT_METRICS ##### -->
+<para>
+The #GObject type for #PangoFontMetrics.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_font_metrics_ref ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_metrics_unref ##### -->
+<para>
+
+</para>
+
+@metrics:
+
+
+<!-- ##### FUNCTION pango_font_metrics_get_ascent ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_metrics_get_descent ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_metrics_get_approximate_char_width ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_metrics_get_approximate_digit_width ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_metrics_get_underline_thickness ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_metrics_get_underline_position ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_metrics_get_strikethrough_thickness ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_metrics_get_strikethrough_position ##### -->
+<para>
+
+</para>
+
+@metrics:
+@Returns:
+
+
+<!-- ##### STRUCT PangoFont ##### -->
+<para>
+The #PangoFont structure is used to represent
+a font in a rendering-system-independent matter.
+To create an implementation of a #PangoFont,
+the rendering-system specific code should allocate
+a larger structure that contains a nested
+#PangoFont, fill in the <structfield>klass</structfield> member of
+the nested #PangoFont with a pointer to
+a appropriate #PangoFontClass, then call
+pango_font_init() on the structure.
+</para>
+<para>
+The #PangoFont structure contains one member
+which the implementation fills in.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_FONT ##### -->
+<para>
+The #GObject type for #PangoFont.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_FONT ##### -->
+<para>
+Casts a #GObject to a #PangoFont.
+</para>
+
+@object: a #GObject.
+
+
+<!-- ##### MACRO PANGO_IS_FONT ##### -->
+<para>
+Returns %TRUE if @object is a #PangoFont.
+</para>
+
+@object: a #GObject.
+
+
+<!-- ##### FUNCTION pango_font_find_shaper ##### -->
+<para>
+
+</para>
+
+@font:
+@language:
+@ch:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_describe ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_describe_with_absolute_size ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_get_coverage ##### -->
+<para>
+
+</para>
+
+@font:
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_get_glyph_extents ##### -->
+<para>
+
+</para>
+
+@font:
+@glyph:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_font_get_metrics ##### -->
+<para>
+
+</para>
+
+@font:
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_get_font_map ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### STRUCT PangoFontFamily ##### -->
+<para>
+The #PangoFontFamily structure is used to represent a family of related
+font faces. The faces in a family share a common design, but differ in
+slant, weight, width and other aspects.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_FONT_FAMILY ##### -->
+<para>
+The #GObject type for #PangoFontFamily.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_FONT_FAMILY ##### -->
+<para>
+Casts a #GObject to a #PangoFontFamily.
+</para>
+
+@object: a #GObject.
+
+
+<!-- ##### MACRO PANGO_IS_FONT_FAMILY ##### -->
+<para>
+Returns %TRUE if @object is a #PangoFontFamily.
+</para>
+
+@object: a #GObject.
+
+
+<!-- ##### FUNCTION pango_font_family_get_name ##### -->
+<para>
+
+</para>
+
+@family:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_family_is_monospace ##### -->
+<para>
+
+</para>
+
+@family:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_family_list_faces ##### -->
+<para>
+
+</para>
+
+@family:
+@faces:
+@n_faces:
+
+
+<!-- ##### STRUCT PangoFontFace ##### -->
+<para>
+The #PangoFontFace structure is used to represent a group of fonts with
+the same family, slant, weight, width, but varying sizes.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_FONT_FACE ##### -->
+<para>
+The #GObject type for #PangoFontFace.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_FONT_FACE ##### -->
+<para>
+Casts a #GObject to a #PangoFontFace.
+</para>
+
+@object: a #GObject.
+
+
+<!-- ##### MACRO PANGO_IS_FONT_FACE ##### -->
+<para>
+Returns %TRUE if @object is a #PangoFontFace.
+</para>
+
+@object: a #GObject.
+
+
+<!-- ##### FUNCTION pango_font_face_get_face_name ##### -->
+<para>
+
+</para>
+
+@face:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_face_list_sizes ##### -->
+<para>
+
+</para>
+
+@face:
+@sizes:
+@n_sizes:
+
+
+<!-- ##### FUNCTION pango_font_face_describe ##### -->
+<para>
+
+</para>
+
+@face:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_face_is_synthesized ##### -->
+<para>
+
+</para>
+
+@face:
+@Returns:
+
+
+<!-- ##### STRUCT PangoFontMap ##### -->
+<para>
+The #PangoFontMap represents the set of fonts available for a
+particular rendering system. This is a virtual object with
+implementations being specific to particular rendering systems. To
+create an implementation of a #PangoFontMap, the rendering-system
+specific code should allocate a larger structure that contains a nested
+#PangoFontMap, fill in the <structfield>klass</structfield> member of the nested #PangoFontMap with a
+pointer to a appropriate #PangoFontMapClass, then call
+pango_font_map_init() on the structure.
+</para>
+<para>
+The #PangoFontMap structure contains one member which the implementation
+fills in.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_FONT_MAP ##### -->
+<para>
+The #GObject type for #PangoFontMap.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_FONT_MAP ##### -->
+<para>
+Casts a #GObject to a #PangoFontMap.
+</para>
+
+@object: a #GObject.
+
+
+<!-- ##### MACRO PANGO_IS_FONT_MAP ##### -->
+<para>
+Returns %TRUE if @object is a #PangoFontMap.
+</para>
+
+@object: a #GObject.
+
+
+<!-- ##### STRUCT PangoFontMapClass ##### -->
+<para>
+The #PangoFontMapClass structure holds the virtual functions for
+a particular #PangoFontMap implementation.
+</para>
+
+@parent_class: parent #GObjectClass.
+@load_font: a function to load a font with a given description. See
+ pango_font_map_load_font().
+@list_families: A function to list available font families. See
+ pango_font_map_list_families().
+@load_fontset: a function to load a fontset with a given given description
+ suitable for a particular language. See
+ pango_font_map_load_fontset().
+@shape_engine_type: the type of rendering-system-dependent engines that
+ can handle fonts of this fonts loaded with this fontmap.
+
+<!-- ##### MACRO PANGO_FONT_MAP_CLASS ##### -->
+<para>
+Casts a #GObject to a #PangoFontMapClass.
+</para>
+
+@klass: a #GObject.
+
+
+<!-- ##### MACRO PANGO_IS_FONT_MAP_CLASS ##### -->
+<para>
+Returns %TRUE if @klass is a subtype of #PangoFontMapClass.
+</para>
+
+@klass: a #GObject.
+
+
+<!-- ##### MACRO PANGO_FONT_MAP_GET_CLASS ##### -->
+<para>
+Returns the type of a #PangoFontMap.
+</para>
+
+@obj: a #PangoFontMap.
+
+
+<!-- ##### FUNCTION pango_font_map_load_font ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@context:
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_map_load_fontset ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@context:
+@desc:
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_font_map_list_families ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@families:
+@n_families:
+
+
+<!-- ##### FUNCTION pango_font_map_get_shape_engine_type ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@Returns:
+
+
+<!-- ##### STRUCT PangoFontset ##### -->
+<para>
+A #PangoFontset represents a set of #PangoFont to use
+when rendering text. It is the result of resolving a
+#PangoFontDescription against a particular #PangoContext.
+It has operations for finding the component font for
+a particular Unicode character, and for finding a composite
+set of metrics for the entire fontset.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_FONTSET ##### -->
+<para>
+The #GObject type for #PangoFontset.
+</para>
+
+
+
+<!-- ##### STRUCT PangoFontsetClass ##### -->
+<para>
+The #PangoFontsetClass structure holds the virtual functions for
+a particular #PangoFontset implementation.
+</para>
+
+@parent_class: parent #GObjectClass.
+@get_font: a function to get the font in the fontset that contains the
+ best glyph for the given Unicode character; see pango_fontset_get_font().
+@get_metrics: a function to get overall metric information for the fonts
+ in the fontset; see pango_fontset_get_metrics().
+@get_language: a function to get the language of the fontset.
+@foreach: a function to loop over the fonts in the fontset. See
+ pango_fontset_foreach().
+
+<!-- ##### FUNCTION pango_fontset_get_font ##### -->
+<para>
+
+</para>
+
+@fontset:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fontset_get_metrics ##### -->
+<para>
+
+</para>
+
+@fontset:
+@Returns:
+
+
+<!-- ##### USER_FUNCTION PangoFontsetForeachFunc ##### -->
+<para>
+
+</para>
+
+@fontset:
+@font:
+@data:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fontset_foreach ##### -->
+<para>
+
+</para>
+
+@fontset:
+@func:
+@data:
+
+
+<!-- ##### STRUCT PangoFontsetSimple ##### -->
+<para>
+#PangoFontsetSimple is a implementation of the abstract
+#PangoFontset base class in terms of an array of fonts,
+which the creator provides when constructing the
+#PangoFontsetSimple.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_FONTSET_SIMPLE ##### -->
+<para>
+The #GObject type for #PangoFontsetSimple.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_fontset_simple_new ##### -->
+<para>
+
+</para>
+
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fontset_simple_append ##### -->
+<para>
+
+</para>
+
+@fontset:
+@font:
+
+
+<!-- ##### FUNCTION pango_fontset_simple_size ##### -->
+<para>
+
+</para>
+
+@fontset:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/freetype-fonts.sgml b/trunk/docs/tmpl/freetype-fonts.sgml
new file mode 100644
index 00000000..06f5006c
--- /dev/null
+++ b/trunk/docs/tmpl/freetype-fonts.sgml
@@ -0,0 +1,222 @@
+<!-- ##### SECTION Title ##### -->
+FreeType Fonts and Rendering
+
+<!-- ##### SECTION Short_Description ##### -->
+Functions for shape engines to manipulate FreeType fonts
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The macros and functions in this section are used to access fonts and render
+text to bitmaps using the FreeType 2 library.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoFT2FontMap ##### -->
+<para>
+The #PangoFT2FontMap is the #PangoFontMap implementation for FreeType fonts.
+</para>
+
+
+<!-- ##### MACRO PANGO_RENDER_TYPE_FT2 ##### -->
+<para>
+A string constant that was used to identify shape engines that work
+with the FreeType backend. See %PANGO_RENDER_TYPE_FC for the replacement.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_ft2_font_map_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ft2_font_map_set_resolution ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@dpi_x:
+@dpi_y:
+
+
+<!-- ##### FUNCTION pango_ft2_font_map_create_context ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@Returns:
+
+
+<!-- ##### USER_FUNCTION PangoFT2SubstituteFunc ##### -->
+<para>
+Function type for doing final config tweaking on prepared FcPatterns.
+</para>
+
+@pattern: the <type>FcPattern</type> to tweak.
+@data: user data.
+
+
+<!-- ##### FUNCTION pango_ft2_font_map_set_default_substitute ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@func:
+@data:
+@notify:
+
+
+<!-- ##### FUNCTION pango_ft2_font_map_substitute_changed ##### -->
+<para>
+
+</para>
+
+@fontmap:
+
+
+<!-- ##### FUNCTION pango_ft2_get_context ##### -->
+<para>
+
+</para>
+
+@dpi_x:
+@dpi_y:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ft2_render ##### -->
+<para>
+
+</para>
+
+@bitmap:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_ft2_render_transformed ##### -->
+<para>
+
+</para>
+
+@bitmap:
+@matrix:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_ft2_render_layout_line ##### -->
+<para>
+
+</para>
+
+@bitmap:
+@line:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_ft2_render_layout_line_subpixel ##### -->
+<para>
+
+</para>
+
+@bitmap:
+@line:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_ft2_render_layout ##### -->
+<para>
+
+</para>
+
+@bitmap:
+@layout:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_ft2_render_layout_subpixel ##### -->
+<para>
+
+</para>
+
+@bitmap:
+@layout:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_ft2_get_unknown_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ft2_font_get_kerning ##### -->
+<para>
+
+</para>
+
+@font:
+@left:
+@right:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ft2_font_get_face ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ft2_font_get_coverage ##### -->
+<para>
+
+</para>
+
+@font:
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ft2_font_map_for_display ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ft2_shutdown_display ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/trunk/docs/tmpl/glyphs.sgml b/trunk/docs/tmpl/glyphs.sgml
new file mode 100644
index 00000000..44dff0db
--- /dev/null
+++ b/trunk/docs/tmpl/glyphs.sgml
@@ -0,0 +1,555 @@
+<!-- ##### SECTION Title ##### -->
+Glyph Storage
+
+<!-- ##### SECTION Short_Description ##### -->
+Structures for storing information about glyphs
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+pango_shape() produces a string of glyphs which
+can be measured or drawn to the screen. The following
+structures are used to store information about
+glyphs.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### MACRO PANGO_SCALE ##### -->
+<para>
+The %PANGO_SCALE macro represents the scale between dimensions used
+for Pango distances and device units. (The definition of device
+units is dependent on the output device; it will typically be pixels
+for a screen, and points for a printer.) %PANGO_SCALE is currently
+1024, but this may be changed in the future.
+</para>
+<para>
+When setting font sizes, device units are always considered to be
+points (as in "12 point font"), rather than pixels.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_PIXELS ##### -->
+<para>
+Converts a dimension to device units by rounding.
+</para>
+
+@d: a dimension in Pango units.
+@Returns: rounded dimension in device units.
+
+
+<!-- ##### MACRO PANGO_PIXELS_FLOOR ##### -->
+<para>
+Converts a dimension to device units by flooring.
+</para>
+
+@d: a dimension in Pango units.
+@Returns: floored dimension in device units.
+@Since: 1.14
+
+
+<!-- ##### MACRO PANGO_PIXELS_CEIL ##### -->
+<para>
+Converts a dimension to device units by ceiling.
+</para>
+
+@d: a dimension in Pango units.
+@Returns: ceiled dimension in device units.
+@Since: 1.14
+
+
+<!-- ##### MACRO PANGO_UNITS_ROUND ##### -->
+<para>
+Rounds a dimension to whole device units, but does not
+convert it to device units.
+</para>
+
+@d: a dimension in Pango units.
+@Returns: rounded dimension in Pango units.
+@Since: 1.18
+
+
+<!-- ##### FUNCTION pango_units_to_double ##### -->
+<para>
+
+</para>
+
+@i:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_units_from_double ##### -->
+<para>
+
+</para>
+
+@d:
+@Returns:
+
+
+<!-- ##### STRUCT PangoRectangle ##### -->
+<para>
+The #PangoRectangle structure represents a rectangle. It is frequently
+used to represent the logical or ink extents of a single glyph or section
+of text. (See, for instance, pango_font_get_glyph_extents())
+</para>
+
+@x: X coordinate of the left side of the rectangle.
+@y: Y coordinate of the the top side of the rectangle.
+@width: width of the rectangle.
+@height: height of the rectangle.
+
+<!-- ##### MACRO PANGO_ASCENT ##### -->
+<para>
+Extracts the <firstterm>ascent</firstterm> from a #PangoRectangle
+representing glyph extents. The ascent is the distance from the
+baseline to the highest point of the character. This is positive if the
+glyph ascends above the baseline.
+</para>
+
+@rect: a #PangoRectangle
+
+
+<!-- ##### MACRO PANGO_DESCENT ##### -->
+<para>
+Extracts the <firstterm>descent</firstterm> from a #PangoRectangle
+representing glyph extents. The descent is the distance from the
+baseline to the lowest point of the character. This is positive if the
+glyph descends below the baseline.
+</para>
+
+@rect: a #PangoRectangle
+
+
+<!-- ##### MACRO PANGO_LBEARING ##### -->
+<para>
+Extracts the <firstterm>left bearing</firstterm> from a #PangoRectangle
+representing glyph extents. The left bearing is the distance from the
+horizontal origin to the farthest left point of the character.
+This is positive for characters drawn completely to the right of the
+glyph origin.
+</para>
+
+@rect: a #PangoRectangle
+
+
+<!-- ##### MACRO PANGO_RBEARING ##### -->
+<para>
+Extracts the <firstterm>right bearing</firstterm> from a #PangoRectangle
+representing glyph extents. The right bearing is the distance from the
+horizontal origin to the farthest right point of the character.
+This is positive except for characters drawn completely to the left of the
+horizontal origin.
+</para>
+
+@rect: a #PangoRectangle
+
+
+<!-- ##### FUNCTION pango_extents_to_pixels ##### -->
+<para>
+
+</para>
+
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### STRUCT PangoMatrix ##### -->
+<para>
+
+</para>
+
+@xx:
+@xy:
+@yx:
+@yy:
+@x0:
+@y0:
+
+<!-- ##### MACRO PANGO_TYPE_MATRIX ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### MACRO PANGO_MATRIX_INIT ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION pango_matrix_copy ##### -->
+<para>
+
+</para>
+
+@matrix:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_matrix_free ##### -->
+<para>
+
+</para>
+
+@matrix:
+
+
+<!-- ##### FUNCTION pango_matrix_translate ##### -->
+<para>
+
+</para>
+
+@matrix:
+@tx:
+@ty:
+
+
+<!-- ##### FUNCTION pango_matrix_scale ##### -->
+<para>
+
+</para>
+
+@matrix:
+@scale_x:
+@scale_y:
+
+
+<!-- ##### FUNCTION pango_matrix_rotate ##### -->
+<para>
+
+</para>
+
+@matrix:
+@degrees:
+
+
+<!-- ##### FUNCTION pango_matrix_concat ##### -->
+<para>
+
+</para>
+
+@matrix:
+@new_matrix:
+
+
+<!-- ##### FUNCTION pango_matrix_transform_point ##### -->
+<para>
+
+</para>
+
+@matrix:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_matrix_transform_distance ##### -->
+<para>
+
+</para>
+
+@matrix:
+@dx:
+@dy:
+
+
+<!-- ##### FUNCTION pango_matrix_transform_rectangle ##### -->
+<para>
+
+</para>
+
+@matrix:
+@rect:
+
+
+<!-- ##### FUNCTION pango_matrix_transform_pixel_rectangle ##### -->
+<para>
+
+</para>
+
+@matrix:
+@rect:
+
+
+<!-- ##### FUNCTION pango_matrix_get_font_scale_factor ##### -->
+<para>
+
+</para>
+
+@matrix:
+@Returns:
+
+
+<!-- ##### TYPEDEF PangoGlyph ##### -->
+<para>
+A #PangoGlyph represents a single glyph in the output form of a string.
+</para>
+
+
+<!-- ##### MACRO PANGO_GLYPH_EMPTY ##### -->
+<para>
+The %PANGO_GLYPH_EMPTY macro represents a #PangoGlyph value that has a
+special meaning, which is a zero-width empty glyph. This is useful for
+example in shaper modules, to use as the glyph for various zero-width
+Unicode characters (those passing pango_is_zero_width()).
+</para>
+
+
+
+<!-- ##### MACRO PANGO_GLYPH_UNKNOWN_FLAG ##### -->
+<para>
+The %PANGO_GLYPH_UNKNOWN_FLAG macro is a flag value that can be added to
+a #gunichar value of a valid Unicode character, to produce a #PangoGlyph
+value, representing an unknown-character glyph for the respective #gunichar.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_GET_UNKNOWN_GLYPH ##### -->
+<para>
+Returns a #PangoGlyph value that means no glyph was found for @wc.
+The way this unknown glyphs are rendered is backend specific. For example,
+a box with the hexadecimal Unicode code-point of the character written in it
+is what is done in the most common backends.
+</para>
+
+@wc: a Unicode character
+
+
+<!-- ##### STRUCT PangoGlyphInfo ##### -->
+<para>
+The #PangoGlyphInfo structure represents a single glyph together with
+positioning information and visual attributes.
+It contains the following fields.
+</para>
+
+@glyph: the glyph itself.
+@geometry: the positional information about the glyph.
+@attr: the visual attributes of the glyph.
+
+<!-- ##### STRUCT PangoGlyphGeometry ##### -->
+<para>
+The #PangoGlyphGeometry structure contains width and positioning
+information for a single glyph.
+</para>
+
+@width: the logical width to use for the the character.
+@x_offset: horizontal offset from nominal character position.
+@y_offset: vertical offset from nominal character position.
+
+<!-- ##### TYPEDEF PangoGlyphUnit ##### -->
+<para>
+The #PangoGlyphUnit type is used to store dimensions within
+Pango. Dimensions are stored in 1/%PANGO_SCALE of a device unit.
+(A device unit might be a pixel for screen display, or
+a point on a printer.) %PANGO_SCALE is currently 1024, and
+may change in the future (unlikely though), but you should not
+depend on its exact value. The PANGO_PIXELS() macro can be used
+to convert from glyph units into device units with correct rounding.
+</para>
+
+
+<!-- ##### STRUCT PangoGlyphVisAttr ##### -->
+<para>
+The PangoGlyphVisAttr is used to communicate information between
+the shaping phase and the rendering phase. More attributes may be
+added in the future.
+</para>
+
+@is_cluster_start: set for the first logical glyph in each cluster. (Clusters
+ are stored in visual order, within the cluster, glyphs
+ are always ordered in logical order, since visual
+ order is meaningless; that is, in Arabic text, accent glyphs
+ follow the glyphs for the base character.)
+
+<!-- ##### STRUCT PangoGlyphString ##### -->
+<para>
+The #PangoGlyphString structure is used to store strings
+of glyphs with geometry and visual attribute information.
+The storage for the glyph information is owned
+by the structure which simplifies memory management.
+</para>
+
+@num_glyphs: the number of glyphs in the string.
+@glyphs: an array of #PangoGlyphInfo structures of length <structfield>num_glyphs</structfield>.
+@log_clusters: for each glyph, byte index of the starting character for the
+cluster. The indices are relative to the start of the text
+corresponding to the PangoGlyphString.
+
+<!-- ##### STRUCT PangoGlyphItem ##### -->
+<para>
+A #PangoGlyphItem is a pair of a #PangoItem and the glyphs
+resulting from shaping the text corresponding to an item.
+As an example of the usage of #PangoGlyphItem, the results
+of shaping text with #PangoLayout is a list of #PangoLayoutLine,
+each of which contains a list of #PangoGlyphItem.
+</para>
+
+@item: a #PangoItem structure that provides information
+ about a segment of text.
+@glyphs: the glyphs obtained by shaping the text
+ corresponding to @item.
+
+<!-- ##### MACRO PANGO_TYPE_GLYPH_STRING ##### -->
+<para>
+The #GObject type for #PangoGlyphString.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_glyph_string_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_glyph_string_copy ##### -->
+<para>
+
+</para>
+
+@string:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_glyph_string_set_size ##### -->
+<para>
+
+</para>
+
+@string:
+@new_len:
+
+
+<!-- ##### FUNCTION pango_glyph_string_free ##### -->
+<para>
+
+</para>
+
+@string:
+
+
+<!-- ##### FUNCTION pango_glyph_string_extents ##### -->
+<para>
+
+</para>
+
+@glyphs:
+@font:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_glyph_string_extents_range ##### -->
+<para>
+
+</para>
+
+@glyphs:
+@start:
+@end:
+@font:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_glyph_string_get_width ##### -->
+<para>
+
+</para>
+
+@glyphs:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_glyph_string_index_to_x ##### -->
+<para>
+
+</para>
+
+@glyphs:
+@text:
+@length:
+@analysis:
+@index_:
+@trailing:
+@x_pos:
+
+
+<!-- ##### FUNCTION pango_glyph_string_x_to_index ##### -->
+<para>
+
+</para>
+
+@glyphs:
+@text:
+@length:
+@analysis:
+@x_pos:
+@index_:
+@trailing:
+
+
+<!-- ##### FUNCTION pango_glyph_string_get_logical_widths ##### -->
+<para>
+
+</para>
+
+@glyphs:
+@text:
+@length:
+@embedding_level:
+@logical_widths:
+
+
+<!-- ##### FUNCTION pango_glyph_item_split ##### -->
+<para>
+
+</para>
+
+@orig:
+@text:
+@split_index:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_glyph_item_apply_attrs ##### -->
+<para>
+
+</para>
+
+@glyph_item:
+@text:
+@list:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_glyph_item_letter_space ##### -->
+<para>
+
+</para>
+
+@glyph_item:
+@text:
+@log_attrs:
+@letter_spacing:
+
+
+<!-- ##### FUNCTION pango_glyph_item_free ##### -->
+<para>
+
+</para>
+
+@glyph_item:
+
+
diff --git a/trunk/docs/tmpl/layout.sgml b/trunk/docs/tmpl/layout.sgml
new file mode 100644
index 00000000..524cbbce
--- /dev/null
+++ b/trunk/docs/tmpl/layout.sgml
@@ -0,0 +1,868 @@
+<!-- ##### SECTION Title ##### -->
+Layout Objects
+
+<!-- ##### SECTION Short_Description ##### -->
+High-level layout driver objects
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+While complete access to the layout capabilities of Pango is provided
+using the detailed interfaces for itemization and shaping, using
+that functionality directly involves writing a fairly large amount
+of code. The objects and functions in this section provide a
+high-level driver for formatting entire paragraphs of text
+at once.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoLayout ##### -->
+<para>
+The #PangoLayout structure represents and entire paragraph
+of text. It is initialized with a #PangoContext, UTF-8 string
+and set of attributes for that string. Once that is done, the
+set of formatted lines can be extracted from the object,
+the layout can be rendered, and conversion between logical
+character positions within the layout's text, and the physical
+position of the resulting glyphs can be made.
+</para>
+
+<para>
+There are also a number of parameters to adjust the formatting
+of a #PangoLayout, which are illustrated in <xref linkend="parameters"/>.
+It is possible, as well, to ignore the 2-D setup, and simply
+treat the results of a #PangoLayout as a list of lines.
+</para>
+
+<figure id="parameters">
+<title>Adjustable parameters for a PangoLayout</title>
+<graphic fileref="layout.gif" format="GIF"></graphic>
+</figure>
+
+<para>
+The #PangoLayout structure is opaque, and has no user-visible
+fields.
+</para>
+
+
+<!-- ##### STRUCT PangoLayoutIter ##### -->
+<para>
+A #PangoLayoutIter structure can be used to
+iterate over the visual extents of a #PangoLayout.
+</para>
+<para>
+The #PangoLayoutIter structure is opaque, and
+has no user-visible fields.
+</para>
+
+
+<!-- ##### FUNCTION pango_layout_new ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_copy ##### -->
+<para>
+
+</para>
+
+@src:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_context ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_context_changed ##### -->
+<para>
+
+</para>
+
+@layout:
+
+
+<!-- ##### FUNCTION pango_layout_set_text ##### -->
+<para>
+
+</para>
+
+@layout:
+@text:
+@length:
+
+
+<!-- ##### FUNCTION pango_layout_get_text ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_markup ##### -->
+<para>
+
+</para>
+
+@layout:
+@markup:
+@length:
+
+
+<!-- ##### FUNCTION pango_layout_set_markup_with_accel ##### -->
+<para>
+
+</para>
+
+@layout:
+@markup:
+@length:
+@accel_marker:
+@accel_char:
+
+
+<!-- ##### FUNCTION pango_layout_set_attributes ##### -->
+<para>
+
+</para>
+
+@layout:
+@attrs:
+
+
+<!-- ##### FUNCTION pango_layout_get_attributes ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_font_description ##### -->
+<para>
+
+</para>
+
+@layout:
+@desc:
+
+
+<!-- ##### FUNCTION pango_layout_get_font_description ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_width ##### -->
+<para>
+
+</para>
+
+@layout:
+@width:
+
+
+<!-- ##### FUNCTION pango_layout_get_width ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_wrap ##### -->
+<para>
+
+</para>
+
+@layout:
+@wrap:
+
+
+<!-- ##### FUNCTION pango_layout_get_wrap ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_is_wrapped ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### ENUM PangoWrapMode ##### -->
+<para>
+A #PangoWrapMode describes how to wrap the lines of a #PangoLayout to the desired width.
+</para>
+
+@PANGO_WRAP_WORD: wrap lines at word boundaries.
+@PANGO_WRAP_CHAR: wrap lines at character boundaries.
+@PANGO_WRAP_WORD_CHAR: wrap lines at word boundaries, but fall back to character boundaries if there is not
+enough space for a full word.
+
+<!-- ##### MACRO PANGO_TYPE_WRAP_MODE ##### -->
+<para>
+The #GObject type for #PangoWrapMode.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_layout_set_ellipsize ##### -->
+<para>
+
+</para>
+
+@layout:
+@ellipsize:
+
+
+<!-- ##### FUNCTION pango_layout_get_ellipsize ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_is_ellipsized ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### ENUM PangoEllipsizeMode ##### -->
+<para>
+
+</para>
+
+@PANGO_ELLIPSIZE_NONE:
+@PANGO_ELLIPSIZE_START:
+@PANGO_ELLIPSIZE_MIDDLE:
+@PANGO_ELLIPSIZE_END:
+
+<!-- ##### MACRO PANGO_TYPE_ELLIPSIZE_MODE ##### -->
+<para>
+The #GObject type for #PangoEllipsizeMode.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_layout_set_indent ##### -->
+<para>
+
+</para>
+
+@layout:
+@indent:
+
+
+<!-- ##### FUNCTION pango_layout_get_indent ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_spacing ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_spacing ##### -->
+<para>
+
+</para>
+
+@layout:
+@spacing:
+
+
+<!-- ##### FUNCTION pango_layout_set_justify ##### -->
+<para>
+
+</para>
+
+@layout:
+@justify:
+
+
+<!-- ##### FUNCTION pango_layout_get_justify ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_auto_dir ##### -->
+<para>
+
+</para>
+
+@layout:
+@auto_dir:
+
+
+<!-- ##### FUNCTION pango_layout_get_auto_dir ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_alignment ##### -->
+<para>
+
+</para>
+
+@layout:
+@alignment:
+
+
+<!-- ##### FUNCTION pango_layout_get_alignment ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_tabs ##### -->
+<para>
+
+</para>
+
+@layout:
+@tabs:
+
+
+<!-- ##### FUNCTION pango_layout_get_tabs ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_set_single_paragraph_mode ##### -->
+<para>
+
+</para>
+
+@layout:
+@setting:
+
+
+<!-- ##### FUNCTION pango_layout_get_single_paragraph_mode ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### ENUM PangoAlignment ##### -->
+<para>
+A #PangoAlignment describes how to align the lines of a #PangoLayout within the
+available space. If the #PangoLayout is set to justify
+using pango_layout_set_justify(), this only has effect for partial lines.
+</para>
+
+@PANGO_ALIGN_LEFT: Put all available space on the right
+@PANGO_ALIGN_CENTER: Center the line within the available space
+@PANGO_ALIGN_RIGHT: Put all available space on the left
+
+<!-- ##### MACRO PANGO_TYPE_ALIGNMENT ##### -->
+<para>
+The #GObject type for #PangoAlignment.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_layout_get_unknown_glyphs_count ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_log_attrs ##### -->
+<para>
+
+</para>
+
+@layout:
+@attrs:
+@n_attrs:
+
+
+<!-- ##### FUNCTION pango_layout_index_to_pos ##### -->
+<para>
+
+</para>
+
+@layout:
+@index_:
+@pos:
+
+
+<!-- ##### FUNCTION pango_layout_index_to_line_x ##### -->
+<para>
+
+</para>
+
+@layout:
+@index_:
+@trailing:
+@line:
+@x_pos:
+
+
+<!-- ##### FUNCTION pango_layout_xy_to_index ##### -->
+<para>
+
+</para>
+
+@layout:
+@x:
+@y:
+@index_:
+@trailing:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_cursor_pos ##### -->
+<para>
+
+</para>
+
+@layout:
+@index_:
+@strong_pos:
+@weak_pos:
+
+
+<!-- ##### FUNCTION pango_layout_move_cursor_visually ##### -->
+<para>
+
+</para>
+
+@layout:
+@strong:
+@old_index:
+@old_trailing:
+@direction:
+@new_index:
+@new_trailing:
+
+
+<!-- ##### FUNCTION pango_layout_get_extents ##### -->
+<para>
+
+</para>
+
+@layout:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_layout_get_pixel_extents ##### -->
+<para>
+
+</para>
+
+@layout:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_layout_get_size ##### -->
+<para>
+
+</para>
+
+@layout:
+@width:
+@height:
+
+
+<!-- ##### FUNCTION pango_layout_get_pixel_size ##### -->
+<para>
+
+</para>
+
+@layout:
+@width:
+@height:
+
+
+<!-- ##### FUNCTION pango_layout_get_line_count ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_line ##### -->
+<para>
+
+</para>
+
+@layout:
+@line:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_line_readonly ##### -->
+<para>
+
+</para>
+
+@layout:
+@line:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_lines ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_lines_readonly ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_get_iter ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_free ##### -->
+<para>
+
+</para>
+
+@iter:
+
+
+<!-- ##### FUNCTION pango_layout_iter_next_run ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_next_char ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_next_cluster ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_next_line ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_at_last_line ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_index ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_baseline ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_run ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_run_readonly ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_line ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_line_readonly ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_char_extents ##### -->
+<para>
+
+</para>
+
+@iter:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_cluster_extents ##### -->
+<para>
+
+</para>
+
+@iter:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_run_extents ##### -->
+<para>
+
+</para>
+
+@iter:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_line_yrange ##### -->
+<para>
+
+</para>
+
+@iter:
+@y0_:
+@y1_:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_line_extents ##### -->
+<para>
+
+</para>
+
+@iter:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_layout_iter_get_layout_extents ##### -->
+<para>
+
+</para>
+
+@iter:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### STRUCT PangoLayoutLine ##### -->
+<para>
+The #PangoLayoutLine structure represents one of the lines resulting
+from laying out a paragraph via #PangoLayout. #PangoLayoutLine
+structures are obtained by calling pango_layout_get_line() and
+are only valid until the text, attributes, or settings of the
+parent #PangoLayout are modified.
+</para>
+<para>
+Routines for rendering PangoLayout objects are provided in
+code specific to each rendering system.
+</para>
+
+@layout: the parent layout for this line
+@start_index: the start of the line as byte index into @layout->text
+@length: the length of the line in bytes
+@runs: a list containing the runs of the line in visual order
+@is_paragraph_start: %TRUE if this is the first line of the paragraph
+@resolved_dir: the resolved #PangoDirection of the line
+
+<!-- ##### TYPEDEF PangoLayoutRun ##### -->
+<para>
+The #PangoLayoutRun structure represents a single run within
+a #PangoLayoutLine; it is simply an alternate name for
+#PangoGlyphItem, present for backwards compatibility.
+See the #PangoGlyphItem docs for details on the fields.
+</para>
+
+
+<!-- ##### FUNCTION pango_layout_line_ref ##### -->
+<para>
+
+</para>
+
+@line:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_line_unref ##### -->
+<para>
+
+</para>
+
+@line:
+
+
+<!-- ##### FUNCTION pango_layout_line_get_extents ##### -->
+<para>
+
+</para>
+
+@line:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_layout_line_get_pixel_extents ##### -->
+<para>
+
+</para>
+
+@layout_line:
+@ink_rect:
+@logical_rect:
+
+
+<!-- ##### FUNCTION pango_layout_line_index_to_x ##### -->
+<para>
+
+</para>
+
+@line:
+@index_:
+@trailing:
+@x_pos:
+
+
+<!-- ##### FUNCTION pango_layout_line_x_to_index ##### -->
+<para>
+
+</para>
+
+@line:
+@x_pos:
+@index_:
+@trailing:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_layout_line_get_x_ranges ##### -->
+<para>
+
+</para>
+
+@line:
+@start_index:
+@end_index:
+@ranges:
+@n_ranges:
+
+
diff --git a/trunk/docs/tmpl/main.sgml b/trunk/docs/tmpl/main.sgml
new file mode 100644
index 00000000..4d2de7f0
--- /dev/null
+++ b/trunk/docs/tmpl/main.sgml
@@ -0,0 +1,488 @@
+<!-- ##### SECTION Title ##### -->
+Rendering
+
+<!-- ##### SECTION Short_Description ##### -->
+Functions to run the rendering pipeline
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The Pango rendering pipeline takes a string of
+Unicode characters and converts it into glyphs.
+The functions described in this section accomplish
+various steps of this process.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoContext ##### -->
+<para>
+The #PangoContext structure stores global information
+used to control the itemization process.
+</para>
+
+
+<!-- ##### STRUCT PangoItem ##### -->
+<para>
+The #PangoItem structure stores information about
+a segment of text. It contains the following fields:
+</para>
+
+@offset: the offset of the segment from the beginning of the
+ string in bytes.
+@length: the length of the segment in bytes.
+@num_chars: the length of the segment in characters.
+@analysis: the properties of the segment.
+
+<!-- ##### STRUCT PangoAnalysis ##### -->
+<para>
+The #PangoAnalysis structure stores information about
+the properties of a segment of text. It has the following
+fields:
+</para>
+
+@shape_engine: the engine for doing rendering-system-dependent processing.
+@lang_engine: the engine for doing rendering-system-independent processing.
+@font: the font for this segment.
+@level: the bidirectional level for this segment.
+@gravity: the glyph orientation for this segment (A #PangoGravity).
+@flags: boolean flags for this segment (currently only one) (Since: 1.16).
+@script: the detected script for this segment (A #PangoScript) (Since: 1.18).
+@language: the detected language for this segment.
+@extra_attrs: extra attributes for this segment.
+
+<!-- ##### MACRO PANGO_ANALYSIS_FLAG_CENTERED_BASELINE ##### -->
+<para>
+Whether the segment should be shifted to center around the baseline.
+Used in vertical writing directions mostly.
+
+Since: 1.16
+</para>
+
+
+
+<!-- ##### ENUM PangoDirection ##### -->
+<para>
+</para>
+
+@PANGO_DIRECTION_LTR:
+@PANGO_DIRECTION_RTL:
+@PANGO_DIRECTION_TTB_LTR:
+@PANGO_DIRECTION_TTB_RTL:
+@PANGO_DIRECTION_WEAK_LTR:
+@PANGO_DIRECTION_WEAK_RTL:
+@PANGO_DIRECTION_NEUTRAL:
+
+<!-- ##### MACRO PANGO_TYPE_DIRECTION ##### -->
+<para>
+The #GObject type for #PangoDirection.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_itemize ##### -->
+<para>
+
+</para>
+
+@context:
+@text:
+@start_index:
+@length:
+@attrs:
+@cached_iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_itemize_with_base_dir ##### -->
+<para>
+
+</para>
+
+@context:
+@base_dir:
+@text:
+@start_index:
+@length:
+@attrs:
+@cached_iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_item_free ##### -->
+<para>
+
+</para>
+
+@item:
+
+
+<!-- ##### FUNCTION pango_item_copy ##### -->
+<para>
+
+</para>
+
+@item:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_item_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_item_split ##### -->
+<para>
+
+</para>
+
+@orig:
+@split_index:
+@split_offset:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_reorder_items ##### -->
+<para>
+
+</para>
+
+@logical_items:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_set_font_map ##### -->
+<para>
+
+</para>
+
+@context:
+@font_map:
+
+
+<!-- ##### FUNCTION pango_context_get_font_map ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_get_font_description ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_set_font_description ##### -->
+<para>
+
+</para>
+
+@context:
+@desc:
+
+
+<!-- ##### FUNCTION pango_context_get_language ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_set_language ##### -->
+<para>
+
+</para>
+
+@context:
+@language:
+
+
+<!-- ##### FUNCTION pango_context_get_base_dir ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_set_base_dir ##### -->
+<para>
+
+</para>
+
+@context:
+@direction:
+
+
+<!-- ##### FUNCTION pango_context_get_base_gravity ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_set_base_gravity ##### -->
+<para>
+
+</para>
+
+@context:
+@gravity:
+
+
+<!-- ##### FUNCTION pango_context_get_gravity ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_get_gravity_hint ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_set_gravity_hint ##### -->
+<para>
+
+</para>
+
+@context:
+@hint:
+
+
+<!-- ##### FUNCTION pango_context_get_matrix ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_set_matrix ##### -->
+<para>
+
+</para>
+
+@context:
+@matrix:
+
+
+<!-- ##### FUNCTION pango_context_load_font ##### -->
+<para>
+
+</para>
+
+@context:
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_load_fontset ##### -->
+<para>
+
+</para>
+
+@context:
+@desc:
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_get_metrics ##### -->
+<para>
+
+</para>
+
+@context:
+@desc:
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_context_list_families ##### -->
+<para>
+
+</para>
+
+@context:
+@families:
+@n_families:
+
+
+<!-- ##### FUNCTION pango_get_mirror_char ##### -->
+<para>
+
+</para>
+
+@ch:
+@mirrored_ch:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_unichar_direction ##### -->
+<para>
+
+</para>
+
+@ch:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_find_base_dir ##### -->
+<para>
+
+</para>
+
+@text:
+@length:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_gravity_to_rotation ##### -->
+<para>
+
+</para>
+
+@gravity:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_break ##### -->
+<para>
+
+</para>
+
+@text:
+@length:
+@analysis:
+@attrs:
+@attrs_len:
+
+
+<!-- ##### FUNCTION pango_get_log_attrs ##### -->
+<para>
+
+</para>
+
+@text:
+@length:
+@level:
+@language:
+@log_attrs:
+@attrs_len:
+
+
+<!-- ##### FUNCTION pango_find_paragraph_boundary ##### -->
+<para>
+
+</para>
+
+@text:
+@length:
+@paragraph_delimiter_index:
+@next_paragraph_start:
+
+
+<!-- ##### FUNCTION pango_default_break ##### -->
+<para>
+
+</para>
+
+@text:
+@length:
+@analysis:
+@attrs:
+@attrs_len:
+
+
+<!-- ##### STRUCT PangoLogAttr ##### -->
+<para>
+The #PangoLogAttr structure stores information
+about the attributes of a single character.
+</para>
+
+@is_line_break: if set, can break line in front of character
+@is_mandatory_break: if set, must break line in front of character
+@is_char_break: if set, can break here when doing character wrapping
+@is_white: is whitespace character
+@is_cursor_position: if set, cursor can appear in front of character.
+ i.e. this is a grapheme boundary, or the first character
+ in the text.
+@is_word_start: is first character in a word
+@is_word_end: is first non-word char after a word
+ Note that in degenerate cases, you could have both @is_word_start
+ and @is_word_end set for some character.
+@is_sentence_boundary: is a sentence boundary.
+ There are two ways to divide sentences. The first assigns all
+ inter-sentence whitespace/control/format chars to some sentence,
+ so all chars are in some sentence; @is_sentence_boundary denotes
+ the boundaries there. The second way doesn't assign
+ between-sentence spaces, etc. to any sentence, so
+ @is_sentence_start/@is_sentence_end mark the boundaries
+ of those sentences.
+@is_sentence_start: is first character in a sentence
+@is_sentence_end: is first char after a sentence.
+ Note that in degenerate cases, you could have both @is_sentence_start
+ and @is_sentence_end set for some character. (e.g. no space after a
+ period, so the next sentence starts right away)
+@backspace_deletes_character: if set, backspace deletes one character
+ rather than the entire grapheme cluster. This
+ field is only meaningful on grapheme
+ boundaries (where @is_cursor_position is
+ set). In some languages, the full grapheme
+ (e.g. letter + diacritics) is considered a
+ unit, while in others, each decomposed
+ character in the grapheme is a unit. In the
+ default implementation of pango_break(), this
+ bit is set on all grapheme boundaries except
+ those following Latin, Cyrillic or Greek base
+ characters.
+@is_expandable_space: is a whitespace character that can possibly be
+ expanded for justification purposes. (Since: 1.18)
+
+<!-- ##### FUNCTION pango_shape ##### -->
+<para>
+
+</para>
+
+@text:
+@length:
+@analysis:
+@glyphs:
+
+
diff --git a/trunk/docs/tmpl/modules.sgml b/trunk/docs/tmpl/modules.sgml
new file mode 100644
index 00000000..0fe8c42f
--- /dev/null
+++ b/trunk/docs/tmpl/modules.sgml
@@ -0,0 +1,87 @@
+<!-- ##### SECTION Title ##### -->
+Modules
+
+<!-- ##### SECTION Short_Description ##### -->
+Support for loadable modules
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+Functions and macros in this section are used to support loading dynamic
+modules that add engines to Pango at run time.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoIncludedModule ##### -->
+<para>
+The #PangoIncludedModule structure for a statically linked module
+contains the functions that would otherwise be loaded from a dynamically
+loaded module.
+</para>
+
+@list: a function that lists the engines defined in this module.
+@init: a function to initialize the module.
+@exit: a function to finalize the module.
+@create: a function to create an engine, given the engine name.
+
+<!-- ##### STRUCT PangoMap ##### -->
+<para>
+A #PangoMap structure can be used to determine the engine to
+use for each character.
+</para>
+
+
+<!-- ##### STRUCT PangoMapEntry ##### -->
+<para>
+A #PangoMapEntry contains information about the engine that should be used
+for the codepoint to which this entry belongs and also whether the engine
+matches the language tag for this entry's map exactly or just approximately.
+</para>
+
+
+<!-- ##### FUNCTION pango_find_map ##### -->
+<para>
+
+</para>
+
+@language:
+@engine_type_id:
+@render_type_id:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_map_get_engine ##### -->
+<para>
+
+</para>
+
+@map:
+@script:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_map_get_engines ##### -->
+<para>
+
+</para>
+
+@map:
+@script:
+@exact_engines:
+@fallback_engines:
+
+
+<!-- ##### FUNCTION pango_module_register ##### -->
+<para>
+
+</para>
+
+@module:
+
+
diff --git a/trunk/docs/tmpl/opentype.sgml b/trunk/docs/tmpl/opentype.sgml
new file mode 100644
index 00000000..3678f178
--- /dev/null
+++ b/trunk/docs/tmpl/opentype.sgml
@@ -0,0 +1,551 @@
+<!-- ##### SECTION Title ##### -->
+OpenType Font Handling
+
+<!-- ##### SECTION Short_Description ##### -->
+Obtaining information from OpenType tables
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+Functions and macros in this section are used to implement the OpenType Layout
+features and algorithms. These are mostly useful when writing Fontconfig-based
+shaping engines
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+Unstable
+
+<!-- ##### TYPEDEF PangoOTTag ##### -->
+<para>
+The <type>PangoOTTag</type> typedef is used to represent TrueType and OpenType
+four letter tags inside Pango. Use PANGO_OT_TAG_MAKE()
+or PANGO_OT_TAG_MAKE_FROM_STRING() macros to create <type>PangoOTTag</type>s manually.
+</para>
+
+
+<!-- ##### STRUCT PangoOTInfo ##### -->
+<para>
+The #PangoOTInfo struct contains the various
+tables associated with an OpenType font. It contains only private fields and
+should only be accessed via the <function>pango_ot_info_*</function> functions
+which are documented below. To obtain a #PangoOTInfo,
+use pango_ot_info_new().
+</para>
+
+
+<!-- ##### STRUCT PangoOTBuffer ##### -->
+<para>
+The #PangoOTBuffer structure is used to store strings of glyphs associated
+with a #PangoFcFont, suitable for OpenType layout processing. It contains
+only private fields and should only be accessed via the
+<function>pango_ot_buffer_*</function> functions which are documented below.
+To obtain a #PangoOTBuffer, use pango_ot_buffer_new().
+</para>
+
+
+<!-- ##### STRUCT PangoOTGlyph ##### -->
+<para>
+The #PangoOTGlyph structure represents a single glyph together with
+information used for OpenType layout processing of the glyph.
+It contains the following fields.
+</para>
+
+@glyph: the glyph itself.
+@properties: the properties value, identifying which features should be
+ applied on this glyph. See pango_ruleset_add_feature().
+@cluster: the cluster that this glyph belongs to.
+@component: a component value, set by the OpenType layout engine.
+@ligID: a ligature index value, set by the OpenType layout engine.
+@property_cache: for internal use.
+
+<!-- ##### STRUCT PangoOTRuleset ##### -->
+<para>
+The #PangoOTRuleset structure holds a
+set of features selected from the tables in an OpenType font.
+(A feature is an operation such as adjusting glyph positioning
+that should be applied to a text feature such as a certain
+type of accent.) A #PangoOTRuleset
+is created with pango_ot_ruleset_new(), features are added
+to it with pango_ot_ruleset_add_feature(), then it is
+applied to a #PangoGlyphString with pango_ot_ruleset_shape().
+</para>
+
+
+<!-- ##### STRUCT PangoOTRulesetDescription ##### -->
+<para>
+The #PangoOTRuleset structure holds all the information needed
+to build a complete #PangoOTRuleset from an OpenType font.
+The main use of this struct is to act as the key for a per-font
+hash of rulesets. The user populates a ruleset description and
+gets the ruleset using pango_ot_ruleset_get_for_description()
+or create a new one using pango_ot_ruleset_new_from_description().
+</para>
+
+@script: a #PangoScript.
+@language: a #PangoLanguage.
+@static_gsub_features: static map of GSUB features, or %NULL.
+@n_static_gsub_features: length of @static_gsub_features, or 0.
+@static_gpos_features: static map of GPOS features, or %NULL.
+@n_static_gpos_features: length of @static_gpos_features, or 0.
+@other_features: map of extra features to add to both GSUB and GPOS, or %NULL.
+ Unlike the static maps, this pointer need not live beyond
+ the life of function calls taking this struct.
+@n_other_features: length of @other_features, or 0.
+@Since: 1.18
+
+<!-- ##### ENUM PangoOTTableType ##### -->
+<para>
+The <type>PangoOTTableType</type> enumeration values are used to
+identify the various OpenType tables in the
+<function>pango_ot_info_*</function> functions.
+</para>
+
+@PANGO_OT_TABLE_GSUB: The GSUB table.
+@PANGO_OT_TABLE_GPOS: The GPOS table.
+
+<!-- ##### STRUCT PangoOTFeatureMap ##### -->
+<para>
+The <type>PangoOTFeatureMap</type> typedef is used to represent an OpenType
+feature with the property bit associated with it. The feature tag is
+represented as a char array instead of a #PangoOTTag for convenience.
+</para>
+
+@feature_name: feature tag in represented as four-letter ASCII string.
+@property_bit: the property bit to use for this feature. See
+ pango_ot_ruleset_add_feature() for details.
+@Since: 1.18
+
+<!-- ##### MACRO PANGO_OT_TAG_MAKE ##### -->
+<para>
+Creates a #PangoOTTag from four characters. This is similar and
+compatible with the <function>FT_MAKE_TAG()</function> macro from
+FreeType.
+</para>
+
+@c1: First character.
+@c2: Second character.
+@c3: Third character.
+@c4: Fourth character.
+
+
+<!-- ##### MACRO PANGO_OT_TAG_MAKE_FROM_STRING ##### -->
+<para>
+Creates a #PangoOTTag from a string. The string should be at least
+four characters long (pad with space characters if needed), and need
+not be nul-terminated. This is a convenience wrapper around
+PANGO_OT_TAG_MAKE(), but cannot be used in certain situations, for
+example, as a switch expression, as it dereferences pointers.
+</para>
+
+@s: The string representation of the tag.
+
+
+<!-- ##### MACRO PANGO_OT_ALL_GLYPHS ##### -->
+<para>
+This is used as the property bit in pango_ot_ruleset_add_feature() when a
+feature should be applied to all glyphs.
+</para>
+
+@Since: 1.16
+
+
+<!-- ##### MACRO PANGO_OT_NO_FEATURE ##### -->
+<para>
+This is used as a feature index that represent no feature, that is, should be
+skipped. It may be returned as feature index by pango_ot_info_find_feature()
+if the feature is not found, and pango_ot_rulset_add_feature() function
+automatically skips this value, so no special handling is required by the
+user.
+</para>
+
+@Since: 1.18
+
+
+<!-- ##### MACRO PANGO_OT_NO_SCRIPT ##### -->
+<para>
+This is used as a script index that represent no script, that is, when the
+requested script was not found, and a default ('DFLT') script was not found
+either. It may be returned as script index by pango_ot_info_find_script()
+if the script or a default script are not found, all other functions
+taking a script index essentially return if the input script index is
+this value, so no special handling is required by the user.
+</para>
+
+@Since: 1.18
+
+
+<!-- ##### MACRO PANGO_OT_DEFAULT_LANGUAGE ##### -->
+<para>
+This is used as the language index in pango_ot_info_find_feature() when
+the default language system of the script is desired.
+
+It is also returned by pango_ot_info_find_language() if the requested language
+is not found, or the requested language tag was PANGO_OT_TAG_DEFAULT_LANGUAGE.
+The end result is that one can always call pango_ot_tag_from_language()
+followed by pango_ot_info_find_language() and pass the result to
+pango_ot_info_find_feature() without having to worry about falling back to
+default language system explicitly.
+</para>
+
+@Since: 1.16
+
+
+<!-- ##### MACRO PANGO_OT_TAG_DEFAULT_LANGUAGE ##### -->
+<para>
+This is a #PangoOTTag representing a special language tag 'dflt'. It is
+returned as language tag by pango_ot_tag_from_language() if the requested
+language is not found. It is safe to pass this value to
+pango_ot_info_find_language() as that function falls back to returning default
+language-system if the requested language tag is not found.
+</para>
+
+@Since: 1.18
+
+
+<!-- ##### MACRO PANGO_OT_TAG_DEFAULT_SCRIPT ##### -->
+<para>
+This is a #PangoOTTag representing the special script tag 'DFLT'. It is
+returned as script tag by pango_ot_tag_from_script() if the requested script
+is not found.
+</para>
+
+@Since: 1.18
+
+
+<!-- ##### FUNCTION pango_ot_info_get ##### -->
+<para>
+
+</para>
+
+@face:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_info_find_script ##### -->
+<para>
+
+</para>
+
+@info:
+@table_type:
+@script_tag:
+@script_index:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_info_find_language ##### -->
+<para>
+
+</para>
+
+@info:
+@table_type:
+@script_index:
+@language_tag:
+@language_index:
+@required_feature_index:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_info_find_feature ##### -->
+<para>
+
+</para>
+
+@info:
+@table_type:
+@feature_tag:
+@script_index:
+@language_index:
+@feature_index:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_info_list_scripts ##### -->
+<para>
+
+</para>
+
+@info:
+@table_type:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_info_list_languages ##### -->
+<para>
+
+</para>
+
+@info:
+@table_type:
+@script_index:
+@language_tag:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_info_list_features ##### -->
+<para>
+
+</para>
+
+@info:
+@table_type:
+@tag:
+@script_index:
+@language_index:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_buffer_new ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_buffer_destroy ##### -->
+<para>
+
+</para>
+
+@buffer:
+
+
+<!-- ##### FUNCTION pango_ot_buffer_clear ##### -->
+<para>
+
+</para>
+
+@buffer:
+
+
+<!-- ##### FUNCTION pango_ot_buffer_add_glyph ##### -->
+<para>
+
+</para>
+
+@buffer:
+@glyph:
+@properties:
+@cluster:
+
+
+<!-- ##### FUNCTION pango_ot_buffer_set_rtl ##### -->
+<para>
+
+</para>
+
+@buffer:
+@rtl:
+
+
+<!-- ##### FUNCTION pango_ot_buffer_set_zero_width_marks ##### -->
+<para>
+
+</para>
+
+@buffer:
+@zero_width_marks:
+
+
+<!-- ##### FUNCTION pango_ot_buffer_get_glyphs ##### -->
+<para>
+
+</para>
+
+@buffer:
+@glyphs:
+@n_glyphs:
+
+
+<!-- ##### FUNCTION pango_ot_buffer_output ##### -->
+<para>
+
+</para>
+
+@buffer:
+@glyphs:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_get_for_description ##### -->
+<para>
+
+</para>
+
+@info:
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_new ##### -->
+<para>
+
+</para>
+
+@info:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_new_for ##### -->
+<para>
+
+</para>
+
+@info:
+@script:
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_new_from_description ##### -->
+<para>
+
+</para>
+
+@info:
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_add_feature ##### -->
+<para>
+
+</para>
+
+@ruleset:
+@table_type:
+@feature_index:
+@property_bit:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_maybe_add_feature ##### -->
+<para>
+
+</para>
+
+@ruleset:
+@table_type:
+@feature_tag:
+@property_bit:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_maybe_add_features ##### -->
+<para>
+
+</para>
+
+@ruleset:
+@table_type:
+@features:
+@n_features:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_get_feature_count ##### -->
+<para>
+
+</para>
+
+@ruleset:
+@n_gsub_features:
+@n_gpos_features:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_substitute ##### -->
+<para>
+
+</para>
+
+@ruleset:
+@buffer:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_position ##### -->
+<para>
+
+</para>
+
+@ruleset:
+@buffer:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_description_copy ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_description_equal ##### -->
+<para>
+
+</para>
+
+@desc1:
+@desc2:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_description_free ##### -->
+<para>
+
+</para>
+
+@desc:
+
+
+<!-- ##### FUNCTION pango_ot_ruleset_description_hash ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_tag_from_language ##### -->
+<para>
+
+</para>
+
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_tag_from_script ##### -->
+<para>
+
+</para>
+
+@script:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_tag_to_language ##### -->
+<para>
+
+</para>
+
+@language_tag:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_ot_tag_to_script ##### -->
+<para>
+
+</para>
+
+@script_tag:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/pango-engine-lang.sgml b/trunk/docs/tmpl/pango-engine-lang.sgml
new file mode 100644
index 00000000..a5a91bf3
--- /dev/null
+++ b/trunk/docs/tmpl/pango-engine-lang.sgml
@@ -0,0 +1,53 @@
+<!-- ##### SECTION Title ##### -->
+PangoEngineLang
+
+<!-- ##### SECTION Short_Description ##### -->
+Rendering-system independent script engines
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The <firstterm>language engines</firstterm> are rendering-system independent
+engines that determine line, word, and character breaks for character strings.
+These engines are used in pango_break().
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+Unstable
+
+<!-- ##### STRUCT PangoEngineLang ##### -->
+<para>
+</para>
+
+
+<!-- ##### STRUCT PangoEngineLangClass ##### -->
+<para>
+
+</para>
+
+@script_break:
+
+<!-- ##### MACRO PANGO_ENGINE_TYPE_LANG ##### -->
+<para>
+A string constant defining the engine type
+for language engines.
+These engines derive from #PangoEngineLang.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_ENGINE_LANG_DEFINE_TYPE ##### -->
+<para>
+
+</para>
+
+@name:
+@prefix:
+@class_init:
+@instance_init:
+
+
diff --git a/trunk/docs/tmpl/pango-engine-shape.sgml b/trunk/docs/tmpl/pango-engine-shape.sgml
new file mode 100644
index 00000000..5e66f2db
--- /dev/null
+++ b/trunk/docs/tmpl/pango-engine-shape.sgml
@@ -0,0 +1,54 @@
+<!-- ##### SECTION Title ##### -->
+PangoEngineShape
+
+<!-- ##### SECTION Short_Description ##### -->
+Rendering-system dependent script engines
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The <firstterm>shape engines</firstterm> are rendering-system dependent
+engines that convert character strings into glyph strings.
+These engines are used in pango_shape().
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+Unstable
+
+<!-- ##### STRUCT PangoEngineShape ##### -->
+<para>
+</para>
+
+
+<!-- ##### STRUCT PangoEngineShapeClass ##### -->
+<para>
+
+</para>
+
+@script_shape:
+@covers:
+
+<!-- ##### MACRO PANGO_ENGINE_TYPE_SHAPE ##### -->
+<para>
+A string constant defining the engine type
+for shaping engines.
+These engines derive from #PangoEngineShape.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_ENGINE_SHAPE_DEFINE_TYPE ##### -->
+<para>
+
+</para>
+
+@name:
+@prefix:
+@class_init:
+@instance_init:
+
+
diff --git a/trunk/docs/tmpl/pango-renderer.sgml b/trunk/docs/tmpl/pango-renderer.sgml
new file mode 100644
index 00000000..181986f0
--- /dev/null
+++ b/trunk/docs/tmpl/pango-renderer.sgml
@@ -0,0 +1,212 @@
+<!-- ##### SECTION Title ##### -->
+PangoRenderer
+
+<!-- ##### SECTION Short_Description ##### -->
+Rendering driver base class
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+#PangoRenderer is a base class that contains the necessary logic for
+rendering a #PangoLayout or #PangoLayoutLine. By subclassing
+#PangoRenderer and overriding operations such as @draw_glyphs and
+@draw_rectangle, renderers for particular font backends and
+destinations can be created.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoRenderer ##### -->
+<para>
+
+</para>
+
+@matrix:
+
+<!-- ##### ENUM PangoRenderPart ##### -->
+<para>
+
+</para>
+
+@PANGO_RENDER_PART_FOREGROUND:
+@PANGO_RENDER_PART_BACKGROUND:
+@PANGO_RENDER_PART_UNDERLINE:
+@PANGO_RENDER_PART_STRIKETHROUGH:
+
+<!-- ##### MACRO PANGO_TYPE_RENDER_PART ##### -->
+<para>
+The #GObject type for #PangoRenderPart.
+</para>
+
+
+
+<!-- ##### STRUCT PangoRendererClass ##### -->
+<para>
+
+</para>
+
+@draw_glyphs:
+@draw_rectangle:
+@draw_error_underline:
+@draw_shape:
+@draw_trapezoid:
+@draw_glyph:
+@part_changed:
+@begin:
+@end:
+@prepare_run:
+
+<!-- ##### FUNCTION pango_renderer_draw_layout ##### -->
+<para>
+
+</para>
+
+@renderer:
+@layout:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_renderer_draw_layout_line ##### -->
+<para>
+
+</para>
+
+@renderer:
+@line:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_renderer_draw_glyphs ##### -->
+<para>
+
+</para>
+
+@renderer:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_renderer_draw_rectangle ##### -->
+<para>
+
+</para>
+
+@renderer:
+@part:
+@x:
+@y:
+@width:
+@height:
+
+
+<!-- ##### FUNCTION pango_renderer_draw_error_underline ##### -->
+<para>
+
+</para>
+
+@renderer:
+@x:
+@y:
+@width:
+@height:
+
+
+<!-- ##### FUNCTION pango_renderer_draw_trapezoid ##### -->
+<para>
+
+</para>
+
+@renderer:
+@part:
+@y1_:
+@x11:
+@x21:
+@y2:
+@x12:
+@x22:
+
+
+<!-- ##### FUNCTION pango_renderer_draw_glyph ##### -->
+<para>
+
+</para>
+
+@renderer:
+@font:
+@glyph:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_renderer_activate ##### -->
+<para>
+
+</para>
+
+@renderer:
+
+
+<!-- ##### FUNCTION pango_renderer_deactivate ##### -->
+<para>
+
+</para>
+
+@renderer:
+
+
+<!-- ##### FUNCTION pango_renderer_part_changed ##### -->
+<para>
+
+</para>
+
+@renderer:
+@part:
+
+
+<!-- ##### FUNCTION pango_renderer_set_color ##### -->
+<para>
+
+</para>
+
+@renderer:
+@part:
+@color:
+
+
+<!-- ##### FUNCTION pango_renderer_get_color ##### -->
+<para>
+
+</para>
+
+@renderer:
+@part:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_renderer_set_matrix ##### -->
+<para>
+
+</para>
+
+@renderer:
+@matrix:
+
+
+<!-- ##### FUNCTION pango_renderer_get_matrix ##### -->
+<para>
+
+</para>
+
+@renderer:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/pango-version.sgml b/trunk/docs/tmpl/pango-version.sgml
new file mode 100644
index 00000000..230946d2
--- /dev/null
+++ b/trunk/docs/tmpl/pango-version.sgml
@@ -0,0 +1,110 @@
+<!-- ##### SECTION Title ##### -->
+Version Checking
+
+<!-- ##### SECTION Short_Description ##### -->
+Tools for checking Pango version at compile- and run-time.
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The capital-letter macros defined here can be used to check the version of
+Pango at compile-time, and to <firstterm>encode</firstterm> Pango versions into
+integers.
+
+The functions can be used to check the version of the linked Pango library
+at run-time.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### MACRO PANGO_VERSION_ENCODE ##### -->
+<para>
+This macro encodes the given Pango version into an integer. The numbers
+returned by %PANGO_VERSION and pango_version() are encoded using this macro.
+Two encoded version numbers can be compared as integers.
+</para>
+
+@major: the major component of the version number
+@minor: the minor component of the version number
+@micro: the micro component of the version number
+
+
+<!-- ##### MACRO PANGO_VERSION ##### -->
+<para>
+The version of Pango available at compile-time, encoded using
+PANGO_VERSION_ENCODE().
+</para>
+
+
+
+<!-- ##### MACRO PANGO_VERSION_MAJOR ##### -->
+<para>
+The major component of the version of Pango available at compile-time.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_VERSION_MINOR ##### -->
+<para>
+The minor component of the version of Pango available at compile-time.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_VERSION_MICRO ##### -->
+<para>
+The micro component of the version of Pango available at compile-time.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_VERSION_STRING ##### -->
+<para>
+A string literal containing the version of Pango available at compile-time.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_VERSION_CHECK ##### -->
+<para>
+Checks that the version of Pango available at compile-time is not older than
+the provided version number.
+</para>
+
+@major: the major component of the version number
+@minor: the minor component of the version number
+@micro: the micro component of the version number
+
+
+<!-- ##### FUNCTION pango_version ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_version_string ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_version_check ##### -->
+<para>
+
+</para>
+
+@required_major:
+@required_minor:
+@required_micro:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/pangocairo.sgml b/trunk/docs/tmpl/pangocairo.sgml
new file mode 100644
index 00000000..5192b975
--- /dev/null
+++ b/trunk/docs/tmpl/pangocairo.sgml
@@ -0,0 +1,409 @@
+<!-- ##### SECTION Title ##### -->
+Cairo Rendering
+
+<!-- ##### SECTION Short_Description ##### -->
+Rendering with the Cairo backend
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The <ulink url="http://cairographics.org">Cairo library</ulink> is a
+vector graphics library with a powerful rendering model. It has such
+features as anti-aliased primitives, alpha-compositing, and
+gradients. Multiple backends for Cairo are available, to allow
+rendering to images, to PDF files, and to the screen on X and on other
+windowing systems. The functions in this section allow using Pango
+to render to Cairo surfaces.
+</para>
+<para>
+Using Pango with Cairo is straightforward. A #PangoContext created
+with pango_cairo_font_map_create_context() can be used on any
+Cairo context (cairo_t), but needs to be updated to match the
+current transformation matrix and target surface of the Cairo context
+using pango_cairo_update_context(). The convenience functions
+pango_cairo_create_layout() and pango_cairo_update_layout() handle
+the common case where the program doesn't need to manipulate the
+properties of the #PangoContext.
+</para>
+<para>
+When you get the metrics of a layout or of a piece of a layout using
+functions such as pango_layout_get_extents(), the reported metrics
+are in user-space coordinates. If a piece of text is 10 units long,
+and you call cairo_scale (cr, 2.0), it still is more-or-less 10
+units long. However, the results will be affected by hinting
+(that is, the process of adjusting the text to look good on the
+pixel grid), so you shouldn't assume they are completely independent
+of the current transformation matrix. Note that the basic metrics
+functions in Pango report results in integer Pango units. To get
+to the floating point units used in Cairo divide by %PANGO_SCALE.
+</para>
+<example id="rotated-example">
+<title>Using Pango with Cairo</title>
+<programlisting>
+#<!-- -->include &lt;math.h>
+#<!-- -->include &lt;pango/pangocairo.h>
+
+static void
+draw_text (cairo_t *cr)
+{
+#<!-- -->define RADIUS 150
+#<!-- -->define N_WORDS 10
+#<!-- -->define FONT "Sans Bold 27"
+
+ PangoLayout *layout;
+ PangoFontDescription *desc;
+ int i;
+
+ /* Center coordinates on the middle of the region we are drawing
+ */
+ cairo_translate (cr, RADIUS, RADIUS);
+
+ /* Create a PangoLayout, set the font and text */
+ layout = pango_cairo_create_layout (cr);
+
+ pango_layout_set_text (layout, "Text", -1);
+ desc = pango_font_description_from_string (FONT);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+
+ /* Draw the layout N_WORDS times in a circle */
+ for (i = 0; i &lt; N_WORDS; i++)
+ {
+ int width, height;
+ double angle = (360. * i) / N_WORDS;
+ double red;
+
+ cairo_save (cr);
+
+ /* Gradient from red at angle == 60 to blue at angle == 240 */
+ red = (1 + cos ((angle - 60) * G_PI / 180.)) / 2;
+ cairo_set_source_rgb (cr, red, 0, 1.0 - red);
+
+ cairo_rotate (cr, angle * G_PI / 180.);
+
+ /* Inform Pango to re-layout the text with the new transformation */
+ pango_cairo_update_layout (cr, layout);
+
+ pango_layout_get_size (layout, &amp;width, &amp;height);
+ cairo_move_to (cr, - ((double)width / PANGO_SCALE) / 2, - RADIUS);
+ pango_cairo_show_layout (cr, layout);
+
+ cairo_restore (cr);
+ }
+
+ /* free the layout object */
+ g_object_unref (layout);
+}
+
+int main (int argc, char **argv)
+{
+ cairo_t *cr;
+ char *filename;
+ cairo_status_t status;
+ cairo_surface_t *surface;
+
+ if (argc != 2)
+ {
+ g_printerr ("Usage: cairosimple OUTPUT_FILENAME\n");
+ return 1;
+ }
+
+ filename = argv[1];
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ 2 * RADIUS, 2 * RADIUS);
+ cr = cairo_create (surface);
+
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_paint (cr);
+ draw_text (cr);
+ cairo_destroy (cr);
+
+ status = cairo_surface_write_to_png (surface, filename);
+ cairo_surface_destroy (surface);
+
+ if (status != CAIRO_STATUS_SUCCESS)
+ {
+ g_printerr ("Could not save png to '%s'\n", filename);
+ return 1;
+ }
+
+ return 0;
+}
+</programlisting>
+</example>
+<figure id="rotated-example-output">
+ <title>Output of <xref linkend="rotated-example"/></title>
+ <graphic fileref="rotated-text.png" format="PNG"/>
+</figure>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoCairoFont ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### STRUCT PangoCairoFontMap ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION pango_cairo_font_map_get_default ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_font_map_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_font_map_new_for_font_type ##### -->
+<para>
+
+</para>
+
+@fonttype:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_font_map_get_font_type ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_font_map_set_resolution ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@dpi:
+
+
+<!-- ##### FUNCTION pango_cairo_font_map_get_resolution ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_font_map_create_context ##### -->
+<para>
+
+</para>
+
+@fontmap:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_font_get_scaled_font ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_context_set_resolution ##### -->
+<para>
+
+</para>
+
+@context:
+@dpi:
+
+
+<!-- ##### FUNCTION pango_cairo_context_get_resolution ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_context_set_font_options ##### -->
+<para>
+
+</para>
+
+@context:
+@options:
+
+
+<!-- ##### FUNCTION pango_cairo_context_get_font_options ##### -->
+<para>
+
+</para>
+
+@context:
+@Returns:
+
+
+<!-- ##### USER_FUNCTION PangoCairoShapeRendererFunc ##### -->
+<para>
+Function type for rendering attributes of type %PANGO_ATTR_SHAPE
+with Pango's Cairo renderer.
+</para>
+
+@cr: a Cairo context with current point set to where the shape should
+ be rendered
+@attr: the %PANGO_ATTR_SHAPE to render
+@do_path: whether only the shape path should be appended to current
+ path of @cr and no filling/stroking done. This will be set
+ to %TRUE when called from pango_cairo_layout_path() and
+ pango_cairo_layout_line_path() rendering functions.
+@data: user data passed to pango_cairo_context_set_shape_renderer()
+
+
+<!-- ##### FUNCTION pango_cairo_context_set_shape_renderer ##### -->
+<para>
+
+</para>
+
+@context:
+@func:
+@data:
+@dnotify:
+
+
+<!-- ##### FUNCTION pango_cairo_context_get_shape_renderer ##### -->
+<para>
+
+</para>
+
+@context:
+@data:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_update_context ##### -->
+<para>
+
+</para>
+
+@cr:
+@context:
+
+
+<!-- ##### FUNCTION pango_cairo_create_layout ##### -->
+<para>
+
+</para>
+
+@cr:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_cairo_update_layout ##### -->
+<para>
+
+</para>
+
+@cr:
+@layout:
+
+
+<!-- ##### FUNCTION pango_cairo_show_glyph_string ##### -->
+<para>
+
+</para>
+
+@cr:
+@font:
+@glyphs:
+
+
+<!-- ##### FUNCTION pango_cairo_show_layout_line ##### -->
+<para>
+
+</para>
+
+@cr:
+@line:
+
+
+<!-- ##### FUNCTION pango_cairo_show_layout ##### -->
+<para>
+
+</para>
+
+@cr:
+@layout:
+
+
+<!-- ##### FUNCTION pango_cairo_show_error_underline ##### -->
+<para>
+
+</para>
+
+@cr:
+@x:
+@y:
+@width:
+@height:
+
+
+<!-- ##### FUNCTION pango_cairo_glyph_string_path ##### -->
+<para>
+
+</para>
+
+@cr:
+@font:
+@glyphs:
+
+
+<!-- ##### FUNCTION pango_cairo_layout_line_path ##### -->
+<para>
+
+</para>
+
+@cr:
+@line:
+
+
+<!-- ##### FUNCTION pango_cairo_layout_path ##### -->
+<para>
+
+</para>
+
+@cr:
+@layout:
+
+
+<!-- ##### FUNCTION pango_cairo_error_underline_path ##### -->
+<para>
+
+</para>
+
+@cr:
+@x:
+@y:
+@width:
+@height:
+
+
diff --git a/trunk/docs/tmpl/pangofc-decoder.sgml b/trunk/docs/tmpl/pangofc-decoder.sgml
new file mode 100644
index 00000000..b8191c73
--- /dev/null
+++ b/trunk/docs/tmpl/pangofc-decoder.sgml
@@ -0,0 +1,55 @@
+<!-- ##### SECTION Title ##### -->
+PangoFcDecoder
+
+<!-- ##### SECTION Short_Description ##### -->
+Custom font encoding handling
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+PangoFcDecoder represents a decoder that an application provides
+for handling a font that is encoded in a custom way.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoFcDecoder ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### STRUCT PangoFcDecoderClass ##### -->
+<para>
+
+</para>
+
+@get_charset:
+@get_glyph:
+
+<!-- ##### FUNCTION pango_fc_decoder_get_charset ##### -->
+<para>
+
+</para>
+
+@decoder:
+@fcfont:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fc_decoder_get_glyph ##### -->
+<para>
+
+</para>
+
+@decoder:
+@fcfont:
+@wc:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/pangofc-font.sgml b/trunk/docs/tmpl/pangofc-font.sgml
new file mode 100644
index 00000000..95ac1dd3
--- /dev/null
+++ b/trunk/docs/tmpl/pangofc-font.sgml
@@ -0,0 +1,122 @@
+<!-- ##### SECTION Title ##### -->
+PangoFcFont
+
+<!-- ##### SECTION Short_Description ##### -->
+Base font class for Fontconfig-based backends
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+#PangoFcFont is a base class for font implementation using the
+Fontconfig and FreeType libraries. It is used in the
+<link linkend="pango-Xft-Fonts-and-Rendering">Xft</link> and
+<link linkend="pango-FreeType-Fonts-and-Rendering">FreeType</link>
+backends shipped with Pango, but can also be used when creating
+new backends. Any backend deriving from this base class will
+take advantage of the wide range of shapers implemented using
+FreeType that come with Pango.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+<variablelist>
+
+<varlistentry>
+<term>#PangoFcFontMap</term>
+<listitem><para>The base class for font maps; creating a new
+Fontconfig-based backend involves deriving from both
+#PangoFcFontMap and #PangoFcFont.
+.</para></listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoFcFont ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG PangoFcFont:pattern ##### -->
+<para>
+
+</para>
+
+<!-- ##### STRUCT PangoFcFontClass ##### -->
+<para>
+
+</para>
+
+@lock_face:
+@unlock_face:
+@has_char:
+@get_glyph:
+@get_unknown_glyph:
+@shutdown:
+
+<!-- ##### MACRO PANGO_RENDER_TYPE_FC ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION pango_fc_font_lock_face ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fc_font_unlock_face ##### -->
+<para>
+
+</para>
+
+@font:
+
+
+<!-- ##### FUNCTION pango_fc_font_has_char ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fc_font_get_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fc_font_get_unknown_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fc_font_kern_glyphs ##### -->
+<para>
+
+</para>
+
+@font:
+@glyphs:
+
+
diff --git a/trunk/docs/tmpl/pangofc-fontmap.sgml b/trunk/docs/tmpl/pangofc-fontmap.sgml
new file mode 100644
index 00000000..340ad03a
--- /dev/null
+++ b/trunk/docs/tmpl/pangofc-fontmap.sgml
@@ -0,0 +1,114 @@
+<!-- ##### SECTION Title ##### -->
+PangoFcFontMap
+
+<!-- ##### SECTION Short_Description ##### -->
+Base fontmap class for Fontconfig-based backends
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+PangoFcFontMap is a base class for font map implementations using the
+Fontconfig and FreeType libraries. It is used in the
+<link linkend="pango-Xft-Fonts-and-Rendering">Xft</link> and
+<link linkend="pango-FreeType-Fonts-and-Rendering">FreeType</link>
+backends shipped with Pango, but can also be used when creating
+new backends. Any backend deriving from this base class will
+take advantage of the wide range of shapers implemented using
+FreeType that come with Pango.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+<variablelist>
+
+<varlistentry>
+<term>#PangoFcFont</term>
+<listitem><para>The base class for fonts; creating a new
+Fontconfig-based backend involves deriving from both
+#PangoFcFontMap and #PangoFcFont.
+</para></listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoFcFontMap ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### STRUCT PangoFcFontMapClass ##### -->
+<para>
+
+</para>
+
+@default_substitute:
+@new_font:
+@get_resolution:
+@context_key_get:
+@context_key_copy:
+@context_key_free:
+@context_key_hash:
+@context_key_equal:
+@context_substitute:
+@create_font:
+
+<!-- ##### FUNCTION pango_fc_font_description_from_pattern ##### -->
+<para>
+
+</para>
+
+@pattern:
+@include_size:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fc_font_map_cache_clear ##### -->
+<para>
+
+</para>
+
+@fcfontmap:
+
+
+<!-- ##### FUNCTION pango_fc_font_map_create_context ##### -->
+<para>
+
+</para>
+
+@fcfontmap:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_fc_font_map_shutdown ##### -->
+<para>
+
+</para>
+
+@fcfontmap:
+
+
+<!-- ##### FUNCTION pango_fc_font_map_add_decoder_find_func ##### -->
+<para>
+
+</para>
+
+@fcfontmap:
+@findfunc:
+@user_data:
+@dnotify:
+
+
+<!-- ##### USER_FUNCTION PangoFcDecoderFindFunc ##### -->
+<para>
+
+</para>
+
+@pattern:
+@user_data:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/scripts.sgml b/trunk/docs/tmpl/scripts.sgml
new file mode 100644
index 00000000..fe64f84d
--- /dev/null
+++ b/trunk/docs/tmpl/scripts.sgml
@@ -0,0 +1,182 @@
+<!-- ##### SECTION Title ##### -->
+Scripts
+
+<!-- ##### SECTION Short_Description ##### -->
+Identifying writing systems
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The functions in this section are used to identify the writing
+system, or <firstterm>script</firstterm> of individual characters
+and of ranges within a larger text string.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoScriptIter ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ENUM PangoScript ##### -->
+<para>
+The #PangoScript enumeration identifies different writing
+systems. The values correspond to the names as defined in the
+Unicode standard.
+Note that new types may be added in the future. Applications should be ready
+to handle unknown values.
+See <ulink
+url="http://www.unicode.org/reports/tr24/">Unicode Standard Annex
+#24: Script names</ulink>.
+</para>
+
+@PANGO_SCRIPT_INVALID_CODE: a value never returned from pango_script_for_unichar()
+@PANGO_SCRIPT_COMMON: a character used by multiple different scripts
+@PANGO_SCRIPT_INHERITED: a mark glyph that takes its script from the
+ base glyph to which it is attached
+@PANGO_SCRIPT_ARABIC: Arabic
+@PANGO_SCRIPT_ARMENIAN: Armenian
+@PANGO_SCRIPT_BENGALI: Bengali
+@PANGO_SCRIPT_BOPOMOFO: Bopomofo
+@PANGO_SCRIPT_CHEROKEE: Cherokee
+@PANGO_SCRIPT_COPTIC: Coptic
+@PANGO_SCRIPT_CYRILLIC: Cyrillic
+@PANGO_SCRIPT_DESERET: Deseret
+@PANGO_SCRIPT_DEVANAGARI: Devanagari
+@PANGO_SCRIPT_ETHIOPIC: Ethiopic
+@PANGO_SCRIPT_GEORGIAN: Georgian
+@PANGO_SCRIPT_GOTHIC: Gothic
+@PANGO_SCRIPT_GREEK: Greek
+@PANGO_SCRIPT_GUJARATI: Gujarati
+@PANGO_SCRIPT_GURMUKHI: Gurmukhi
+@PANGO_SCRIPT_HAN: Han
+@PANGO_SCRIPT_HANGUL: Hangul
+@PANGO_SCRIPT_HEBREW: Hebrew
+@PANGO_SCRIPT_HIRAGANA: Hiragana
+@PANGO_SCRIPT_KANNADA: Kannada
+@PANGO_SCRIPT_KATAKANA: Katakana
+@PANGO_SCRIPT_KHMER: Khmer
+@PANGO_SCRIPT_LAO: Lao
+@PANGO_SCRIPT_LATIN: Latin
+@PANGO_SCRIPT_MALAYALAM: Malayalam
+@PANGO_SCRIPT_MONGOLIAN: Mongolian
+@PANGO_SCRIPT_MYANMAR: Myanmar
+@PANGO_SCRIPT_OGHAM: Ogham
+@PANGO_SCRIPT_OLD_ITALIC: Old Italic
+@PANGO_SCRIPT_ORIYA: Oriya
+@PANGO_SCRIPT_RUNIC: Runic
+@PANGO_SCRIPT_SINHALA: Sinhala
+@PANGO_SCRIPT_SYRIAC: Syriac
+@PANGO_SCRIPT_TAMIL: Tamil
+@PANGO_SCRIPT_TELUGU: Telugu
+@PANGO_SCRIPT_THAANA: Thaana
+@PANGO_SCRIPT_THAI: Thai
+@PANGO_SCRIPT_TIBETAN: Tibetan
+@PANGO_SCRIPT_CANADIAN_ABORIGINAL: Canadian Aboriginal
+@PANGO_SCRIPT_YI: Yi
+@PANGO_SCRIPT_TAGALOG: Tagalog
+@PANGO_SCRIPT_HANUNOO: Hanunoo
+@PANGO_SCRIPT_BUHID: Buhid
+@PANGO_SCRIPT_TAGBANWA: Tagbanwa
+@PANGO_SCRIPT_BRAILLE: Braille
+@PANGO_SCRIPT_CYPRIOT: Cypriot
+@PANGO_SCRIPT_LIMBU: Limbu
+@PANGO_SCRIPT_OSMANYA: Osmanya
+@PANGO_SCRIPT_SHAVIAN: Shavian
+@PANGO_SCRIPT_LINEAR_B: Linear B
+@PANGO_SCRIPT_TAI_LE: Tai Le
+@PANGO_SCRIPT_UGARITIC: Ugaritic
+@PANGO_SCRIPT_NEW_TAI_LUE: New Tai Lue
+@PANGO_SCRIPT_BUGINESE: Buginese
+@PANGO_SCRIPT_GLAGOLITIC: Glagolitic
+@PANGO_SCRIPT_TIFINAGH: Tifinagh
+@PANGO_SCRIPT_SYLOTI_NAGRI: Syloti Nagri
+@PANGO_SCRIPT_OLD_PERSIAN: Old Persian
+@PANGO_SCRIPT_KHAROSHTHI: Kharoshthi
+@PANGO_SCRIPT_UNKNOWN: an unassigned code point
+@PANGO_SCRIPT_BALINESE: Balinese
+@PANGO_SCRIPT_CUNEIFORM: Cuneiform
+@PANGO_SCRIPT_PHOENICIAN: Phoenician
+@PANGO_SCRIPT_PHAGS_PA: Phags-pa
+@PANGO_SCRIPT_NKO: N'Ko
+
+<!-- ##### MACRO PANGO_TYPE_SCRIPT ##### -->
+<para>
+The #GObject type for #PangoScript
+</para>
+
+
+
+<!-- ##### FUNCTION pango_script_for_unichar ##### -->
+<para>
+
+</para>
+
+@ch:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_script_get_sample_language ##### -->
+<para>
+
+</para>
+
+@script:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_language_includes_script ##### -->
+<para>
+
+</para>
+
+@language:
+@script:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_script_iter_new ##### -->
+<para>
+
+</para>
+
+@text:
+@length:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_script_iter_get_range ##### -->
+<para>
+
+</para>
+
+@iter:
+@start:
+@end:
+@script:
+
+
+<!-- ##### FUNCTION pango_script_iter_next ##### -->
+<para>
+
+</para>
+
+@iter:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_script_iter_free ##### -->
+<para>
+
+</para>
+
+@iter:
+
+
diff --git a/trunk/docs/tmpl/tab-stops.sgml b/trunk/docs/tmpl/tab-stops.sgml
new file mode 100644
index 00000000..03ae3792
--- /dev/null
+++ b/trunk/docs/tmpl/tab-stops.sgml
@@ -0,0 +1,147 @@
+<!-- ##### SECTION Title ##### -->
+Tab Stops
+
+<!-- ##### SECTION Short_Description ##### -->
+Structures for storing tab stops
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+Functions in this section are used to deal with #PangoTabArray objects
+that can be used to set tab stop positions in a #PangoLayout.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoTabArray ##### -->
+<para>
+A #PangoTabArray struct contains an array
+of tab stops. Each tab stop has an alignment and a position.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_TAB_ARRAY ##### -->
+<para>
+The #GObject type for #PangoTabArray.
+</para>
+
+
+
+<!-- ##### ENUM PangoTabAlign ##### -->
+<para>
+A #PangoTabAlign specifies where a tab stop appears relative to the text.
+</para>
+
+@PANGO_TAB_LEFT: the tab stop appears to the left of the text.
+
+<!-- ##### MACRO PANGO_TYPE_TAB_ALIGN ##### -->
+<para>
+The #GObject type for #PangoTabAlign.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_tab_array_new ##### -->
+<para>
+
+</para>
+
+@initial_size:
+@positions_in_pixels:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_tab_array_new_with_positions ##### -->
+<para>
+
+</para>
+
+@size:
+@positions_in_pixels:
+@first_alignment:
+@first_position:
+@Varargs:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_tab_array_copy ##### -->
+<para>
+
+</para>
+
+@src:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_tab_array_free ##### -->
+<para>
+
+</para>
+
+@tab_array:
+
+
+<!-- ##### FUNCTION pango_tab_array_get_size ##### -->
+<para>
+
+</para>
+
+@tab_array:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_tab_array_resize ##### -->
+<para>
+
+</para>
+
+@tab_array:
+@new_size:
+
+
+<!-- ##### FUNCTION pango_tab_array_set_tab ##### -->
+<para>
+
+</para>
+
+@tab_array:
+@tab_index:
+@alignment:
+@location:
+
+
+<!-- ##### FUNCTION pango_tab_array_get_tab ##### -->
+<para>
+
+</para>
+
+@tab_array:
+@tab_index:
+@alignment:
+@location:
+
+
+<!-- ##### FUNCTION pango_tab_array_get_tabs ##### -->
+<para>
+
+</para>
+
+@tab_array:
+@alignments:
+@locations:
+
+
+<!-- ##### FUNCTION pango_tab_array_get_positions_in_pixels ##### -->
+<para>
+
+</para>
+
+@tab_array:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/text-attributes.sgml b/trunk/docs/tmpl/text-attributes.sgml
new file mode 100644
index 00000000..79f9ac94
--- /dev/null
+++ b/trunk/docs/tmpl/text-attributes.sgml
@@ -0,0 +1,838 @@
+<!-- ##### SECTION Title ##### -->
+Text Attributes
+
+<!-- ##### SECTION Short_Description ##### -->
+Font and other attributes for annotating text
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+Attributed text is used in a number of places in Pango. It
+is used as the input to the itemization process and also when
+creating a #PangoLayout. The data types and functions in
+this section are used to represent and manipulate sets
+of attributes applied to a portion of text.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### ENUM PangoAttrType ##### -->
+<para>
+The #PangoAttrType
+distinguishes between different types of attributes. Along with the
+predefined values, it is possible to allocate additional values
+for custom attributes using pango_attr_type_register(). The predefined
+values are given below. The type of structure used to store the
+attribute is listed in parentheses after the description.
+</para>
+
+@PANGO_ATTR_INVALID: does not happen
+@PANGO_ATTR_LANGUAGE: language (#PangoAttrLanguage)
+@PANGO_ATTR_FAMILY: font family name list (#PangoAttrString)
+@PANGO_ATTR_STYLE: font slant style (#PangoAttrInt)
+@PANGO_ATTR_WEIGHT: font weight (#PangoAttrInt)
+@PANGO_ATTR_VARIANT: font variant (normal or small caps) (#PangoAttrInt)
+@PANGO_ATTR_STRETCH: font stretch (#PangoAttrInt)
+@PANGO_ATTR_SIZE: font size in points scaled by %PANGO_SCALE (#PangoAttrInt)
+@PANGO_ATTR_FONT_DESC: font description (#PangoAttrFontDesc)
+@PANGO_ATTR_FOREGROUND: foreground color (#PangoAttrColor)
+@PANGO_ATTR_BACKGROUND: background color (#PangoAttrColor)
+@PANGO_ATTR_UNDERLINE: whether the text has an underline (#PangoAttrInt)
+@PANGO_ATTR_STRIKETHROUGH: whether the text is struck-through (#PangoAttrInt)
+@PANGO_ATTR_RISE: baseline displacement (#PangoAttrInt)
+@PANGO_ATTR_SHAPE: shape (#PangoAttrShape)
+@PANGO_ATTR_SCALE: font size scale factor (#PangoAttrFloat)
+@PANGO_ATTR_FALLBACK: whether fallback is enabled (#PangoAttrInt)
+@PANGO_ATTR_LETTER_SPACING: letter spacing (#PangoAttrInt)
+@PANGO_ATTR_UNDERLINE_COLOR: underline color (#PangoAttrColor)
+@PANGO_ATTR_STRIKETHROUGH_COLOR: strikethrough color (#PangoAttrColor)
+@PANGO_ATTR_ABSOLUTE_SIZE: font size in pixels scaled by %PANGO_SCALE (#PangoAttrInt)
+@PANGO_ATTR_GRAVITY: base text gravity (#PangoAttrInt)
+@PANGO_ATTR_GRAVITY_HINT: gravity hint (#PangoAttrInt)
+
+<!-- ##### MACRO PANGO_TYPE_ATTR_TYPE ##### -->
+<para>
+The #GObject type for #PangoAttrType.
+</para>
+
+
+
+<!-- ##### STRUCT PangoAttrClass ##### -->
+<para>
+The #PangoAttrClass structure stores the type and operations for
+a particular type of attribute. The functions in this structure should
+not be called directly. Instead, one should use the wrapper functions
+provided for #PangoAttribute.
+</para>
+
+@type: the type ID for this attribute
+@copy: function to duplicate an attribute of this type (see pango_attribute_copy())
+@destroy: function to free an attribute of this type (see pango_attribute_destroy())
+@equal: function to check two attributes of this type for equality (see pango_attribute_equal())
+
+<!-- ##### STRUCT PangoAttribute ##### -->
+<para>
+The #PangoAttribute structure represents the common portions of all
+attributes. Particular types of attributes include this structure
+as their initial portion. The common portion of the attribute holds
+the range to which the value in the type-specific part of the attribute
+applies.
+</para>
+
+@klass: the class structure holding information about the type of the attribute
+@start_index: the start index of the range (in bytes).
+@end_index: end index of the range (in bytes). The character at this index
+ is not included in the range.
+
+<!-- ##### STRUCT PangoAttrString ##### -->
+<para>
+The #PangoAttrString structure is used to represent attributes with
+a string value.
+</para>
+
+@attr: the common portion of the attribute
+@value: the string which is the value of the attribute
+
+<!-- ##### STRUCT PangoAttrLanguage ##### -->
+<para>
+The #PangoAttrLanguage structure is used to represent attributes that
+are languages.
+</para>
+
+@attr: the common portion of the attribute
+@value: the #PangoLanguage which is the value of the attribute
+
+<!-- ##### STRUCT PangoAttrColor ##### -->
+<para>
+The #PangoAttrColor structure is used to represent attributes that
+are colors.
+</para>
+
+@attr: the common portion of the attribute
+@color: the #PangoColor which is the value of the attribute
+
+<!-- ##### STRUCT PangoAttrInt ##### -->
+<para>
+The #PangoAttrInt structure is used to represent attributes with
+an integer or enumeration value.
+</para>
+
+@attr: the common portion of the attribute
+@value: the value of the attribute
+
+<!-- ##### STRUCT PangoAttrFloat ##### -->
+<para>
+The #PangoAttrFloat structure is used to represent attributes with
+a float or double value.
+</para>
+
+@attr: the common portion of the attribute
+@value: the value of the attribute
+
+<!-- ##### STRUCT PangoAttrFontDesc ##### -->
+<para>
+The #PangoAttrFontDesc structure is used to store an attribute that
+sets all aspects of the font description at once.
+</para>
+
+@attr: the common portion of the attribute
+@desc: the font description which is the value of this attribute
+
+<!-- ##### STRUCT PangoAttrShape ##### -->
+<para>
+The #PangoAttrShape structure is used to represent attributes which
+impose shape restrictions.
+</para>
+
+@attr: the common portion of the attribute
+@ink_rect: the ink rectangle to restrict to
+@logical_rect: the logical rectangle to restrict to
+@data: user data set (see pango_attr_shape_new_with_data())
+@copy_func: copy function for the user data
+@destroy_func: destroy function for the user data
+
+<!-- ##### STRUCT PangoAttrSize ##### -->
+<para>
+The #PangoAttrShape structure is used to represent attributes which
+set font size.
+</para>
+
+@attr: the common portion of the attribute
+@size: size of font, in units of 1/%PANGO_SCALE of a point (for
+ %PANGO_ATTR_SIZE) or of a device uni (for %PANGO_ATTR_ABSOLUTE_SIZE)
+@absolute: whether the font size is in device units or points.
+ This field is only present for compatibility with Pango-1.8.0
+ (%PANGO_ATTR_ABSOLUTE_SIZE was added in 1.8.1); and always will
+ be %FALSE for %PANGO_ATTR_SIZE and %TRUE for %PANGO_ATTR_ABSOLUTE_SIZE.
+
+<!-- ##### FUNCTION pango_parse_markup ##### -->
+<para>
+
+</para>
+
+@markup_text:
+@length:
+@accel_marker:
+@attr_list:
+@text:
+@accel_char:
+@error:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_type_register ##### -->
+<para>
+
+</para>
+
+@name:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attribute_copy ##### -->
+<para>
+
+</para>
+
+@attr:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attribute_equal ##### -->
+<para>
+
+</para>
+
+@attr1:
+@attr2:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attribute_destroy ##### -->
+<para>
+
+</para>
+
+@attr:
+
+
+<!-- ##### FUNCTION pango_attr_language_new ##### -->
+<para>
+
+</para>
+
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_family_new ##### -->
+<para>
+
+</para>
+
+@family:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_style_new ##### -->
+<para>
+
+</para>
+
+@style:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_variant_new ##### -->
+<para>
+
+</para>
+
+@variant:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_stretch_new ##### -->
+<para>
+
+</para>
+
+@stretch:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_weight_new ##### -->
+<para>
+
+</para>
+
+@weight:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_size_new ##### -->
+<para>
+
+</para>
+
+@size:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_size_new_absolute ##### -->
+<para>
+
+</para>
+
+@size:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_font_desc_new ##### -->
+<para>
+
+</para>
+
+@desc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_foreground_new ##### -->
+<para>
+
+</para>
+
+@red:
+@green:
+@blue:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_background_new ##### -->
+<para>
+
+</para>
+
+@red:
+@green:
+@blue:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_strikethrough_new ##### -->
+<para>
+
+</para>
+
+@strikethrough:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_strikethrough_color_new ##### -->
+<para>
+
+</para>
+
+@red:
+@green:
+@blue:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_underline_new ##### -->
+<para>
+
+</para>
+
+@underline:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_underline_color_new ##### -->
+<para>
+
+</para>
+
+@red:
+@green:
+@blue:
+@Returns:
+
+
+<!-- ##### ENUM PangoUnderline ##### -->
+<para>
+the #PangoUnderline enumeration is used to specify
+whether text should be underlined, and if so, the type
+of underlining.
+</para>
+
+@PANGO_UNDERLINE_NONE: no underline should be drawn
+@PANGO_UNDERLINE_SINGLE: a single underline should be drawn
+@PANGO_UNDERLINE_DOUBLE: a double underline should be drawn
+@PANGO_UNDERLINE_LOW: a single underline should be drawn at a position
+ beneath the ink extents of the text being
+ underlined. This should be used only for underlining
+ single characters, such as for keyboard
+ accelerators. %PANGO_UNDERLINE_SINGLE should
+ be used for extended portions of text.
+@PANGO_UNDERLINE_ERROR: a wavy underline should be drawn below.
+ This underline is typically used to indicate
+ an error such as a possilble mispelling; in some
+ cases a contrasting color may automatically
+ be used. This type of underlining is available
+ since Pango 1.4.
+
+<!-- ##### MACRO PANGO_TYPE_UNDERLINE ##### -->
+<para>
+The #GObject type for #PangoUnderline.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_attr_shape_new ##### -->
+<para>
+
+</para>
+
+@ink_rect:
+@logical_rect:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_shape_new_with_data ##### -->
+<para>
+
+</para>
+
+@ink_rect:
+@logical_rect:
+@data:
+@copy_func:
+@destroy_func:
+@Returns:
+
+
+<!-- ##### USER_FUNCTION PangoAttrDataCopyFunc ##### -->
+<para>
+A copy function passed to attribute new functions that take
+user data.
+</para>
+
+@data: the user data
+@Returns: a new copy of @data.
+
+
+<!-- ##### FUNCTION pango_attr_scale_new ##### -->
+<para>
+
+</para>
+
+@scale_factor:
+@Returns:
+
+
+<!-- ##### MACRO PANGO_SCALE_XX_SMALL ##### -->
+<para>
+The scale factor for three shrinking steps (1 / (1.2 * 1.2 * 1.2)).
+</para>
+
+
+
+<!-- ##### MACRO PANGO_SCALE_X_SMALL ##### -->
+<para>
+The scale factor for two shrinking steps (1 / (1.2 * 1.2)).
+</para>
+
+
+
+<!-- ##### MACRO PANGO_SCALE_SMALL ##### -->
+<para>
+The scale factor for one shrinking step (1 / 1.2).
+</para>
+
+
+
+<!-- ##### MACRO PANGO_SCALE_MEDIUM ##### -->
+<para>
+The scale factor for normal size (1.0).
+</para>
+
+
+
+<!-- ##### MACRO PANGO_SCALE_LARGE ##### -->
+<para>
+The scale factor for one magnification step (1.2).
+</para>
+
+
+
+<!-- ##### MACRO PANGO_SCALE_X_LARGE ##### -->
+<para>
+The scale factor for two magnification steps (1.2 * 1.2).
+</para>
+
+
+
+<!-- ##### MACRO PANGO_SCALE_XX_LARGE ##### -->
+<para>
+The scale factor for three magnification steps (1.2 * 1.2 * 1.2).
+</para>
+
+
+
+<!-- ##### FUNCTION pango_attr_rise_new ##### -->
+<para>
+
+</para>
+
+@rise:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_letter_spacing_new ##### -->
+<para>
+
+</para>
+
+@letter_spacing:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_fallback_new ##### -->
+<para>
+
+</para>
+
+@enable_fallback:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_gravity_new ##### -->
+<para>
+
+</para>
+
+@gravity:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_gravity_hint_new ##### -->
+<para>
+
+</para>
+
+@hint:
+@Returns:
+
+
+<!-- ##### STRUCT PangoColor ##### -->
+<para>
+The #PangoColor structure is used to
+represent a color in an uncalibrated RGB color-space.
+</para>
+
+@red: The red component of the color. This is a value between 0 and 65535,
+ with 65535 indicating full intensity.
+@green: The green component of the color. This is a value between 0 and 65535,
+ with 65535 indicating full intensity.
+@blue: The blue component of the color. This is a value between 0 and 65535,
+ with 65535 indicating full intensity.
+
+<!-- ##### MACRO PANGO_TYPE_COLOR ##### -->
+<para>
+The #GObject type for #PangoColor.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_color_parse ##### -->
+<para>
+
+</para>
+
+@color:
+@spec:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_color_copy ##### -->
+<para>
+
+</para>
+
+@src:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_color_free ##### -->
+<para>
+
+</para>
+
+@color:
+
+
+<!-- ##### FUNCTION pango_color_to_string ##### -->
+<para>
+
+</para>
+
+@color:
+@Returns:
+
+
+<!-- ##### STRUCT PangoLanguage ##### -->
+<para>
+The #PangoLanguage structure is used to
+represent a language.
+</para>
+<para>
+#PangoLanguage pointers can be efficiently
+copied and compared with each other.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_LANGUAGE ##### -->
+<para>
+The #GObject type for #PangoLanguage.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_language_from_string ##### -->
+<para>
+
+</para>
+
+@language:
+@Returns:
+
+
+<!-- ##### MACRO pango_language_to_string ##### -->
+<para>
+Returns a RFC-3066 format string representing the given language tag.
+</para>
+
+@language: a language tag.
+@Returns: a string representing the language tag.
+
+
+<!-- ##### FUNCTION pango_language_matches ##### -->
+<para>
+
+</para>
+
+@language:
+@range_list:
+@Returns:
+
+
+<!-- ##### STRUCT PangoAttrList ##### -->
+<para>
+The #PangoAttrList structure represents a list of attributes
+that apply to a section of text. The attributes are, in general,
+allowed to overlap in an arbitrary fashion, however, if the
+attributes are manipulated only through pango_attr_list_change(),
+the overlap between properties will meet stricter criteria.
+</para>
+<para>
+Since the #PangoAttrList structure is stored as a linear list,
+it is not suitable for storing attributes for large amounts
+of text. In general, you should not use a single #PangoAttrList
+for more than one paragraph of text.
+</para>
+
+
+<!-- ##### MACRO PANGO_TYPE_ATTR_LIST ##### -->
+<para>
+The #GObject type for #PangoAttrList.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_attr_list_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_list_ref ##### -->
+<para>
+
+</para>
+
+@list:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_list_unref ##### -->
+<para>
+
+</para>
+
+@list:
+
+
+<!-- ##### FUNCTION pango_attr_list_copy ##### -->
+<para>
+
+</para>
+
+@list:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_list_insert ##### -->
+<para>
+
+</para>
+
+@list:
+@attr:
+
+
+<!-- ##### FUNCTION pango_attr_list_insert_before ##### -->
+<para>
+
+</para>
+
+@list:
+@attr:
+
+
+<!-- ##### FUNCTION pango_attr_list_change ##### -->
+<para>
+
+</para>
+
+@list:
+@attr:
+
+
+<!-- ##### FUNCTION pango_attr_list_splice ##### -->
+<para>
+
+</para>
+
+@list:
+@other:
+@pos:
+@len:
+
+
+<!-- ##### FUNCTION pango_attr_list_filter ##### -->
+<para>
+
+</para>
+
+@list:
+@func:
+@data:
+@Returns:
+
+
+<!-- ##### USER_FUNCTION PangoAttrFilterFunc ##### -->
+<para>
+A predicate function used by pango_attr_list_filter()
+to filter out a subset of attributes for a list.
+</para>
+
+@attribute: a #PangoAttribute
+@data: callback data passed to pango_attr_list_filter()
+@Returns: %TRUE if the attribute should be filtered out
+
+
+<!-- ##### FUNCTION pango_attr_list_get_iterator ##### -->
+<para>
+
+</para>
+
+@list:
+@Returns:
+
+
+<!-- ##### STRUCT PangoAttrIterator ##### -->
+<para>
+The #PangoAttrIterator structure is used to represent an
+iterator through a #PangoAttrList. A new iterator is created
+with pango_attr_list_get_iterator(). Once the iterator
+is created, it can be advanced through the style changes
+in the text using pango_attr_iterator_next(). At each
+style change, the range of the current style segment and the
+attributes currently in effect can be queried.
+</para>
+
+
+<!-- ##### FUNCTION pango_attr_iterator_copy ##### -->
+<para>
+
+</para>
+
+@iterator:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_iterator_next ##### -->
+<para>
+
+</para>
+
+@iterator:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_iterator_range ##### -->
+<para>
+
+</para>
+
+@iterator:
+@start:
+@end:
+
+
+<!-- ##### FUNCTION pango_attr_iterator_get ##### -->
+<para>
+
+</para>
+
+@iterator:
+@type:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_iterator_get_font ##### -->
+<para>
+
+</para>
+
+@iterator:
+@desc:
+@language:
+@extra_attrs:
+
+
+<!-- ##### FUNCTION pango_attr_iterator_get_attrs ##### -->
+<para>
+
+</para>
+
+@iterator:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_iterator_destroy ##### -->
+<para>
+
+</para>
+
+@iterator:
+
+
diff --git a/trunk/docs/tmpl/utils.sgml b/trunk/docs/tmpl/utils.sgml
new file mode 100644
index 00000000..f53c776f
--- /dev/null
+++ b/trunk/docs/tmpl/utils.sgml
@@ -0,0 +1,225 @@
+<!-- ##### SECTION Title ##### -->
+Miscellaneous Utilities
+
+<!-- ##### SECTION Short_Description ##### -->
+Various convenience and utility functions
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The functions and utilities in this section are mostly used from Pango
+backends and modules, but may be useful for other purposes too.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION pango_split_file_list ##### -->
+<para>
+
+</para>
+
+@str:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_trim_string ##### -->
+<para>
+
+</para>
+
+@str:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_read_line ##### -->
+<para>
+
+</para>
+
+@stream:
+@str:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_skip_space ##### -->
+<para>
+
+</para>
+
+@pos:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_scan_word ##### -->
+<para>
+
+</para>
+
+@pos:
+@out:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_scan_string ##### -->
+<para>
+
+</para>
+
+@pos:
+@out:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_scan_int ##### -->
+<para>
+
+</para>
+
+@pos:
+@out:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_config_key_get ##### -->
+<para>
+
+</para>
+
+@key:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_lookup_aliases ##### -->
+<para>
+
+</para>
+
+@fontname:
+@families:
+@n_families:
+
+
+<!-- ##### FUNCTION pango_parse_enum ##### -->
+<para>
+
+</para>
+
+@type:
+@str:
+@value:
+@warn:
+@possible_values:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_parse_style ##### -->
+<para>
+
+</para>
+
+@str:
+@style:
+@warn:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_parse_variant ##### -->
+<para>
+
+</para>
+
+@str:
+@variant:
+@warn:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_parse_weight ##### -->
+<para>
+
+</para>
+
+@str:
+@weight:
+@warn:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_parse_stretch ##### -->
+<para>
+
+</para>
+
+@str:
+@stretch:
+@warn:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_get_sysconf_subdirectory ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_get_lib_subdirectory ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_log2vis_get_embedding_levels ##### -->
+<para>
+
+</para>
+
+@text:
+@length:
+@pbase_dir:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_language_get_default ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_language_get_sample_string ##### -->
+<para>
+
+</para>
+
+@language:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_is_zero_width ##### -->
+<para>
+
+</para>
+
+@ch:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_quantize_line_geometry ##### -->
+<para>
+
+</para>
+
+@thickness:
+@position:
+
+
diff --git a/trunk/docs/tmpl/vertical.sgml b/trunk/docs/tmpl/vertical.sgml
new file mode 100644
index 00000000..5df8f4df
--- /dev/null
+++ b/trunk/docs/tmpl/vertical.sgml
@@ -0,0 +1,100 @@
+<!-- ##### SECTION Title ##### -->
+Vertical Text
+
+<!-- ##### SECTION Short_Description ##### -->
+Laying text out in vertical directions
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+Since 1.16, Pango is able to correctly lay vertical text out. In fact, it can
+set layouts of mixed vertical and non-vertical text. This section describes
+the types used for setting vertical text parameters.
+</para>
+<para>
+The way this is implemented is through the concept of
+<firstterm>gravity</firstterm>. Gravity of normal Latin text is south. A
+gravity value of east means that glyphs will be rotated ninety degrees
+counterclockwise. So, to render vertical text one needs to set the gravity
+and rotate the layout using the matrix machinery already in place. This has
+the huge advantage that most algorithms working on a #PangoLayout do not need
+any change as the assumption that lines run in the X direction and stack in
+the Y direction holds even for vertical text layouts.
+</para>
+<para>
+Applications should only need to set base gravity on #PangoContext in use, and
+let Pango decide the gravity assigned to each run of text. This automatically
+handles text with mixed scripts. A very common use is to set the context base
+gravity to auto and rotate the layout normally. Pango will make sure that
+Asian languages take the right form, while other scripts are rotated normally.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### ENUM PangoGravity ##### -->
+<para>
+
+</para>
+
+@PANGO_GRAVITY_SOUTH:
+@PANGO_GRAVITY_EAST:
+@PANGO_GRAVITY_NORTH:
+@PANGO_GRAVITY_WEST:
+@PANGO_GRAVITY_AUTO:
+
+<!-- ##### MACRO PANGO_TYPE_GRAVITY ##### -->
+<para>
+The #GObject type for #PangoGravity.
+</para>
+
+
+
+<!-- ##### ENUM PangoGravityHint ##### -->
+<para>
+
+</para>
+
+@PANGO_GRAVITY_HINT_NATURAL:
+@PANGO_GRAVITY_HINT_STRONG:
+@PANGO_GRAVITY_HINT_LINE:
+
+<!-- ##### MACRO PANGO_TYPE_GRAVITY_HINT ##### -->
+<para>
+The #GObject type for #PangoGravity.
+</para>
+
+
+
+<!-- ##### MACRO PANGO_GRAVITY_IS_VERTICAL ##### -->
+<para>
+
+</para>
+
+@gravity:
+
+
+<!-- ##### FUNCTION pango_gravity_get_for_matrix ##### -->
+<para>
+
+</para>
+
+@matrix:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_gravity_get_for_script ##### -->
+<para>
+
+</para>
+
+@script:
+@base_gravity:
+@hint:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/win32-fonts.sgml b/trunk/docs/tmpl/win32-fonts.sgml
new file mode 100644
index 00000000..8ead0d0f
--- /dev/null
+++ b/trunk/docs/tmpl/win32-fonts.sgml
@@ -0,0 +1,258 @@
+<!-- ##### SECTION Title ##### -->
+Win32 Fonts and Rendering
+
+<!-- ##### SECTION Short_Description ##### -->
+Functions for shape engines to manipulate Win32 fonts
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The macros and functions in this section are used to access fonts natively on
+Win32 systems and to render text in conjunction with Win32 APIs.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### MACRO PANGO_RENDER_TYPE_WIN32 ##### -->
+<para>
+A string constant identifying the Win32 renderer. The associated quark (see
+g_quark_from_string()) is used to identify the renderer in pango_find_map().
+</para>
+
+
+
+<!-- ##### FUNCTION pango_win32_get_context ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_render ##### -->
+<para>
+
+</para>
+
+@hdc:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_win32_render_transformed ##### -->
+<para>
+
+</para>
+
+@hdc:
+@matrix:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_win32_render_layout_line ##### -->
+<para>
+
+</para>
+
+@hdc:
+@line:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_win32_render_layout ##### -->
+<para>
+
+</para>
+
+@hdc:
+@layout:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_win32_get_unknown_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_get_glyph_index ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_select_font ##### -->
+<para>
+
+</para>
+
+@font:
+@hdc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_done_font ##### -->
+<para>
+
+</para>
+
+@font:
+
+
+<!-- ##### FUNCTION pango_win32_font_get_metrics_factor ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_get_debug_flag ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_get_dc ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### STRUCT PangoWin32FontCache ##### -->
+<para>
+A #PangoWin32FontCache caches
+HFONTs by their LOGFONT descriptions.
+</para>
+
+
+<!-- ##### FUNCTION pango_win32_font_cache_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_cache_free ##### -->
+<para>
+
+</para>
+
+@cache:
+
+
+<!-- ##### FUNCTION pango_win32_font_cache_load ##### -->
+<para>
+
+</para>
+
+@cache:
+@logfont:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_cache_loadw ##### -->
+<para>
+
+</para>
+
+@cache:
+@logfont:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_cache_unload ##### -->
+<para>
+
+</para>
+
+@cache:
+@hfont:
+
+
+<!-- ##### FUNCTION pango_win32_font_map_for_display ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_shutdown_display ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION pango_win32_font_map_get_font_cache ##### -->
+<para>
+
+</para>
+
+@font_map:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_logfont ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_logfontw ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_description_from_logfont ##### -->
+<para>
+
+</para>
+
+@lfp:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_win32_font_description_from_logfontw ##### -->
+<para>
+
+</para>
+
+@lfp:
+@Returns:
+
+
diff --git a/trunk/docs/tmpl/x-fonts.sgml b/trunk/docs/tmpl/x-fonts.sgml
new file mode 100644
index 00000000..ca76af76
--- /dev/null
+++ b/trunk/docs/tmpl/x-fonts.sgml
@@ -0,0 +1,313 @@
+<!-- ##### SECTION Title ##### -->
+Deprecated X font backend
+
+<!-- ##### SECTION Short_Description ##### -->
+Font handling and rendering with the deprecated X font backend
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The functions and macros in this section are for use with the old
+X font backend which used server-side bitmap fonts. This font backend
+is no longer supported, and attempts to use it will produce
+unpredictable results. Use the <link linkend="pango-Xft-Fonts-and-Rendering">Xft</link>
+or <link linkend="pango-Cairo-Rendering">Cairo</link> backend instead.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### MACRO PANGO_RENDER_TYPE_X ##### -->
+<para>
+A string constant identifying the X renderer. The associated quark (see
+g_quark_from_string()) is used to identify the renderer in pango_find_map().
+</para>
+
+
+
+<!-- ##### FUNCTION pango_x_get_context ##### -->
+<para>
+
+</para>
+
+@display:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_context_set_funcs ##### -->
+<para>
+
+</para>
+
+@context:
+@get_gc_func:
+@free_gc_func:
+
+
+<!-- ##### USER_FUNCTION PangoGetGCFunc ##### -->
+<para>
+Specifies the type of the function used to create a new GC for a given
+color.
+</para>
+
+@context: a #PangoContext.
+@color: the color to create a new GC for.
+@base_gc: the GC to base the new GC on.
+@Returns: the new GC.
+
+
+<!-- ##### USER_FUNCTION PangoFreeGCFunc ##### -->
+<para>
+Specifies the type of the function used to free a GC created with
+the corresponding #PangoGetGCFunc function.
+</para>
+
+@context: a #PangoContext.
+@gc: the GC to free.
+
+
+<!-- ##### FUNCTION pango_x_render ##### -->
+<para>
+
+</para>
+
+@display:
+@d:
+@gc:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_x_render_layout_line ##### -->
+<para>
+
+</para>
+
+@display:
+@drawable:
+@gc:
+@line:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_x_render_layout ##### -->
+<para>
+
+</para>
+
+@display:
+@drawable:
+@gc:
+@layout:
+@x:
+@y:
+
+
+<!-- ##### TYPEDEF PangoXSubfont ##### -->
+<para>
+The #PangoXSubFont type is an integer ID that identifies one
+particular X font within the fonts referenced in a #PangoFont.
+</para>
+
+
+<!-- ##### MACRO PANGO_X_MAKE_GLYPH ##### -->
+<para>
+Make a glyph index from a #PangoXSubFont index and a index
+of a character with the corresponding X font.
+</para>
+
+@subfont: a #PangoXSubfont index
+@index_: the index of a character within an X font.
+
+
+<!-- ##### MACRO PANGO_X_GLYPH_SUBFONT ##### -->
+<para>
+Extract the subfont index from a glyph index.
+</para>
+
+@glyph: a #PangoGlyphIndex
+
+
+<!-- ##### MACRO PANGO_X_GLYPH_INDEX ##### -->
+<para>
+Extract the character index within the X font from a
+glyph index.
+</para>
+
+@glyph: a #PangoGlyphIndex
+
+
+<!-- ##### FUNCTION pango_x_load_font ##### -->
+<para>
+
+</para>
+
+@display:
+@spec:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_get_unknown_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_has_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@glyph:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_list_subfonts ##### -->
+<para>
+
+</para>
+
+@font:
+@charsets:
+@n_charsets:
+@subfont_ids:
+@subfont_charsets:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_font_map_for_display ##### -->
+<para>
+
+</para>
+
+@display:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_shutdown_display ##### -->
+<para>
+
+</para>
+
+@display:
+
+
+<!-- ##### FUNCTION pango_x_font_map_get_font_cache ##### -->
+<para>
+
+</para>
+
+@font_map:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_font_subfont_xlfd ##### -->
+<para>
+
+</para>
+
+@font:
+@subfont_id:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_find_first_subfont ##### -->
+<para>
+
+</para>
+
+@font:
+@charsets:
+@n_charsets:
+@rfont:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_font_get_unknown_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_apply_ligatures ##### -->
+<para>
+
+</para>
+
+@font:
+@subfont:
+@glyphs:
+@n_glyphs:
+@clusters:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_fallback_shape ##### -->
+<para>
+
+</para>
+
+@font:
+@glyphs:
+@text:
+@n_chars:
+
+
+<!-- ##### STRUCT PangoXFontCache ##### -->
+<para>
+A #PangoXFontCache caches
+<type>XFontStructs</type> for a single display by their XLFD name.
+</para>
+
+
+<!-- ##### FUNCTION pango_x_font_cache_new ##### -->
+<para>
+
+</para>
+
+@display:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_font_cache_free ##### -->
+<para>
+
+</para>
+
+@cache:
+
+
+<!-- ##### FUNCTION pango_x_font_cache_load ##### -->
+<para>
+
+</para>
+
+@cache:
+@xlfd:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_x_font_cache_unload ##### -->
+<para>
+
+</para>
+
+@cache:
+@fs:
+
+
diff --git a/trunk/docs/tmpl/xft-fonts.sgml b/trunk/docs/tmpl/xft-fonts.sgml
new file mode 100644
index 00000000..76e755ab
--- /dev/null
+++ b/trunk/docs/tmpl/xft-fonts.sgml
@@ -0,0 +1,308 @@
+<!-- ##### SECTION Title ##### -->
+Xft Fonts and Rendering
+
+<!-- ##### SECTION Short_Description ##### -->
+Font handling and rendering with the Xft backend
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The Xft library is a library for displaying fonts on the X window
+system; internally it uses the fontconfig library to locate font
+files, and the FreeType library to load and render fonts. The
+Xft backend is the recommended Pango font backend for screen
+display with X. (The <link linkend="pango-Cairo-Rendering">Cairo back end</link> is another possibility.)
+</para>
+<para>
+Using the Xft backend is generally straightforward;
+pango_xft_get_context() creates a context for a specified display
+and screen. You can then create a #PangoLayout with that context
+and render it with pango_xft_render_layout(). At a more advanced
+level, the low-level fontconfig options used for rendering fonts
+can be affected using pango_xft_set_default_substitute(), and
+pango_xft_substitute_changed().
+</para>
+<para>
+A range of functions for drawing pieces of a layout, such as
+individual layout lines and glyphs strings are provided. You can also
+directly create a #PangoXftRenderer. Finally, in some advanced cases, it
+is useful to derive from #PangoXftRenderer. Deriving from
+#PangoXftRenderer is useful for two reasons. One reason is be to
+support custom attributes by overriding #PangoRendererClass virtual
+functions like 'prepare_run' or 'draw_shape'. The reason is to
+customize exactly how the final bits are drawn to the destination by
+overriding the #PangoXftRendererClass virtual functions
+'composite_glyphs' and 'composite_trapezoids'.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PangoXftFont ##### -->
+<para>
+#PangoXftFont is an implementation of #PangoFcFont using the Xft
+library for rendering. It is used in conjunction with #PangoXftFontMap.
+</para>
+
+
+<!-- ##### STRUCT PangoXftFontMap ##### -->
+<para>
+#PangoXftFontMap is an implementation of #PangoFcFontMap suitable for
+the Xft library as the renderer. It is used in to create fonts of
+type #PangoXftFont.
+</para>
+
+
+<!-- ##### MACRO PANGO_RENDER_TYPE_XFT ##### -->
+<para>
+A string constant that was used to identify shape engines that work
+with the Xft backend. See %PANGO_RENDER_TYPE_FC for the replacement.
+</para>
+
+
+
+<!-- ##### FUNCTION pango_xft_get_context ##### -->
+<para>
+
+</para>
+
+@display:
+@screen:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_xft_get_font_map ##### -->
+<para>
+
+</para>
+
+@display:
+@screen:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_xft_set_default_substitute ##### -->
+<para>
+
+</para>
+
+@display:
+@screen:
+@func:
+@data:
+@notify:
+
+
+<!-- ##### USER_FUNCTION PangoXftSubstituteFunc ##### -->
+<para>
+Function type for doing final config tweaking on prepared FcPatterns.
+</para>
+
+@pattern: the FcPattern to tweak.
+@data: user data.
+
+
+<!-- ##### FUNCTION pango_xft_substitute_changed ##### -->
+<para>
+
+</para>
+
+@display:
+@screen:
+
+
+<!-- ##### FUNCTION pango_xft_shutdown_display ##### -->
+<para>
+
+</para>
+
+@display:
+@screen:
+
+
+<!-- ##### FUNCTION pango_xft_font_get_font ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_xft_font_get_display ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_xft_font_has_char ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_xft_font_lock_face ##### -->
+<para>
+
+</para>
+
+@font:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_xft_font_unlock_face ##### -->
+<para>
+
+</para>
+
+@font:
+
+
+<!-- ##### FUNCTION pango_xft_font_get_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_xft_font_get_unknown_glyph ##### -->
+<para>
+
+</para>
+
+@font:
+@wc:
+@Returns:
+
+
+<!-- ##### STRUCT PangoXftRenderer ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG PangoXftRenderer:display ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG PangoXftRenderer:screen ##### -->
+<para>
+
+</para>
+
+<!-- ##### STRUCT PangoXftRendererClass ##### -->
+<para>
+
+</para>
+
+@composite_trapezoids:
+@composite_glyphs:
+
+<!-- ##### FUNCTION pango_xft_renderer_new ##### -->
+<para>
+
+</para>
+
+@display:
+@screen:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_xft_renderer_set_draw ##### -->
+<para>
+
+</para>
+
+@xftrenderer:
+@draw:
+
+
+<!-- ##### FUNCTION pango_xft_renderer_set_default_color ##### -->
+<para>
+
+</para>
+
+@xftrenderer:
+@default_color:
+
+
+<!-- ##### FUNCTION pango_xft_render ##### -->
+<para>
+
+</para>
+
+@draw:
+@color:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_xft_picture_render ##### -->
+<para>
+
+</para>
+
+@display:
+@src_picture:
+@dest_picture:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_xft_render_transformed ##### -->
+<para>
+
+</para>
+
+@draw:
+@color:
+@matrix:
+@font:
+@glyphs:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_xft_render_layout_line ##### -->
+<para>
+
+</para>
+
+@draw:
+@color:
+@line:
+@x:
+@y:
+
+
+<!-- ##### FUNCTION pango_xft_render_layout ##### -->
+<para>
+
+</para>
+
+@draw:
+@color:
+@layout:
+@x:
+@y:
+
+
diff --git a/trunk/docs/version.xml.in b/trunk/docs/version.xml.in
new file mode 100644
index 00000000..8f556477
--- /dev/null
+++ b/trunk/docs/version.xml.in
@@ -0,0 +1 @@
+@PANGO_VERSION@
diff --git a/trunk/examples/Makefile.am b/trunk/examples/Makefile.am
new file mode 100644
index 00000000..12ff04c3
--- /dev/null
+++ b/trunk/examples/Makefile.am
@@ -0,0 +1,31 @@
+## Process this file with automake to create Makefile.in.
+
+EXTRA_DIST = \
+ pangowin32tobmp.c
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(PANGO_DEBUG_FLAGS) \
+ $(GLIB_CFLAGS) \
+ $(XFT_CFLAGS) \
+ $(CAIRO_CFLAGS) \
+ $(FREETYPE_CFLAGS) \
+ $(X_CFLAGS)
+
+noinst_PROGRAMS =
+
+if HAVE_CAIRO_PNG
+noinst_PROGRAMS += cairosimple cairotwisted cairoshape
+
+cairosimple_LDADD = \
+ ../pango/libpango-$(PANGO_API_VERSION).la \
+ ../pango/libpangocairo-$(PANGO_API_VERSION).la \
+ $(GLIB_LIBS) \
+ $(CAIRO_LIBS)
+if HAVE_FREETYPE
+cairosimple_LDADD += \
+ ../pango/libpangoft2-$(PANGO_API_VERSION).la
+endif
+cairotwisted_LDADD = $(cairosimple_LDADD)
+cairoshape_LDADD = $(cairosimple_LDADD)
+endif
diff --git a/trunk/examples/cairoshape.c b/trunk/examples/cairoshape.c
new file mode 100644
index 00000000..addde87e
--- /dev/null
+++ b/trunk/examples/cairoshape.c
@@ -0,0 +1,209 @@
+/* example to use pangocairo to render arbitrary shapes inside a text layout */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <pango/pangocairo.h>
+
+#define BULLET "•"
+
+const char text[] =
+"The GNOME project provides two things:\n"
+"\n"
+" • The GNOME desktop environment\n"
+" • The GNOME development platform\n"
+" • Planet GNOME";
+
+typedef struct {
+ double width, height;
+ const char *path;
+} MiniSvg;
+
+static MiniSvg GnomeFootLogo = {
+ 96.2152, 118.26,
+ "M 86.068,1 C 61.466,0 56.851,35.041 70.691,35.041 C 84.529,35.041 110.671,0 86.068,0 z "
+ "M 45.217,30.699 C 52.586,31.149 60.671,2.577 46.821,4.374 C 32.976,6.171 37.845,30.249 45.217,30.699 z "
+ "M 11.445,48.453 C 16.686,46.146 12.12,23.581 3.208,29.735 C -5.7,35.89 6.204,50.759 11.445,48.453 z "
+ "M 26.212,36.642 C 32.451,35.37 32.793,9.778 21.667,14.369 C 10.539,18.961 19.978,37.916 26.212,36.642 L 26.212,36.642 z "
+ "M 58.791,93.913 C 59.898,102.367 52.589,106.542 45.431,101.092 C 22.644,83.743 83.16,75.088 79.171,51.386 C 75.86,31.712 15.495,37.769 8.621,68.553 C 3.968,89.374 27.774,118.26 52.614,118.26 C 64.834,118.26 78.929,107.226 81.566,93.248 C 83.58,82.589 57.867,86.86 58.791,93.913 L 58.791,93.913 z "
+ "\0"
+};
+
+static void
+mini_svg_render (MiniSvg *shape,
+ cairo_t *cr,
+ gboolean do_path)
+{
+ double x, y;
+ const char *p;
+ char op[2];
+ int items, len;
+
+ cairo_get_current_point (cr, &x, &y);
+ cairo_translate (cr, x, y);
+
+ for (p = shape->path; (items = sscanf (p, "%1s %n", op, &len)), p += len, *p;)
+ switch (*op)
+ {
+ case 'M':
+ {
+ sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len;
+ cairo_move_to (cr, x, y);
+ break;
+ }
+ case 'L':
+ {
+ sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len;
+ cairo_line_to (cr, x, y);
+ break;
+ }
+ case 'C':
+ {
+ double x1, y1, x2, y2, x3, y3;
+ sscanf (p, "%lf,%lf %lf,%lf %lf,%lf %n", &x1, &y1, &x2, &y2, &x3, &y3, &len); p += len;
+ cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
+ break;
+ }
+ case 'z':
+ {
+ cairo_close_path (cr);
+ break;
+ }
+ default:
+ {
+ g_warning ("Invalid MiniSvg operation '%c'", *op);
+ break;
+ }
+ }
+
+ if (!do_path)
+ cairo_fill (cr);
+}
+
+static void
+mini_svg_shape_renderer (cairo_t *cr,
+ PangoAttrShape *attr,
+ gboolean do_path,
+ gpointer data)
+{
+ MiniSvg *shape = (MiniSvg *) attr->data;
+ double scale_x, scale_y;
+
+ scale_x = (double) attr->ink_rect.width / (PANGO_SCALE * shape->width );
+ scale_y = (double) attr->ink_rect.height / (PANGO_SCALE * shape->height);
+
+ cairo_rel_move_to (cr,
+ (double) attr->ink_rect.x / PANGO_SCALE,
+ (double) attr->ink_rect.y / PANGO_SCALE);
+ cairo_scale (cr, scale_x, scale_y);
+
+ mini_svg_render (shape, cr, do_path);
+}
+
+
+static PangoLayout *
+get_layout (cairo_t *cr)
+{
+ PangoLayout *layout;
+ PangoAttrList *attrs;
+ PangoRectangle ink_rect = {1 * PANGO_SCALE, -11 * PANGO_SCALE, 8 * PANGO_SCALE, 10 * PANGO_SCALE};
+ PangoRectangle logical_rect = {0 * PANGO_SCALE, -12 * PANGO_SCALE, 10 * PANGO_SCALE, 12 * PANGO_SCALE};
+ const char *p;
+
+ /* Create a PangoLayout, set the font and text */
+ layout = pango_cairo_create_layout (cr);
+
+ pango_cairo_context_set_shape_renderer (pango_layout_get_context (layout),
+ mini_svg_shape_renderer, NULL, NULL);
+
+ pango_layout_set_text (layout, text, -1);
+
+ attrs = pango_attr_list_new ();
+
+ /* set gnome shape attributes for bullets */
+ for (p = text; (p = strstr (p, BULLET)); p += strlen (BULLET))
+ {
+ PangoAttribute *attr;
+
+ attr = pango_attr_shape_new_with_data (&ink_rect,
+ &logical_rect,
+ &GnomeFootLogo,
+ NULL, NULL);
+
+ attr->start_index = p - text;
+ attr->end_index = attr->start_index + strlen (BULLET);
+
+ pango_attr_list_insert (attrs, attr);
+ }
+
+ pango_layout_set_attributes (layout, attrs);
+ pango_attr_list_unref (attrs);
+
+ return layout;
+}
+
+static void
+draw_text (cairo_t *cr, int *width, int *height)
+{
+
+ PangoLayout *layout = get_layout (cr);
+
+ if (width || height)
+ {
+ pango_layout_get_pixel_size (layout, width, height);
+ if (width)
+ *width += 20;
+ if (height)
+ *height += 20;
+ }
+
+ cairo_move_to (cr, 10, 10);
+ pango_cairo_show_layout (cr, layout);
+
+ g_object_unref (layout);
+}
+
+int main (int argc, char **argv)
+{
+ cairo_t *cr;
+ char *filename;
+ cairo_status_t status;
+ cairo_surface_t *surface;
+ int width, height;
+
+ if (argc != 2)
+ {
+ g_printerr ("Usage: cairoshape OUTPUT_FILENAME\n");
+ return 1;
+ }
+
+ filename = argv[1];
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ 0, 0);
+ cr = cairo_create (surface);
+ draw_text (cr, &width, &height);
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width, height);
+ cr = cairo_create (surface);
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_paint (cr);
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.5);
+ draw_text (cr, NULL, NULL);
+ cairo_destroy (cr);
+
+ status = cairo_surface_write_to_png (surface, filename);
+ cairo_surface_destroy (surface);
+
+ if (status != CAIRO_STATUS_SUCCESS)
+ {
+ g_printerr ("Could not save png to '%s'\n", filename);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/trunk/examples/cairosimple.c b/trunk/examples/cairosimple.c
new file mode 100644
index 00000000..d07f004c
--- /dev/null
+++ b/trunk/examples/cairosimple.c
@@ -0,0 +1,93 @@
+/* simple example to use pangocairo to render rotated text */
+
+#include <math.h>
+#include <pango/pangocairo.h>
+
+static void
+draw_text (cairo_t *cr)
+{
+#define RADIUS 150
+#define N_WORDS 10
+#define FONT "Sans Bold 27"
+
+ PangoLayout *layout;
+ PangoFontDescription *desc;
+ int i;
+
+ /* Center coordinates on the middle of the region we are drawing
+ */
+ cairo_translate (cr, RADIUS, RADIUS);
+
+ /* Create a PangoLayout, set the font and text */
+ layout = pango_cairo_create_layout (cr);
+
+ pango_layout_set_text (layout, "Text", -1);
+ desc = pango_font_description_from_string (FONT);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+
+ /* Draw the layout N_WORDS times in a circle */
+ for (i = 0; i < N_WORDS; i++)
+ {
+ int width, height;
+ double angle = (360. * i) / N_WORDS;
+ double red;
+
+ cairo_save (cr);
+
+ /* Gradient from red at angle == 60 to blue at angle == 240 */
+ red = (1 + cos ((angle - 60) * G_PI / 180.)) / 2;
+ cairo_set_source_rgb (cr, red, 0, 1.0 - red);
+
+ cairo_rotate (cr, angle * G_PI / 180.);
+
+ /* Inform Pango to re-layout the text with the new transformation */
+ pango_cairo_update_layout (cr, layout);
+
+ pango_layout_get_size (layout, &width, &height);
+ cairo_move_to (cr, - ((double)width / PANGO_SCALE) / 2, - RADIUS);
+ pango_cairo_show_layout (cr, layout);
+
+ cairo_restore (cr);
+ }
+
+ /* free the layout object */
+ g_object_unref (layout);
+}
+
+int main (int argc, char **argv)
+{
+ cairo_t *cr;
+ char *filename;
+ cairo_status_t status;
+ cairo_surface_t *surface;
+
+ if (argc != 2)
+ {
+ g_printerr ("Usage: cairosimple OUTPUT_FILENAME\n");
+ return 1;
+ }
+
+ filename = argv[1];
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ 2 * RADIUS, 2 * RADIUS);
+ cr = cairo_create (surface);
+
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_paint (cr);
+ draw_text (cr);
+ cairo_destroy (cr);
+
+ status = cairo_surface_write_to_png (surface, filename);
+ cairo_surface_destroy (surface);
+
+ if (status != CAIRO_STATUS_SUCCESS)
+ {
+ g_printerr ("Could not save png to '%s'\n", filename);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/trunk/examples/cairotwisted.c b/trunk/examples/cairotwisted.c
new file mode 100644
index 00000000..93fa5164
--- /dev/null
+++ b/trunk/examples/cairotwisted.c
@@ -0,0 +1,458 @@
+/* example to use pangocairo to render text projected on a path */
+/* Written by Behdad Esfahbod, 2006. Not copyrighted, in public domain. */
+
+#include <math.h>
+#include <stdlib.h>
+#include <pango/pangocairo.h>
+
+void fancy_cairo_stroke (cairo_t *cr);
+void fancy_cairo_stroke_preserve (cairo_t *cr);
+
+
+static double
+two_points_distance (cairo_path_data_t *a, cairo_path_data_t *b)
+{
+ double dx, dy;
+
+ dx = b->point.x - a->point.x;
+ dy = b->point.y - a->point.y;
+
+ return sqrt (dx * dx + dy * dy);
+}
+
+typedef double parametrization_t;
+
+static parametrization_t *
+parametrize_path (cairo_path_t *path)
+{
+ int i;
+ cairo_path_data_t *data, current_point;
+ parametrization_t *parametrization;
+
+ parametrization = malloc (path->num_data * sizeof (parametrization[0]));
+
+ for (i=0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ parametrization[i] = 0.0;
+ switch (data->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ current_point = data[1];
+ break;
+ case CAIRO_PATH_LINE_TO:
+ parametrization[i] = two_points_distance (&current_point, &data[1]);
+ current_point = data[1];
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ /*
+ parametrization[i] = curve_length (current_point.point.x, current_point.point.x,
+ data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
+ */
+ parametrization[i] = two_points_distance (&current_point, &data[1]);
+ parametrization[i] += two_points_distance (&data[1], &data[2]);
+ parametrization[i] += two_points_distance (&data[2], &data[3]);
+
+ current_point = data[3];
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ break;
+ }
+ }
+
+ return parametrization;
+}
+
+static void
+_fancy_cairo_stroke (cairo_t *cr, cairo_bool_t preserve)
+{
+ int i;
+ double line_width;
+ cairo_path_t *path;
+ cairo_path_data_t *data;
+ const double dash[] = {10, 10};
+
+ cairo_save (cr);
+ cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
+
+ line_width = cairo_get_line_width (cr);
+ path = cairo_copy_path (cr);
+ cairo_new_path (cr);
+
+ cairo_save (cr);
+ cairo_set_line_width (cr, line_width / 3);
+ cairo_set_dash (cr, dash, G_N_ELEMENTS (dash), 0);
+ for (i=0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ switch (data->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ case CAIRO_PATH_LINE_TO:
+ cairo_move_to (cr, data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ cairo_line_to (cr, data[1].point.x, data[1].point.y);
+ cairo_move_to (cr, data[2].point.x, data[2].point.y);
+ cairo_line_to (cr, data[3].point.x, data[3].point.y);
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ break;
+ }
+ }
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ cairo_save (cr);
+ cairo_set_line_width (cr, line_width * 4);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ for (i=0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ switch (data->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ cairo_move_to (cr, data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_LINE_TO:
+ cairo_rel_line_to (cr, 0, 0);
+ cairo_move_to (cr, data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ cairo_rel_line_to (cr, 0, 0);
+ cairo_move_to (cr, data[1].point.x, data[1].point.y);
+ cairo_rel_line_to (cr, 0, 0);
+ cairo_move_to (cr, data[2].point.x, data[2].point.y);
+ cairo_rel_line_to (cr, 0, 0);
+ cairo_move_to (cr, data[3].point.x, data[3].point.y);
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ cairo_rel_line_to (cr, 0, 0);
+ break;
+ }
+ }
+ cairo_rel_line_to (cr, 0, 0);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ for (i=0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ switch (data->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ cairo_move_to (cr, data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_LINE_TO:
+ cairo_line_to (cr, data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ cairo_curve_to (cr, data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ cairo_close_path (cr);
+ break;
+ }
+ }
+ cairo_stroke (cr);
+
+ if (preserve)
+ cairo_append_path (cr, path);
+
+ cairo_path_destroy (path);
+
+ cairo_restore (cr);
+}
+
+void
+fancy_cairo_stroke (cairo_t *cr)
+{
+ _fancy_cairo_stroke (cr, FALSE);
+}
+
+void
+fancy_cairo_stroke_preserve (cairo_t *cr)
+{
+ _fancy_cairo_stroke (cr, TRUE);
+}
+
+typedef void (*transform_point_func_t) (void *closure, double *x, double *y);
+
+static void
+transform_path (cairo_path_t *path, transform_point_func_t f, void *closure)
+{
+ int i;
+ cairo_path_data_t *data;
+
+ for (i=0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ switch (data->header.type) {
+ case CAIRO_PATH_CURVE_TO:
+ f (closure, &data[3].point.x, &data[3].point.y);
+ f (closure, &data[2].point.x, &data[2].point.y);
+ case CAIRO_PATH_MOVE_TO:
+ case CAIRO_PATH_LINE_TO:
+ f (closure, &data[1].point.x, &data[1].point.y);
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ break;
+ }
+ }
+}
+
+typedef struct {
+ cairo_path_t *path;
+ parametrization_t *parametrization;
+} parametrized_path_t;
+
+static void
+point_on_path (parametrized_path_t *param,
+ double *x, double *y)
+{
+ int i;
+ double ratio, oldy = *y, d = *x, dx, dy;
+ cairo_path_data_t *data, current_point;
+ cairo_path_t *path = param->path;
+ parametrization_t *parametrization = param->parametrization;
+
+ for (i=0; i + path->data[i].header.length < path->num_data &&
+ (d > parametrization[i] ||
+ path->data[i].header.type == CAIRO_PATH_MOVE_TO);
+ i += path->data[i].header.length) {
+ d -= parametrization[i];
+ data = &path->data[i];
+ switch (data->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ current_point = data[1];
+ break;
+ case CAIRO_PATH_LINE_TO:
+ current_point = data[1];
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ current_point = data[3];
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ break;
+ }
+ }
+ data = &path->data[i];
+
+ switch (data->header.type) {
+
+ case CAIRO_PATH_MOVE_TO:
+ break;
+ case CAIRO_PATH_LINE_TO:
+ ratio = d / parametrization[i];
+ *x = current_point.point.x * (1 - ratio) + data[1].point.x * ratio;
+ *y = current_point.point.y * (1 - ratio) + data[1].point.y * ratio;
+
+ dx = -(current_point.point.x - data[1].point.x);
+ dy = -(current_point.point.y - data[1].point.y);
+
+ d = oldy;
+ ratio = d / parametrization[i];
+ /*ratio = d / sqrt (dx * dx + dy * dy);*/
+
+ *x += -dy * ratio;
+ *y += dx * ratio;
+
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ ratio = d / parametrization[i];
+ *x = current_point.point.x * (1 - ratio) * (1 - ratio) * (1 - ratio)
+ + 3 * data[1].point.x * (1 - ratio) * (1 - ratio) * ratio
+ + 3 * data[2].point.x * (1 - ratio) * ratio * ratio
+ + data[3].point.x * ratio * ratio * ratio;
+ *y = current_point.point.y * (1 - ratio) * (1 - ratio) * (1 - ratio)
+ + 3 * data[1].point.y * (1 - ratio) * (1 - ratio) * ratio
+ + 3 * data[2].point.y * (1 - ratio) * ratio * ratio
+ + data[3].point.y * ratio * ratio * ratio;
+
+ dx =-3 * current_point.point.x * (1 - ratio) * (1 - ratio)
+ + 3 * data[1].point.x * (1 - 4 * ratio + 3 * ratio * ratio)
+ + 3 * data[2].point.x * ( 2 * ratio - 3 * ratio * ratio)
+ + 3 * data[3].point.x * ratio * ratio;
+ dy =-3 * current_point.point.y * (1 - ratio) * (1 - ratio)
+ + 3 * data[1].point.y * (1 - 4 * ratio + 3 * ratio * ratio)
+ + 3 * data[2].point.y * ( 2 * ratio - 3 * ratio * ratio)
+ + 3 * data[3].point.y * ratio * ratio;
+
+ d = oldy;
+ ratio = d / sqrt (dx * dx + dy * dy);
+
+ *x += -dy * ratio;
+ *y += dx * ratio;
+
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ break;
+ }
+}
+
+static void
+map_path_onto (cairo_t *cr, cairo_path_t *path)
+{
+ cairo_path_t *current_path;
+ parametrized_path_t param;
+
+ param.path = path;
+ param.parametrization = parametrize_path (path);
+
+ current_path = cairo_copy_path (cr);
+ cairo_new_path (cr);
+
+ transform_path (current_path,
+ (transform_point_func_t) point_on_path, &param);
+
+ cairo_append_path (cr, current_path);
+}
+
+
+typedef void (*draw_path_func_t) (cairo_t *cr);
+
+static void
+draw_text (cairo_t *cr,
+ double x,
+ double y,
+ const char *font,
+ const char *text)
+{
+ PangoLayout *layout;
+ PangoLayoutLine *line;
+ PangoFontDescription *desc;
+ cairo_font_options_t *font_options;
+
+ font_options = cairo_font_options_create ();
+
+ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
+
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ layout = pango_cairo_create_layout (cr);
+
+ desc = pango_font_description_from_string (font);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+
+ pango_layout_set_text (layout, text, -1);
+
+ /* Use pango_layout_get_line() instead of pango_layout_get_line_readonly()
+ * for older versions of pango
+ */
+ line = pango_layout_get_line_readonly (layout, 0);
+
+ cairo_move_to (cr, x, y);
+ pango_cairo_layout_line_path (cr, line);
+
+ g_object_unref (layout);
+}
+
+static void
+draw_twisted (cairo_t *cr,
+ double x,
+ double y,
+ const char *font,
+ const char *text)
+{
+ cairo_path_t *path;
+
+ cairo_save (cr);
+
+ /* Decrease tolerance a bit, since it's going to be magnified */
+ cairo_set_tolerance (cr, 0.05);
+
+ path = cairo_copy_path_flat (cr);
+ /*path = cairo_copy_path (cr);*/
+
+ cairo_new_path (cr);
+
+ draw_text (cr, x, y, font, text);
+ map_path_onto (cr, path);
+
+ cairo_fill_preserve (cr);
+
+ cairo_save (cr);
+ cairo_set_source_rgb (cr, 0.1, 0.1, 0.1);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ cairo_restore (cr);
+}
+
+static void
+draw_dream (cairo_t *cr)
+{
+ cairo_move_to (cr, 50, 650);
+
+ cairo_rel_line_to (cr, 250, 50);
+ cairo_rel_curve_to (cr, 250, 50, 600, -50, 600, -250);
+ cairo_rel_curve_to (cr, 0, -400, -300, -100, -800, -300);
+
+ cairo_set_line_width (cr, 1.5);
+ cairo_set_source_rgba (cr, 0.3, 0.3, 1.0, 0.3);
+
+ fancy_cairo_stroke_preserve (cr);
+
+ draw_twisted (cr,
+ 0, 0,
+ "Serif 72",
+ "It was a dream... Oh Just a dream...");
+}
+
+static void
+draw_wow (cairo_t *cr)
+{
+ cairo_move_to (cr, 400, 780);
+
+ cairo_rel_curve_to (cr, 50, -50, 150, -50, 200, 0);
+
+ cairo_scale (cr, 1.0, 2.0);
+ cairo_set_line_width (cr, 2.0);
+ cairo_set_source_rgba (cr, 0.3, 1.0, 0.3, 1.0);
+
+ fancy_cairo_stroke_preserve (cr);
+
+ draw_twisted (cr,
+ -20, -150,
+ "Serif 60",
+ "WOW!");
+}
+
+int main (int argc, char **argv)
+{
+ cairo_t *cr;
+ char *filename;
+ cairo_status_t status;
+ cairo_surface_t *surface;
+
+ if (argc != 2)
+ {
+ g_printerr ("Usage: cairotwisted OUTPUT_FILENAME\n");
+ return 1;
+ }
+
+ filename = argv[1];
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ 1000, 800);
+ cr = cairo_create (surface);
+
+ /* cairo_scale (cr, 0.5, 0.5); */
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_paint (cr);
+
+ draw_dream (cr);
+ draw_wow (cr);
+
+ cairo_destroy (cr);
+
+ status = cairo_surface_write_to_png (surface, filename);
+ cairo_surface_destroy (surface);
+
+ if (status != CAIRO_STATUS_SUCCESS)
+ {
+ g_printerr ("Could not save png to '%s'\n", filename);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/trunk/examples/pangowin32tobmp.c b/trunk/examples/pangowin32tobmp.c
new file mode 100644
index 00000000..19ef392d
--- /dev/null
+++ b/trunk/examples/pangowin32tobmp.c
@@ -0,0 +1,450 @@
+/* Pango
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * testfonts.c:
+ * Copyright (C) 2001 Hans Breuer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <stdlib.h>
+#include <gmodule.h>
+#include "pango.h"
+#include "pango-impl-utils.h"
+#include "pangowin32.h"
+
+
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <locale.h>
+
+#include <windows.h>
+
+static HDC pre_render (int width, int height);
+static void post_render (HDC hdc, const char* sFile);
+
+static float
+calc_duration (GTimeVal *tv1, GTimeVal *tv0)
+{
+ return ( ((float)tv1->tv_sec - tv0->tv_sec)
+ + (tv1->tv_usec - tv0->tv_usec) / 1000000.0);
+}
+
+static int
+compare_font_family (PangoFontFamily** a,
+ PangoFontFamily** b)
+{
+ return strcmp (pango_font_family_get_name (*a), pango_font_family_get_name (*b));
+}
+
+int main (int argc, char **argv)
+{
+ PangoFontMap *fontmap = pango_win32_font_map_for_display();
+ PangoContext *context;
+ PangoCoverage * coverage = NULL;
+ PangoFont* font = NULL;
+ PangoFontFamily** families = NULL;
+ PangoFontFace** faces = NULL;
+ int nb, i;
+ gchar* family_name = NULL;
+ PangoLanguage *lang = pango_language_from_string (g_win32_getlocale ());
+ HDC hdc = NULL;
+ int line = 0;
+ GTimeVal tv0, tv1;
+ int my_font_size = 12;
+
+ printf ("# Pango Font Test\n"
+ "# Language: %s\n"
+ "#\n", pango_language_to_string (lang));
+
+ /* this wasn't necessary with previous version
+ *
+ * force initialization of built-in engines, otherwise
+ * the rendering get's really fast - too fast to work :-(
+ */
+ context = pango_win32_get_context ();
+
+ if (argc == 1) /* No arguments given */
+ {
+ char *std_fonts[] = {"Sans 12", "Serif 12", "Monospace 12"};
+
+ /* try to load some fonts often hardcoded */
+ for (i = 0; i < G_N_ELEMENTS (std_fonts); i++)
+ {
+ PangoFontDescription *desc = pango_font_description_from_string(std_fonts[i]);
+
+ /* spits warnings if font cannot be loaded */
+ font = pango_font_map_load_font (fontmap, context, desc);
+
+ g_object_unref (font);
+ }
+ }
+ else
+ {
+ PangoFontDescription *desc = NULL;
+ GString *s;
+
+ s = g_string_new (argv[1]);
+ for (i = 2; i < argc; i++)
+ {
+ s = g_string_append_c (s, ' ');
+ s = g_string_append (s, argv[i]);
+
+ if (0 != atoi (argv[i]))
+ my_font_size = atoi (argv[i]);
+ }
+
+ desc = pango_font_description_from_string(s->str);
+ family_name = g_strdup (pango_font_description_get_family (desc));
+
+ font = pango_font_map_load_font (fontmap, context, desc);
+
+ coverage = pango_font_get_coverage (font, lang);
+
+ /* ... */
+
+ pango_coverage_unref (coverage);
+ pango_font_description_free (desc);
+ g_object_unref (font);
+ }
+
+ pango_font_map_list_families (fontmap, &families, &nb);
+
+ if (!family_name)
+ {
+ qsort (families, nb, sizeof (PangoFontFamily*), compare_font_family);
+ }
+ else
+ {
+ /* Get on the family faces. No simple way ? */
+ for (i = 0; i < nb; i++)
+ {
+ if (0 == g_ascii_strcasecmp (pango_font_family_get_name (families[i]), family_name))
+ {
+ pango_font_family_list_faces (families[i], &faces, &nb);
+ /* now nb is the number of faces */
+ break;
+ }
+ }
+ g_free (families);
+ families = NULL;
+ g_free (family_name);
+ family_name = NULL;
+ }
+
+ hdc = pre_render(my_font_size * 64, 3 * my_font_size * nb / 2);
+
+ for (i = 0; i < nb; i++)
+ {
+ PangoFontDescription *desc;
+ const char *f_name;
+ PangoWeight weight;
+ PangoStyle style;
+
+ if (families)
+ {
+ desc = pango_font_description_new ();
+
+ f_name = pango_font_family_get_name (families[i]);
+ pango_font_description_set_family (desc, f_name);
+ }
+ else
+ {
+ desc = pango_font_face_describe (faces[i]);
+ /* this is _not_ the family name from above */
+ f_name = pango_font_description_get_family (desc);
+ }
+ weight = pango_font_description_get_weight (desc);
+ style = pango_font_description_get_style (desc);
+
+ g_print ("%s; Style: %d; Weight: %d\n",
+ f_name, style, weight);
+
+ /* give it an arbitray size to load it */
+ pango_font_description_set_size (desc, my_font_size * PANGO_SCALE);
+
+ g_get_current_time (&tv0);
+ font = pango_font_map_load_font (fontmap, context, desc);
+ g_get_current_time (&tv1);
+ g_print ("\tpango_font_map_load_font took %.3f sec\n", calc_duration (&tv1, &tv0));
+
+ if (font)
+ {
+ PangoItem *item;
+ PangoGlyphString * glyphs;
+ char s[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "1234567890 -+*/!\xc2\xa7$%&()[]{}<>|#=?@";
+
+ g_get_current_time (&tv0);
+ coverage = pango_font_get_coverage (font, lang);
+ g_get_current_time (&tv1);
+ g_print ("\tpango_font_get_coverage took %.3f sec\n", calc_duration (&tv1, &tv0));
+
+ /* ... */
+ pango_context_set_language (context, lang);
+ pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
+ pango_context_set_font_description (context, desc);
+
+ glyphs = pango_glyph_string_new ();
+ item = pango_item_new ();
+
+ item->analysis.shape_engine = pango_font_find_shaper (font, lang, s[0]);
+ item->analysis.font = g_object_ref (font);
+ pango_shape ( s, sizeof(s), &(item->analysis), glyphs);
+
+ if (hdc)
+ {
+ /* the positioning isn't correct */
+ char* name = g_strdup_printf ("%s (%s%s)",
+ f_name,
+ weight == PANGO_WEIGHT_NORMAL ? "n" :
+ (weight == PANGO_WEIGHT_HEAVY ? "h" :
+ (weight > PANGO_WEIGHT_NORMAL ? "b" : "l")),
+ style == PANGO_STYLE_OBLIQUE ? "o" :
+ (style == PANGO_STYLE_ITALIC ? "i" : "n"));
+
+ TextOut (hdc, 0, line, name, strlen(name));
+ g_get_current_time (&tv0);
+ pango_win32_render (hdc, font, glyphs, 200, line);
+ g_get_current_time (&tv1);
+ g_print ("\tpango_win32_render took %.3f sec\n",
+ calc_duration (&tv1, &tv0));
+ line += (3 * my_font_size / 2);
+ g_free(name);
+ }
+
+ /* free glyphs, ... */
+ pango_glyph_string_free (glyphs);
+ pango_item_free (item);
+
+ pango_coverage_unref (coverage);
+ g_object_unref (font);
+ }
+ pango_font_description_free (desc);
+ }
+
+ if (hdc)
+ post_render (hdc, "pango-fonts.bmp");
+
+ g_free (families);
+ g_free (faces);
+
+ return 0;
+}
+
+/*
+ * Real Win32 specific render support
+ */
+static HBITMAP hbmpold = NULL;
+static HWND hwndRender = NULL;
+
+static BOOL
+SaveBitmap (HBITMAP hBmp, const char* pszFile);
+
+static HDC
+pre_render (int width, int height)
+{
+ HDC hmemdc;
+ HDC hdc;
+ HBITMAP hbmp;
+ RECT r;
+ r.top = 0; r.left = 0;
+ r.right = width;
+ r.bottom = height;
+
+ hwndRender = CreateWindow ("EDIT",
+ "pango-render-window",
+ WS_DISABLED,
+ 0, 0, width, height,
+ GetDesktopWindow(),
+ NULL,
+ GetModuleHandle(NULL),
+ NULL);
+
+ if (hwndRender == NULL)
+ fprintf (stderr, "Couldn't create window\n"), exit (1);
+
+ hdc = GetDC(hwndRender);
+ hmemdc = CreateCompatibleDC (hdc);
+ if (hdc == NULL)
+ fprintf (stderr, "CreateCompatibleDC failed\n"), exit (1);
+
+ hbmp = CreateCompatibleBitmap (hdc, width, height);
+ if (hbmp == NULL)
+ fprintf (stderr, "CreateCompatibleBitmap failed\n"), exit (1);
+
+ hbmpold = SelectObject(hmemdc, hbmp);
+
+ FillRect (hmemdc, &r, GetStockObject(WHITE_BRUSH));
+ SetTextColor (hmemdc, RGB (0,0,0));
+ SetBkMode (hmemdc, TRANSPARENT);
+ return hmemdc;
+}
+
+static void
+post_render (HDC hdc, const char* sFile)
+{
+ HBITMAP hbmp = SelectObject(hdc, hbmpold);
+ if (sFile)
+ SaveBitmap (hbmp, sFile);
+ DeleteObject (hbmp);
+ DeleteDC (hdc);
+ ReleaseDC(hwndRender, GetDC(hwndRender));
+ DestroyWindow (hwndRender);
+}
+
+static BOOL
+SaveBitmap (HBITMAP hBmp, const char* pszFile)
+{
+ BITMAP bmp;
+ PBITMAPINFO pbmi;
+ WORD cClrBits;
+ /* Retrieve the bitmap's color format, width, and height. */
+ if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
+ return FALSE;
+ /* Convert the color format to a count of bits. */
+ cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
+ if (cClrBits == 1)
+ cClrBits = 1;
+ else if (cClrBits <= 4)
+ cClrBits = 4;
+ else if (cClrBits <= 8)
+ cClrBits = 8;
+ else if (cClrBits <= 16)
+ cClrBits = 16;
+ else if (cClrBits <= 24)
+ cClrBits = 24;
+ else
+ cClrBits = 32;
+
+ /*
+ * Allocate memory for the BITMAPINFO structure. (This structure
+ * contains a BITMAPINFOHEADER structure and an array of RGBQUAD data
+ * structures.) */
+ if (cClrBits < 24)
+ pbmi = (PBITMAPINFO) GlobalAlloc(LPTR,
+ sizeof(BITMAPINFOHEADER) +
+ sizeof(RGBQUAD) * (1 << cClrBits));
+ /*
+ * There is no RGBQUAD array for the 24-bit-per-pixel format. */
+ else
+ pbmi = (PBITMAPINFO) GlobalAlloc(LPTR,
+ sizeof(BITMAPINFOHEADER));
+ /* Initialize the fields in the BITMAPINFO structure. */
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = bmp.bmWidth;
+ pbmi->bmiHeader.biHeight = bmp.bmHeight;
+ pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
+ pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
+ if (cClrBits < 24)
+ pbmi->bmiHeader.biClrUsed = (1 << cClrBits);
+ else
+ pbmi->bmiHeader.biClrUsed = 0;
+ /* If the bitmap is not compressed, set the BI_RGB flag. */
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ /*
+ * Compute the number of bytes in the array of color
+ * indices and store the result in biSizeImage.
+ */
+ pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
+ * pbmi->bmiHeader.biHeight
+ * cClrBits;
+ /*
+ * Set biClrImportant to 0, indicating that all of the
+ * device colors are important.
+ */
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ { /* C sucks */
+ HANDLE hf; /* file handle */
+ BITMAPFILEHEADER hdr; /* bitmap file-header */
+ PBITMAPINFOHEADER pbih; /* bitmap info-header */
+ LPBYTE lpBits; /* memory pointer */
+ DWORD dwTotal; /* total count of bytes */
+ DWORD cb; /* incremental count of bytes */
+ DWORD dwTmp;
+ HDC hDC;
+
+ pbih = (PBITMAPINFOHEADER) pbmi;
+ lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
+ if (!lpBits)
+ return FALSE;
+ /*
+ * Retrieve the color table (RGBQUAD array) and the bits
+ * (array of palette indices) from the DIB.
+ */
+ hDC = CreateCompatibleDC(NULL);
+ if (!GetDIBits(hDC, hBmp, 0, (WORD) pbih->biHeight,
+ lpBits, pbmi, DIB_RGB_COLORS))
+ return FALSE;
+ /* Create the .BMP file. */
+ hf = CreateFile (pszFile,
+ GENERIC_READ | GENERIC_WRITE,
+ (DWORD) 0,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ (HANDLE) NULL);
+
+ if (hf == INVALID_HANDLE_VALUE)
+ return FALSE;
+ hdr.bfType = 0x4d42; /* 0x42 = "B" 0x4d = "M" */
+ /* Compute the size of the entire file. */
+ hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER)
+ + pbih->biSize + pbih->biClrUsed
+ * sizeof(RGBQUAD) + pbih->biSizeImage);
+ hdr.bfReserved1 = 0;
+ hdr.bfReserved2 = 0;
+ /* Compute the offset to the array of color indices. */
+ hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER)
+ + pbih->biSize + pbih->biClrUsed
+ * sizeof (RGBQUAD);
+ /* Copy the BITMAPFILEHEADER into the .BMP file. */
+ if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
+ (LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
+ return FALSE;
+ /* Copy the BITMAPINFOHEADER and RGBQUAD array into the file. */
+ if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
+ + pbih->biClrUsed * sizeof (RGBQUAD),
+ (LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
+ return FALSE;
+ /* Copy the array of color indices into the .BMP file. */
+ dwTotal = cb = pbih->biSizeImage;
+
+ if (!WriteFile(hf, (LPSTR) lpBits, (int) cb,
+ (LPDWORD) &dwTotal, (LPOVERLAPPED) NULL))
+ return FALSE;
+
+ /* Close the .BMP file. */
+ if (!CloseHandle(hf))
+ return FALSE;
+
+ /* Free memory. */
+ GlobalFree((HGLOBAL)lpBits);
+ GlobalFree((HGLOBAL)pbmi);
+
+ DeleteDC(hDC);
+ } /* C sucks */
+ return TRUE;
+}
diff --git a/trunk/modules/Makefile.am b/trunk/modules/Makefile.am
new file mode 100644
index 00000000..7b6fcbd6
--- /dev/null
+++ b/trunk/modules/Makefile.am
@@ -0,0 +1,74 @@
+## Process this file with automake to create Makefile.in.
+
+SUBDIRS = \
+ arabic \
+ basic \
+ hangul \
+ hebrew \
+ indic \
+ khmer \
+ syriac \
+ thai \
+ tibetan
+
+EXTRA_DIST = \
+ Module.mk \
+ module.def \
+ pangorc
+
+CLEANFILES = \
+ pango.modules
+
+if CROSS_COMPILING
+RUN_QUERY_MODULES_TEST=false
+else
+RUN_QUERY_MODULES_TEST=true
+all-local: pango.modules
+endif
+
+install-data-local: $(top_builddir)/pango/pango-querymodules$(EXEEXT)
+ @if $(RUN_QUERY_MODULES_TEST) && test -z "$(DESTDIR)" ; then \
+ echo $(mkinstalldirs) $(DESTDIR)$(sysconfdir)/pango \&\& \
+ $(top_builddir)/pango/pango-querymodules$(EXEEXT) \
+ \> $(DESTDIR)$(sysconfdir)/pango/pango.modules ; \
+ $(mkinstalldirs) $(DESTDIR)$(sysconfdir)/pango && \
+ $(top_builddir)/pango/pango-querymodules$(EXEEXT) \
+ > $(DESTDIR)$(sysconfdir)/pango/pango.modules ; \
+ else \
+ echo "***" ; \
+ echo "*** Warning: $(sysconfdir)/pango/pango.modules" ; \
+ echo "*** not created" ; \
+ echo "*** Generate this file on the target system" ; \
+ echo "*** using pango-querymodules" ; \
+ echo "***" ; \
+ fi
+
+uninstall-local:
+ $(RM) $(DESTDIR)$(sysconfdir)/pango/pango.modules
+
+pango.modules: \
+ $(SUBDIRS) \
+ $(top_builddir)/config.status \
+ $(top_builddir)/pango/pango-querymodules$(EXEEXT)
+ @if $(RUN_QUERY_MODULES_TEST) && find . -name '*.la' | grep -v '\.libs' | grep -v libpango | grep '.' > /dev/null ; then \
+ echo "Writing a pango.modules file to use with tests/examples."; \
+ $(top_builddir)/pango/pango-querymodules$(EXEEXT) `find . -name '*.la' | grep -v '\.libs' | grep -v libpango` > $@ ;\
+ else \
+ echo "***" ; \
+ echo "*** No dynamic modules found, or cross-compiling" ; \
+ echo "*** Will use only static modules for tests and examples." ; \
+ echo "***" ; \
+ > $@; \
+ fi
+
+included-modules:
+ @for d in $(SUBDIRS) ; do \
+ ( cd $$d && $(MAKE) $(AM_MAKEFLAGS) included-modules ) ; \
+ done
+
+dynamic-modules:
+ @for d in $(SUBDIRS) ; do \
+ ( cd $$d && $(MAKE) $(AM_MAKEFLAGS) dynamic-modules ) ; \
+ done
+
+.PHONY: included-modules dynamic-modules
diff --git a/trunk/modules/Module.mk b/trunk/modules/Module.mk
new file mode 100644
index 00000000..aa504700
--- /dev/null
+++ b/trunk/modules/Module.mk
@@ -0,0 +1,35 @@
+pangolibs = \
+ $(GLIB_LIBS) \
+ $(top_builddir)/pango/libpango-$(PANGO_API_VERSION).la
+pangoxlibs = \
+ $(pangolibs) \
+ $(top_builddir)/pango/libpangox-$(PANGO_API_VERSION).la \
+ $(X_LIBS)
+pangoft2libs = \
+ $(pangolibs) \
+ $(top_builddir)/pango/libpangoft2-$(PANGO_API_VERSION).la \
+ $(FREETYPE_LIBS)
+pangowin32libs = \
+ $(pangolibs) \
+ $(top_builddir)/pango/libpangowin32-$(PANGO_API_VERSION).la
+pangoatsuilibs = \
+ $(pangolibs) \
+ $(top_builddir)/pango/libpangocairo-$(PANGO_API_VERSION).la
+
+INCLUDES = \
+ -DG_LOG_DOMAIN=\"Pango\" \
+ -DPANGO_ENABLE_ENGINE \
+ $(PANGO_DEBUG_FLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/pango \
+ $(GLIB_CFLAGS)
+
+moduledir = $(libdir)/pango/$(PANGO_MODULE_VERSION)/modules
+module_LTLIBRARIES =
+noinst_LTLIBRARIES =
+
+
+included-modules: $(noinst_LTLIBRARIES)
+dynamic-modules: $(module_LTLIBRARIES)
+
+.PHONY: included-modules dynamic-modules
diff --git a/trunk/modules/arabic/Makefile.am b/trunk/modules/arabic/Makefile.am
new file mode 100644
index 00000000..26b232eb
--- /dev/null
+++ b/trunk/modules/arabic/Makefile.am
@@ -0,0 +1,41 @@
+include $(top_srcdir)/modules/Module.mk
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_ARABIC_FC
+noinst_LTLIBRARIES += libpango-arabic-fc.la
+else
+if DYNAMIC_ARABIC_FC
+module_LTLIBRARIES += pango-arabic-fc.la
+endif
+endif
+endif
+
+fc_sources = \
+ arabic-fc.c \
+ arabic-ot.c \
+ arabic-ot.h
+
+pango_arabic_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_arabic_fc_la_LIBADD = $(pangoft2libs)
+pango_arabic_fc_la_SOURCES = $(fc_sources)
+libpango_arabic_fc_la_SOURCES = $(fc_sources)
+libpango_arabic_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_arabic_fc
+
+
+if INCLUDE_ARABIC_LANG
+noinst_LTLIBRARIES += libpango-arabic-lang.la
+else
+if DYNAMIC_ARABIC_LANG
+module_LTLIBRARIES += pango-arabic-lang.la
+endif
+endif
+
+lang_sources = \
+ arabic-lang.c
+
+pango_arabic_lang_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_arabic_lang_la_LIBADD = $(pangolibs)
+pango_arabic_lang_la_SOURCES = $(lang_sources)
+libpango_arabic_lang_la_SOURCES = $(lang_sources)
+libpango_arabic_lang_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_arabic_lang
diff --git a/trunk/modules/arabic/arabic-fc.c b/trunk/modules/arabic/arabic-fc.c
new file mode 100644
index 00000000..5765982b
--- /dev/null
+++ b/trunk/modules/arabic/arabic-fc.c
@@ -0,0 +1,224 @@
+/* Pango
+ * arabic-fc.c: Arabic shaper for FreeType-based backends
+ *
+ * Copyright (C) 2000, 2003, 2007 Red Hat Software
+ * Authors:
+ * Owen Taylor <otaylor@redhat.com>
+ * Behdad Esfahbod <behdad@behdad.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "arabic-ot.h"
+
+#include "pango-engine.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape ArabicEngineFc;
+typedef PangoEngineShapeClass ArabicEngineFcClass ;
+
+#define SCRIPT_ENGINE_NAME "ArabicScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+static PangoEngineScriptInfo arabic_scripts[] = {
+ { PANGO_SCRIPT_ARABIC, "*" },
+ { PANGO_SCRIPT_NKO, "*" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ arabic_scripts, G_N_ELEMENTS(arabic_scripts)
+ }
+};
+
+static const PangoOTFeatureMap gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"isol", isolated},
+ {"fina", final},
+ {"medi", medial},
+ {"init", initial},
+ {"rlig", PANGO_OT_ALL_GLYPHS},
+ {"calt", PANGO_OT_ALL_GLYPHS},
+ {"liga", PANGO_OT_ALL_GLYPHS},
+ /* 'dlig' should be turned-on/off-able. lets turn off for now. */
+ /* {"dlig", PANGO_OT_ALL_GLYPHS}, */
+ {"cswh", PANGO_OT_ALL_GLYPHS},
+ {"mset", PANGO_OT_ALL_GLYPHS}
+};
+
+static const PangoOTFeatureMap gpos_features[] =
+{
+ {"curs", PANGO_OT_ALL_GLYPHS},
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
+
+static void
+arabic_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ PangoFcFont *fc_font;
+ FT_Face face;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ gulong *properties = NULL;
+ glong n_chars;
+ gunichar *wcs;
+ const char *p;
+ int cluster = 0;
+ gboolean rtl = analysis->level % 2 != 0;
+ int i;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return;
+
+ buffer = pango_ot_buffer_new (fc_font);
+ pango_ot_buffer_set_rtl (buffer, rtl);
+ pango_ot_buffer_set_zero_width_marks (buffer, TRUE);
+
+ wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);
+ properties = g_new0 (gulong, n_chars);
+
+ Arabic_Assign_Properties (wcs, properties, n_chars, !rtl);
+
+ g_free (wcs);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ gunichar wc;
+ PangoGlyph glyph;
+
+ wc = g_utf8_get_char (p);
+
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
+
+ if (pango_is_zero_width (wc))
+ glyph = PANGO_GLYPH_EMPTY;
+ else
+ {
+ gunichar c = wc;
+
+ if (analysis->level % 2)
+ g_unichar_get_mirror_char (c, &c);
+
+ /* Hack - Microsoft fonts are strange and don't contain the
+ * correct rules to shape ARABIC LETTER FARSI YEH in
+ * medial/initial position. It looks identical to ARABIC LETTER
+ * YEH in these positions, so we substitute if the font contains
+ * ARABIC LETTER YEH
+ */
+ if (c == 0x6cc &&
+ ((properties[i] & (initial | medial)) != (initial | medial)) &&
+ pango_fc_font_has_char (fc_font, 0x64a))
+ c = 0x64a;
+
+ glyph = pango_fc_font_get_glyph (fc_font, c);
+ }
+
+ if (!glyph)
+ glyph = PANGO_GET_UNKNOWN_GLYPH (wc);
+
+ pango_ot_buffer_add_glyph (buffer, glyph, properties[i], cluster);
+
+ p = g_utf8_next_char (p);
+ }
+
+ g_free (properties);
+
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
+ desc.static_gsub_features = gsub_features;
+ desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
+ desc.static_gpos_features = gpos_features;
+
+ /* TODO populate other_features from analysis->extra_attrs */
+ desc.n_other_features = 0;
+ desc.other_features = NULL;
+
+ ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
+
+ pango_ot_ruleset_substitute (ruleset, buffer);
+ pango_ot_ruleset_position (ruleset, buffer);
+ pango_ot_buffer_output (buffer, glyphs);
+
+ pango_ot_buffer_destroy (buffer);
+
+ pango_fc_font_unlock_face (fc_font);
+}
+
+static void
+arabic_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = arabic_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (ArabicEngineFc, arabic_engine_fc,
+ arabic_engine_fc_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ arabic_engine_fc_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (arabic_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/arabic/arabic-lang.c b/trunk/modules/arabic/arabic-lang.c
new file mode 100644
index 00000000..7022b04e
--- /dev/null
+++ b/trunk/modules/arabic/arabic-lang.c
@@ -0,0 +1,152 @@
+/* Pango
+ * arabic-lang.c:
+ *
+ * Copyright (C) 2006 Red Hat Software
+ * Copyright (C) 2006 Sharif FarsiWeb, Inc.
+ * Authors: Behdad Esfahbod <besfahbo@redhat.com>
+ * Roozbeh Pournader <roozbeh@farsiweb.info>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "pango-engine.h"
+#include "pango-break.h"
+
+/* No extra fields needed */
+typedef PangoEngineLang ArabicEngineLang;
+typedef PangoEngineLangClass ArabicEngineLangClass ;
+
+#define SCRIPT_ENGINE_NAME "ArabicScriptEngineLang"
+#define RENDER_TYPE PANGO_RENDER_TYPE_NONE
+
+static PangoEngineScriptInfo arabic_scripts[] = {
+ { PANGO_SCRIPT_ARABIC, "*" },
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_LANG,
+ RENDER_TYPE,
+ arabic_scripts, G_N_ELEMENTS(arabic_scripts)
+ }
+};
+
+
+#define ALEF_WITH_MADDA_ABOVE 0x0622
+#define YEH_WITH_HAMZA_ABOVE 0x0626
+#define ALEF 0x0627
+#define WAW 0x0648
+#define YEH 0x064A
+
+#define MADDAH_ABOVE 0x0653
+#define HAMZA_ABOVE 0x0654
+#define HAMZA_BELOW 0x0655
+
+/*
+ * Arabic characters with canonical decompositions that are not just
+ * ligatures. The characters U+06C0, U+06C2, and U+06D3 are intentionally
+ * excluded as they are marked as "not an independent letter" in Unicode
+ * Character Database's NamesList.txt
+ */
+#define IS_COMPOSITE(c) (ALEF_WITH_MADDA_ABOVE <= (c) && (c) <= YEH_WITH_HAMZA_ABOVE)
+
+/* If a character is the second part of a composite Arabic character with an Alef */
+#define IS_COMPOSITE_WITH_ALEF(c) (MADDAH_ABOVE <= (c) && (c) <= HAMZA_BELOW)
+
+static void
+arabic_engine_break (PangoEngineLang *engine,
+ const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len)
+{
+ int i;
+ const char *p;
+ gunichar prev_wc, this_wc;
+
+ /* See http://bugzilla.gnome.org/show_bug.cgi?id=350132 for issues this
+ * module tries to solve.
+ */
+
+ for (p = text, i = 0, prev_wc = 0;
+ p < text + length;
+ p = g_utf8_next_char (p), i++, prev_wc = this_wc)
+ {
+ this_wc = g_utf8_get_char (p);
+
+ /*
+ * Unset backspace_deletes_character for various combinations.
+ *
+ * A few more combinations may need to be handled here, but are not
+ * handled yet, as expectations of users is not known or may differ
+ * among different languages or users:
+ * some letters combined with U+0658 ARABIC MARK NOON GHUNNA;
+ * combinations considered one letter in Azerbaijani (WAW+SUKUN and
+ * FARSI_YEH+HAMZA_ABOVE); combinations of YEH and ALEF_MAKSURA with
+ * HAMZA_BELOW (Qur'anic); TATWEEL+HAMZA_ABOVE (Qur'anic).
+ *
+ * FIXME: Ordering these in some other way may lower the time spent here, or not.
+ */
+ if (G_UNLIKELY (
+ IS_COMPOSITE (this_wc) ||
+ (prev_wc == ALEF && IS_COMPOSITE_WITH_ALEF (this_wc)) ||
+ (this_wc == HAMZA_ABOVE && (prev_wc == WAW || prev_wc == YEH))
+ ))
+ attrs[i+1].backspace_deletes_character = FALSE;
+ }
+}
+
+static void
+arabic_engine_lang_class_init (PangoEngineLangClass *class)
+{
+ class->script_break = arabic_engine_break;
+}
+
+PANGO_ENGINE_LANG_DEFINE_TYPE (ArabicEngineLang, arabic_engine_lang,
+ arabic_engine_lang_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ arabic_engine_lang_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (arabic_engine_lang_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/arabic/arabic-ot.c b/trunk/modules/arabic/arabic-ot.c
new file mode 100644
index 00000000..ba8e9bad
--- /dev/null
+++ b/trunk/modules/arabic/arabic-ot.c
@@ -0,0 +1,461 @@
+/* This file is taken from the FreeType (1) tree. It's been reindented
+ * to roughly match Pango guidelines (in anticipation of future changes),
+ * but not otherwise much altered.
+ */
+
+/****************************************************************************/
+/* */
+/* The FreeType project -- a free and portable quality TrueType renderer. */
+/* */
+/* Copyright 1996-2000 by */
+/* D. Turner, R.Wilhelm, and W. Lemberg */
+/* */
+/* arabic -- An implementation of the contextual algorithm given in the */
+/* Unicode 2.0 book to assign the `isolated', `initial', `medial', and */
+/* `final' properties to an input string of character codes for the Arabic */
+/* script. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* The code, like the FreeType code it is derived from is dual-licensed */
+/* under the GNU General Public License and the FreeType license. See */
+/* pango/opentype/COPYING for full details of this licensing scheme. */
+/****************************************************************************/
+
+#include <config.h>
+
+#include "arabic-ot.h"
+
+
+/*
+ *
+ * Here a table of the joining classes for characters in the range
+ * U+0620 - U+06FF and U+0750 - U+077F.
+ *
+ * The following character also has a joining class:
+ *
+ * U+200D ZERO WIDTH JOINER -> causing
+ *
+ * All other characters are given the joining class `none'.
+ *
+ */
+
+static const joining_class arabic[] =
+{
+ /* U+0620 */
+ none, none, right, right,
+ right, right, dual, right,
+ dual, right, dual, dual,
+ dual, dual, dual, right,
+
+ /* U+0630 */
+ right, right, right, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, none,
+ none, none, none, none,
+
+ /* U+0640 */
+ causing, dual, dual, dual,
+ dual, dual, dual, dual,
+ right, dual, dual, transparent,
+ transparent, transparent, transparent, transparent,
+
+ /* U+0650 */
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, none,
+
+ /* U+0660 */
+ none, none, none, none,
+ none, none, none, none,
+ none, none, none, none,
+ none, none, dual, dual,
+
+ /* U+0670 */
+ transparent, right, right, right,
+ none, right, right, right,
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+
+ /* U+0680 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ right, right, right, right,
+ right, right, right, right,
+
+ /* U+0690 */
+ right, right, right, right,
+ right, right, right, right,
+ right, right, dual, dual,
+ dual, dual, dual, dual,
+
+ /* U+06A0 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+
+ /* U+06B0 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+
+ /* U+06C0 */
+ right, dual, right, right,
+ right, right, right, right,
+ right, right, right, right,
+ dual, right, dual, right,
+
+ /* U+06D0 */
+ dual, dual, right, right,
+ none, right, none, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+
+ /* U+06E0 */
+ transparent, transparent, transparent, transparent,
+ transparent, none, none, transparent,
+ transparent, none, transparent, transparent,
+ transparent, transparent, right, right,
+
+ /* U+06F0 */
+ none, none, none, none,
+ none, none, none, none,
+ none, none, dual, dual,
+ dual, none, none, dual
+};
+
+static const joining_class arabic_supplement[] =
+{
+ /* U+0750 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, right, right, right,
+ dual, dual, dual, dual,
+
+ /* U+0760 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, right,
+ right, dual, none, none,
+
+ /* U+0770 */
+ none, none, none, none,
+ none, none, none, none,
+ none, none, none, none,
+ none, none, none, none
+};
+
+/* Here a table of the joining classes for characters in the range
+ * U+07C0 - U+07FF.
+ *
+ * The following character also has a joining class:
+ *
+ * U+200C ZERO WIDTH NON-JOINER -> causing
+ *
+ * All other characters are given the joining class `none'.
+ */
+static const joining_class nko[] =
+{
+ /* U+07C0 */
+ none, none, none, none,
+ none, none, none, none,
+ none, none, dual, dual,
+ dual, dual, dual, dual,
+
+ /* U+07D0 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+
+ /* U+07E0 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ dual, dual, dual, transparent,
+ transparent, transparent, transparent, transparent,
+
+ /* U+07F0 */
+ transparent, transparent, transparent, transparent,
+ none, none, none, none,
+ none, none, causing, none,
+ none, none, none, none,
+};
+
+#if 0
+struct cgc_
+{
+ FT_UShort char_code;
+ FT_UShort glyph_index;
+ FT_UShort class;
+};
+
+typedef struct cgc_ cgc;
+
+int compare_cgc (const void* a,
+ const void* b)
+{
+ return (((cgc*)a)->glyph_index > ((cgc*)b)->glyph_index) ?
+ 1 : ((((cgc*)a)->glyph_index == ((cgc*)b)->glyph_index) ?
+ 0 : -1);
+}
+
+
+TT_Error Build_Arabic_Glyph_Properties (TT_CharMap char_map,
+ TT_UShort max_glyphs,
+ TTO_GDEFHeader** gdef)
+{
+ TT_UShort i, j, num_glyphs;
+
+ cgc Arabic[0x0700 - 0x0620];
+
+ TT_UShort glyph_indices[0x700 - 0x0620];
+ TT_UShort classes[0x700 - 0x0620];
+
+ if (!gdef)
+ return TT_Err_Invalid_Argument;
+
+ j = 0;
+
+ for (i = 0x0620; i < 0x0700; i++)
+ {
+ Arabic[j].char_code = i;
+ Arabic[j].class = (arabic[i - 0x0620] == transparent) ?
+ MARK_GLYPH : SIMPLE_GLYPH;
+ Arabic[j].glyph_index = TT_Char_Index (char_map, i);
+ if (Arabic[j].glyph_index)
+ j++;
+ }
+ num_glyphs = j;
+
+ if (!num_glyphs)
+ {
+ /* no Arabic font */
+ *gdef = NULL;
+ return TT_Err_Ok;
+ }
+
+ /* sort it */
+
+ qsort (Arabic, num_glyphs, sizeof (cgc), compare_cgc);
+
+ /* write it to the arrays, removing duplicates */
+
+ glyph_indices[0] = Arabic[0].glyph_index;
+ classes[0] = Arabic[0].class;
+
+ j = 1;
+
+ for (i = 1; i < num_glyphs; i++)
+ {
+ glyph_indices[j] = Arabic[i].glyph_index;
+ classes[j] = Arabic[i].class;
+
+ if (glyph_indices[j - 1] != glyph_indices[j])
+ j++;
+ }
+ num_glyphs = j;
+
+ TT_GDEF_Build_ClassDefinition (*gdef, max_glyphs, num_glyphs,
+ glyph_indices, classes);
+
+ return TT_Err_Ok;
+}
+#endif
+
+/* The joining rules as given in the Unicode 2.0 book (characters are
+ * here specified as appearing in the byte stream, i.e. *not* in
+ * visual order). Joining classes are given in angle brackets, glyph
+ * forms in square brackets. Glyphs affected by a specific rule are
+ * enclosed with vertical bars.
+ *
+ * Note: The description of the joining algorithm in the book is
+ * severely broken. You can get a corrected version from
+ * www.unicode.org (as of 29-Jun-1999, this hasn't appeared).
+ *
+ * R1: <anything1> <transparent> <anything2>
+ *
+ * apply joining rules for
+ * <anything1> <anything2> -> [shape1] [shape2]
+ *
+ * -> [shape1] [isolated] [shape2]
+ *
+ * R2: <causing|left|dual> |<right>|
+ *
+ * -> [final]
+ *
+ * R3: |<left>| <causing|right|dual>
+ *
+ * -> [initial]
+ *
+ * R4: <causing|left|dual> |<dual>| <causing|right|dual>
+ *
+ * -> [medial]
+ *
+ * R5: <causing|left|dual> |<dual>| <!(causing|right|dual)>
+ *
+ * -> [final]
+ *
+ * R6: <!(causing|left|dual)> |<dual>| <causing|right|dual>
+ *
+ * -> [initial]
+ *
+ * R7: If R1-R6 fail:
+ *
+ * <anything> -> [isolated]
+ */
+
+/* `direction' can be -1, 0, or 1 to indicate the last non-transparent
+ * glyph, the current glyph, and the next non-transparent glyph,
+ * respectively.
+ */
+
+static joining_class Get_Joining_Class (gunichar* string,
+ int pos,
+ int length,
+ int direction,
+ gboolean reverse)
+{
+ joining_class j;
+
+
+ while (1)
+ {
+ if (pos == 0 && direction < 0)
+ return none;
+
+ pos += direction;
+
+ if (pos >= length)
+ return none;
+
+ if (string[pos] >= 0x0620 &&
+ string[pos] < 0x0700)
+ j = arabic[string[pos] - 0x0620];
+ else if (string[pos] >= 0x0750 &&
+ string[pos] < 0x0780)
+ j = arabic_supplement[string[pos] - 0x0750];
+ else if (string[pos] >= 0x07C0 &&
+ string[pos] < 0x0800)
+ j = nko[string[pos] - 0x07C0];
+ else if (string[pos] == 0x200D)
+ return causing;
+ else
+ return none;
+
+ if (!direction || j != transparent)
+ {
+ if (G_UNLIKELY (reverse))
+ return j == right ? left : j == left ? right : j;
+ else
+ return j;
+ }
+ }
+}
+
+
+FT_Error Arabic_Assign_Properties (gunichar *string,
+ gulong *properties,
+ int length,
+ gboolean reverse)
+{
+ joining_class previous, current, next;
+ int i;
+
+ if (!string || !properties || length == 0)
+ return FT_Err_Invalid_Argument;
+
+ for (i = 0; i < length; i++)
+ {
+ previous = Get_Joining_Class (string, i, length, -1, reverse);
+ current = Get_Joining_Class (string, i, length, 0, reverse);
+ next = Get_Joining_Class (string, i, length, 1, reverse);
+
+ /* R1 */
+
+ if (current == transparent)
+ {
+ properties[i] |= isolated_p;
+ continue;
+ }
+
+ /* R2 */
+
+ if (previous == causing ||
+ previous == left ||
+ previous == dual )
+ if (current == right)
+ {
+ properties[i] |= reverse ? initial_p : final_p;
+ continue;
+ }
+
+ /* R3 */
+
+ if (current == left)
+ if (next == causing ||
+ next == right ||
+ next == dual )
+ {
+ properties[i] |= reverse ? final_p : initial_p;
+ continue;
+ }
+
+ /* R4 */
+
+ if (previous == causing ||
+ previous == left ||
+ previous == dual )
+ if (current == dual)
+ if (next == causing ||
+ next == right ||
+ next == dual )
+ {
+ properties[i] |= medial_p;
+ continue;
+ }
+
+ /* R5 */
+
+ if (previous == causing ||
+ previous == left ||
+ previous == dual )
+ if (current == dual)
+ if (!(next == causing ||
+ next == right ||
+ next == dual ))
+ {
+ properties[i] |= reverse ? initial_p : final_p;
+ continue;
+ }
+
+ /* R6 */
+
+ if (!(previous == causing ||
+ previous == left ||
+ previous == dual ))
+ if (current == dual)
+ if (next == causing ||
+ next == right ||
+ next == dual )
+ {
+ properties[i] |= reverse ? final_p : initial_p;
+ continue;
+ }
+
+ /* R7 */
+
+ properties[i] |= isolated_p;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* End */
diff --git a/trunk/modules/arabic/arabic-ot.h b/trunk/modules/arabic/arabic-ot.h
new file mode 100644
index 00000000..db9a9aa9
--- /dev/null
+++ b/trunk/modules/arabic/arabic-ot.h
@@ -0,0 +1,80 @@
+/* This file is taken from the FreeType (1) tree. It's been reindented
+ * to roughly match Pango guidelines (in anticipation of future changes),
+ * but not otherwise much altered.
+ */
+
+/****************************************************************************/
+/* */
+/* The FreeType project -- a free and portable quality TrueType renderer. */
+/* */
+/* Copyright 1996-2000 by */
+/* D. Turner, R.Wilhelm, and W. Lemberg */
+/* */
+/* arabic -- An implementation of the contextual algorithm given in the */
+/* Unicode 2.0 book to assign the `isolated', `initial', `medial', and */
+/* `final' properties to an input string of character codes for the Arabic */
+/* script. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* The file LICENSE.TXT can be found in the Pango distribution as */
+/* pango/opentype/FT-license.txt */
+/****************************************************************************/
+
+#include <pango/pango-ot.h>
+
+
+enum joining_type_
+{
+ isolated = 1, /* nominal */
+ final = 2, /* right_joining */
+ initial = 4, /* left_joining */
+ medial = 8 /* double_joining */
+};
+
+typedef enum joining_type_ joining_type;
+
+
+ /* A glyph's property value as needed by e.g. TT_GSUB_Apply_String()
+ specifies which features should *not* be applied */
+
+enum arabic_glyph_property_
+{
+ isolated_p = final | initial | medial,
+ final_p = isolated | initial | medial,
+ initial_p = isolated | final | medial,
+ medial_p = isolated | final | initial
+};
+
+typedef enum arabic_glyph_property_ arabic_glyph_property;
+
+
+enum joining_class_
+{
+ right,
+ left, /* not used */
+ dual,
+ causing,
+ none,
+ transparent
+};
+
+typedef enum joining_class_ joining_class;
+
+
+FT_Error Arabic_Assign_Properties (gunichar *string,
+ gulong *properties,
+ int length,
+ gboolean reverse);
+#if 0
+TT_Error Build_Arabic_Glyph_Properties (TT_CharMap char_map,
+ TT_UShort max_glyphs,
+ TTO_GDEFHeader** gdef );
+#endif
+
+
+/* End */
diff --git a/trunk/modules/basic/Makefile.am b/trunk/modules/basic/Makefile.am
new file mode 100644
index 00000000..e8a71c94
--- /dev/null
+++ b/trunk/modules/basic/Makefile.am
@@ -0,0 +1,74 @@
+include $(top_srcdir)/modules/Module.mk
+
+if HAVE_X
+INCLUDES += $(X_CFLAGS)
+if INCLUDE_BASIC_X
+noinst_LTLIBRARIES += libpango-basic-x.la
+else
+if DYNAMIC_BASIC_X
+module_LTLIBRARIES += pango-basic-x.la
+endif
+endif
+endif
+
+pango_basic_x_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_basic_x_la_LIBADD = $(pangoxlibs)
+pango_basic_x_la_SOURCES = basic-x.c
+libpango_basic_x_la_SOURCES = basic-x.c
+libpango_basic_x_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_x
+
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_BASIC_FC
+noinst_LTLIBRARIES += libpango-basic-fc.la
+else
+if DYNAMIC_BASIC_FC
+module_LTLIBRARIES += pango-basic-fc.la
+endif
+endif
+endif
+
+pango_basic_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_basic_fc_la_LIBADD = $(pangoft2libs)
+pango_basic_fc_la_SOURCES = basic-fc.c
+libpango_basic_fc_la_SOURCES = basic-fc.c
+libpango_basic_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_fc
+
+
+if HAVE_WIN32
+if INCLUDE_BASIC_WIN32
+noinst_LTLIBRARIES += libpango-basic-win32.la
+else
+if DYNAMIC_BASIC_WIN32
+module_LTLIBRARIES += pango-basic-win32.la
+endif
+endif
+endif
+
+pango_basic_win32_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_basic_win32_la_LIBADD = $(pangowin32libs) -lgdi32
+pango_basic_win32_la_SOURCES = basic-win32.c
+libpango_basic_win32_la_SOURCES = basic-win32.c
+libpango_basic_win32_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_win32
+
+if HAVE_CAIRO_ATSUI
+INCLUDES += $(ATSUI_CFLAGS) $(CAIRO_CFLAGS)
+if INCLUDE_BASIC_ATSUI
+noinst_LTLIBRARIES += libpango-basic-atsui.la
+else
+if DYNAMIC_BASIC_ATSUI
+module_LTLIBRARIES += pango-basic-atsui.la
+endif
+endif
+endif
+
+pango_basic_atsui_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS) -framework Carbon
+pango_basic_atsui_la_LIBADD = $(pangoatsuilibs)
+pango_basic_atsui_la_SOURCES = basic-atsui.c
+libpango_basic_atsui_la_SOURCES = basic-atsui.c
+libpango_basic_atsui_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_atsui
+
+EXTRA_DIST = \
+ tables-big.i \
+ tables-small.i
diff --git a/trunk/modules/basic/basic-atsui.c b/trunk/modules/basic/basic-atsui.c
new file mode 100644
index 00000000..b175be3e
--- /dev/null
+++ b/trunk/modules/basic/basic-atsui.c
@@ -0,0 +1,205 @@
+/* Pango
+ * basic-atsui.c
+ *
+ * Copyright (C) 2005 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <string.h>
+#include <Carbon/Carbon.h>
+#include "pango-engine.h"
+#include "pango-utils.h"
+#include "pango-fontmap.h"
+#include "pangoatsui.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape BasicEngineATSUI;
+typedef PangoEngineShapeClass BasicEngineATSUIClass ;
+
+#define SCRIPT_ENGINE_NAME "BasicScriptEngineATSUI"
+#define RENDER_TYPE PANGO_RENDER_TYPE_ATSUI
+
+static PangoEngineScriptInfo basic_scripts[] = {
+ { PANGO_SCRIPT_COMMON, "" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ basic_scripts, G_N_ELEMENTS(basic_scripts)
+ }
+};
+
+static void
+set_glyph (PangoFont *font,
+ PangoGlyphString *glyphs,
+ int i,
+ int offset,
+ PangoGlyph glyph)
+{
+ PangoRectangle logical_rect;
+
+ glyphs->glyphs[i].glyph = G_UNLIKELY (glyph == kATSDeletedGlyphcode) ?
+ PANGO_GLYPH_EMPTY : glyph;
+
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+
+ glyphs->log_clusters[i] = offset;
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+}
+
+static void
+basic_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ gunichar2 *utf16;
+ long n16;
+ ATSUTextLayout text_layout;
+ ATSLayoutRecord *layout_records;
+ OSStatus err;
+ ItemCount glyph_count;
+ int i;
+ const char *p;
+ PangoATSUIFont *afont = PANGO_ATSUI_FONT (font);
+ ATSUStyle style;
+ ATSUFontID fontID;
+ ATSUAttributeTag styleTags[] = { kATSUFontTag };
+ ATSUAttributeValuePtr styleValues[] = { &fontID };
+ ByteCount styleSizes[] = { sizeof (ATSUFontID) };
+
+ utf16 = g_utf8_to_utf16 (text, length, NULL, &n16, NULL);
+
+ err = ATSUCreateTextLayout (&text_layout);
+ err = ATSUSetTextPointerLocation (text_layout, utf16, 0, n16, n16);
+
+ err = ATSUCreateStyle(&style);
+ fontID = pango_atsui_font_get_atsu_font_id (afont);
+
+ err = ATSUSetAttributes(style,
+ sizeof(styleTags) / sizeof(styleTags[0]),
+ styleTags, styleSizes, styleValues);
+
+ err = ATSUSetRunStyle(text_layout,
+ style, kATSUFromTextBeginning, kATSUToTextEnd);
+
+ err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout (text_layout, 0,
+ kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
+ (void *)&layout_records,
+ &glyph_count);
+
+ p = text;
+ pango_glyph_string_set_size (glyphs, glyph_count - 1);
+
+ for (i = 0; i < glyph_count - 1; i++)
+ {
+ gunichar wc;
+ gunichar mirrored_ch;
+
+ wc = g_utf8_get_char (p);
+
+ if (analysis->level % 2)
+ if (pango_get_mirror_char (wc, &mirrored_ch))
+ wc = mirrored_ch;
+
+ if (wc == 0xa0) /* non-break-space */
+ wc = 0x20;
+
+ if (pango_is_zero_width (wc))
+ {
+ set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
+ }
+ else
+ {
+ set_glyph (font, glyphs, i, p - text, layout_records[i].glyphID);
+
+ if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
+ {
+ if (i > 0)
+ {
+ PangoRectangle logical_rect, ink_rect;
+
+ glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
+ glyphs->glyphs[i].geometry.width);
+ glyphs->glyphs[i-1].geometry.width = 0;
+ glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
+
+ /* Some heuristics to try to guess how overstrike glyphs are
+ * done and compensate
+ */
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
+ if (logical_rect.width == 0 && ink_rect.x == 0)
+ glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
+ }
+ }
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ ATSUDirectReleaseLayoutDataArrayPtr (NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
+ (void *)&layout_records);
+
+ ATSUDisposeTextLayout (text_layout);
+}
+
+static void
+basic_engine_atsui_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = basic_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineATSUI, basic_engine_atsui,
+ basic_engine_atsui_class_init, NULL);
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ basic_engine_atsui_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (basic_engine_atsui_type, NULL);
+ else
+ return NULL;
+}
+
diff --git a/trunk/modules/basic/basic-fc.c b/trunk/modules/basic/basic-fc.c
new file mode 100644
index 00000000..f01b28d4
--- /dev/null
+++ b/trunk/modules/basic/basic-fc.c
@@ -0,0 +1,250 @@
+/* Pango
+ * basic-fc.c: Basic shaper for FreeType-based backends
+ *
+ * Copyright (C) 2000, 2007 Red Hat Software
+ * Authors:
+ * Owen Taylor <otaylor@redhat.com>
+ * Behdad Esfahbod <behdad@behdad.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <glib/gprintf.h>
+#include "pango-engine.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+#include "pango-ot.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape BasicEngineFc;
+typedef PangoEngineShapeClass BasicEngineFcClass;
+
+#define SCRIPT_ENGINE_NAME "BasicScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+static PangoEngineScriptInfo basic_scripts[] = {
+ /* Listed in OpenType "Standard scripts" standard */
+ { PANGO_SCRIPT_LATIN, "*" },
+ { PANGO_SCRIPT_CYRILLIC, "*" },
+ { PANGO_SCRIPT_GREEK, "*" },
+ { PANGO_SCRIPT_ARMENIAN, "*" },
+ { PANGO_SCRIPT_GEORGIAN, "*" },
+ { PANGO_SCRIPT_RUNIC, "*" },
+ { PANGO_SCRIPT_OGHAM, "*" },
+
+ /* The following are simple and can be shaped easily too */
+
+ { PANGO_SCRIPT_BOPOMOFO, "*" },
+ { PANGO_SCRIPT_CHEROKEE, "*" },
+ { PANGO_SCRIPT_COPTIC, "*" },
+ { PANGO_SCRIPT_DESERET, "*" },
+ { PANGO_SCRIPT_ETHIOPIC, "*" },
+ { PANGO_SCRIPT_GOTHIC, "*" },
+ { PANGO_SCRIPT_HAN, "*" },
+ { PANGO_SCRIPT_HIRAGANA, "*" },
+ { PANGO_SCRIPT_KATAKANA, "*" },
+ { PANGO_SCRIPT_OLD_ITALIC, "*" },
+ { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" },
+ { PANGO_SCRIPT_YI, "*" },
+
+ /* Unicode-4.0 additions */
+ { PANGO_SCRIPT_BRAILLE, "*" },
+ { PANGO_SCRIPT_CYPRIOT, "*" },
+ { PANGO_SCRIPT_LIMBU, "*" },
+ { PANGO_SCRIPT_OSMANYA, "*" },
+ { PANGO_SCRIPT_SHAVIAN, "*" },
+ { PANGO_SCRIPT_LINEAR_B, "*" },
+ { PANGO_SCRIPT_UGARITIC, "*" },
+
+ /* Unicode-4.1 additions */
+ { PANGO_SCRIPT_GLAGOLITIC, "*" },
+
+ /* Unicode-5.0 additions */
+ { PANGO_SCRIPT_CUNEIFORM, "*" },
+ { PANGO_SCRIPT_PHOENICIAN, "*" },
+
+ /* In fact any script we don't know how to shape can go here */
+ { PANGO_SCRIPT_COMMON, "" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ basic_scripts, G_N_ELEMENTS(basic_scripts)
+ }
+};
+
+static const PangoOTFeatureMap gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"liga", PANGO_OT_ALL_GLYPHS},
+ {"clig", PANGO_OT_ALL_GLYPHS}
+};
+
+static const PangoOTFeatureMap gpos_features[] =
+{
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
+
+static const PangoOTFeatureMap vertical_gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"vert", PANGO_OT_ALL_GLYPHS}
+};
+
+static void
+basic_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ PangoFcFont *fc_font;
+ FT_Face face;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ glong n_chars;
+ const char *p;
+ int cluster = 0;
+ int i;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return;
+
+ buffer = pango_ot_buffer_new (fc_font);
+ pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
+
+ n_chars = g_utf8_strlen (text, length);
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ gunichar wc;
+ PangoGlyph glyph;
+
+ wc = g_utf8_get_char (p);
+
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
+
+ if (pango_is_zero_width (wc))
+ glyph = PANGO_GLYPH_EMPTY;
+ else
+ {
+ gunichar c = wc;
+
+ if (analysis->level % 2)
+ g_unichar_get_mirror_char (c, &c);
+
+ glyph = pango_fc_font_get_glyph (fc_font, c);
+ }
+
+ if (!glyph)
+ glyph = PANGO_GET_UNKNOWN_GLYPH (wc);
+
+ pango_ot_buffer_add_glyph (buffer, glyph, 0, cluster);
+
+ p = g_utf8_next_char (p);
+ }
+
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity))
+ {
+ desc.n_static_gsub_features = G_N_ELEMENTS (vertical_gsub_features);
+ desc.static_gsub_features = vertical_gsub_features;
+ desc.n_static_gpos_features = 0;
+ desc.static_gpos_features = NULL;
+ }
+ else
+ {
+ desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
+ desc.static_gsub_features = gsub_features;
+ desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
+ desc.static_gpos_features = gpos_features;
+ }
+
+ /* TODO populate other_features from analysis->extra_attrs */
+ desc.n_other_features = 0;
+ desc.other_features = NULL;
+
+ ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
+
+ pango_ot_ruleset_substitute (ruleset, buffer);
+ pango_ot_ruleset_position (ruleset, buffer);
+ pango_ot_buffer_output (buffer, glyphs);
+
+ pango_ot_buffer_destroy (buffer);
+
+ pango_fc_font_unlock_face (fc_font);
+}
+
+static void
+basic_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = basic_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineFc, basic_engine_fc,
+ basic_engine_fc_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ basic_engine_fc_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (basic_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/basic/basic-win32.c b/trunk/modules/basic/basic-win32.c
new file mode 100644
index 00000000..c0880fb8
--- /dev/null
+++ b/trunk/modules/basic/basic-win32.c
@@ -0,0 +1,946 @@
+/* Pango
+ * basic-win32.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2001 Alexander Larsson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#define BASIC_WIN32_DEBUGGING
+
+#include <math.h>
+#include <stdlib.h>
+
+#include <glib.h>
+
+#include "pangowin32.h"
+#include "pango-engine.h"
+#include "pango-utils.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape BasicEngineWin32;
+typedef PangoEngineShapeClass BasicEngineWin32Class ;
+
+#define SCRIPT_ENGINE_NAME "BasicScriptEngineWin32"
+
+static gboolean pango_win32_debug = FALSE;
+
+#include <usp10.h>
+
+static gboolean have_uniscribe = FALSE;
+
+static HDC hdc;
+
+typedef HRESULT (WINAPI *pScriptGetProperties) (const SCRIPT_PROPERTIES ***,
+ int *);
+
+typedef HRESULT (WINAPI *pScriptItemize) (const WCHAR *,
+ int,
+ int,
+ const SCRIPT_CONTROL *,
+ const SCRIPT_STATE *,
+ SCRIPT_ITEM *,
+ int *);
+
+typedef HRESULT (WINAPI *pScriptShape) (HDC,
+ SCRIPT_CACHE *,
+ const WCHAR *,
+ int,
+ int,
+ SCRIPT_ANALYSIS *,
+ WORD *,
+ WORD *,
+ SCRIPT_VISATTR *,
+ int *);
+
+typedef HRESULT (WINAPI *pScriptPlace) (HDC,
+ SCRIPT_CACHE *,
+ const WORD *,
+ int,
+ const SCRIPT_VISATTR *,
+ SCRIPT_ANALYSIS *,
+ int *,
+ GOFFSET *,
+ ABC *);
+
+typedef HRESULT (WINAPI *pScriptFreeCache) (SCRIPT_CACHE *);
+
+typedef HRESULT (WINAPI *pScriptIsComplex) (WCHAR *,
+ int,
+ DWORD);
+
+static pScriptGetProperties script_get_properties;
+static pScriptItemize script_itemize;
+static pScriptShape script_shape;
+static pScriptPlace script_place;
+static pScriptFreeCache script_free_cache;
+static pScriptIsComplex script_is_complex;
+
+#ifdef BASIC_WIN32_DEBUGGING
+static const SCRIPT_PROPERTIES **scripts;
+static int nscripts;
+#endif
+
+static PangoEngineScriptInfo uniscribe_scripts[] = {
+ /* We claim to cover everything ;-) */
+ { PANGO_SCRIPT_COMMON, "" },
+};
+
+static PangoEngineScriptInfo basic_scripts[] = {
+ /* Those characters that can be rendered legibly without Uniscribe.
+ * I am not certain this list is correct.
+ */
+ { PANGO_SCRIPT_ARMENIAN, "*" },
+ { PANGO_SCRIPT_BOPOMOFO, "*" },
+ { PANGO_SCRIPT_CHEROKEE, "*" },
+ { PANGO_SCRIPT_COPTIC, "*" },
+ { PANGO_SCRIPT_CYRILLIC, "*" },
+ { PANGO_SCRIPT_DESERET, "*" },
+ { PANGO_SCRIPT_ETHIOPIC, "*" },
+ { PANGO_SCRIPT_GEORGIAN, "*" },
+ { PANGO_SCRIPT_GOTHIC, "*" },
+ { PANGO_SCRIPT_GREEK, "*" },
+ { PANGO_SCRIPT_HAN, "*" },
+ { PANGO_SCRIPT_HANGUL, "*" },
+ { PANGO_SCRIPT_HIRAGANA, "*" },
+ { PANGO_SCRIPT_KATAKANA, "*" },
+ { PANGO_SCRIPT_LATIN, "*" },
+ { PANGO_SCRIPT_OGHAM, "*" },
+ { PANGO_SCRIPT_OLD_ITALIC, "*" },
+ { PANGO_SCRIPT_RUNIC, "*" },
+ { PANGO_SCRIPT_THAI, "*" },
+ { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" },
+ { PANGO_SCRIPT_YI, "*" },
+ { PANGO_SCRIPT_BRAILLE, "*" },
+ { PANGO_SCRIPT_CYPRIOT, "*" },
+ { PANGO_SCRIPT_LIMBU, "*" },
+ { PANGO_SCRIPT_OSMANYA, "*" },
+ { PANGO_SCRIPT_SHAVIAN, "*" },
+ { PANGO_SCRIPT_LINEAR_B, "*" },
+ { PANGO_SCRIPT_UGARITIC, "*" },
+
+ /* Claim to handle everything as a fallback */
+ { PANGO_SCRIPT_COMMON, "" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ PANGO_RENDER_TYPE_WIN32,
+ NULL, 0
+ }
+};
+
+static PangoGlyph
+find_char (PangoFont *font,
+ gunichar wc)
+{
+ return pango_win32_font_get_glyph_index (font, wc);
+}
+
+static void
+set_glyph (PangoFont *font,
+ PangoGlyphString *glyphs,
+ int i,
+ int offset,
+ PangoGlyph glyph)
+{
+ PangoRectangle logical_rect;
+
+ glyphs->glyphs[i].glyph = glyph;
+
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+
+ glyphs->log_clusters[i] = offset;
+
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+}
+
+static void
+swap_range (PangoGlyphString *glyphs,
+ int start,
+ int end)
+{
+ int i, j;
+
+ for (i = start, j = end - 1; i < j; i++, j--)
+ {
+ PangoGlyphInfo glyph_info;
+ gint log_cluster;
+
+ glyph_info = glyphs->glyphs[i];
+ glyphs->glyphs[i] = glyphs->glyphs[j];
+ glyphs->glyphs[j] = glyph_info;
+
+ log_cluster = glyphs->log_clusters[i];
+ glyphs->log_clusters[i] = glyphs->log_clusters[j];
+ glyphs->log_clusters[j] = log_cluster;
+ }
+}
+
+#ifdef BASIC_WIN32_DEBUGGING
+
+static char *
+lang_name (int lang)
+{
+ LCID lcid = MAKELCID (lang, SORT_DEFAULT);
+ static char retval[10];
+
+ if (!GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, retval, G_N_ELEMENTS (retval)))
+ sprintf (retval, "%#02x", lang);
+
+ return retval;
+}
+
+#endif /* BASIC_WIN32_DEBUGGING */
+
+static WORD
+make_langid (PangoLanguage *lang)
+{
+#define CASE(t,p,s) if (pango_language_matches (lang, t)) return MAKELANGID (LANG_##p, SUBLANG_##p##_##s)
+#define CASEN(t,p) if (pango_language_matches (lang, t)) return MAKELANGID (LANG_##p, SUBLANG_NEUTRAL)
+
+ /* Languages that most probably don't affect Uniscribe have been
+ * left out. Uniscribe is documented to use
+ * SCRIPT_CONTROL::uDefaultLanguage only to select digit shapes, so
+ * just leave languages with own digits.
+ */
+
+ CASEN ("ar", ARABIC);
+ CASEN ("hy", ARMENIAN);
+ CASEN ("as", ASSAMESE);
+ CASEN ("az", AZERI);
+ CASEN ("bn", BENGALI);
+ CASE ("zh-tw", CHINESE, TRADITIONAL);
+ CASE ("zh-cn", CHINESE, SIMPLIFIED);
+ CASE ("zh-hk", CHINESE, HONGKONG);
+ CASE ("zh-sg", CHINESE, SINGAPORE);
+ CASE ("zh-mo", CHINESE, MACAU);
+ CASEN ("dib", DIVEHI);
+ CASEN ("fa", FARSI);
+ CASEN ("ka", GEORGIAN);
+ CASEN ("gu", GUJARATI);
+ CASEN ("he", HEBREW);
+ CASEN ("hi", HINDI);
+ CASEN ("ja", JAPANESE);
+ CASEN ("kn", KANNADA);
+ CASE ("ks-in", KASHMIRI, INDIA);
+ CASEN ("ks", KASHMIRI);
+ CASEN ("kk", KAZAK);
+ CASEN ("kok", KONKANI);
+ CASEN ("ko", KOREAN);
+ CASEN ("ky", KYRGYZ);
+ CASEN ("ml", MALAYALAM);
+ CASEN ("mni", MANIPURI);
+ CASEN ("mr", MARATHI);
+ CASEN ("mn", MONGOLIAN);
+ CASE ("ne-in", NEPALI, INDIA);
+ CASEN ("ne", NEPALI);
+ CASEN ("or", ORIYA);
+ CASEN ("pa", PUNJABI);
+ CASEN ("sa", SANSKRIT);
+ CASEN ("sd", SINDHI);
+ CASEN ("syr", SYRIAC);
+ CASEN ("ta", TAMIL);
+ CASEN ("tt", TATAR);
+ CASEN ("te", TELUGU);
+ CASEN ("th", THAI);
+ CASE ("ur-pk", URDU, PAKISTAN);
+ CASE ("ur-in", URDU, INDIA);
+ CASEN ("ur", URDU);
+ CASEN ("uz", UZBEK);
+
+#undef CASE
+#undef CASEN
+
+ return MAKELANGID (LANG_NEUTRAL, SUBLANG_NEUTRAL);
+}
+
+#ifdef BASIC_WIN32_DEBUGGING
+
+static void
+dump_glyphs_and_log_clusters (gboolean rtl,
+ int itemlen,
+ int charix0,
+ WORD *log_clusters,
+ WORD *iglyphs,
+ int nglyphs)
+{
+ if (pango_win32_debug)
+ {
+ int j, k, nclusters, clusterix, charix, ng;
+
+ g_print (" ScriptShape: nglyphs=%d: ", nglyphs);
+
+ for (j = 0; j < nglyphs; j++)
+ g_print ("%d%s", iglyphs[j], (j < nglyphs-1) ? "," : "");
+ g_print ("\n");
+
+ g_print (" log_clusters: ");
+ for (j = 0; j < itemlen; j++)
+ g_print ("%d ", log_clusters[j]);
+ g_print ("\n");
+ nclusters = 0;
+ for (j = 0; j < itemlen; j++)
+ {
+ if (j == 0 || log_clusters[j-1] != log_clusters[j])
+ nclusters++;
+ }
+ g_print (" %d clusters:\n", nclusters);
+
+ /* If RTL, first char is the last in the run, otherwise the
+ * first.
+ */
+ clusterix = 0;
+ if (rtl)
+ {
+ int firstglyphix = 0;
+ for (j = itemlen - 1, charix = charix0 + j; j >= 0; j--, charix--)
+ {
+ if (j == itemlen - 1 || log_clusters[j] != log_clusters[j+1])
+ g_print (" Cluster %d: chars %d--",
+ clusterix, charix);
+ if (j == 0 || log_clusters[j-1] != log_clusters[j])
+ {
+ ng = log_clusters[j] - firstglyphix + 1;
+ g_print ("%d: %d glyphs: ",
+ charix, ng);
+ for (k = firstglyphix; k <= log_clusters[j]; k++)
+ {
+ g_print ("%d", iglyphs[k]);
+ if (k < log_clusters[j])
+ g_print (",");
+ }
+ firstglyphix = log_clusters[j] + 1;
+ clusterix++;
+ g_print ("\n");
+ }
+ }
+ }
+ else
+ {
+ for (j = 0, charix = charix0; j < itemlen; j++, charix++)
+ {
+ if (j == 0 || log_clusters[j-1] != log_clusters[j])
+ g_print (" Cluster %d: wchar_t %d--",
+ clusterix, charix);
+ if (j == itemlen - 1 || log_clusters[j] != log_clusters[j+1])
+ {
+ int klim = ((j == itemlen-1) ? nglyphs : log_clusters[j+1]);
+ ng = klim - log_clusters[j];
+ g_print ("%d: %d glyphs: ",
+ charix, ng);
+ for (k = log_clusters[j]; k < klim; k++)
+ {
+ g_print ("%d", iglyphs[k]);
+ if (k != klim - 1)
+ g_print (",");
+ }
+ clusterix++;
+ g_print ("\n");
+ }
+ }
+ }
+ }
+}
+
+#endif /* BASIC_WIN32_DEBUGGING */
+
+static int
+unichar_index (wchar_t *wtext,
+ int ix)
+{
+ int i, index;
+
+ index = 0;
+ for (i = 0; i < ix; i++)
+ /* Ignore the low surrogate */
+ if (!(wtext[i] >= 0xDC00 && wtext[i] < 0xE000))
+ index++;
+
+ return index;
+}
+
+static void
+set_up_pango_log_clusters (wchar_t *wtext,
+ gboolean rtl,
+ int itemlen,
+ WORD *usp_log_clusters,
+ int nglyphs,
+ gint *pango_log_clusters,
+ int char_offset)
+{
+ int j, k;
+ int first_char_in_cluster;
+
+ if (rtl)
+ {
+ /* RTL. Walk Uniscribe log_clusters array backwards, build Pango
+ * log_clusters array forwards.
+ */
+ int glyph0 = 0;
+ first_char_in_cluster = unichar_index (wtext, itemlen - 1);
+ for (j = itemlen - 1; j >= 0; j--)
+ {
+ if (j < itemlen - 1 && usp_log_clusters[j+1] != usp_log_clusters[j])
+ {
+ /* Cluster starts */
+ first_char_in_cluster = unichar_index (wtext, j);
+ }
+ if (j == 0)
+ {
+ /* First char, cluster ends */
+ for (k = glyph0; k < nglyphs; k++)
+ pango_log_clusters[k] = first_char_in_cluster + char_offset;
+ }
+ else if (usp_log_clusters[j-1] == usp_log_clusters[j])
+ {
+ /* Cluster continues */
+ first_char_in_cluster = unichar_index (wtext, j-1);
+ }
+ else
+ {
+ /* Cluster ends */
+ for (k = glyph0; k <= usp_log_clusters[j]; k++)
+ pango_log_clusters[k] = first_char_in_cluster + char_offset;
+ glyph0 = usp_log_clusters[j] + 1;
+ }
+ }
+ }
+ else
+ {
+ /* LTR. Walk Uniscribe log_clusters array forwards, build Pango
+ * log_clusters array also forwards.
+ */
+ first_char_in_cluster = 0;
+ for (j = 0; j < itemlen; j++)
+ {
+ if (j > 0 && usp_log_clusters[j-1] != usp_log_clusters[j])
+ {
+ /* Cluster starts */
+ first_char_in_cluster = unichar_index (wtext, j);
+ }
+ if (j == itemlen - 1)
+ {
+ /* Last char, cluster ends */
+ for (k = usp_log_clusters[j]; k < nglyphs; k++)
+ pango_log_clusters[k] = first_char_in_cluster + char_offset;
+ }
+ else if (usp_log_clusters[j] == usp_log_clusters[j+1])
+ {
+ /* Cluster continues */
+ }
+ else
+ {
+ /* Cluster ends */
+ for (k = usp_log_clusters[j]; k < usp_log_clusters[j+1]; k++)
+ pango_log_clusters[k] = first_char_in_cluster + char_offset;
+ }
+ }
+ }
+}
+
+static void
+convert_log_clusters_to_byte_offsets (const char *text,
+ gint length,
+ PangoGlyphString *glyphs)
+{
+ const char *p;
+ int charix, glyphix;
+ int n_chars = g_utf8_strlen (text, length);
+ int *byte_offset = g_new (int, n_chars);
+
+ p = text;
+ charix = 0;
+ while (p < text + length)
+ {
+ byte_offset[charix] = p - text;
+ charix++;
+ p = g_utf8_next_char (p);
+ }
+
+ /* Convert char indexes in the log_clusters array to byte offsets.
+ */
+ for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++)
+ {
+ g_assert (glyphs->log_clusters[glyphix] < n_chars);
+ glyphs->log_clusters[glyphix] = byte_offset[glyphs->log_clusters[glyphix]];
+ }
+
+ g_free (byte_offset);
+}
+
+static gboolean
+itemize_shape_and_place (PangoFont *font,
+ HDC hdc,
+ wchar_t *wtext,
+ int wlen,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs,
+ SCRIPT_CACHE *script_cache)
+{
+ int i;
+ int item, nitems, item_step;
+ int itemlen, glyphix, nglyphs;
+ SCRIPT_CONTROL control;
+ SCRIPT_STATE state;
+ SCRIPT_ITEM items[100];
+ double scale = pango_win32_font_get_metrics_factor (font);
+
+ memset (&control, 0, sizeof (control));
+ memset (&state, 0, sizeof (state));
+
+ control.uDefaultLanguage = make_langid (analysis->language);
+ state.uBidiLevel = analysis->level;
+
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ g_print (G_STRLOC ": ScriptItemize: uDefaultLanguage:%04x uBidiLevel:%d\n",
+ control.uDefaultLanguage, state.uBidiLevel);
+#endif
+ if ((*script_itemize) (wtext, wlen, G_N_ELEMENTS (items), &control, NULL,
+ items, &nitems))
+ {
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ g_print ("ScriptItemize failed\n");
+#endif
+ return FALSE;
+ }
+
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ g_print ("%d items:\n", nitems);
+#endif
+
+ if (analysis->level % 2)
+ {
+ item = nitems - 1;
+ item_step = -1;
+ }
+ else
+ {
+ item = 0;
+ item_step = 1;
+ }
+
+ for (i = 0; i < nitems; i++, item += item_step)
+ {
+ WORD iglyphs[1000];
+ WORD log_clusters[1000];
+ SCRIPT_VISATTR visattrs[1000];
+ int advances[1000];
+ GOFFSET offsets[1000];
+ ABC abc;
+ int script = items[item].a.eScript;
+ int ng;
+ int char_offset;
+
+ memset (advances, 0, sizeof (advances));
+ memset (offsets, 0, sizeof (offsets));
+ memset (&abc, 0, sizeof (abc));
+
+ /* Note that itemlen is number of wchar_t's i.e. surrogate pairs
+ * count as two!
+ */
+ itemlen = items[item+1].iCharPos - items[item].iCharPos;
+ char_offset = unichar_index (wtext, items[item].iCharPos);
+
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ g_print (" Item %d: iCharPos=%d eScript=%d (%s) %s%s%s%s%s%s%s wchar_t %d--%d (%d)\n",
+ item, items[item].iCharPos, script,
+ lang_name (scripts[script]->langid),
+ scripts[script]->fComplex ? "complex" : "simple",
+ items[item].a.fRTL ? " fRTL" : "",
+ items[item].a.fLayoutRTL ? " fLayoutRTL" : "",
+ items[item].a.fLinkBefore ? " fLinkBefore" : "",
+ items[item].a.fLinkAfter ? " fLinkAfter" : "",
+ items[item].a.fLogicalOrder ? " fLogicalOrder" : "",
+ items[item].a.fNoGlyphIndex ? " fNoGlyphIndex" : "",
+ items[item].iCharPos, items[item+1].iCharPos-1, itemlen);
+#endif
+
+ items[item].a.fRTL = analysis->level % 2;
+ if ((*script_shape) (hdc, &script_cache[script],
+ wtext + items[item].iCharPos, itemlen,
+ G_N_ELEMENTS (iglyphs),
+ &items[item].a,
+ iglyphs,
+ log_clusters,
+ visattrs,
+ &nglyphs))
+ {
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ g_print ("pango-basic-win32: ScriptShape failed\n");
+#endif
+ return FALSE;
+ }
+
+#ifdef BASIC_WIN32_DEBUGGING
+ dump_glyphs_and_log_clusters (items[item].a.fRTL, itemlen,
+ items[item].iCharPos, log_clusters,
+ iglyphs, nglyphs);
+#endif
+
+ ng = glyphs->num_glyphs;
+ pango_glyph_string_set_size (glyphs, ng + nglyphs);
+
+ set_up_pango_log_clusters (wtext,
+ items[item].a.fRTL, itemlen, log_clusters,
+ nglyphs, glyphs->log_clusters + ng,
+ char_offset);
+
+ if ((*script_place) (hdc, &script_cache[script], iglyphs, nglyphs,
+ visattrs, &items[item].a,
+ advances, offsets, &abc))
+ {
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ g_print ("pango-basic-win32: ScriptPlace failed\n");
+#endif
+ return FALSE;
+ }
+
+ for (glyphix = 0; glyphix < nglyphs; glyphix++)
+ {
+ if (iglyphs[glyphix] != 0)
+ {
+ glyphs->glyphs[ng+glyphix].glyph = iglyphs[glyphix];
+ glyphs->glyphs[ng+glyphix].geometry.width = floor (0.5 + scale * advances[glyphix]);
+ glyphs->glyphs[ng+glyphix].geometry.x_offset = floor (0.5 + scale * offsets[glyphix].du);
+ glyphs->glyphs[ng+glyphix].geometry.y_offset = floor (0.5 + scale * offsets[glyphix].dv);
+ }
+ else
+ {
+ PangoRectangle logical_rect;
+ /* Should pass actual char that was not found to
+ * PANGO_GET_UNKNOWN_GLYPH(), but a bit hard to
+ * find out that at this point, so cheat and use 0.
+ */
+ PangoGlyph unk = PANGO_GET_UNKNOWN_GLYPH (0);
+
+ glyphs->glyphs[ng+glyphix].glyph = unk;
+ pango_font_get_glyph_extents (font, unk, NULL, &logical_rect);
+ glyphs->glyphs[ng+glyphix].geometry.width = logical_rect.width;
+ glyphs->glyphs[ng+glyphix].geometry.x_offset = 0;
+ glyphs->glyphs[ng+glyphix].geometry.y_offset = 0;
+ }
+ }
+ }
+
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ {
+ g_print (" Pango log_clusters (level:%d), char index:", analysis->level);
+ for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++)
+ g_print ("%d ", glyphs->log_clusters[glyphix]);
+ g_print ("\n");
+ }
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+uniscribe_shape (PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ wchar_t *wtext;
+ long wlen;
+ int i;
+ gboolean retval = TRUE;
+ SCRIPT_CACHE script_cache[100];
+
+ if (!pango_win32_font_select_font (font, hdc))
+ return FALSE;
+
+ wtext = g_utf8_to_utf16 (text, length, NULL, &wlen, NULL);
+ if (wtext == NULL)
+ retval = FALSE;
+
+ if (retval)
+ {
+ memset (script_cache, 0, sizeof (script_cache));
+ retval = itemize_shape_and_place (font, hdc, wtext, wlen, analysis, glyphs, script_cache);
+ for (i = 0; i < G_N_ELEMENTS (script_cache); i++)
+ if (script_cache[i])
+ (*script_free_cache)(&script_cache[i]);
+ }
+
+ if (retval)
+ {
+ convert_log_clusters_to_byte_offsets (text, length, glyphs);
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ {
+ int glyphix;
+
+ g_print (" Pango log_clusters, byte offsets:");
+ for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++)
+ g_print ("%d ", glyphs->log_clusters[glyphix]);
+ g_print ("\n");
+ }
+#endif
+ }
+
+ pango_win32_font_done_font (font);
+
+ g_free (wtext);
+
+ return retval && glyphs->num_glyphs > 0;
+}
+
+static gboolean
+text_is_simple (const char *text,
+ gint length)
+{
+ gboolean retval;
+ wchar_t *wtext;
+ long wlen;
+
+ wtext = (wchar_t *) g_utf8_to_utf16 (text, length, NULL, &wlen, NULL);
+ if (wtext == NULL)
+ return TRUE;
+
+ retval = ((*script_is_complex) (wtext, wlen, SIC_COMPLEX) == S_FALSE);
+
+ g_free (wtext);
+
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ g_print ("text_is_simple: %.*s (%ld wchar_t): %s\n",
+ MIN (length, 10), text, wlen, retval ? "YES" : "NO");
+#endif
+
+ return retval;
+}
+
+static void
+basic_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ int n_chars;
+ int i;
+ const char *p;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ if (have_uniscribe &&
+ !text_is_simple (text, length) &&
+ uniscribe_shape (font, text, length, analysis, glyphs))
+ return;
+
+ n_chars = g_utf8_strlen (text, length);
+
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ p = text;
+ for (i = 0; i < n_chars; i++)
+ {
+ gunichar wc;
+ gunichar mirrored_ch;
+ PangoGlyph index;
+
+ wc = g_utf8_get_char (p);
+
+ if (analysis->level % 2)
+ if (pango_get_mirror_char (wc, &mirrored_ch))
+ wc = mirrored_ch;
+
+ if (wc == 0xa0) /* non-break-space */
+ wc = 0x20;
+
+ if (pango_is_zero_width (wc))
+ {
+ set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
+ }
+ else
+ {
+ index = find_char (font, wc);
+ if (index)
+ {
+ set_glyph (font, glyphs, i, p - text, index);
+
+ if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
+ {
+ if (i > 0)
+ {
+ PangoRectangle logical_rect, ink_rect;
+
+ glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
+ glyphs->glyphs[i].geometry.width);
+ glyphs->glyphs[i-1].geometry.width = 0;
+ glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
+
+ /* Some heuristics to try to guess how overstrike glyphs are
+ * done and compensate
+ */
+ /* FIXME: (alex) Is this double call to get_glyph_extents really necessary? */
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
+ if (logical_rect.width == 0 && ink_rect.x == 0)
+ glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
+ }
+ }
+ }
+ else
+ set_glyph (font, glyphs, i, p - text, PANGO_GET_UNKNOWN_GLYPH (wc));
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ /* Simple bidi support... may have separate modules later */
+
+ if (analysis->level % 2)
+ {
+ int start, end;
+
+ /* Swap all glyphs */
+ swap_range (glyphs, 0, n_chars);
+
+ /* Now reorder glyphs within each cluster back to LTR */
+ for (start = 0; start < n_chars;)
+ {
+ end = start;
+ while (end < n_chars &&
+ glyphs->log_clusters[end] == glyphs->log_clusters[start])
+ end++;
+
+ swap_range (glyphs, start, end);
+ start = end;
+ }
+ }
+}
+
+static void
+init_uniscribe (void)
+{
+ HMODULE usp10_dll;
+
+ have_uniscribe = FALSE;
+
+ if ((usp10_dll = LoadLibrary ("usp10.dll")) != NULL)
+ {
+ (script_get_properties = (pScriptGetProperties)
+ GetProcAddress (usp10_dll, "ScriptGetProperties")) &&
+ (script_itemize = (pScriptItemize)
+ GetProcAddress (usp10_dll, "ScriptItemize")) &&
+ (script_shape = (pScriptShape)
+ GetProcAddress (usp10_dll, "ScriptShape")) &&
+ (script_place = (pScriptPlace)
+ GetProcAddress (usp10_dll, "ScriptPlace")) &&
+ (script_free_cache = (pScriptFreeCache)
+ GetProcAddress (usp10_dll, "ScriptFreeCache")) &&
+ (script_is_complex = (pScriptIsComplex)
+ GetProcAddress (usp10_dll, "ScriptIsComplex")) &&
+ (have_uniscribe = TRUE);
+ }
+ if (have_uniscribe)
+ {
+#ifdef BASIC_WIN32_DEBUGGING
+ (*script_get_properties) (&scripts, &nscripts);
+#endif
+ hdc = pango_win32_get_dc ();
+ }
+}
+
+static void
+basic_engine_win32_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = basic_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineWin32, basic_engine_win32,
+ basic_engine_win32_class_init, NULL);
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ init_uniscribe ();
+
+ if (pango_win32_get_debug_flag ())
+ pango_win32_debug = TRUE;
+
+ basic_engine_win32_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ init_uniscribe ();
+
+ script_engines[0].scripts = basic_scripts;
+ script_engines[0].n_scripts = G_N_ELEMENTS (basic_scripts);
+
+ if (have_uniscribe)
+ {
+#if 0
+ int i;
+ GArray *ranges = g_array_new (FALSE, FALSE, sizeof (PangoEngineRange));
+
+ /* Walk through scripts supported by the Uniscribe implementation on this
+ * machine, and mark corresponding Unicode ranges.
+ */
+ for (i = 0; i < nscripts; i++)
+ {
+ }
+
+ /* Sort range array */
+ g_array_sort (ranges, compare_range);
+ script_engines[0].ranges = ranges;
+ script_engines[0].n_ranges = ranges->len;
+#else
+ script_engines[0].scripts = uniscribe_scripts;
+ script_engines[0].n_scripts = G_N_ELEMENTS (uniscribe_scripts);
+#endif
+ }
+
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (basic_engine_win32_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/basic/basic-x.c b/trunk/modules/basic/basic-x.c
new file mode 100644
index 00000000..471b043b
--- /dev/null
+++ b/trunk/modules/basic/basic-x.c
@@ -0,0 +1,720 @@
+/* Pango
+ * basic.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <string.h>
+#include "pango-engine.h"
+#include "pango-utils.h"
+
+#undef PANGO_DISABLE_DEPRECATED
+#include "pangox.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape BasicEngineX;
+typedef PangoEngineShapeClass BasicEngineXClass ;
+
+typedef struct _CharRange CharRange;
+typedef struct _Charset Charset;
+typedef struct _CharsetOrdering CharsetOrdering;
+typedef struct _CharCache CharCache;
+typedef struct _CharCachePointer CharCachePointer;
+typedef struct _MaskTable MaskTable;
+
+typedef PangoGlyph (*ConvFunc) (CharCache *cache,
+ GIConv cd,
+ const gchar *input);
+
+#define MAX_CHARSETS 32
+
+#define SCRIPT_ENGINE_NAME "BasicScriptEngineX"
+
+struct _Charset
+{
+ int index;
+ const char *id;
+ const char *x_charset;
+ ConvFunc conv_func;
+};
+
+struct _CharsetOrdering
+{
+ const char *langs;
+ char charsets[MAX_CHARSETS];
+};
+
+struct _CharRange
+{
+ guint16 start;
+ guint16 end;
+ guint16 charsets;
+};
+
+struct _MaskTable
+{
+ int n_subfonts;
+
+ PangoXSubfont *subfonts;
+ Charset **charsets;
+};
+
+struct _CharCache
+{
+ guint ref_count;
+ CharsetOrdering *ordering;
+ MaskTable *mask_tables[256];
+ GIConv converters[MAX_CHARSETS];
+ PangoCoverage *coverage;
+};
+
+struct _CharCachePointer
+{
+ PangoLanguage *lang;
+ CharCache *cache;
+};
+
+static PangoGlyph conv_8bit (CharCache *cache,
+ GIConv cd,
+ const char *input);
+static PangoGlyph conv_eucjp (CharCache *cache,
+ GIConv cd,
+ const char *input);
+static PangoGlyph conv_16bit (CharCache *cache,
+ GIConv cd,
+ const char *input);
+static PangoGlyph conv_ucs4 (CharCache *cache,
+ GIConv cd,
+ const char *input);
+static PangoGlyph conv_16bit_MSB_on (CharCache *cache,
+ GIConv cd,
+ const char *input);
+static PangoGlyph conv_gb18030_1 (CharCache *cache,
+ GIConv cd,
+ const char *input);
+static PangoGlyph conv_euctw (CharCache *cache,
+ GIConv cd,
+ const char *input);
+
+#include "tables-big.i"
+
+static PangoEngineScriptInfo basic_scripts[] = {
+ { PANGO_SCRIPT_COMMON, "" },
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ PANGO_RENDER_TYPE_X,
+ basic_scripts, G_N_ELEMENTS(basic_scripts)
+ }
+};
+
+/*
+ * X window system script engine portion
+ */
+
+/* Structure of our cache:
+ *
+ * PangoFont => CharCachePointer ===\
+ * | \
+ * CharCachePointer ======> CharCache => CharsetOrdering
+ * | |======> MaskTable[0] => {subfonts,charset}[n_subfonts],
+ * | |======> MaskTable[1] => {subfonts,charset}[n_subfonts],
+ * | \======> MaskTable[...] => {subfonts,charset}[n_subfonts]
+ * |
+ * CharCachePointer ======> CharCache => CharsetOrdering
+ * |======> MaskTable[0] => {subfonts,charset}[n_subfonts],
+ * |======> MaskTable[1] => {subfonts,charset}[n_subfonts],
+ * \======> MaskTable[...] => {subfonts,charset}[n_subfonts]
+ *
+ * A CharCache structure caches the lookup of what subfonts can be used for what characters for a pair of a Font
+ * and CharsetOrdering. Multiple language tags can share the same CharsetOrdering - the list of CharCachePointer
+ * structures that is attached to the font as object data provides lookups from language tag to charcache.
+ */
+static CharCache *
+char_cache_new (CharsetOrdering *ordering)
+{
+ CharCache *result;
+ int i;
+
+ result = g_new0 (CharCache, 1);
+
+ result->ref_count = 1;
+ result->ordering = ordering;
+ for (i=0; i<MAX_CHARSETS; i++)
+ result->converters[i] = (GIConv)-1;
+
+ return result;
+}
+
+static void
+char_cache_free (CharCache *cache)
+{
+ int i;
+
+ for (i=0; i<256; i++)
+ if (cache->mask_tables[i])
+ {
+ g_free (cache->mask_tables[i]->subfonts);
+ g_free (cache->mask_tables[i]->charsets);
+
+ g_free (cache->mask_tables[i]);
+ }
+
+ for (i=0; i<MAX_CHARSETS; i++)
+ if (cache->converters[i] != (GIConv)-1)
+ g_iconv_close (cache->converters[i]);
+
+ g_free (cache);
+}
+
+static PangoGlyph
+find_char (CharCache *cache, PangoFont *font, gunichar wc, const char *input)
+{
+ int mask_index;
+ MaskTable *mask_table;
+ int i;
+
+ switch (wc)
+ {
+ case '\n':
+ case '\r':
+ case 0x2028: /* Line separator */
+ case 0x2029: /* Paragraph separator */
+ return PANGO_GET_UNKNOWN_GLYPH (wc);
+ break;
+ }
+
+ if (wc >= G_N_ELEMENTS (char_masks))
+ mask_index = 0;
+ else
+ mask_index = char_masks[wc];
+
+ if (cache->mask_tables[mask_index])
+ mask_table = cache->mask_tables[mask_index];
+ else
+ {
+ const char *charset_names[G_N_ELEMENTS(charsets)];
+ Charset *charsets_map[G_N_ELEMENTS(charsets)];
+ guint mask;
+ int n_charsets = 0;
+ int *subfont_charsets;
+
+ mask_table = g_new (MaskTable, 1);
+
+ mask = char_mask_map[mask_index] | ENC_ISO_10646;
+
+ /* Find the character sets that are included in this mask
+ */
+
+ for (i=0; i<(int)G_N_ELEMENTS(charsets); i++)
+ {
+ int charset_index = cache->ordering->charsets[i];
+
+ if (mask & (1 << charset_index))
+ {
+ charset_names[n_charsets] = charsets[charset_index].x_charset;
+ charsets_map[n_charsets] = &charsets[charset_index];
+
+ n_charsets++;
+ }
+ }
+
+ mask_table->n_subfonts = pango_x_list_subfonts (font, (char**)charset_names, n_charsets, &mask_table->subfonts, &subfont_charsets);
+
+ mask_table->charsets = g_new (Charset *, mask_table->n_subfonts);
+ for (i=0; i<mask_table->n_subfonts; i++)
+ mask_table->charsets[i] = charsets_map[subfont_charsets[i]];
+
+ g_free (subfont_charsets);
+
+ cache->mask_tables[mask_index] = mask_table;
+ }
+
+ for (i=0; i < mask_table->n_subfonts; i++)
+ {
+ PangoGlyph index;
+ PangoGlyph glyph;
+ Charset *charset;
+
+ charset = mask_table->charsets[i];
+ if (charset)
+ {
+ GIConv cd = cache->converters[charset->index];
+
+ if (charset->id && cd == (GIConv)-1)
+ {
+ cd = g_iconv_open (charset->id, "UTF-8");
+ if (cd == (GIConv)-1)
+ {
+ g_warning ("Could not load converter from %s to UTF-8", charset->id);
+ mask_table->charsets[i] = NULL;
+ continue;
+ }
+
+ cache->converters[charset->index] = cd;
+ }
+
+ index = (*charset->conv_func) (cache, cd, input);
+ glyph = PANGO_X_MAKE_GLYPH (mask_table->subfonts[i], index);
+
+ if (pango_x_has_glyph (font, glyph))
+ return glyph;
+ }
+ }
+
+ return 0;
+}
+
+static void
+set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGlyph glyph)
+{
+ PangoRectangle logical_rect;
+
+ glyphs->glyphs[i].glyph = glyph;
+
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+
+ glyphs->log_clusters[i] = offset;
+
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+}
+
+static PangoGlyph
+conv_8bit (CharCache *cache,
+ GIConv cd,
+ const char *input)
+{
+ char outbuf;
+
+ const char *inptr = input;
+ size_t inbytesleft;
+ char *outptr = &outbuf;
+ size_t outbytesleft = 1;
+
+ inbytesleft = g_utf8_next_char (input) - input;
+
+ g_iconv (cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
+
+ return (guchar)outbuf;
+}
+
+static PangoGlyph
+conv_eucjp (CharCache *cache,
+ GIConv cd,
+ const char *input)
+{
+ char outbuf[4];
+
+ const char *inptr = input;
+ size_t inbytesleft;
+ char *outptr = outbuf;
+ size_t outbytesleft = 4;
+
+ inbytesleft = g_utf8_next_char (input) - input;
+
+ g_iconv (cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
+
+ if ((guchar)outbuf[0] < 128)
+ return outbuf[0];
+ else if ((guchar)outbuf[0] == 0x8e && outbytesleft == 2)
+ return ((guchar)outbuf[1]);
+ else if ((guchar)outbuf[0] == 0x8f && outbytesleft == 1)
+ return ((guchar)outbuf[1] & 0x7f) * 256 + ((guchar)outbuf[2] & 0x7f);
+ else
+ return ((guchar)outbuf[0] & 0x7f) * 256 + ((guchar)outbuf[1] & 0x7f);
+}
+
+static PangoGlyph
+conv_16bit (CharCache *cache,
+ GIConv cd,
+ const char *input)
+{
+ char outbuf[2];
+
+ const char *inptr = input;
+ size_t inbytesleft;
+ char *outptr = outbuf;
+ size_t outbytesleft = 2;
+
+ inbytesleft = g_utf8_next_char (input) - input;
+
+ g_iconv (cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
+
+ if ((guchar)outbuf[0] < 128)
+ return outbuf[0];
+ else
+ return ((guchar)outbuf[0] & 0x7f) * 256 + ((guchar)outbuf[1] & 0x7f);
+}
+
+static PangoGlyph
+conv_16bit_MSB_on (CharCache *cache,
+ GIConv cd,
+ const char *input)
+{
+ char outbuf[2];
+
+ const char *inptr = input;
+ size_t inbytesleft;
+ char *outptr = outbuf;
+ size_t outbytesleft = 2;
+
+ inbytesleft = g_utf8_next_char (input) - input;
+
+ g_iconv (cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
+
+ if ((guchar)outbuf[0] < 128)
+ return outbuf[0];
+ else
+ return (guchar)outbuf[0] * 256 + (guchar)outbuf[1];
+}
+
+static PangoGlyph
+conv_gb18030_1 (CharCache *cache,
+ GIConv cd,
+ const char *input)
+{
+ char outbuf[4];
+
+ const char *inptr = input;
+ size_t inbytesleft;
+ char *outptr = outbuf;
+ size_t outbytesleft = 4;
+
+
+ inbytesleft = g_utf8_next_char (input) - input;
+
+ g_iconv (cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
+
+ if ((guchar)outbuf[0] < 128)
+ return outbuf[0];
+ else
+ return 12600 * ((guchar)outbuf[0] - 0x81) + 1260 * ((guchar)outbuf[1] - 0x30) + 10 * ((guchar)outbuf[2] - 0x81) + ((guchar)outbuf[3] - 0x30);
+}
+
+static PangoGlyph
+conv_euctw (CharCache *cache,
+ GIConv cd,
+ const char *input)
+{
+ char outbuf[4];
+
+ const char *inptr = input;
+ size_t inbytesleft;
+ char *outptr = outbuf;
+ size_t outbytesleft = 4;
+
+ inbytesleft = g_utf8_next_char (input) - input;
+
+ g_iconv (cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
+
+ /* The first two bytes determine which page of CNS to use; we
+ * get this information from tables-big.i, so ignore them
+ */
+ if ((guchar)outbuf[0] < 128)
+ return outbuf[0];
+ else
+ return ((guchar)outbuf[2] & 0x7f) * 256 + ((guchar)outbuf[3] & 0x7f);
+}
+
+static PangoGlyph
+conv_ucs4 (CharCache *cache,
+ GIConv cd,
+ const char *input)
+{
+ return g_utf8_get_char (input);
+}
+
+static void
+swap_range (PangoGlyphString *glyphs, int start, int end)
+{
+ int i, j;
+
+ for (i = start, j = end - 1; i < j; i++, j--)
+ {
+ PangoGlyphInfo glyph_info;
+ gint log_cluster;
+
+ glyph_info = glyphs->glyphs[i];
+ glyphs->glyphs[i] = glyphs->glyphs[j];
+ glyphs->glyphs[j] = glyph_info;
+
+ log_cluster = glyphs->log_clusters[i];
+ glyphs->log_clusters[i] = glyphs->log_clusters[j];
+ glyphs->log_clusters[j] = log_cluster;
+ }
+}
+
+static void
+char_caches_free (GSList *caches)
+{
+ GSList *tmp_list = caches;
+ while (tmp_list)
+ {
+ CharCachePointer *pointer = tmp_list->data;
+
+ pointer->cache->ref_count--;
+ if (pointer->cache->ref_count == 0)
+ char_cache_free (pointer->cache);
+ g_free (pointer);
+
+ tmp_list = tmp_list->next;
+ }
+ g_slist_free (caches);
+}
+
+static CharsetOrdering *
+ordering_for_lang (PangoLanguage *lang)
+{
+ int i;
+
+ for (i = 0; i < (int)G_N_ELEMENTS (charset_orderings) - 1; i++)
+ {
+ if (pango_language_matches (lang, charset_orderings[i].langs))
+ return &charset_orderings[i];
+ }
+
+ return &charset_orderings[i];
+}
+
+static CharCache *
+get_char_cache (PangoFont *font,
+ PangoLanguage *lang)
+{
+ GQuark cache_id = g_quark_from_string ("basic-char-cache");
+ CharCache *cache = NULL;
+ CharCachePointer *pointer;
+ CharsetOrdering *ordering;
+ GSList *caches;
+ GSList *tmp_list;
+
+ caches = g_object_get_qdata (G_OBJECT (font), cache_id);
+ tmp_list = caches;
+ while (tmp_list)
+ {
+ pointer = tmp_list->data;
+ if (pointer->lang == lang)
+ return pointer->cache;
+
+ tmp_list = tmp_list->next;
+ }
+
+ ordering = ordering_for_lang (lang);
+
+ tmp_list = caches;
+ while (tmp_list)
+ {
+ pointer = tmp_list->data;
+ if (pointer->cache->ordering == ordering)
+ {
+ cache = pointer->cache;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!cache)
+ cache = char_cache_new (ordering);
+ else
+ cache->ref_count++;
+
+ pointer = g_new (CharCachePointer, 1);
+ pointer->lang = lang;
+ pointer->cache = cache;
+
+ caches = g_slist_prepend (caches, pointer);
+
+ g_object_steal_qdata (G_OBJECT (font), cache_id);
+ g_object_set_qdata_full (G_OBJECT (font), cache_id,
+ caches, (GDestroyNotify)char_caches_free);
+
+ return cache;
+}
+
+static void
+basic_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ int n_chars;
+ int i;
+ const char *p;
+
+ CharCache *cache;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ cache = get_char_cache (font, analysis->language);
+
+ n_chars = g_utf8_strlen (text, length);
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ gunichar wc;
+ gunichar mirrored_ch;
+ PangoGlyph index;
+ char buf[6];
+ const char *input;
+
+ wc = g_utf8_get_char (p);
+
+ input = p;
+ if (analysis->level % 2)
+ if (pango_get_mirror_char (wc, &mirrored_ch))
+ {
+ wc = mirrored_ch;
+
+ g_unichar_to_utf8 (wc, buf);
+ input = buf;
+ }
+
+ if (wc == 0xa0) /* non-break-space */
+ {
+ wc = 0x20;
+
+ g_unichar_to_utf8 (wc, buf);
+ input = buf;
+ }
+
+ if (pango_is_zero_width (wc))
+ {
+ set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
+ }
+ else
+ {
+ index = find_char (cache, font, wc, input);
+ if (index)
+ {
+ set_glyph (font, glyphs, i, p - text, index);
+
+ if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
+ {
+ if (i > 0)
+ {
+ PangoRectangle logical_rect, ink_rect;
+
+ glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
+ glyphs->glyphs[i].geometry.width);
+ glyphs->glyphs[i-1].geometry.width = 0;
+ glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
+
+ /* Some heuristics to try to guess how overstrike glyphs are
+ * done and compensate
+ */
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
+ if (logical_rect.width == 0 && ink_rect.x == 0)
+ glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
+ }
+ }
+ }
+ else
+ set_glyph (font, glyphs, i, p - text, PANGO_GET_UNKNOWN_GLYPH (wc));
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ /* Simple bidi support... may have separate modules later */
+
+ if (analysis->level % 2)
+ {
+ int start, end;
+
+ /* Swap all glyphs */
+ swap_range (glyphs, 0, n_chars);
+
+ /* Now reorder glyphs within each cluster back to LTR */
+ for (start=0; start<n_chars;)
+ {
+ end = start;
+ while (end < n_chars &&
+ glyphs->log_clusters[end] == glyphs->log_clusters[start])
+ end++;
+
+ swap_range (glyphs, start, end);
+ start = end;
+ }
+ }
+}
+
+static PangoCoverageLevel
+basic_engine_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *lang,
+ gunichar wc)
+{
+ CharCache *cache = get_char_cache (font, lang);
+ char buf[6];
+
+ g_unichar_to_utf8 (wc, buf);
+
+ return find_char (cache, font, wc, buf) ? PANGO_COVERAGE_EXACT : PANGO_COVERAGE_NONE;
+}
+
+static void
+basic_engine_x_class_init (PangoEngineShapeClass *class)
+{
+ class->covers = basic_engine_covers;
+ class->script_shape = basic_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineX, basic_engine_x,
+ basic_engine_x_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ basic_engine_x_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (basic_engine_x_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/basic/tables-big.i b/trunk/modules/basic/tables-big.i
new file mode 100644
index 00000000..7cca755a
--- /dev/null
+++ b/trunk/modules/basic/tables-big.i
@@ -0,0 +1,4397 @@
+enum {
+ ENC_ISO_8859_1 = 1 << 0,
+ ENC_ISO_8859_2 = 1 << 1,
+ ENC_ISO_8859_3 = 1 << 2,
+ ENC_ISO_8859_4 = 1 << 3,
+ ENC_ISO_8859_5 = 1 << 4,
+ ENC_ISO_8859_6 = 1 << 5,
+ ENC_ISO_8859_7 = 1 << 6,
+ ENC_ISO_8859_8 = 1 << 7,
+ ENC_ISO_8859_9 = 1 << 8,
+ ENC_ISO_8859_10 = 1 << 9,
+ ENC_ISO_8859_13 = 1 << 10,
+ ENC_ISO_8859_14 = 1 << 11,
+ ENC_ISO_8859_15 = 1 << 12,
+ ENC_KOI8_R = 1 << 13,
+ ENC_TIS_620 = 1 << 14,
+ ENC_JIS_0208 = 1 << 15,
+ ENC_GB_2312 = 1 << 16,
+ ENC_KSC_5601 = 1 << 17,
+ ENC_JIS_0201 = 1 << 18,
+ ENC_JIS_0212 = 1 << 19,
+ ENC_BIG5_1 = 1 << 20,
+ ENC_BIG5 = 1 << 21,
+ ENC_GB18030_0 = 1 << 22,
+ ENC_GB18030_1 = 1 << 23,
+ ENC_HKSCS_1 = 1 << 24,
+ ENC_CNS11643_1 = 1 << 25,
+ ENC_CNS11643_2 = 1 << 26,
+ ENC_CNS11643_3 = 1 << 27,
+ ENC_GBK = 1 << 28,
+ ENC_ISO_10646 = 1 << 29
+};
+
+static Charset charsets[] = {
+ { 0, NULL, "iso8859-1", conv_ucs4 },
+ { 1, "ISO-8859-2", "iso8859-2", conv_8bit },
+ { 2, "ISO-8859-3", "iso8859-3", conv_8bit },
+ { 3, "ISO-8859-4", "iso8859-4", conv_8bit },
+ { 4, "ISO-8859-5", "iso8859-5", conv_8bit },
+ { 5, "ISO-8859-6", "iso8859-6", conv_8bit },
+ { 6, "ISO-8859-7", "iso8859-7", conv_8bit },
+ { 7, "ISO-8859-8", "iso8859-8", conv_8bit },
+ { 8, "ISO-8859-9", "iso8859-9", conv_8bit },
+ { 9, "ISO-8859-10", "iso8859-10", conv_8bit },
+ { 10, "ISO-8859-13", "iso8859-13", conv_8bit },
+ { 11, "ISO-8859-14", "iso8859-14", conv_8bit },
+ { 12, "ISO-8859-15", "iso8859-15", conv_8bit },
+ { 13, "KOI8-R", "koi8-r", conv_8bit },
+ { 14, "TIS-620", "tis620.2529-1", conv_8bit },
+ { 15, "EUC-JP", "jisx0208.1983-0", conv_eucjp },
+ { 16, "GB2312", "gb2312.1980-0", conv_16bit },
+ { 17, "EUC-KR", "ksc5601.1987-0", conv_16bit },
+ { 18, "EUC-JP", "jisx0201.1976-0", conv_eucjp },
+ { 19, "EUC-JP", "jisx0212.1990-0", conv_eucjp },
+ { 20, "BIG5", "big5-1", conv_16bit_MSB_on },
+ { 21, "BIG5", "big5-0", conv_16bit_MSB_on },
+ { 22, "GB18030", "gb18030.2000-0", conv_16bit_MSB_on },
+ { 23, "GB18030", "gb18030.2000-1", conv_gb18030_1 },
+ { 24, "BIG5-HKSCS", "hkscs-1", conv_16bit_MSB_on },
+ { 25, "EUC-TW", "cns11643-1", conv_16bit },
+ { 26, "EUC-TW", "cns11643-2", conv_euctw },
+ { 27, "EUC-TW", "cns11643-3", conv_euctw },
+ { 28, "GBK", "gbk-0", conv_16bit_MSB_on },
+ { 29, NULL, "iso10646-1", conv_ucs4 }
+};
+
+static CharsetOrdering charset_orderings[] = {
+ { "ja", { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 16, 17, 20, 21, 24, 25, 26, 27, 28, 22, 23, 29} },
+ { "ko", { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 15, 16, 18, 19, 20, 21, 24, 25, 26, 27, 28, 22, 23, 29} },
+ { "zh-cn", { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 28, 22, 23, 16, 17, 15, 18, 19, 20, 21, 24, 25, 26, 27, 29} },
+ { "zh-tw", { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21, 25, 26, 27, 24, 22, 23, 16, 17, 15, 18, 19, 28, 29} },
+ { "zh-hk", { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 24, 20, 21, 25, 26, 27, 22, 23, 16, 17, 15, 18, 19, 28, 29} },
+ { "zh", { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 28, 22, 23, 16, 17, 15, 18, 19, 20, 21, 24, 25, 26, 27, 29} },
+ { NULL, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 29, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28} }
+};
+static const guint32 char_mask_map[] = {
+ 0,
+ ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_6|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KOI8_R,
+ ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_6|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0201|ENC_KOI8_R|ENC_TIS_620,
+ ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_6|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KOI8_R|ENC_TIS_620,
+ ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_6|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KOI8_R|ENC_TIS_620,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_6|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_6|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KOI8_R,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_15|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_6|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_15|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0201,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KOI8_R,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_6|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_15|ENC_ISO_8859_4|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KOI8_R|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KOI8_R|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KOI8_R|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_3|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_HKSCS_1|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_15|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_JIS_0212,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_15|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_8|ENC_ISO_8859_9|ENC_JIS_0208|ENC_KOI8_R|ENC_KSC_5601,
+ ENC_GB18030_1|ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_1|ENC_ISO_8859_13|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_4|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_1|ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_13|ENC_ISO_8859_4|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_13|ENC_ISO_8859_4|ENC_JIS_0212,
+ ENC_ISO_8859_2|ENC_JIS_0212,
+ ENC_ISO_8859_10|ENC_ISO_8859_13|ENC_ISO_8859_2|ENC_ISO_8859_4|ENC_JIS_0212,
+ ENC_ISO_8859_13|ENC_ISO_8859_2|ENC_JIS_0212,
+ ENC_ISO_8859_3|ENC_JIS_0212,
+ ENC_ISO_8859_14|ENC_ISO_8859_3|ENC_JIS_0212,
+ ENC_ISO_8859_10|ENC_ISO_8859_2|ENC_ISO_8859_4|ENC_JIS_0212,
+ ENC_ISO_8859_10|ENC_ISO_8859_2|ENC_ISO_8859_4|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_10|ENC_ISO_8859_13|ENC_ISO_8859_4|ENC_JIS_0212,
+ ENC_HKSCS_1|ENC_ISO_8859_2|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_2|ENC_JIS_0212,
+ ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_ISO_8859_10|ENC_ISO_8859_13|ENC_ISO_8859_4,
+ ENC_ISO_8859_3|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_10|ENC_ISO_8859_4|ENC_JIS_0212,
+ ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_10|ENC_ISO_8859_4|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_13|ENC_ISO_8859_2|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GBK|ENC_ISO_8859_13|ENC_ISO_8859_2|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GBK|ENC_ISO_8859_2|ENC_JIS_0212,
+ ENC_HKSCS_1|ENC_ISO_8859_10|ENC_ISO_8859_4|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_15|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_HKSCS_1|ENC_ISO_8859_15|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_13|ENC_ISO_8859_4|ENC_JIS_0212,
+ ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_9|ENC_JIS_0212,
+ ENC_ISO_8859_10|ENC_ISO_8859_13|ENC_ISO_8859_15|ENC_ISO_8859_2|ENC_ISO_8859_4|ENC_JIS_0212,
+ ENC_ISO_8859_14|ENC_JIS_0212,
+ ENC_ISO_8859_14|ENC_ISO_8859_15|ENC_JIS_0212,
+ ENC_ISO_8859_13|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_JIS_0212,
+ ENC_HKSCS_1|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0212,
+ ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GBK,
+ ENC_HKSCS_1,
+ ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_2|ENC_ISO_8859_4|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK,
+ ENC_KSC_5601,
+ ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_2|ENC_ISO_8859_4|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_2|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_ISO_8859_7|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_7|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_5|ENC_JIS_0208|ENC_KOI8_R|ENC_KSC_5601,
+ ENC_ISO_8859_5|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_5|ENC_JIS_0208|ENC_KOI8_R|ENC_KSC_5601,
+ ENC_ISO_8859_8,
+ ENC_GB18030_1|ENC_ISO_8859_6,
+ ENC_GB18030_1,
+ ENC_TIS_620,
+ ENC_ISO_8859_14,
+ ENC_GB18030_0|ENC_GBK|ENC_JIS_0208,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_10|ENC_ISO_8859_7|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_13|ENC_ISO_8859_7|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_ISO_8859_13|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_ISO_8859_13,
+ ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_JIS_0201,
+ ENC_GB18030_0|ENC_GBK|ENC_ISO_8859_15,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_ISO_8859_5|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK,
+ ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_KSC_5601,
+ ENC_JIS_0208,
+ ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK,
+ ENC_KOI8_R,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208|ENC_KOI8_R|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_0|ENC_GBK,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_KOI8_R,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_KOI8_R|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_JIS_0208,
+ ENC_CNS11643_1,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_KOI8_R,
+ ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_KOI8_R,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_KOI8_R,
+ ENC_KOI8_R|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GBK|ENC_KOI8_R,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208,
+ ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208,
+ ENC_CNS11643_1|ENC_GB_2312|ENC_JIS_0208,
+ ENC_CNS11643_3|ENC_GB18030_1,
+ ENC_GB18030_1|ENC_HKSCS_1,
+ ENC_CNS11643_3|ENC_GB18030_1|ENC_HKSCS_1,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK,
+ ENC_GB18030_0|ENC_GBK|ENC_JIS_0212,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0212,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GBK,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_JIS_0212,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0212,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GBK|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GBK|ENC_JIS_0208,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_JIS_0208,
+ ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0212,
+ ENC_GB18030_0|ENC_GBK|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GB_2312|ENC_GBK,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0212,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GBK|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GBK|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GBK|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GBK|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0212,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0212|ENC_KSC_5601,
+ ENC_CNS11643_3|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_2|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_KSC_5601,
+ ENC_BIG5_1|ENC_BIG5|ENC_CNS11643_1|ENC_GB18030_0|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_CNS11643_1|ENC_GB18030_1,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_KSC_5601,
+ ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_HKSCS_1|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_JIS_0201,
+ ENC_BIG5_1|ENC_BIG5|ENC_JIS_0201,
+ ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_KSC_5601,
+ ENC_CNS11643_1|ENC_GB18030_0|ENC_GB_2312|ENC_GBK|ENC_JIS_0208|ENC_KSC_5601,
+ ENC_BIG5|ENC_BIG5|ENC_BIG5|ENC_BIG5|ENC_BIG5|ENC_BIG5|ENC_BIG5,
+};
+
+static const guchar char_masks[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 7, 16, 31, 32, 31, 7,
+ 33, 34, 35, 36, 37, 38, 39, 40, 33, 41, 33, 35, 42, 35, 35, 43,
+ 44, 42, 33, 45, 35, 38, 37, 46, 39, 42, 35, 47, 37, 48, 49, 50,
+ 51, 52, 35, 36, 37, 38, 39, 40, 51, 53, 51, 35, 51, 52, 35, 43,
+ 49, 42, 51, 54, 35, 38, 37, 55, 56, 51, 52, 47, 53, 48, 49, 57,
+ 58, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, 61, 61, 60, 60,
+ 65, 66, 58, 59, 0, 0, 67, 67, 61, 61, 68, 69, 63, 63, 70, 70,
+ 64, 64, 67, 71, 63, 63, 72, 72, 73, 73, 67, 59, 0, 0, 67, 67,
+ 70, 74, 75, 75, 63, 63, 67, 67, 76, 60, 60, 67, 67, 60, 60, 75,
+ 75, 77, 77, 62, 78, 67, 67, 60, 79, 75, 76, 80, 58, 59, 0, 0,
+ 60, 60, 81, 82, 60, 60, 83, 83, 60, 60, 62, 62, 63, 63, 84, 84,
+ 85, 85, 60, 60, 60, 60, 76, 76, 73, 73, 67, 59, 63, 63, 60, 60,
+ 60, 60, 67, 67, 86, 86, 86, 86, 87, 62, 62, 88, 88, 85, 85, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 90, 91,
+ 90, 89, 90, 91, 90, 91, 90, 91, 90, 91, 90, 91, 90, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 93, 94, 0, 0, 93, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0,
+ 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 93, 95, 0, 96, 97, 97, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 99, 100, 75, 101, 0, 102, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 103, 103, 103, 0, 103, 103, 103, 0, 103, 0, 103, 103,
+ 103, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
+ 104, 104, 0, 104, 104, 104, 104, 104, 104, 104, 103, 103, 103, 103, 103, 103,
+ 103, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
+ 104, 104, 103, 104, 104, 104, 104, 104, 104, 104, 103, 103, 103, 103, 103, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 105, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 0, 106, 106,
+ 107, 107, 107, 107, 105, 105, 105, 105, 105, 105, 105, 105, 105, 107, 107, 107,
+ 107, 107, 107, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
+ 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
+ 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
+ 0, 105, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 0, 106, 106,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
+ 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 110, 110, 110, 109,
+ 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
+ 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 110, 110, 110, 110, 110,
+ 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
+ 109, 109, 109, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 0, 0, 0, 0, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 112, 112, 0, 0, 0, 0, 0, 0, 112, 112, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 112, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 112, 112, 0, 0, 0, 0, 0, 0, 0, 0,
+ 112, 112, 0, 0, 0, 0, 0, 0, 0, 0, 112, 112, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 112, 112, 112, 112, 112, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93,
+ 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 112, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 108,
+ 113, 0, 0, 97, 97, 114, 115, 108, 104, 116, 0, 0, 117, 117, 118, 0,
+ 119, 119, 120, 0, 0, 121, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 123, 0, 122, 123, 0, 97, 0, 0, 0, 0, 0, 122, 0, 0, 124, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98,
+ 0, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 122, 0, 97, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 98, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 128, 75, 0, 0, 0, 98, 0, 0, 0, 0, 119, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 98, 0,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 130, 130, 0, 0, 0, 0,
+ 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 122, 122, 122, 122, 98, 98, 126, 126, 126, 126, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 119, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 119, 0, 119, 119, 0, 0, 0, 119, 123, 0, 0, 119, 0, 0, 0, 132,
+ 0, 132, 133, 0, 0, 134, 0, 0, 0, 135, 136, 0, 0, 123, 122, 97,
+ 122, 0, 0, 137, 0, 138, 0, 123, 123, 122, 122, 122, 119, 0, 129, 0,
+ 0, 0, 0, 0, 122, 122, 130, 130, 0, 0, 0, 0, 139, 123, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 130, 0, 0, 0,
+ 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 122, 122, 0, 0, 141, 141, 142, 142, 0, 0, 119, 119, 0, 0, 130, 130,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 119, 119, 0, 0, 119, 119, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 92, 0, 0, 0, 132, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 135, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143,
+ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143,
+ 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 98, 98, 98, 98, 98, 0,
+ 0, 0, 0, 0, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 132, 132,
+ 132, 132, 132, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 136, 123, 136, 123, 130, 130, 130, 130, 130, 130, 130, 130, 136, 132, 132, 123,
+ 136, 132, 132, 123, 136, 132, 132, 123, 136, 132, 132, 123, 136, 123, 132, 132,
+ 123, 132, 132, 123, 136, 123, 132, 132, 123, 132, 132, 123, 136, 132, 132, 123,
+ 123, 132, 132, 123, 136, 132, 132, 123, 123, 132, 132, 123, 136, 132, 132, 123,
+ 132, 132, 123, 132, 132, 132, 132, 132, 132, 132, 132, 123, 0, 0, 0, 0,
+ 145, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 145, 146,
+ 146, 145, 146, 146, 146, 146, 146, 146, 146, 146, 145, 146, 146, 147, 147, 147,
+ 147, 97, 97, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 135, 97, 97, 97, 148, 97, 97, 97, 148, 97, 97, 97, 148, 97, 97, 97,
+ 135, 135, 149, 150, 97, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 136, 122, 0, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 122, 122, 0, 0, 98, 98, 0, 0, 0, 0, 121, 121, 0, 0,
+ 98, 98, 0, 0, 0, 0, 122, 122, 98, 0, 0, 122, 0, 0, 122, 122,
+ 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 97, 97, 97, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 122, 122, 0, 0, 97, 0, 0, 0, 0, 98, 98,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 122, 151, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 98, 98, 98, 119, 0, 98, 119, 0, 133,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 93, 92, 0, 0, 94, 0, 93, 93, 94, 0, 93, 92, 94, 93, 0, 0,
+ 0, 0, 0, 0, 0, 93, 0, 92, 0, 0, 0, 0, 93, 93, 0, 0,
+ 0, 0, 0, 0, 0, 93, 0, 94, 0, 0, 94, 0, 93, 0, 94, 0,
+ 0, 0, 0, 92, 0, 0, 94, 92, 0, 0, 0, 92, 93, 0, 93, 0,
+ 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 94, 0, 93, 93, 0, 93,
+ 0, 0, 0, 0, 0, 0, 93, 93, 0, 0, 0, 0, 0, 0, 93, 0,
+ 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0,
+ 122, 122, 122, 122, 0, 152, 153, 153, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 142, 123, 122, 122, 130, 130, 0, 0, 0, 0, 133, 97, 97, 0,
+ 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0,
+ 0, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 0, 0, 0, 0, 0, 0, 0, 153, 153, 155, 155, 0,
+ 0, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+ 154, 154, 154, 154, 154, 154, 154, 0, 0, 0, 0, 156, 153, 153, 155, 0,
+ 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0, 0, 0,
+ 0, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 0, 0, 0, 0, 0, 0,
+ 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 98,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 98, 98, 98, 0, 0, 0, 98, 98, 98, 98, 98, 98, 126, 126,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 126, 126, 126, 98,
+ 98, 126, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 126, 98, 98, 98, 98, 98, 98, 0, 0, 0, 97, 98,
+ 98, 97, 97, 98, 0, 97, 98, 0, 98, 0, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 157, 110, 110, 157, 110, 110, 110, 157, 157, 110, 157, 110, 110, 157, 110,
+ 110, 157, 157, 157, 157, 158, 110, 110, 110, 157, 110, 157, 157, 110, 110, 110,
+ 158, 110, 157, 157, 157, 110, 110, 92, 110, 157, 110, 110, 158, 157, 110, 110,
+ 110, 157, 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 110, 157, 110, 110,
+ 110, 110, 110, 110, 159, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157,
+ 157, 110, 110, 94, 157, 110, 110, 110, 110, 110, 159, 157, 157, 159, 158, 110,
+ 110, 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 157, 157, 157, 110, 110,
+ 110, 110, 157, 159, 110, 157, 159, 157, 110, 157, 110, 110, 110, 157, 157, 110,
+ 110, 110, 110, 110, 110, 159, 157, 110, 110, 110, 157, 110, 110, 110, 110, 159,
+ 157, 110, 157, 157, 110, 110, 110, 157, 157, 110, 157, 110, 158, 110, 110, 110,
+ 110, 158, 157, 157, 110, 157, 110, 157, 159, 110, 157, 157, 157, 110, 110, 157,
+ 157, 157, 110, 110, 157, 157, 110, 157, 110, 110, 110, 110, 157, 110, 110, 158,
+ 110, 110, 110, 110, 158, 110, 110, 157, 157, 157, 110, 110, 110, 110, 157, 157,
+ 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 159, 110, 157, 110, 110,
+ 110, 110, 110, 157, 157, 110, 158, 157, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 157, 110,
+ 110, 110, 157, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110,
+ 110, 110, 157, 110, 110, 110, 110, 110, 110, 157, 110, 157, 110, 157, 158, 110,
+ 110, 110, 157, 110, 157, 157, 157, 157, 157, 110, 157, 157, 110, 157, 110, 110,
+ 110, 159, 110, 158, 157, 157, 157, 110, 157, 110, 110, 157, 157, 110, 110, 110,
+ 157, 159, 110, 110, 157, 157, 157, 157, 110, 157, 110, 157, 157, 158, 110, 157,
+ 158, 157, 159, 157, 110, 110, 157, 159, 159, 110, 157, 110, 110, 110, 110, 110,
+ 157, 157, 157, 157, 159, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110,
+ 157, 110, 157, 157, 110, 110, 110, 159, 158, 110, 110, 110, 110, 110, 92, 157,
+ 157, 158, 110, 157, 157, 158, 157, 110, 110, 110, 110, 110, 110, 158, 110, 110,
+ 110, 110, 110, 110, 157, 110, 110, 157, 110, 157, 157, 110, 110, 157, 157, 159,
+ 110, 159, 110, 157, 110, 158, 110, 159, 110, 110, 158, 157, 110, 157, 158, 110,
+ 157, 110, 158, 110, 110, 110, 159, 110, 110, 110, 157, 159, 110, 158, 110, 110,
+ 110, 110, 110, 157, 157, 157, 110, 110, 110, 157, 157, 110, 110, 110, 110, 110,
+ 110, 158, 158, 159, 110, 157, 110, 110, 110, 110, 110, 158, 110, 157, 158, 110,
+ 110, 157, 157, 110, 110, 110, 110, 157, 110, 158, 110, 110, 157, 110, 92, 110,
+ 110, 110, 110, 110, 157, 157, 110, 110, 158, 157, 160, 110, 110, 157, 157, 157,
+ 110, 157, 157, 159, 110, 110, 157, 157, 110, 157, 157, 110, 157, 159, 110, 157,
+ 157, 157, 110, 157, 157, 158, 157, 110, 157, 159, 157, 157, 110, 110, 158, 157,
+ 110, 110, 157, 157, 157, 157, 110, 159, 159, 159, 157, 110, 110, 110, 158, 157,
+ 110, 157, 110, 157, 110, 157, 110, 110, 110, 110, 110, 157, 157, 110, 110, 158,
+ 110, 110, 110, 157, 110, 157, 110, 110, 157, 157, 110, 157, 157, 110, 110, 110,
+ 157, 110, 157, 157, 157, 157, 157, 110, 157, 157, 158, 110, 157, 110, 110, 110,
+ 110, 159, 110, 110, 157, 157, 110, 110, 110, 110, 110, 110, 157, 110, 157, 157,
+ 157, 110, 110, 157, 110, 110, 110, 110, 110, 110, 159, 110, 110, 110, 157, 157,
+ 110, 157, 157, 157, 157, 158, 110, 110, 157, 157, 159, 157, 159, 157, 157, 110,
+ 159, 159, 110, 157, 157, 159, 157, 157, 157, 158, 157, 157, 159, 157, 110, 157,
+ 110, 159, 110, 158, 159, 159, 110, 158, 158, 110, 110, 110, 110, 157, 157, 157,
+ 157, 157, 110, 159, 159, 157, 159, 110, 110, 157, 110, 157, 157, 159, 157, 110,
+ 110, 158, 158, 110, 110, 158, 159, 157, 157, 157, 110, 157, 157, 157, 157, 157,
+ 157, 157, 157, 157, 157, 159, 110, 157, 110, 110, 157, 157, 110, 157, 157, 110,
+ 110, 158, 157, 159, 157, 110, 157, 110, 159, 157, 159, 157, 110, 159, 110, 157,
+ 157, 157, 157, 157, 110, 157, 110, 110, 110, 110, 157, 157, 159, 110, 110, 110,
+ 157, 157, 158, 158, 110, 159, 157, 110, 157, 157, 157, 110, 158, 158, 110, 110,
+ 159, 157, 158, 158, 157, 157, 157, 110, 157, 110, 158, 157, 157, 157, 110, 110,
+ 159, 110, 110, 159, 157, 110, 110, 110, 157, 110, 157, 110, 157, 110, 157, 110,
+ 157, 110, 157, 110, 157, 157, 157, 110, 110, 110, 110, 157, 157, 157, 110, 110,
+ 157, 110, 159, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 110, 110, 158,
+ 110, 157, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 110, 110,
+ 157, 157, 110, 110, 157, 157, 157, 158, 110, 157, 110, 110, 110, 110, 110, 110,
+ 158, 157, 157, 110, 157, 157, 157, 157, 157, 110, 110, 110, 110, 157, 110, 157,
+ 110, 110, 157, 110, 110, 157, 157, 110, 110, 159, 110, 110, 110, 110, 159, 110,
+ 157, 157, 110, 110, 157, 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 110,
+ 110, 157, 110, 110, 157, 110, 110, 157, 157, 110, 157, 110, 110, 157, 110, 110,
+ 157, 110, 110, 110, 110, 157, 157, 157, 157, 110, 110, 157, 110, 157, 110, 157,
+ 110, 110, 158, 110, 110, 110, 157, 110, 158, 110, 110, 158, 110, 110, 157, 110,
+ 157, 157, 110, 110, 157, 110, 110, 110, 157, 110, 110, 110, 157, 110, 110, 159,
+ 110, 110, 110, 110, 110, 110, 157, 110, 157, 159, 110, 110, 157, 110, 110, 110,
+ 158, 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 159, 110, 157,
+ 110, 110, 157, 110, 110, 110, 159, 110, 158, 157, 110, 157, 110, 110, 110, 110,
+ 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110,
+ 110, 110, 110, 157, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 157, 110, 157, 158, 110, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 157,
+ 157, 157, 157, 110, 110, 110, 110, 110, 110, 157, 110, 157, 110, 157, 157, 110,
+ 110, 110, 110, 110, 110, 110, 157, 110, 157, 110, 110, 110, 157, 110, 110, 110,
+ 157, 110, 110, 157, 110, 110, 110, 110, 157, 157, 110, 110, 110, 110, 110, 110,
+ 159, 157, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 157, 110, 157, 110,
+ 110, 110, 157, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 157, 157, 110,
+ 110, 110, 110, 158, 110, 110, 157, 110, 110, 110, 110, 157, 158, 157, 157, 157,
+ 157, 158, 110, 157, 157, 110, 110, 110, 110, 157, 110, 110, 157, 110, 110, 157,
+ 110, 110, 110, 110, 110, 157, 157, 110, 110, 110, 110, 110, 157, 110, 110, 110,
+ 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 158, 157, 157, 110, 110, 110,
+ 110, 157, 157, 157, 110, 157, 110, 110, 159, 110, 110, 157, 157, 110, 110, 110,
+ 157, 157, 110, 157, 158, 110, 110, 110, 92, 157, 110, 157, 110, 110, 110, 157,
+ 110, 110, 110, 110, 110, 110, 110, 158, 157, 110, 157, 110, 157, 110, 110, 110,
+ 157, 110, 159, 157, 110, 157, 110, 157, 110, 157, 110, 110, 110, 110, 110, 158,
+ 157, 110, 110, 157, 110, 110, 110, 157, 157, 110, 110, 157, 157, 159, 157, 110,
+ 110, 157, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110,
+ 157, 110, 110, 158, 157, 110, 110, 157, 110, 110, 110, 157, 157, 157, 92, 110,
+ 110, 110, 157, 110, 110, 157, 157, 110, 110, 157, 157, 110, 110, 110, 110, 157,
+ 158, 110, 157, 157, 157, 110, 110, 110, 110, 159, 159, 110, 110, 157, 110, 110,
+ 110, 110, 158, 110, 157, 110, 157, 110, 110, 158, 110, 158, 110, 110, 157, 110,
+ 110, 159, 110, 110, 158, 110, 110, 110, 157, 110, 110, 157, 110, 157, 157, 157,
+ 110, 110, 110, 110, 110, 110, 110, 157, 159, 110, 110, 110, 157, 157, 110, 110,
+ 110, 110, 157, 110, 110, 157, 110, 110, 110, 110, 110, 157, 157, 157, 157, 92,
+ 92, 110, 110, 157, 110, 157, 157, 110, 110, 110, 157, 110, 158, 110, 110, 92,
+ 110, 110, 158, 157, 157, 159, 157, 110, 157, 110, 157, 110, 158, 110, 157, 157,
+ 110, 157, 157, 157, 157, 157, 110, 157, 159, 110, 110, 158, 157, 110, 158, 157,
+ 157, 158, 157, 158, 157, 110, 158, 157, 157, 110, 110, 157, 110, 157, 110, 157,
+ 110, 110, 110, 157, 157, 110, 110, 159, 158, 110, 110, 157, 110, 110, 157, 157,
+ 110, 110, 157, 157, 157, 157, 157, 157, 157, 159, 159, 110, 110, 110, 110, 110,
+ 157, 157, 157, 110, 159, 157, 157, 110, 157, 110, 157, 110, 157, 110, 110, 157,
+ 157, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 158, 110, 110, 157, 110,
+ 110, 110, 159, 110, 110, 157, 157, 159, 157, 157, 157, 157, 159, 157, 159, 110,
+ 110, 157, 110, 110, 110, 157, 159, 158, 157, 110, 157, 110, 157, 157, 110, 110,
+ 157, 110, 110, 161, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 157, 110, 110, 110, 110, 157, 110, 157, 110, 110, 110, 157, 110, 157, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 158, 110, 110, 157, 110, 110, 110, 110, 157,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 159, 110, 110, 110, 157,
+ 110, 157, 110, 110, 157, 110, 157, 157, 157, 110, 110, 110, 110, 158, 110, 110,
+ 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 157, 157, 110, 110, 110, 110,
+ 110, 110, 110, 157, 157, 157, 110, 157, 157, 157, 110, 110, 110, 157, 158, 110,
+ 159, 157, 110, 110, 110, 110, 110, 110, 110, 157, 110, 157, 110, 110, 110, 110,
+ 158, 110, 158, 157, 110, 157, 110, 157, 157, 110, 157, 158, 110, 157, 110, 110,
+ 110, 110, 110, 157, 157, 157, 157, 157, 157, 157, 110, 110, 157, 157, 158, 157,
+ 157, 110, 110, 110, 157, 157, 110, 110, 110, 159, 110, 157, 157, 110, 110, 110,
+ 157, 157, 158, 110, 110, 110, 110, 110, 110, 157, 157, 159, 157, 157, 110, 110,
+ 157, 110, 157, 157, 157, 110, 157, 110, 157, 158, 110, 110, 110, 110, 110, 157,
+ 110, 157, 159, 110, 157, 110, 110, 157, 157, 110, 157, 157, 110, 110, 92, 110,
+ 110, 157, 157, 110, 110, 157, 110, 110, 158, 110, 110, 110, 157, 110, 110, 110,
+ 159, 110, 157, 110, 110, 110, 110, 110, 157, 110, 157, 157, 110, 110, 110, 110,
+ 110, 159, 159, 110, 110, 110, 110, 110, 110, 157, 110, 159, 159, 110, 110, 110,
+ 159, 110, 110, 157, 110, 157, 157, 157, 157, 110, 110, 110, 157, 157, 157, 110,
+ 110, 110, 157, 157, 157, 110, 159, 110, 157, 159, 157, 157, 157, 110, 110, 157,
+ 110, 159, 110, 157, 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 157, 110,
+ 110, 110, 110, 157, 157, 110, 110, 110, 157, 110, 157, 110, 158, 110, 158, 157,
+ 110, 110, 159, 110, 159, 110, 110, 157, 157, 110, 110, 110, 157, 157, 157, 157,
+ 157, 110, 110, 157, 110, 110, 157, 159, 110, 110, 157, 157, 157, 158, 157, 157,
+ 157, 110, 157, 110, 157, 157, 157, 110, 110, 110, 157, 110, 159, 157, 157, 110,
+ 110, 110, 159, 159, 158, 157, 157, 110, 110, 157, 110, 110, 110, 110, 110, 110,
+ 157, 110, 110, 110, 110, 157, 157, 110, 157, 157, 157, 110, 110, 159, 157, 110,
+ 157, 159, 110, 110, 110, 159, 157, 157, 110, 157, 157, 157, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110,
+ 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157,
+ 110, 110, 110, 157, 110, 110, 110, 110, 157, 157, 110, 110, 110, 110, 110, 110,
+ 110, 110, 157, 110, 159, 157, 110, 110, 157, 110, 157, 110, 110, 110, 157, 157,
+ 157, 157, 157, 110, 110, 110, 110, 110, 157, 110, 157, 110, 110, 157, 92, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 157,
+ 110, 110, 110, 110, 157, 110, 157, 157, 110, 110, 157, 110, 157, 110, 157, 110,
+ 110, 110, 157, 110, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 110, 110,
+ 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110,
+ 110, 157, 110, 110, 157, 157, 157, 157, 110, 157, 157, 157, 110, 110, 157, 110,
+ 157, 110, 157, 110, 157, 110, 157, 110, 110, 110, 157, 159, 157, 159, 157, 157,
+ 110, 159, 157, 110, 110, 110, 159, 110, 110, 157, 110, 110, 158, 157, 157, 110,
+ 92, 110, 110, 110, 110, 157, 157, 110, 110, 157, 110, 159, 157, 157, 157, 158,
+ 110, 110, 110, 157, 110, 157, 110, 110, 157, 110, 157, 157, 157, 157, 110, 110,
+ 110, 110, 110, 110, 110, 157, 157, 157, 157, 110, 157, 110, 110, 110, 110, 110,
+ 110, 157, 110, 159, 110, 157, 157, 157, 110, 110, 157, 157, 157, 159, 110, 110,
+ 110, 110, 110, 110, 110, 110, 157, 157, 157, 157, 157, 110, 110, 110, 157, 110,
+ 157, 157, 158, 157, 157, 110, 110, 110, 157, 110, 110, 159, 157, 110, 157, 110,
+ 157, 110, 157, 110, 110, 110, 158, 110, 110, 110, 157, 110, 158, 157, 159, 110,
+ 110, 159, 110, 157, 110, 110, 157, 110, 157, 157, 110, 110, 110, 110, 110, 158,
+ 110, 157, 159, 110, 110, 157, 157, 110, 110, 159, 159, 110, 157, 110, 110, 159,
+ 157, 110, 110, 157, 110, 159, 110, 110, 157, 110, 110, 157, 110, 158, 110, 110,
+ 110, 110, 110, 110, 110, 158, 110, 110, 157, 110, 158, 110, 157, 110, 110, 158,
+ 110, 159, 110, 110, 110, 110, 110, 157, 157, 110, 157, 110, 157, 110, 110, 110,
+ 157, 157, 110, 110, 157, 158, 157, 110, 157, 110, 157, 157, 157, 159, 157, 157,
+ 157, 110, 110, 157, 158, 157, 110, 110, 110, 157, 157, 157, 110, 110, 110, 158,
+ 110, 110, 157, 110, 110, 157, 158, 158, 110, 157, 157, 157, 158, 159, 157, 157,
+ 157, 110, 157, 159, 110, 110, 110, 110, 157, 157, 110, 158, 110, 110, 110, 110,
+ 157, 157, 110, 110, 110, 110, 157, 158, 158, 110, 110, 159, 157, 157, 157, 157,
+ 110, 110, 110, 158, 157, 157, 110, 159, 157, 110, 110, 157, 159, 158, 157, 110,
+ 157, 157, 110, 157, 157, 110, 158, 110, 157, 157, 157, 157, 110, 110, 110, 110,
+ 157, 157, 110, 157, 157, 157, 157, 110, 157, 110, 157, 110, 110, 157, 157, 110,
+ 110, 110, 110, 110, 110, 110, 157, 157, 110, 157, 110, 110, 110, 110, 110, 110,
+ 157, 157, 110, 157, 110, 157, 157, 110, 110, 110, 110, 110, 110, 157, 110, 110,
+ 159, 110, 110, 158, 110, 110, 110, 157, 158, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 159, 157, 110, 110, 110, 110, 110, 110, 110, 157, 110,
+ 157, 110, 110, 110, 157, 157, 157, 110, 110, 110, 110, 110, 110, 110, 157, 110,
+ 110, 157, 110, 110, 158, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110,
+ 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 159, 158, 159, 157, 157, 159, 157, 110,
+ 157, 159, 110, 157, 110, 157, 110, 157, 159, 110, 110, 110, 110, 110, 110, 158,
+ 157, 157, 159, 110, 157, 110, 110, 158, 157, 157, 159, 157, 158, 157, 157, 110,
+ 158, 159, 110, 110, 157, 157, 159, 159, 110, 110, 158, 110, 110, 110, 159, 157,
+ 110, 159, 158, 110, 110, 110, 110, 159, 110, 158, 110, 158, 110, 157, 157, 157,
+ 159, 157, 157, 158, 158, 157, 110, 110, 157, 157, 158, 110, 158, 157, 110, 159,
+ 158, 110, 157, 110, 158, 110, 158, 157, 110, 110, 110, 110, 110, 110, 158, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 157, 157, 110, 157,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110,
+ 110, 157, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110,
+ 157, 110, 157, 158, 110, 110, 110, 157, 158, 159, 110, 110, 110, 110, 157, 157,
+ 110, 110, 157, 159, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 157, 157, 158, 157, 110, 110,
+ 110, 110, 157, 110, 110, 110, 110, 157, 110, 110, 110, 110, 157, 110, 110, 110,
+ 110, 157, 110, 158, 110, 157, 157, 110, 157, 110, 110, 110, 110, 157, 157, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110,
+ 158, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 159, 110, 110, 110, 110, 159, 157, 157, 157,
+ 110, 157, 157, 157, 110, 158, 110, 110, 110, 110, 110, 110, 157, 158, 110, 110,
+ 110, 110, 110, 110, 110, 157, 157, 110, 110, 158, 158, 110, 110, 110, 110, 110,
+ 157, 110, 157, 157, 159, 110, 157, 110, 110, 110, 110, 157, 110, 110, 157, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 158, 157, 110,
+ 157, 157, 157, 110, 157, 110, 110, 110, 110, 110, 157, 157, 110, 110, 110, 157,
+ 110, 157, 110, 157, 110, 110, 110, 110, 110, 158, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 157, 110, 158, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157,
+ 110, 110, 110, 158, 157, 110, 92, 159, 110, 110, 110, 110, 110, 110, 157, 110,
+ 110, 110, 159, 157, 110, 158, 157, 157, 110, 110, 158, 110, 110, 110, 110, 159,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110,
+ 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 157, 157, 110, 110, 110, 157, 110, 157, 157, 110,
+ 110, 110, 110, 157, 157, 157, 110, 110, 158, 110, 110, 157, 110, 157, 110, 157,
+ 157, 110, 110, 110, 157, 110, 110, 110, 110, 110, 157, 158, 157, 110, 157, 158,
+ 110, 110, 110, 110, 110, 110, 110, 110, 158, 157, 110, 157, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 159, 157, 110, 157, 110, 110, 110, 158,
+ 110, 110, 110, 157, 110, 157, 157, 110, 110, 157, 110, 157, 110, 110, 110, 110,
+ 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 159, 157, 110, 157, 110, 110,
+ 110, 157, 110, 159, 159, 110, 110, 157, 157, 158, 110, 110, 110, 157, 159, 157,
+ 110, 157, 157, 157, 110, 157, 110, 110, 110, 157, 110, 157, 110, 110, 110, 110,
+ 157, 157, 157, 110, 110, 157, 110, 157, 110, 110, 110, 157, 157, 157, 110, 110,
+ 110, 110, 158, 110, 110, 110, 110, 157, 157, 110, 110, 110, 110, 157, 110, 110,
+ 110, 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 110, 110, 110, 157, 110,
+ 157, 110, 157, 110, 110, 157, 110, 157, 110, 157, 110, 157, 110, 110, 110, 92,
+ 157, 157, 110, 157, 157, 110, 157, 158, 110, 110, 110, 110, 158, 110, 159, 110,
+ 157, 110, 157, 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 157, 110, 159,
+ 110, 157, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110,
+ 159, 110, 110, 157, 157, 110, 110, 157, 157, 157, 110, 110, 157, 110, 110, 110,
+ 110, 157, 110, 157, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 158, 110, 110, 157, 157, 110, 110, 110, 110, 157, 110, 110, 110, 110,
+ 110, 110, 157, 157, 158, 110, 157, 157, 110, 157, 158, 110, 157, 110, 157, 158,
+ 110, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 159, 110, 110, 110, 110,
+ 157, 110, 110, 110, 157, 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 159,
+ 110, 110, 110, 110, 110, 157, 110, 110, 110, 159, 157, 110, 157, 110, 157, 110,
+ 110, 110, 110, 110, 157, 110, 110, 157, 110, 110, 157, 110, 110, 110, 110, 110,
+ 110, 159, 157, 110, 157, 110, 157, 110, 110, 157, 110, 110, 110, 110, 110, 157,
+ 110, 110, 110, 110, 157, 157, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110,
+ 157, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110,
+ 159, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 157,
+ 110, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 110, 110, 157, 110, 110,
+ 159, 157, 157, 110, 110, 110, 110, 110, 110, 157, 158, 157, 110, 110, 157, 110,
+ 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 158, 157, 157, 110, 110, 110,
+ 157, 110, 110, 110, 157, 157, 110, 157, 157, 157, 157, 157, 158, 157, 110, 157,
+ 157, 110, 157, 157, 159, 157, 157, 110, 110, 110, 157, 110, 157, 157, 110, 110,
+ 157, 110, 110, 110, 110, 157, 110, 110, 110, 157, 157, 110, 110, 110, 157, 110,
+ 110, 110, 110, 110, 157, 158, 110, 157, 157, 159, 110, 110, 159, 157, 110, 157,
+ 110, 157, 110, 157, 157, 110, 110, 110, 110, 110, 157, 157, 110, 110, 157, 110,
+ 110, 110, 157, 157, 157, 157, 110, 157, 157, 157, 157, 157, 110, 110, 157, 110,
+ 157, 157, 110, 110, 110, 157, 157, 157, 110, 110, 110, 110, 157, 157, 157, 157,
+ 110, 110, 157, 157, 158, 110, 110, 110, 157, 157, 157, 159, 159, 110, 110, 110,
+ 157, 110, 110, 157, 157, 157, 110, 157, 110, 157, 157, 110, 110, 157, 110, 157,
+ 110, 157, 110, 157, 157, 110, 110, 110, 110, 157, 157, 157, 110, 110, 110, 110,
+ 110, 157, 157, 110, 157, 110, 157, 157, 157, 157, 110, 158, 157, 110, 110, 110,
+ 110, 110, 157, 110, 110, 110, 110, 92, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 157, 157, 110, 110, 157, 110, 110, 110, 157, 110, 110, 110,
+ 157, 157, 157, 157, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 157, 157,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 158, 110,
+ 110, 110, 157, 110, 157, 110, 157, 110, 110, 157, 110, 110, 110, 110, 157, 157,
+ 110, 157, 110, 110, 110, 157, 157, 110, 110, 110, 110, 157, 110, 157, 110, 157,
+ 157, 110, 110, 110, 110, 110, 157, 159, 157, 157, 110, 110, 157, 157, 110, 110,
+ 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 92, 110, 110, 110,
+ 110, 92, 110, 157, 157, 157, 110, 110, 110, 157, 158, 110, 110, 110, 157, 157,
+ 110, 158, 157, 110, 110, 110, 110, 110, 157, 110, 157, 110, 110, 110, 110, 110,
+ 157, 110, 157, 157, 110, 110, 110, 110, 110, 158, 110, 157, 157, 92, 110, 158,
+ 110, 110, 157, 157, 110, 110, 157, 110, 110, 110, 110, 110, 110, 158, 110, 157,
+ 110, 110, 159, 110, 110, 110, 110, 110, 110, 157, 157, 157, 110, 110, 157, 110,
+ 110, 158, 158, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 157,
+ 110, 110, 110, 159, 110, 110, 157, 110, 157, 157, 110, 110, 110, 110, 110, 110,
+ 110, 157, 110, 110, 110, 159, 157, 110, 110, 110, 110, 110, 110, 158, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 157, 110, 157, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 157, 157, 110, 110, 110, 110, 110, 157, 157, 157, 110, 110, 157, 157,
+ 110, 110, 110, 157, 157, 110, 157, 110, 110, 110, 157, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 157, 110, 110, 110, 110, 157, 158, 110, 110, 110, 110, 110,
+ 110, 110, 157, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 158,
+ 110, 110, 110, 157, 157, 157, 110, 110, 157, 110, 157, 157, 157, 157, 110, 159,
+ 158, 110, 159, 157, 110, 157, 157, 110, 157, 157, 157, 157, 157, 110, 110, 110,
+ 158, 157, 110, 157, 157, 157, 110, 159, 110, 157, 157, 110, 110, 110, 110, 110,
+ 158, 157, 110, 110, 110, 159, 110, 110, 157, 110, 110, 110, 110, 110, 159, 110,
+ 110, 157, 157, 110, 110, 110, 92, 110, 110, 110, 110, 110, 110, 158, 110, 159,
+ 110, 157, 157, 110, 158, 157, 110, 157, 110, 158, 158, 158, 158, 110, 110, 110,
+ 157, 110, 110, 110, 158, 157, 157, 157, 110, 157, 110, 110, 110, 157, 110, 110,
+ 110, 157, 110, 158, 158, 157, 110, 110, 110, 159, 110, 158, 157, 157, 157, 110,
+ 157, 110, 110, 110, 157, 110, 159, 110, 110, 157, 157, 157, 110, 159, 110, 157,
+ 110, 157, 157, 157, 110, 157, 110, 158, 110, 110, 110, 157, 110, 110, 158, 110,
+ 110, 110, 110, 159, 110, 157, 110, 157, 110, 110, 110, 158, 110, 159, 110, 158,
+ 157, 110, 110, 158, 110, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 157,
+ 110, 159, 159, 110, 110, 159, 157, 157, 157, 110, 110, 110, 158, 110, 110, 157,
+ 157, 110, 159, 110, 157, 110, 110, 110, 157, 110, 159, 110, 157, 110, 110, 157,
+ 110, 157, 110, 110, 157, 110, 110, 158, 157, 110, 110, 157, 157, 110, 110, 110,
+ 110, 157, 110, 110, 110, 158, 110, 110, 157, 110, 110, 157, 157, 157, 110, 157,
+ 110, 157, 157, 110, 110, 157, 157, 110, 110, 110, 110, 110, 110, 157, 157, 157,
+ 157, 110, 110, 110, 157, 157, 110, 157, 110, 110, 110, 110, 110, 110, 157, 110,
+ 157, 110, 110, 110, 157, 157, 110, 110, 157, 157, 110, 110, 110, 157, 110, 110,
+ 157, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 157, 157, 110, 157, 157,
+ 110, 157, 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 157, 110, 157, 110,
+ 110, 110, 157, 110, 110, 110, 157, 110, 157, 158, 110, 157, 157, 110, 157, 110,
+ 110, 110, 157, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 157, 157, 110, 110, 110, 159, 157, 157, 110, 110, 110, 110, 157, 110, 159,
+ 110, 157, 157, 110, 110, 158, 110, 159, 110, 157, 157, 110, 157, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 157, 157, 157, 157, 110,
+ 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110,
+ 157, 157, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 92, 110, 110, 110,
+ 110, 157, 110, 110, 110, 110, 157, 157, 110, 157, 110, 159, 110, 157, 110, 110,
+ 110, 92, 110, 110, 110, 110, 110, 110, 157, 110, 157, 110, 110, 110, 157, 110,
+ 157, 110, 110, 110, 110, 110, 110, 157, 157, 110, 158, 110, 110, 110, 110, 157,
+ 159, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 157, 110, 110, 157, 110, 157, 110, 157, 110, 157, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110,
+ 157, 110, 157, 110, 157, 157, 110, 110, 110, 157, 157, 157, 110, 157, 157, 110,
+ 110, 110, 157, 110, 110, 157, 157, 110, 110, 157, 157, 157, 110, 110, 110, 158,
+ 159, 110, 157, 110, 157, 110, 157, 110, 110, 110, 157, 157, 157, 110, 110, 110,
+ 110, 157, 110, 110, 157, 110, 157, 157, 157, 110, 110, 110, 110, 157, 110, 110,
+ 110, 157, 110, 110, 157, 158, 110, 110, 157, 110, 157, 157, 110, 110, 157, 110,
+ 157, 157, 110, 110, 110, 110, 110, 157, 157, 110, 157, 110, 110, 157, 110, 110,
+ 110, 110, 110, 159, 110, 110, 157, 110, 159, 110, 110, 110, 110, 110, 110, 110,
+ 157, 110, 110, 92, 110, 110, 110, 110, 110, 92, 110, 110, 110, 157, 110, 157,
+ 110, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 157, 110, 157, 110, 157,
+ 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 158, 110,
+ 110, 110, 110, 157, 157, 110, 110, 110, 157, 110, 110, 110, 157, 157, 157, 157,
+ 157, 157, 157, 110, 110, 157, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110,
+ 110, 157, 157, 110, 110, 157, 157, 157, 110, 110, 110, 110, 94, 110, 157, 157,
+ 110, 110, 110, 110, 157, 110, 110, 110, 110, 157, 157, 110, 110, 92, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 158, 110, 110, 157, 157, 157, 110, 157,
+ 157, 110, 157, 110, 110, 110, 158, 110, 157, 110, 110, 110, 110, 110, 157, 110,
+ 157, 110, 110, 157, 110, 110, 159, 110, 110, 110, 110, 110, 157, 110, 110, 110,
+ 110, 110, 157, 110, 110, 110, 157, 110, 157, 110, 110, 110, 110, 110, 157, 110,
+ 110, 110, 110, 110, 157, 158, 157, 110, 110, 110, 157, 110, 110, 110, 157, 110,
+ 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 158, 110, 110,
+ 157, 157, 110, 110, 158, 110, 110, 110, 110, 110, 157, 110, 157, 157, 110, 110,
+ 159, 110, 157, 157, 110, 110, 110, 110, 110, 110, 157, 158, 110, 110, 157, 157,
+ 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110,
+ 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 157, 157, 157, 110, 110, 110, 157, 159, 157, 157, 110, 110, 110, 110, 157, 157,
+ 110, 157, 110, 110, 110, 157, 157, 157, 157, 110, 110, 157, 157, 157, 110, 157,
+ 157, 110, 157, 157, 110, 157, 110, 110, 110, 110, 110, 157, 110, 158, 110, 110,
+ 157, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110,
+ 110, 158, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 157, 110, 110, 157,
+ 110, 110, 110, 110, 157, 110, 110, 157, 110, 110, 157, 110, 110, 157, 110, 110,
+ 110, 110, 157, 110, 110, 157, 110, 110, 110, 157, 110, 159, 157, 110, 157, 110,
+ 157, 110, 157, 110, 110, 157, 157, 110, 110, 157, 157, 157, 157, 158, 158, 110,
+ 157, 110, 110, 157, 110, 157, 157, 157, 157, 110, 110, 157, 110, 157, 157, 110,
+ 110, 157, 157, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 157, 110,
+ 158, 157, 110, 110, 110, 157, 110, 110, 110, 110, 157, 157, 110, 158, 157, 110,
+ 110, 110, 110, 157, 110, 157, 110, 157, 157, 110, 110, 157, 110, 158, 110, 157,
+ 157, 157, 110, 158, 110, 157, 110, 110, 110, 110, 158, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 157, 110, 158, 110, 157, 110, 110, 110, 110, 110, 110, 110,
+ 110, 158, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 157, 159, 157,
+ 157, 157, 110, 110, 157, 158, 157, 110, 110, 110, 158, 157, 110, 159, 157, 110,
+ 157, 110, 110, 157, 157, 158, 110, 110, 157, 110, 110, 110, 158, 157, 159, 110,
+ 110, 110, 110, 110, 110, 159, 157, 92, 157, 110, 157, 157, 157, 110, 110, 110,
+ 157, 159, 157, 158, 157, 110, 157, 110, 110, 110, 157, 110, 110, 110, 157, 110,
+ 110, 157, 110, 110, 157, 159, 157, 157, 157, 110, 158, 157, 110, 157, 110, 110,
+ 110, 110, 159, 157, 157, 157, 110, 157, 157, 110, 92, 110, 110, 92, 110, 110,
+ 110, 110, 92, 92, 110, 92, 92, 110, 110, 158, 110, 110, 157, 110, 157, 110,
+ 157, 157, 157, 110, 110, 110, 157, 157, 157, 110, 157, 92, 110, 110, 157, 161,
+ 110, 158, 157, 110, 157, 157, 157, 159, 110, 110, 110, 110, 110, 157, 157, 110,
+ 110, 110, 110, 110, 110, 110, 92, 92, 110, 110, 157, 157, 110, 110, 110, 110,
+ 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 110, 157, 110, 157, 110, 110,
+ 157, 157, 110, 157, 157, 157, 157, 157, 110, 157, 157, 157, 110, 110, 157, 159,
+ 157, 157, 157, 157, 157, 159, 110, 159, 110, 110, 110, 110, 110, 110, 157, 110,
+ 110, 157, 110, 157, 157, 157, 157, 110, 157, 157, 157, 157, 157, 157, 157, 157,
+ 157, 110, 157, 157, 157, 157, 157, 157, 110, 157, 157, 157, 157, 110, 157, 158,
+ 110, 110, 157, 110, 157, 110, 110, 157, 157, 157, 110, 110, 157, 159, 110, 157,
+ 157, 110, 157, 110, 158, 110, 157, 157, 110, 110, 110, 110, 110, 157, 157, 157,
+ 110, 157, 110, 110, 110, 159, 157, 157, 157, 157, 157, 157, 110, 110, 110, 110,
+ 110, 110, 110, 157, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 157, 110, 157, 110, 110, 157, 110, 110, 110, 110, 110, 157, 157, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 110, 110, 157, 157, 157, 110,
+ 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 110, 157, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 110, 157, 110, 157, 110, 110,
+ 110, 110, 110, 110, 157, 110, 158, 110, 157, 110, 110, 110, 110, 157, 157, 110,
+ 157, 157, 157, 157, 110, 110, 157, 157, 157, 157, 110, 110, 110, 157, 110, 110,
+ 157, 110, 110, 110, 158, 110, 110, 110, 159, 110, 157, 110, 110, 110, 110, 157,
+ 110, 110, 110, 110, 110, 157, 110, 157, 157, 157, 110, 157, 110, 110, 157, 110,
+ 157, 159, 157, 157, 110, 157, 110, 110, 110, 157, 157, 110, 110, 157, 110, 110,
+ 110, 110, 110, 157, 158, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110,
+ 110, 110, 110, 157, 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 110, 158,
+ 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 157, 157, 157, 110, 159, 157, 110, 157, 110, 110, 110,
+ 157, 157, 157, 110, 157, 157, 110, 157, 110, 157, 157, 110, 158, 157, 157, 110,
+ 157, 157, 157, 110, 110, 157, 157, 158, 110, 157, 110, 110, 157, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 157, 110, 157, 110,
+ 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 157, 157, 110, 110, 110, 157,
+ 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 110, 157, 157, 110, 110, 158,
+ 159, 110, 159, 157, 157, 110, 157, 110, 157, 110, 157, 159, 157, 157, 159, 110,
+ 157, 157, 110, 157, 110, 110, 157, 157, 157, 110, 157, 110, 110, 110, 158, 157,
+ 159, 110, 157, 158, 110, 110, 159, 158, 157, 110, 110, 157, 110, 158, 157, 110,
+ 110, 110, 110, 110, 110, 157, 157, 110, 110, 110, 157, 110, 110, 110, 110, 157,
+ 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 110, 159, 158, 157,
+ 158, 157, 110, 110, 110, 110, 157, 157, 110, 157, 157, 110, 110, 110, 157, 157,
+ 157, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 110, 110, 157, 110, 110,
+ 110, 157, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 157, 110, 110,
+ 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 157, 110, 110, 110, 110, 157,
+ 110, 110, 110, 110, 158, 157, 110, 158, 110, 110, 110, 110, 110, 157, 158, 110,
+ 110, 157, 110, 110, 110, 110, 110, 110, 110, 157, 157, 157, 157, 110, 157, 157,
+ 110, 110, 110, 157, 110, 157, 110, 110, 157, 110, 157, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 158, 110, 110, 158, 157,
+ 110, 110, 110, 157, 157, 110, 157, 157, 157, 157, 110, 157, 110, 110, 110, 157,
+ 110, 110, 110, 110, 157, 110, 157, 110, 110, 110, 110, 158, 110, 110, 110, 110,
+ 157, 110, 110, 110, 110, 110, 157, 157, 157, 110, 110, 157, 110, 158, 110, 157,
+ 110, 110, 157, 157, 110, 110, 157, 161, 110, 157, 157, 110, 157, 159, 110, 157,
+ 110, 110, 157, 110, 157, 110, 157, 110, 110, 110, 110, 110, 110, 110, 157, 157,
+ 110, 110, 157, 110, 110, 110, 157, 110, 110, 157, 110, 110, 110, 110, 110, 92,
+ 92, 92, 92, 92, 158, 157, 157, 157, 157, 157, 110, 157, 110, 110, 159, 110,
+ 158, 110, 110, 157, 157, 157, 110, 159, 110, 110, 157, 110, 157, 110, 157, 110,
+ 110, 110, 157, 110, 157, 110, 157, 110, 157, 110, 110, 157, 157, 158, 157, 157,
+ 157, 110, 157, 110, 110, 110, 110, 157, 157, 110, 110, 110, 110, 110, 157, 110,
+ 110, 159, 110, 110, 110, 110, 157, 110, 157, 157, 110, 110, 157, 158, 110, 110,
+ 157, 157, 110, 110, 110, 110, 157, 110, 110, 110, 157, 110, 157, 157, 110, 157,
+ 110, 110, 110, 110, 157, 157, 110, 110, 110, 158, 157, 110, 110, 157, 110, 157,
+ 159, 110, 157, 92, 92, 92, 92, 92, 92, 92, 110, 110, 110, 110, 110, 110,
+ 110, 110, 157, 157, 110, 110, 157, 110, 110, 157, 157, 157, 110, 110, 157, 110,
+ 110, 110, 110, 110, 158, 157, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 157,
+ 110, 110, 110, 157, 110, 110, 110, 157, 110, 157, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 157, 110, 110, 157, 110, 157, 110, 110, 110,
+ 110, 158, 110, 110, 110, 110, 110, 110, 110, 110, 157, 110, 158, 110, 157, 110,
+ 110, 110, 110, 110, 110, 110, 157, 157, 157, 110, 110, 110, 110, 110, 92, 110,
+ 110, 110, 110, 110, 110, 157, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 122, 122, 162, 122, 163, 164, 92, 165, 122, 122, 122, 122, 166, 122, 167, 168,
+ 169, 122, 162, 130, 122, 122, 122, 113, 122, 122, 170, 130, 170, 130, 122, 171,
+ 161, 172, 173, 162, 174, 130, 142, 130, 174, 92, 175, 176, 170, 122, 177, 162,
+ 176, 178, 122, 168, 130, 162, 175, 94, 122, 122, 130, 122, 178, 179, 130, 175,
+ 162, 162, 180, 122, 162, 122, 161, 166, 96, 179, 92, 122, 130, 122, 122, 122,
+ 130, 162, 96, 96, 173, 113, 122, 181, 122, 122, 182, 94, 166, 122, 122, 122,
+ 130, 130, 181, 164, 92, 92, 130, 92, 164, 176, 94, 183, 92, 183, 92, 92,
+ 130, 184, 92, 122, 162, 162, 183, 183, 94, 164, 92, 92, 92, 92, 122, 177,
+ 172, 160, 121, 168, 168, 172, 122, 160, 122, 175, 113, 122, 122, 166, 122, 173,
+ 183, 122, 122, 185, 122, 122, 162, 164, 186, 142, 170, 122, 181, 164, 121, 169,
+ 187, 122, 122, 161, 122, 122, 122, 130, 122, 130, 92, 122, 122, 122, 122, 164,
+ 181, 161, 173, 169, 92, 130, 180, 160, 92, 177, 122, 170, 160, 92, 161, 170,
+ 122, 122, 167, 176, 122, 173, 169, 122, 168, 185, 122, 122, 161, 122, 175, 181,
+ 162, 130, 92, 130, 122, 122, 122, 122, 122, 122, 177, 162, 168, 165, 169, 122,
+ 164, 166, 162, 122, 122, 122, 161, 161, 166, 168, 170, 170, 130, 113, 172, 164,
+ 122, 177, 122, 176, 168, 166, 122, 165, 160, 161, 161, 122, 161, 176, 162, 176,
+ 177, 122, 177, 163, 168, 168, 161, 161, 177, 122, 122, 188, 162, 122, 165, 122,
+ 122, 122, 177, 168, 168, 171, 164, 189, 185, 176, 175, 130, 181, 178, 130, 130,
+ 130, 92, 185, 92, 130, 130, 130, 130, 160, 94, 130, 130, 168, 168, 162, 122,
+ 169, 164, 179, 177, 122, 164, 122, 163, 122, 163, 122, 177, 122, 122, 177, 168,
+ 164, 168, 163, 122, 161, 160, 122, 121, 188, 177, 161, 163, 177, 122, 122, 122,
+ 122, 122, 177, 167, 171, 122, 177, 169, 166, 122, 122, 122, 122, 169, 169, 166,
+ 176, 168, 168, 176, 185, 130, 161, 185, 161, 122, 177, 168, 176, 161, 177, 122,
+ 122, 162, 160, 122, 185, 142, 165, 177, 177, 177, 188, 169, 167, 177, 190, 122,
+ 168, 191, 177, 122, 192, 177, 121, 168, 122, 166, 193, 122, 164, 122, 164, 122,
+ 177, 122, 177, 164, 166, 168, 121, 166, 180, 162, 177, 122, 168, 122, 177, 164,
+ 184, 181, 160, 173, 92, 130, 130, 130, 170, 130, 130, 153, 130, 113, 122, 122,
+ 160, 161, 177, 168, 161, 122, 121, 171, 161, 177, 168, 177, 162, 163, 164, 122,
+ 177, 177, 121, 122, 122, 166, 164, 168, 163, 191, 122, 177, 163, 177, 122, 176,
+ 169, 122, 164, 194, 180, 161, 168, 122, 169, 168, 122, 178, 166, 122, 96, 122,
+ 188, 122, 162, 184, 153, 172, 130, 161, 130, 130, 130, 92, 168, 130, 122, 122,
+ 164, 129, 163, 122, 168, 180, 178, 168, 122, 160, 122, 161, 164, 163, 169, 164,
+ 171, 162, 195, 160, 164, 178, 121, 177, 160, 121, 162, 121, 176, 122, 177, 169,
+ 164, 121, 122, 177, 169, 168, 121, 177, 176, 122, 122, 177, 192, 164, 191, 122,
+ 168, 122, 177, 121, 196, 169, 122, 191, 122, 169, 122, 121, 165, 122, 174, 168,
+ 177, 168, 164, 177, 94, 177, 181, 168, 161, 181, 130, 197, 96, 92, 130, 161,
+ 177, 177, 164, 122, 161, 177, 177, 122, 165, 121, 177, 168, 176, 168, 176, 122,
+ 181, 177, 164, 177, 161, 122, 172, 177, 160, 164, 122, 168, 122, 168, 168, 177,
+ 177, 168, 177, 177, 168, 122, 163, 162, 168, 168, 177, 168, 175, 171, 168, 97,
+ 177, 164, 178, 168, 121, 121, 122, 96, 196, 161, 97, 173, 161, 142, 130, 130,
+ 122, 163, 168, 177, 162, 122, 162, 168, 179, 161, 162, 168, 168, 122, 177, 164,
+ 182, 121, 177, 162, 177, 168, 171, 161, 121, 121, 142, 177, 177, 168, 177, 162,
+ 162, 162, 171, 185, 92, 130, 160, 130, 130, 130, 164, 161, 122, 121, 168, 171,
+ 177, 168, 122, 121, 178, 121, 168, 121, 168, 164, 166, 96, 161, 177, 121, 168,
+ 162, 168, 178, 164, 177, 121, 168, 171, 168, 180, 180, 168, 164, 172, 171, 122,
+ 163, 121, 161, 177, 177, 121, 122, 168, 164, 160, 122, 168, 164, 177, 196, 163,
+ 168, 160, 164, 178, 177, 121, 166, 122, 177, 171, 168, 161, 185, 122, 169, 177,
+ 168, 171, 162, 185, 160, 169, 177, 161, 168, 121, 162, 122, 160, 168, 177, 194,
+ 121, 198, 142, 177, 121, 97, 192, 166, 171, 121, 168, 166, 177, 163, 163, 161,
+ 171, 168, 122, 168, 142, 142, 181, 177, 142, 162, 178, 164, 177, 164, 164, 121,
+ 168, 122, 168, 162, 168, 168, 168, 164, 164, 168, 121, 160, 162, 177, 168, 164,
+ 168, 177, 121, 171, 177, 177, 161, 121, 171, 177, 180, 142, 121, 168, 161, 169,
+ 122, 122, 162, 122, 122, 122, 122, 121, 122, 122, 164, 122, 121, 122, 196, 162,
+ 181, 173, 121, 162, 169, 176, 179, 171, 162, 97, 167, 97, 122, 97, 97, 177,
+ 160, 97, 122, 97, 164, 122, 164, 126, 122, 121, 198, 122, 122, 122, 122, 92,
+ 130, 122, 161, 130, 170, 122, 122, 122, 122, 179, 92, 130, 122, 130, 164, 161,
+ 122, 130, 175, 162, 164, 184, 198, 168, 170, 169, 121, 164, 184, 122, 162, 178,
+ 181, 142, 122, 178, 168, 122, 175, 122, 177, 184, 94, 130, 170, 164, 168, 161,
+ 122, 164, 169, 164, 169, 122, 181, 94, 172, 113, 121, 187, 122, 162, 92, 130,
+ 169, 167, 175, 175, 172, 175, 122, 122, 163, 168, 162, 130, 166, 122, 177, 162,
+ 130, 161, 164, 160, 165, 178, 122, 179, 177, 186, 168, 122, 122, 121, 168, 174,
+ 168, 174, 163, 163, 168, 162, 181, 168, 177, 161, 161, 175, 121, 122, 191, 160,
+ 169, 122, 163, 161, 179, 164, 113, 113, 161, 113, 113, 130, 161, 175, 162, 130,
+ 122, 121, 162, 176, 163, 167, 122, 162, 122, 122, 122, 130, 170, 122, 172, 130,
+ 122, 176, 90, 122, 181, 163, 122, 122, 122, 168, 122, 172, 168, 130, 122, 161,
+ 168, 122, 176, 177, 181, 164, 176, 122, 189, 130, 130, 130, 168, 122, 168, 160,
+ 179, 168, 162, 161, 122, 121, 160, 172, 176, 122, 121, 173, 92, 130, 122, 161,
+ 122, 177, 177, 167, 160, 177, 122, 122, 122, 199, 122, 122, 163, 130, 161, 130,
+ 130, 96, 130, 122, 178, 164, 168, 121, 161, 177, 122, 121, 122, 122, 97, 181,
+ 130, 130, 168, 161, 122, 177, 122, 163, 162, 160, 177, 121, 176, 126, 167, 177,
+ 163, 192, 168, 181, 181, 184, 162, 173, 160, 122, 122, 168, 168, 168, 177, 122,
+ 181, 113, 122, 172, 142, 121, 161, 171, 177, 163, 168, 168, 168, 122, 161, 122,
+ 177, 185, 176, 121, 168, 162, 161, 121, 122, 121, 171, 168, 177, 121, 161, 94,
+ 179, 121, 200, 176, 172, 162, 177, 177, 177, 168, 163, 122, 164, 173, 173, 122,
+ 122, 170, 130, 122, 201, 162, 177, 162, 179, 122, 122, 122, 169, 167, 168, 162,
+ 162, 202, 130, 173, 181, 172, 162, 162, 162, 172, 162, 171, 178, 164, 122, 173,
+ 177, 121, 168, 122, 164, 198, 162, 122, 162, 122, 161, 130, 163, 180, 161, 164,
+ 179, 163, 122, 168, 164, 121, 192, 142, 122, 121, 92, 188, 162, 121, 121, 122,
+ 172, 163, 121, 121, 122, 162, 142, 181, 162, 177, 164, 168, 162, 161, 161, 168,
+ 176, 177, 181, 121, 177, 121, 162, 177, 121, 187, 122, 126, 168, 161, 122, 122,
+ 189, 153, 113, 164, 161, 122, 169, 161, 122, 168, 177, 177, 162, 122, 168, 122,
+ 122, 177, 168, 162, 161, 122, 122, 122, 162, 122, 167, 162, 177, 169, 164, 177,
+ 122, 122, 168, 122, 161, 164, 130, 163, 162, 162, 122, 162, 182, 177, 130, 121,
+ 177, 142, 163, 172, 168, 164, 161, 168, 172, 122, 184, 175, 177, 177, 176, 122,
+ 121, 122, 182, 122, 126, 169, 181, 122, 122, 122, 122, 164, 177, 180, 170, 173,
+ 161, 122, 122, 122, 121, 173, 130, 122, 181, 162, 122, 162, 122, 160, 122, 179,
+ 122, 176, 130, 166, 170, 164, 122, 179, 183, 175, 92, 130, 177, 163, 169, 122,
+ 122, 122, 177, 169, 186, 122, 161, 122, 169, 171, 173, 142, 168, 203, 182, 122,
+ 161, 92, 167, 162, 122, 130, 173, 162, 162, 173, 168, 173, 130, 130, 177, 168,
+ 92, 92, 168, 193, 177, 130, 178, 168, 165, 177, 122, 161, 168, 176, 168, 122,
+ 198, 162, 170, 130, 177, 122, 186, 168, 175, 175, 163, 163, 168, 121, 175, 162,
+ 172, 161, 171, 181, 177, 162, 175, 164, 162, 168, 164, 122, 92, 162, 161, 130,
+ 162, 179, 175, 121, 161, 163, 92, 92, 122, 122, 122, 122, 175, 122, 181, 162,
+ 160, 170, 163, 162, 122, 164, 122, 122, 170, 175, 163, 122, 161, 164, 162, 169,
+ 174, 180, 121, 122, 122, 122, 176, 162, 169, 122, 122, 122, 122, 122, 169, 122,
+ 122, 122, 122, 122, 161, 176, 175, 175, 122, 173, 113, 96, 96, 130, 94, 161,
+ 161, 169, 162, 122, 122, 161, 96, 168, 122, 122, 122, 142, 122, 122, 122, 122,
+ 122, 122, 96, 174, 94, 173, 179, 130, 168, 168, 163, 122, 168, 122, 96, 122,
+ 122, 174, 161, 179, 168, 168, 122, 176, 166, 122, 177, 122, 169, 169, 169, 174,
+ 168, 176, 179, 126, 189, 176, 142, 168, 122, 122, 161, 122, 122, 178, 122, 161,
+ 169, 168, 121, 176, 164, 168, 169, 177, 122, 181, 122, 179, 161, 163, 142, 177,
+ 173, 196, 130, 130, 185, 130, 130, 130, 130, 130, 161, 130, 130, 92, 162, 181,
+ 168, 168, 176, 168, 166, 168, 166, 177, 122, 163, 198, 177, 168, 163, 162, 168,
+ 178, 122, 185, 122, 177, 122, 169, 169, 96, 161, 168, 122, 122, 122, 168, 177,
+ 122, 177, 185, 162, 169, 163, 122, 168, 177, 164, 161, 169, 122, 177, 122, 175,
+ 122, 177, 169, 160, 179, 176, 176, 94, 168, 130, 96, 130, 182, 130, 160, 164,
+ 168, 177, 178, 179, 186, 178, 176, 176, 122, 176, 176, 122, 122, 166, 177, 169,
+ 168, 176, 172, 122, 179, 161, 168, 177, 122, 163, 177, 176, 178, 122, 178, 176,
+ 122, 122, 169, 168, 122, 168, 166, 169, 122, 122, 164, 160, 179, 174, 176, 185,
+ 179, 130, 130, 130, 130, 130, 168, 130, 113, 130, 179, 92, 130, 130, 185, 130,
+ 177, 121, 178, 94, 168, 122, 169, 185, 122, 169, 176, 168, 162, 122, 122, 163,
+ 161, 168, 122, 185, 161, 161, 164, 168, 168, 161, 122, 168, 176, 169, 162, 166,
+ 164, 176, 160, 168, 180, 177, 122, 122, 177, 176, 168, 168, 177, 163, 191, 169,
+ 122, 185, 168, 160, 169, 162, 113, 168, 160, 161, 168, 130, 183, 92, 94, 92,
+ 130, 92, 130, 170, 130, 94, 168, 96, 160, 161, 166, 163, 96, 168, 169, 122,
+ 185, 122, 177, 169, 168, 191, 177, 96, 142, 178, 161, 177, 166, 162, 122, 179,
+ 178, 176, 92, 96, 122, 178, 122, 182, 168, 174, 176, 168, 181, 177, 168, 121,
+ 166, 177, 168, 198, 161, 96, 122, 142, 164, 161, 164, 162, 169, 172, 188, 97,
+ 162, 176, 168, 121, 176, 185, 176, 130, 161, 94, 96, 160, 130, 130, 130, 92,
+ 92, 160, 160, 160, 92, 185, 185, 185, 130, 94, 161, 169, 122, 168, 169, 177,
+ 122, 166, 176, 169, 122, 161, 193, 122, 166, 122, 122, 169, 168, 168, 177, 166,
+ 94, 166, 177, 177, 176, 168, 161, 164, 122, 122, 121, 161, 122, 122, 181, 169,
+ 161, 168, 168, 177, 177, 168, 168, 122, 178, 198, 121, 121, 121, 177, 121, 161,
+ 153, 96, 171, 96, 160, 185, 113, 130, 92, 170, 160, 96, 94, 130, 130, 177,
+ 168, 163, 168, 177, 167, 122, 171, 121, 168, 176, 168, 177, 166, 185, 171, 168,
+ 168, 176, 166, 176, 165, 168, 185, 163, 182, 168, 121, 177, 122, 185, 163, 122,
+ 92, 96, 177, 122, 122, 96, 96, 97, 96, 177, 179, 130, 170, 92, 161, 96,
+ 160, 94, 185, 130, 161, 170, 171, 169, 161, 178, 168, 160, 168, 122, 122, 177,
+ 96, 185, 168, 161, 168, 163, 121, 161, 176, 122, 162, 161, 185, 171, 176, 166,
+ 171, 163, 177, 168, 121, 168, 142, 121, 184, 162, 92, 169, 168, 168, 179, 96,
+ 160, 94, 160, 170, 130, 94, 161, 185, 161, 142, 168, 161, 166, 179, 97, 121,
+ 171, 184, 122, 177, 122, 177, 122, 163, 178, 176, 168, 176, 162, 177, 168, 176,
+ 177, 177, 178, 182, 164, 168, 177, 161, 168, 177, 168, 164, 167, 174, 169, 163,
+ 172, 161, 160, 126, 174, 92, 161, 96, 185, 96, 168, 113, 130, 94, 177, 161,
+ 177, 163, 176, 177, 169, 97, 177, 161, 122, 176, 169, 122, 169, 177, 168, 171,
+ 168, 176, 177, 168, 121, 162, 96, 168, 142, 97, 153, 179, 170, 161, 168, 168,
+ 142, 168, 168, 168, 177, 176, 165, 142, 162, 160, 172, 182, 177, 168, 96, 169,
+ 97, 161, 160, 185, 181, 171, 161, 168, 168, 177, 177, 161, 168, 177, 163, 163,
+ 181, 94, 113, 130, 94, 121, 177, 177, 171, 162, 168, 177, 191, 177, 121, 179,
+ 161, 182, 168, 177, 121, 168, 142, 176, 161, 160, 161, 161, 122, 168, 177, 94,
+ 142, 142, 142, 178, 161, 177, 168, 161, 142, 171, 190, 177, 171, 191, 113, 162,
+ 162, 121, 161, 178, 185, 92, 94, 167, 181, 162, 122, 122, 162, 176, 122, 166,
+ 122, 166, 170, 181, 176, 177, 164, 177, 162, 161, 97, 176, 161, 174, 178, 160,
+ 122, 174, 181, 181, 130, 130, 164, 177, 161, 165, 122, 161, 161, 175, 130, 169,
+ 172, 177, 177, 122, 122, 161, 130, 177, 122, 169, 166, 121, 177, 121, 161, 181,
+ 92, 162, 121, 121, 168, 163, 121, 161, 121, 92, 177, 177, 167, 163, 168, 122,
+ 177, 161, 177, 166, 164, 162, 113, 181, 122, 176, 166, 92, 176, 122, 166, 176,
+ 122, 161, 160, 176, 177, 161, 161, 113, 113, 130, 130, 122, 161, 164, 176, 163,
+ 122, 168, 186, 160, 161, 177, 163, 122, 161, 168, 122, 168, 166, 190, 122, 169,
+ 122, 122, 177, 161, 160, 161, 161, 179, 161, 161, 130, 170, 130, 130, 130, 179,
+ 130, 122, 177, 161, 122, 164, 122, 163, 166, 169, 122, 166, 92, 166, 204, 166,
+ 191, 177, 168, 166, 177, 191, 185, 176, 161, 162, 182, 166, 190, 168, 182, 172,
+ 168, 164, 122, 176, 130, 130, 130, 92, 205, 113, 160, 122, 166, 160, 161, 168,
+ 160, 161, 173, 122, 177, 177, 161, 177, 168, 177, 177, 185, 163, 177, 177, 177,
+ 122, 174, 122, 122, 167, 168, 173, 174, 164, 206, 153, 130, 164, 130, 96, 92,
+ 113, 92, 130, 113, 170, 168, 168, 161, 166, 168, 168, 160, 168, 177, 160, 168,
+ 181, 168, 96, 122, 160, 161, 178, 191, 193, 161, 161, 122, 177, 161, 122, 166,
+ 168, 161, 167, 113, 169, 166, 113, 94, 130, 130, 130, 161, 178, 174, 163, 122,
+ 122, 177, 168, 178, 176, 168, 163, 177, 161, 177, 161, 92, 168, 166, 168, 179,
+ 191, 168, 168, 168, 165, 177, 177, 121, 166, 122, 122, 168, 180, 166, 163, 164,
+ 165, 168, 122, 163, 177, 121, 122, 185, 191, 188, 121, 167, 177, 166, 168, 161,
+ 168, 130, 160, 161, 168, 202, 92, 92, 161, 167, 161, 177, 168, 142, 192, 164,
+ 176, 122, 160, 168, 122, 168, 163, 191, 168, 168, 122, 161, 168, 177, 168, 121,
+ 122, 121, 177, 168, 121, 122, 168, 168, 168, 177, 198, 168, 161, 178, 161, 177,
+ 153, 113, 92, 92, 170, 161, 92, 160, 168, 177, 121, 121, 176, 166, 168, 191,
+ 164, 122, 142, 168, 122, 177, 161, 121, 122, 178, 121, 168, 160, 168, 122, 163,
+ 161, 204, 121, 168, 191, 185, 161, 164, 177, 172, 161, 169, 179, 97, 92, 168,
+ 113, 168, 172, 160, 168, 121, 168, 161, 164, 121, 168, 168, 191, 97, 122, 177,
+ 176, 166, 168, 122, 161, 122, 168, 177, 177, 192, 171, 168, 164, 164, 168, 177,
+ 177, 168, 173, 122, 177, 161, 164, 181, 168, 170, 170, 161, 121, 177, 129, 122,
+ 177, 177, 164, 168, 161, 168, 171, 160, 122, 190, 160, 178, 168, 161, 121, 168,
+ 160, 177, 164, 121, 161, 160, 94, 161, 113, 113, 180, 198, 166, 168, 121, 168,
+ 161, 122, 177, 161, 164, 122, 168, 121, 177, 168, 181, 94, 113, 164, 188, 168,
+ 164, 122, 177, 121, 177, 122, 177, 113, 121, 121, 177, 168, 172, 177, 121, 121,
+ 160, 162, 171, 168, 122, 113, 161, 168, 168, 171, 92, 122, 122, 92, 184, 121,
+ 175, 181, 172, 174, 168, 161, 130, 181, 92, 122, 121, 198, 178, 121, 168, 168,
+ 161, 161, 175, 168, 179, 163, 177, 170, 161, 181, 172, 164, 177, 185, 168, 122,
+ 181, 160, 177, 162, 190, 122, 122, 168, 181, 122, 122, 113, 122, 162, 92, 179,
+ 97, 162, 121, 164, 176, 169, 161, 122, 162, 122, 122, 122, 178, 122, 122, 166,
+ 164, 122, 172, 162, 179, 162, 164, 122, 169, 130, 130, 92, 185, 161, 121, 162,
+ 168, 130, 130, 162, 122, 168, 162, 122, 122, 122, 168, 173, 161, 161, 122, 122,
+ 121, 122, 164, 177, 122, 122, 130, 122, 169, 162, 122, 164, 168, 164, 164, 162,
+ 122, 177, 122, 164, 161, 187, 161, 121, 181, 142, 121, 191, 196, 188, 121, 162,
+ 168, 168, 177, 122, 122, 163, 176, 168, 122, 176, 161, 177, 177, 122, 168, 168,
+ 168, 169, 122, 122, 122, 168, 173, 130, 130, 160, 122, 162, 164, 169, 177, 168,
+ 168, 92, 176, 122, 160, 162, 122, 192, 168, 122, 160, 181, 161, 142, 96, 163,
+ 168, 168, 168, 169, 176, 122, 168, 177, 122, 130, 130, 130, 198, 164, 176, 176,
+ 163, 168, 167, 171, 168, 168, 168, 163, 160, 122, 177, 122, 177, 168, 122, 161,
+ 168, 177, 161, 191, 163, 97, 122, 168, 177, 198, 176, 122, 168, 171, 168, 168,
+ 122, 122, 176, 122, 122, 161, 168, 173, 96, 198, 122, 168, 122, 192, 177, 164,
+ 168, 168, 161, 176, 177, 169, 121, 164, 122, 168, 121, 172, 129, 168, 191, 163,
+ 160, 177, 177, 168, 177, 168, 178, 177, 203, 179, 168, 122, 168, 168, 168, 122,
+ 177, 122, 160, 122, 189, 130, 130, 130, 130, 169, 168, 160, 176, 163, 162, 168,
+ 161, 122, 163, 176, 161, 168, 168, 168, 122, 168, 181, 126, 122, 161, 177, 122,
+ 122, 160, 161, 176, 163, 122, 161, 182, 162, 122, 163, 160, 160, 177, 168, 181,
+ 162, 173, 130, 168, 130, 178, 122, 168, 168, 168, 161, 161, 122, 160, 168, 161,
+ 169, 121, 168, 168, 177, 163, 122, 177, 177, 122, 96, 161, 177, 168, 161, 161,
+ 177, 168, 168, 168, 160, 166, 168, 168, 168, 160, 122, 168, 168, 168, 177, 168,
+ 168, 160, 122, 163, 168, 177, 121, 166, 160, 168, 169, 160, 178, 177, 160, 161,
+ 168, 160, 92, 161, 130, 173, 130, 176, 168, 160, 166, 177, 168, 168, 163, 169,
+ 161, 160, 160, 168, 168, 161, 160, 161, 160, 161, 168, 177, 168, 161, 168, 168,
+ 177, 160, 122, 177, 168, 168, 163, 168, 161, 163, 122, 122, 177, 168, 177, 177,
+ 163, 160, 177, 161, 195, 168, 168, 171, 161, 168, 173, 160, 177, 92, 168, 168,
+ 168, 177, 176, 176, 168, 166, 168, 168, 166, 168, 177, 177, 142, 142, 169, 177,
+ 168, 122, 122, 160, 191, 161, 177, 168, 177, 122, 168, 178, 122, 168, 160, 163,
+ 181, 161, 130, 160, 130, 168, 169, 142, 96, 168, 177, 168, 166, 168, 168, 168,
+ 166, 122, 168, 169, 160, 177, 122, 161, 168, 122, 177, 185, 168, 168, 177, 161,
+ 160, 130, 94, 168, 168, 171, 177, 168, 168, 168, 172, 142, 161, 177, 160, 168,
+ 164, 177, 168, 168, 161, 194, 161, 168, 171, 122, 161, 121, 121, 160, 161, 168,
+ 168, 160, 161, 168, 168, 161, 165, 166, 161, 177, 168, 177, 161, 171, 168, 160,
+ 168, 177, 181, 168, 97, 177, 168, 168, 168, 161, 121, 160, 178, 177, 168, 168,
+ 142, 161, 167, 161, 176, 161, 113, 173, 171, 161, 161, 161, 168, 168, 178, 168,
+ 122, 182, 161, 121, 160, 178, 160, 168, 168, 161, 160, 177, 177, 168, 168, 160,
+ 122, 122, 162, 96, 122, 122, 177, 122, 122, 130, 122, 169, 122, 122, 162, 122,
+ 161, 92, 185, 122, 122, 167, 175, 161, 182, 122, 173, 121, 185, 94, 177, 162,
+ 122, 122, 168, 169, 160, 122, 160, 168, 121, 161, 122, 168, 193, 176, 164, 171,
+ 175, 166, 160, 169, 166, 122, 164, 122, 122, 122, 162, 122, 122, 181, 177, 122,
+ 182, 162, 168, 192, 164, 165, 204, 122, 122, 122, 122, 122, 122, 175, 179, 172,
+ 130, 130, 122, 122, 122, 122, 122, 168, 177, 162, 170, 173, 191, 177, 121, 162,
+ 122, 162, 162, 122, 122, 122, 122, 164, 122, 122, 162, 161, 164, 130, 130, 122,
+ 191, 177, 122, 198, 122, 122, 122, 122, 161, 113, 168, 168, 122, 177, 168, 162,
+ 122, 168, 122, 122, 180, 160, 177, 193, 177, 177, 164, 181, 161, 184, 122, 122,
+ 177, 122, 121, 168, 122, 122, 121, 121, 122, 121, 168, 121, 126, 92, 122, 191,
+ 169, 177, 168, 172, 162, 121, 121, 161, 122, 173, 122, 130, 130, 164, 181, 175,
+ 161, 122, 113, 168, 122, 172, 184, 121, 121, 122, 122, 121, 177, 121, 121, 122,
+ 168, 122, 168, 172, 179, 185, 122, 162, 173, 195, 169, 161, 170, 130, 163, 177,
+ 172, 161, 169, 182, 122, 185, 162, 130, 180, 162, 168, 164, 176, 113, 162, 161,
+ 177, 122, 162, 168, 130, 162, 164, 97, 122, 122, 122, 165, 122, 184, 122, 122,
+ 122, 169, 130, 92, 168, 122, 121, 168, 122, 179, 175, 122, 168, 121, 122, 169,
+ 169, 122, 161, 172, 168, 122, 168, 161, 97, 166, 162, 195, 171, 97, 175, 161,
+ 122, 184, 188, 166, 121, 122, 130, 177, 171, 177, 168, 161, 121, 177, 167, 122,
+ 162, 122, 92, 168, 177, 162, 113, 161, 161, 122, 166, 177, 177, 162, 168, 130,
+ 161, 130, 130, 92, 161, 160, 168, 162, 166, 168, 177, 168, 169, 185, 161, 177,
+ 122, 122, 177, 168, 169, 168, 130, 130, 130, 170, 170, 130, 179, 177, 160, 177,
+ 177, 121, 166, 166, 168, 168, 177, 168, 178, 122, 177, 122, 165, 185, 168, 168,
+ 168, 122, 162, 122, 164, 192, 178, 122, 122, 161, 193, 181, 113, 130, 200, 130,
+ 183, 179, 94, 92, 130, 113, 168, 178, 168, 177, 168, 166, 168, 161, 168, 168,
+ 168, 160, 176, 168, 168, 161, 168, 177, 168, 122, 168, 168, 161, 164, 168, 168,
+ 200, 184, 161, 92, 130, 179, 173, 92, 122, 172, 169, 161, 168, 169, 177, 198,
+ 122, 177, 162, 161, 188, 161, 121, 168, 168, 168, 181, 122, 161, 121, 161, 168,
+ 168, 171, 130, 130, 92, 92, 176, 122, 161, 161, 161, 178, 168, 191, 122, 168,
+ 160, 121, 177, 161, 122, 172, 122, 121, 172, 121, 178, 169, 161, 168, 185, 178,
+ 168, 161, 142, 177, 176, 168, 166, 190, 168, 122, 161, 162, 160, 130, 185, 160,
+ 168, 177, 168, 168, 176, 168, 168, 168, 168, 177, 168, 161, 168, 166, 179, 177,
+ 168, 168, 177, 177, 161, 168, 163, 96, 163, 168, 166, 165, 122, 161, 178, 161,
+ 121, 177, 178, 161, 92, 177, 94, 160, 130, 177, 92, 179, 113, 130, 168, 162,
+ 164, 162, 177, 168, 164, 168, 161, 168, 168, 122, 162, 185, 165, 164, 161, 122,
+ 182, 168, 168, 113, 170, 161, 113, 168, 161, 177, 177, 161, 168, 168, 177, 177,
+ 168, 177, 167, 164, 142, 94, 168, 121, 177, 168, 177, 198, 181, 168, 160, 161,
+ 181, 161, 177, 177, 171, 177, 161, 168, 161, 166, 168, 164, 168, 122, 168, 177,
+ 191, 168, 180, 161, 160, 161, 161, 177, 168, 168, 194, 163, 178, 168, 178, 168,
+ 177, 168, 177, 161, 177, 168, 160, 167, 188, 163, 121, 161, 121, 121, 161, 161,
+ 168, 160, 168, 177, 161, 130, 168, 177, 161, 142, 161, 177, 181, 122, 162, 168,
+ 164, 168, 121, 181, 97, 168, 121, 160, 177, 162, 92, 175, 92, 122, 122, 168,
+ 177, 122, 129, 181, 164, 122, 122, 122, 122, 206, 92, 122, 92, 92, 122, 130,
+ 168, 122, 122, 122, 122, 172, 161, 122, 162, 177, 161, 181, 92, 122, 122, 168,
+ 164, 130, 122, 122, 168, 130, 122, 162, 173, 160, 168, 172, 122, 162, 168, 130,
+ 130, 122, 163, 161, 166, 176, 122, 168, 176, 165, 169, 122, 130, 122, 161, 171,
+ 177, 168, 168, 168, 168, 121, 130, 130, 177, 168, 161, 121, 161, 122, 174, 181,
+ 181, 130, 164, 121, 168, 164, 121, 169, 122, 161, 161, 130, 130, 122, 177, 183,
+ 121, 168, 179, 142, 165, 122, 161, 196, 160, 162, 168, 177, 122, 168, 178, 168,
+ 162, 162, 161, 168, 169, 122, 162, 142, 177, 168, 161, 176, 177, 168, 174, 121,
+ 168, 122, 122, 121, 113, 161, 168, 168, 177, 168, 177, 171, 177, 177, 177, 168,
+ 177, 161, 122, 122, 122, 178, 169, 195, 122, 121, 175, 122, 122, 122, 121, 175,
+ 166, 181, 168, 172, 165, 161, 170, 122, 168, 168, 122, 166, 168, 168, 162, 122,
+ 173, 130, 161, 130, 130, 122, 169, 122, 161, 173, 122, 168, 122, 161, 130, 130,
+ 122, 161, 177, 168, 177, 166, 122, 122, 177, 161, 177, 121, 177, 122, 168, 161,
+ 168, 177, 168, 166, 168, 122, 122, 122, 122, 185, 161, 161, 92, 163, 190, 164,
+ 161, 142, 121, 113, 97, 168, 177, 168, 121, 122, 122, 177, 177, 160, 177, 181,
+ 198, 166, 166, 122, 177, 177, 122, 168, 168, 168, 121, 165, 177, 142, 177, 121,
+ 121, 178, 121, 121, 92, 177, 168, 168, 167, 178, 173, 162, 121, 161, 168, 168,
+ 181, 178, 168, 121, 175, 161, 122, 122, 172, 160, 122, 198, 172, 161, 169, 169,
+ 130, 122, 166, 184, 122, 168, 164, 177, 176, 113, 122, 169, 172, 172, 163, 122,
+ 113, 199, 97, 122, 121, 122, 113, 122, 122, 162, 168, 122, 162, 177, 161, 122,
+ 130, 164, 177, 177, 177, 175, 122, 122, 177, 122, 130, 162, 162, 169, 177, 184,
+ 177, 122, 161, 168, 164, 121, 177, 142, 178, 173, 207, 164, 122, 162, 181, 162,
+ 166, 113, 161, 168, 177, 162, 97, 162, 121, 168, 121, 168, 121, 163, 121, 168,
+ 174, 172, 173, 184, 177, 173, 165, 122, 166, 121, 161, 204, 153, 208, 134, 92,
+ 164, 175, 122, 163, 176, 97, 199, 191, 92, 122, 122, 121, 122, 122, 161, 177,
+ 122, 122, 163, 167, 177, 162, 168, 122, 177, 122, 162, 170, 122, 177, 177, 121,
+ 122, 122, 167, 172, 184, 122, 168, 122, 169, 176, 122, 122, 122, 164, 161, 164,
+ 122, 121, 122, 181, 161, 130, 177, 122, 122, 122, 161, 168, 176, 162, 121, 168,
+ 121, 122, 162, 92, 182, 168, 168, 163, 122, 121, 122, 177, 171, 167, 122, 177,
+ 162, 182, 168, 181, 181, 129, 168, 129, 164, 121, 160, 168, 167, 122, 168, 168,
+ 168, 168, 161, 122, 90, 122, 130, 164, 164, 166, 161, 162, 122, 122, 161, 185,
+ 166, 166, 166, 164, 177, 168, 122, 122, 122, 122, 161, 160, 181, 169, 177, 160,
+ 122, 166, 162, 168, 167, 168, 161, 173, 177, 164, 176, 122, 164, 166, 166, 177,
+ 181, 169, 164, 177, 168, 122, 164, 168, 169, 161, 177, 167, 164, 122, 173, 122,
+ 185, 130, 130, 130, 130, 130, 130, 164, 161, 168, 166, 168, 168, 166, 169, 122,
+ 178, 168, 122, 177, 176, 169, 122, 177, 164, 167, 177, 169, 165, 122, 168, 162,
+ 122, 122, 168, 160, 177, 122, 167, 122, 122, 169, 122, 169, 168, 177, 168, 122,
+ 161, 172, 168, 177, 168, 176, 161, 168, 92, 168, 113, 170, 130, 161, 92, 130,
+ 177, 165, 165, 122, 168, 168, 142, 177, 164, 177, 172, 184, 177, 122, 161, 161,
+ 122, 164, 186, 168, 177, 122, 164, 162, 168, 122, 167, 168, 161, 192, 168, 178,
+ 181, 164, 122, 122, 122, 121, 168, 166, 122, 122, 122, 169, 122, 122, 168, 122,
+ 122, 162, 168, 173, 161, 172, 130, 153, 130, 130, 130, 130, 173, 130, 163, 176,
+ 168, 178, 162, 167, 169, 126, 177, 168, 177, 122, 177, 181, 122, 122, 177, 92,
+ 168, 162, 167, 164, 122, 177, 122, 178, 164, 161, 122, 165, 168, 166, 163, 122,
+ 122, 161, 177, 122, 193, 162, 184, 198, 176, 181, 181, 130, 130, 130, 161, 130,
+ 191, 166, 122, 198, 122, 142, 121, 177, 122, 168, 168, 176, 122, 121, 177, 168,
+ 168, 168, 162, 168, 177, 122, 169, 121, 177, 177, 166, 176, 168, 168, 177, 177,
+ 161, 122, 161, 178, 177, 176, 161, 160, 169, 177, 122, 177, 122, 166, 163, 122,
+ 122, 121, 177, 172, 168, 164, 96, 175, 187, 179, 161, 130, 130, 130, 173, 130,
+ 122, 121, 177, 122, 169, 177, 122, 178, 177, 122, 122, 121, 177, 163, 168, 168,
+ 169, 122, 162, 178, 168, 168, 122, 163, 122, 122, 177, 168, 163, 122, 122, 122,
+ 177, 164, 171, 177, 177, 122, 177, 162, 168, 163, 122, 121, 171, 168, 164, 122,
+ 173, 181, 164, 96, 130, 161, 130, 122, 178, 168, 164, 166, 178, 92, 168, 168,
+ 193, 164, 168, 161, 121, 162, 177, 188, 161, 162, 161, 168, 196, 172, 121, 122,
+ 168, 177, 198, 161, 121, 177, 177, 121, 122, 177, 165, 121, 122, 142, 169, 168,
+ 160, 130, 168, 180, 168, 122, 168, 161, 121, 198, 142, 168, 160, 122, 177, 121,
+ 163, 168, 122, 121, 203, 178, 168, 122, 122, 161, 168, 121, 177, 92, 121, 172,
+ 122, 178, 177, 178, 178, 169, 121, 122, 164, 168, 168, 164, 171, 203, 121, 162,
+ 177, 193, 121, 177, 162, 161, 161, 172, 161, 168, 121, 166, 168, 177, 122, 161,
+ 121, 121, 177, 177, 122, 160, 178, 164, 193, 198, 121, 168, 163, 166, 161, 177,
+ 162, 168, 168, 161, 121, 162, 161, 122, 166, 122, 177, 121, 122, 177, 121, 168,
+ 168, 168, 121, 168, 168, 168, 121, 179, 177, 163, 180, 161, 177, 161, 122, 168,
+ 163, 177, 176, 180, 161, 168, 178, 121, 122, 121, 122, 122, 178, 142, 164, 163,
+ 172, 130, 130, 160, 130, 162, 168, 92, 168, 161, 160, 161, 164, 164, 177, 177,
+ 168, 162, 163, 142, 168, 177, 122, 177, 168, 177, 168, 168, 162, 177, 168, 162,
+ 168, 168, 121, 161, 113, 96, 121, 121, 121, 168, 121, 168, 121, 178, 142, 122,
+ 121, 177, 161, 177, 177, 161, 130, 191, 122, 178, 122, 130, 122, 122, 122, 173,
+ 122, 122, 122, 164, 178, 176, 122, 130, 173, 168, 122, 169, 162, 113, 181, 122,
+ 177, 122, 176, 177, 185, 185, 113, 177, 161, 177, 122, 177, 179, 168, 122, 181,
+ 121, 195, 142, 169, 122, 161, 126, 179, 181, 163, 168, 181, 161, 166, 129, 122,
+ 122, 122, 177, 166, 162, 161, 177, 122, 122, 122, 168, 122, 90, 122, 169, 161,
+ 177, 176, 176, 122, 176, 113, 162, 161, 122, 168, 177, 169, 177, 161, 178, 161,
+ 178, 168, 168, 169, 177, 168, 185, 173, 153, 130, 130, 130, 130, 176, 122, 176,
+ 185, 180, 168, 176, 168, 161, 122, 168, 161, 122, 177, 168, 122, 177, 169, 122,
+ 122, 168, 172, 178, 122, 160, 97, 168, 168, 122, 122, 161, 168, 164, 177, 177,
+ 182, 122, 122, 169, 178, 122, 169, 122, 122, 161, 130, 199, 181, 160, 181, 130,
+ 130, 130, 130, 161, 170, 173, 163, 161, 176, 168, 168, 122, 169, 168, 168, 168,
+ 168, 122, 161, 177, 168, 122, 177, 164, 168, 122, 164, 167, 122, 122, 177, 176,
+ 161, 161, 122, 94, 176, 175, 169, 122, 122, 122, 167, 97, 122, 122, 176, 180,
+ 122, 178, 122, 122, 122, 163, 190, 122, 122, 122, 176, 122, 122, 181, 161, 179,
+ 181, 181, 130, 130, 161, 170, 130, 130, 130, 130, 164, 168, 122, 122, 122, 122,
+ 168, 122, 177, 122, 176, 178, 167, 122, 168, 168, 168, 168, 176, 176, 122, 122,
+ 168, 122, 169, 177, 164, 161, 92, 122, 169, 122, 162, 177, 178, 177, 185, 168,
+ 177, 122, 92, 177, 168, 168, 176, 161, 182, 181, 130, 173, 92, 130, 130, 184,
+ 130, 173, 130, 130, 130, 130, 92, 113, 169, 177, 176, 122, 168, 177, 160, 122,
+ 161, 160, 185, 168, 168, 163, 177, 160, 168, 166, 122, 194, 177, 122, 121, 181,
+ 168, 177, 176, 166, 177, 185, 176, 168, 168, 122, 177, 166, 122, 169, 176, 122,
+ 122, 168, 164, 164, 177, 122, 168, 178, 177, 168, 168, 164, 181, 161, 130, 130,
+ 161, 130, 130, 130, 160, 177, 164, 122, 121, 169, 161, 142, 163, 166, 165, 168,
+ 168, 176, 121, 161, 164, 177, 169, 122, 177, 160, 122, 122, 177, 177, 161, 193,
+ 169, 168, 166, 121, 171, 168, 161, 166, 122, 122, 166, 160, 122, 168, 167, 169,
+ 166, 168, 122, 161, 177, 162, 122, 168, 122, 171, 162, 121, 168, 168, 177, 178,
+ 122, 121, 122, 169, 177, 122, 162, 122, 122, 122, 122, 178, 169, 166, 166, 177,
+ 185, 168, 181, 130, 202, 113, 161, 130, 130, 94, 173, 113, 130, 177, 167, 161,
+ 121, 163, 168, 178, 165, 177, 122, 168, 177, 169, 168, 168, 168, 96, 166, 122,
+ 122, 163, 169, 177, 162, 177, 122, 168, 168, 168, 121, 121, 177, 168, 179, 168,
+ 166, 122, 160, 169, 168, 177, 160, 168, 168, 169, 176, 168, 162, 129, 121, 168,
+ 168, 168, 166, 177, 122, 177, 165, 195, 174, 171, 181, 94, 94, 130, 160, 130,
+ 130, 130, 130, 161, 92, 130, 142, 160, 161, 177, 177, 185, 185, 121, 168, 122,
+ 166, 161, 177, 169, 190, 168, 121, 121, 177, 161, 168, 185, 122, 161, 176, 168,
+ 166, 185, 191, 168, 177, 177, 167, 168, 178, 164, 176, 168, 122, 122, 168, 177,
+ 177, 161, 160, 168, 169, 177, 142, 168, 160, 168, 186, 160, 161, 176, 121, 166,
+ 168, 185, 113, 168, 130, 130, 173, 173, 130, 161, 130, 177, 161, 168, 178, 164,
+ 168, 171, 176, 177, 176, 161, 161, 161, 122, 168, 182, 177, 177, 177, 185, 171,
+ 191, 177, 161, 162, 161, 168, 168, 169, 168, 122, 161, 168, 168, 176, 168, 121,
+ 168, 160, 168, 177, 177, 168, 178, 168, 122, 129, 122, 171, 160, 177, 161, 168,
+ 161, 161, 185, 181, 130, 166, 161, 176, 121, 168, 168, 168, 168, 160, 161, 177,
+ 171, 209, 122, 121, 161, 169, 185, 168, 177, 176, 121, 164, 168, 177, 122, 177,
+ 168, 164, 97, 177, 122, 121, 177, 161, 164, 169, 161, 121, 176, 122, 122, 160,
+ 122, 168, 121, 171, 160, 130, 160, 130, 130, 181, 130, 121, 169, 177, 171, 171,
+ 179, 121, 169, 168, 188, 122, 161, 121, 161, 177, 188, 171, 162, 122, 190, 168,
+ 166, 164, 122, 160, 121, 164, 168, 166, 122, 168, 121, 168, 161, 94, 130, 161,
+ 142, 198, 122, 178, 166, 193, 122, 198, 168, 177, 163, 168, 121, 171, 161, 178,
+ 171, 142, 121, 168, 121, 162, 181, 171, 168, 161, 121, 171, 168, 178, 121, 177,
+ 122, 177, 92, 168, 191, 181, 97, 168, 164, 166, 163, 161, 168, 168, 168, 171,
+ 168, 160, 130, 177, 171, 168, 177, 168, 122, 171, 161, 177, 142, 121, 163, 163,
+ 168, 168, 177, 121, 142, 185, 177, 161, 161, 177, 121, 122, 121, 168, 166, 122,
+ 94, 164, 168, 168, 175, 175, 122, 180, 122, 122, 162, 122, 162, 177, 122, 122,
+ 161, 168, 161, 177, 161, 122, 168, 162, 122, 176, 168, 161, 130, 198, 195, 122,
+ 162, 122, 162, 168, 171, 169, 122, 121, 142, 169, 161, 130, 168, 169, 122, 163,
+ 164, 161, 122, 122, 168, 168, 122, 177, 168, 92, 168, 174, 122, 203, 161, 168,
+ 184, 161, 122, 168, 122, 121, 168, 122, 121, 168, 177, 168, 168, 162, 183, 168,
+ 168, 177, 121, 121, 168, 193, 94, 122, 172, 172, 162, 173, 165, 161, 181, 92,
+ 122, 122, 177, 130, 168, 171, 168, 122, 162, 122, 161, 122, 122, 177, 168, 122,
+ 177, 122, 168, 162, 122, 122, 164, 122, 168, 130, 168, 122, 121, 184, 177, 122,
+ 122, 92, 177, 177, 162, 160, 168, 121, 168, 122, 161, 168, 122, 122, 160, 177,
+ 92, 122, 177, 167, 167, 122, 167, 161, 162, 164, 161, 122, 122, 168, 176, 122,
+ 177, 160, 165, 168, 182, 92, 176, 122, 162, 113, 168, 178, 161, 168, 168, 177,
+ 186, 178, 169, 203, 161, 122, 122, 184, 122, 122, 161, 161, 122, 122, 185, 185,
+ 166, 122, 177, 168, 191, 177, 173, 130, 92, 164, 122, 180, 194, 194, 164, 193,
+ 176, 161, 169, 167, 177, 168, 122, 121, 177, 191, 122, 168, 122, 177, 122, 122,
+ 194, 191, 177, 122, 122, 190, 162, 161, 160, 130, 161, 161, 178, 166, 193, 122,
+ 122, 177, 177, 163, 171, 122, 177, 122, 122, 164, 162, 177, 164, 122, 177, 122,
+ 193, 190, 168, 177, 165, 167, 165, 164, 161, 177, 194, 195, 184, 92, 130, 113,
+ 164, 122, 121, 122, 198, 171, 164, 168, 160, 121, 177, 186, 176, 161, 164, 122,
+ 161, 177, 169, 170, 130, 130, 130, 174, 162, 191, 96, 191, 177, 121, 121, 165,
+ 164, 166, 178, 160, 122, 194, 122, 198, 122, 196, 177, 193, 177, 161, 122, 122,
+ 169, 168, 168, 193, 122, 162, 122, 190, 191, 177, 122, 177, 177, 160, 176, 164,
+ 177, 181, 130, 113, 122, 94, 168, 122, 121, 121, 168, 177, 166, 171, 198, 161,
+ 191, 122, 163, 161, 168, 168, 122, 122, 121, 177, 163, 162, 164, 122, 92, 177,
+ 191, 168, 121, 92, 163, 161, 181, 130, 96, 168, 168, 121, 161, 163, 122, 168,
+ 168, 171, 191, 203, 122, 177, 160, 168, 142, 122, 168, 191, 181, 168, 165, 163,
+ 177, 181, 162, 164, 121, 161, 126, 121, 177, 121, 168, 168, 177, 160, 163, 177,
+ 161, 161, 168, 92, 164, 161, 121, 161, 168, 122, 178, 166, 122, 122, 168, 164,
+ 121, 161, 161, 168, 168, 161, 122, 161, 177, 169, 92, 177, 171, 168, 177, 161,
+ 122, 94, 122, 122, 122, 181, 168, 122, 121, 122, 197, 162, 122, 113, 122, 122,
+ 122, 168, 160, 121, 168, 177, 161, 162, 122, 122, 185, 122, 160, 122, 163, 178,
+ 185, 161, 168, 177, 122, 122, 172, 122, 168, 164, 161, 122, 162, 122, 198, 122,
+ 177, 168, 177, 168, 161, 160, 122, 121, 122, 92, 122, 122, 122, 122, 121, 173,
+ 92, 122, 161, 177, 122, 96, 198, 181, 178, 168, 165, 168, 168, 122, 177, 178,
+ 130, 113, 130, 130, 160, 177, 122, 177, 166, 122, 161, 168, 166, 168, 122, 122,
+ 122, 122, 161, 122, 164, 177, 122, 97, 161, 178, 168, 161, 122, 177, 122, 122,
+ 169, 175, 153, 113, 113, 184, 162, 94, 130, 130, 169, 161, 177, 122, 162, 122,
+ 122, 121, 169, 122, 177, 122, 177, 122, 168, 168, 168, 191, 169, 168, 122, 122,
+ 161, 166, 161, 168, 166, 178, 168, 122, 161, 122, 161, 122, 178, 168, 177, 193,
+ 122, 177, 168, 188, 168, 122, 164, 122, 166, 177, 122, 162, 122, 122, 130, 168,
+ 153, 113, 184, 173, 160, 130, 113, 130, 130, 113, 130, 130, 160, 130, 168, 122,
+ 190, 163, 177, 165, 142, 166, 122, 165, 122, 178, 168, 177, 164, 162, 183, 160,
+ 177, 167, 177, 166, 122, 177, 178, 161, 177, 177, 178, 168, 168, 168, 178, 122,
+ 122, 122, 190, 122, 122, 161, 160, 163, 167, 176, 122, 168, 166, 122, 169, 168,
+ 130, 162, 169, 168, 178, 96, 177, 178, 161, 122, 168, 168, 122, 168, 178, 122,
+ 192, 122, 177, 122, 122, 121, 191, 177, 168, 163, 168, 196, 168, 130, 198, 169,
+ 179, 160, 153, 153, 153, 173, 161, 130, 130, 130, 130, 130, 130, 94, 130, 130,
+ 160, 130, 194, 122, 177, 161, 165, 122, 97, 164, 168, 160, 168, 166, 172, 177,
+ 168, 122, 198, 161, 161, 168, 168, 164, 177, 169, 122, 178, 164, 177, 168, 191,
+ 164, 177, 167, 166, 178, 168, 160, 179, 122, 122, 168, 177, 122, 122, 179, 162,
+ 122, 122, 122, 122, 166, 176, 169, 160, 122, 185, 90, 168, 176, 178, 165, 168,
+ 122, 122, 164, 122, 122, 174, 160, 162, 164, 181, 161, 162, 113, 153, 161, 113,
+ 130, 130, 130, 202, 130, 170, 130, 202, 130, 130, 92, 166, 161, 194, 177, 177,
+ 164, 177, 177, 161, 167, 177, 122, 167, 168, 177, 164, 177, 177, 168, 178, 121,
+ 168, 122, 171, 169, 163, 122, 176, 168, 182, 168, 168, 168, 168, 113, 161, 165,
+ 168, 168, 168, 122, 121, 161, 177, 122, 163, 161, 164, 178, 177, 121, 161, 121,
+ 178, 188, 122, 177, 168, 164, 175, 122, 122, 177, 177, 168, 168, 122, 177, 122,
+ 122, 121, 177, 122, 168, 122, 198, 161, 161, 172, 113, 162, 113, 94, 92, 92,
+ 130, 161, 130, 160, 121, 193, 178, 168, 177, 122, 172, 122, 177, 122, 168, 164,
+ 177, 177, 122, 177, 178, 122, 177, 121, 122, 162, 122, 161, 177, 177, 168, 121,
+ 122, 178, 161, 169, 168, 164, 168, 121, 191, 168, 177, 177, 177, 164, 122, 178,
+ 166, 166, 121, 168, 168, 176, 177, 168, 168, 122, 122, 171, 166, 177, 161, 161,
+ 198, 175, 160, 160, 178, 122, 177, 168, 178, 163, 177, 167, 178, 122, 122, 178,
+ 166, 177, 122, 177, 168, 168, 162, 177, 160, 113, 153, 153, 181, 92, 161, 130,
+ 130, 113, 113, 113, 130, 178, 113, 183, 113, 161, 178, 92, 160, 130, 161, 168,
+ 122, 164, 168, 177, 167, 177, 172, 168, 177, 167, 92, 177, 168, 165, 160, 165,
+ 168, 168, 166, 160, 168, 177, 160, 161, 168, 177, 121, 168, 168, 161, 177, 168,
+ 161, 168, 168, 121, 122, 198, 168, 192, 168, 180, 122, 171, 178, 169, 122, 168,
+ 122, 198, 180, 190, 163, 177, 166, 160, 188, 177, 178, 122, 177, 121, 122, 180,
+ 177, 166, 182, 172, 178, 121, 168, 122, 165, 122, 177, 177, 184, 181, 113, 162,
+ 90, 113, 169, 168, 130, 160, 96, 130, 130, 130, 153, 92, 92, 166, 178, 161,
+ 168, 178, 164, 168, 169, 122, 177, 168, 174, 168, 168, 122, 122, 161, 168, 160,
+ 178, 177, 160, 97, 168, 191, 171, 165, 176, 168, 168, 176, 168, 176, 121, 177,
+ 168, 167, 172, 168, 122, 168, 168, 176, 162, 168, 164, 122, 177, 168, 178, 178,
+ 160, 122, 168, 121, 168, 164, 168, 113, 164, 168, 167, 121, 122, 121, 167, 168,
+ 122, 163, 161, 142, 185, 160, 163, 162, 181, 178, 92, 130, 92, 113, 113, 130,
+ 130, 160, 177, 161, 168, 177, 168, 178, 121, 160, 195, 178, 168, 169, 177, 164,
+ 161, 177, 167, 171, 168, 162, 168, 168, 168, 172, 160, 180, 168, 122, 177, 165,
+ 177, 171, 121, 182, 168, 142, 168, 168, 168, 168, 122, 172, 172, 168, 161, 177,
+ 161, 188, 181, 121, 178, 177, 168, 165, 185, 121, 163, 178, 160, 177, 121, 122,
+ 177, 122, 181, 121, 164, 168, 168, 168, 166, 181, 184, 153, 160, 160, 113, 130,
+ 162, 130, 177, 160, 177, 122, 181, 164, 121, 121, 121, 177, 168, 122, 166, 177,
+ 168, 168, 161, 161, 122, 163, 177, 169, 121, 177, 164, 121, 160, 168, 177, 168,
+ 166, 177, 193, 203, 168, 177, 177, 160, 122, 122, 168, 166, 161, 168, 168, 121,
+ 168, 122, 142, 161, 177, 170, 178, 177, 168, 168, 177, 126, 161, 168, 161, 168,
+ 161, 174, 113, 162, 94, 92, 168, 161, 113, 130, 160, 92, 130, 161, 171, 178,
+ 122, 177, 160, 177, 122, 168, 164, 177, 161, 191, 160, 162, 168, 180, 165, 160,
+ 169, 166, 168, 168, 97, 168, 168, 122, 161, 160, 168, 177, 121, 163, 177, 177,
+ 169, 168, 121, 121, 168, 177, 168, 160, 168, 130, 181, 174, 169, 168, 142, 171,
+ 164, 163, 160, 121, 177, 160, 168, 168, 142, 168, 168, 121, 161, 177, 163, 164,
+ 161, 181, 121, 121, 161, 168, 177, 168, 163, 182, 160, 168, 177, 168, 161, 168,
+ 177, 178, 161, 121, 163, 164, 162, 161, 160, 168, 121, 121, 177, 171, 178, 178,
+ 168, 168, 161, 161, 162, 97, 161, 177, 178, 161, 178, 168, 171, 161, 168, 168,
+ 177, 177, 162, 168, 161, 161, 128, 92, 168, 168, 142, 121, 177, 164, 161, 161,
+ 168, 161, 177, 177, 121, 153, 164, 164, 168, 177, 121, 168, 183, 161, 161, 177,
+ 171, 177, 180, 168, 161, 92, 121, 177, 168, 168, 168, 164, 161, 172, 177, 113,
+ 122, 122, 173, 122, 206, 168, 161, 184, 177, 161, 161, 164, 177, 168, 161, 177,
+ 161, 168, 122, 168, 168, 163, 177, 167, 178, 167, 122, 177, 168, 121, 122, 177,
+ 161, 168, 168, 167, 161, 168, 192, 122, 168, 169, 177, 168, 122, 177, 121, 161,
+ 121, 168, 163, 181, 178, 168, 177, 160, 164, 169, 92, 178, 97, 164, 168, 121,
+ 177, 121, 122, 122, 122, 129, 122, 176, 161, 181, 122, 164, 161, 168, 164, 172,
+ 162, 161, 126, 181, 172, 162, 168, 126, 121, 169, 160, 122, 130, 162, 177, 121,
+ 178, 179, 166, 122, 165, 162, 122, 130, 168, 122, 122, 184, 168, 167, 168, 168,
+ 161, 168, 130, 130, 168, 178, 122, 177, 121, 168, 130, 166, 161, 161, 180, 177,
+ 177, 173, 177, 177, 142, 168, 168, 168, 162, 162, 167, 178, 162, 177, 188, 121,
+ 177, 113, 121, 167, 184, 122, 168, 122, 162, 162, 121, 181, 121, 177, 164, 122,
+ 142, 207, 130, 177, 177, 122, 121, 168, 168, 177, 168, 122, 177, 122, 181, 129,
+ 168, 161, 122, 122, 122, 130, 192, 129, 180, 130, 171, 122, 160, 161, 168, 113,
+ 168, 174, 168, 177, 168, 161, 177, 177, 168, 161, 179, 122, 121, 161, 162, 169,
+ 168, 162, 168, 167, 161, 130, 161, 177, 168, 166, 160, 168, 168, 96, 168, 177,
+ 168, 168, 177, 168, 177, 176, 185, 130, 121, 177, 161, 168, 168, 166, 162, 122,
+ 176, 122, 162, 122, 167, 185, 96, 113, 185, 166, 185, 169, 160, 168, 161, 176,
+ 168, 185, 130, 121, 169, 168, 176, 176, 176, 130, 185, 97, 171, 161, 176, 96,
+ 185, 160, 173, 171, 122, 90, 177, 198, 122, 160, 182, 177, 161, 170, 121, 177,
+ 122, 122, 122, 168, 161, 161, 185, 130, 92, 170, 166, 177, 168, 171, 121, 177,
+ 122, 161, 177, 161, 166, 122, 161, 122, 160, 171, 198, 176, 166, 122, 122, 122,
+ 122, 96, 113, 161, 130, 168, 168, 177, 122, 185, 122, 177, 161, 191, 160, 177,
+ 122, 168, 122, 178, 176, 160, 190, 161, 177, 174, 121, 177, 161, 122, 122, 160,
+ 168, 122, 122, 122, 168, 190, 190, 191, 122, 176, 168, 168, 122, 142, 168, 185,
+ 122, 161, 121, 165, 190, 191, 121, 164, 171, 122, 180, 122, 177, 168, 161, 174,
+ 161, 184, 172, 130, 130, 130, 130, 130, 92, 130, 179, 122, 97, 185, 122, 160,
+ 177, 169, 174, 122, 177, 92, 168, 168, 122, 122, 178, 122, 122, 122, 122, 122,
+ 168, 121, 191, 168, 122, 169, 177, 168, 161, 122, 122, 160, 122, 177, 160, 177,
+ 166, 177, 177, 122, 166, 122, 176, 122, 161, 178, 177, 122, 171, 178, 185, 160,
+ 176, 122, 122, 122, 161, 122, 161, 177, 122, 177, 175, 192, 177, 168, 192, 122,
+ 122, 169, 177, 122, 164, 96, 130, 130, 130, 168, 130, 130, 130, 130, 130, 161,
+ 168, 185, 160, 168, 166, 160, 160, 166, 168, 168, 177, 122, 122, 168, 176, 177,
+ 168, 191, 167, 164, 161, 161, 168, 122, 168, 165, 166, 122, 161, 168, 122, 178,
+ 168, 161, 168, 161, 160, 122, 163, 190, 177, 121, 122, 169, 168, 168, 176, 177,
+ 168, 176, 122, 167, 168, 122, 121, 168, 121, 190, 168, 122, 166, 122, 122, 177,
+ 168, 122, 168, 130, 181, 184, 130, 130, 130, 92, 130, 130, 92, 130, 170, 130,
+ 92, 130, 130, 130, 130, 92, 161, 163, 168, 122, 122, 160, 186, 161, 166, 177,
+ 185, 177, 168, 165, 178, 171, 122, 177, 168, 122, 122, 161, 121, 168, 122, 166,
+ 177, 160, 160, 161, 122, 168, 168, 122, 122, 121, 168, 168, 166, 168, 168, 194,
+ 168, 160, 166, 168, 168, 122, 168, 188, 122, 129, 97, 168, 122, 194, 122, 160,
+ 168, 192, 177, 122, 176, 122, 163, 177, 177, 181, 161, 184, 113, 130, 130, 130,
+ 130, 130, 92, 130, 170, 160, 130, 130, 130, 130, 176, 185, 177, 161, 96, 122,
+ 161, 160, 122, 168, 177, 122, 161, 177, 169, 163, 168, 168, 142, 177, 168, 176,
+ 165, 161, 168, 195, 190, 122, 122, 122, 177, 168, 177, 122, 169, 168, 164, 191,
+ 168, 122, 142, 168, 168, 178, 166, 168, 122, 122, 126, 177, 168, 166, 122, 177,
+ 166, 122, 177, 168, 169, 177, 169, 161, 121, 177, 121, 122, 169, 168, 122, 177,
+ 177, 122, 168, 122, 177, 121, 177, 122, 195, 122, 121, 122, 166, 168, 161, 161,
+ 177, 161, 160, 168, 163, 169, 161, 181, 181, 181, 175, 113, 173, 130, 130, 160,
+ 130, 130, 161, 113, 130, 153, 130, 210, 160, 121, 122, 121, 168, 169, 164, 180,
+ 122, 122, 177, 122, 122, 122, 121, 177, 168, 175, 160, 165, 121, 122, 178, 122,
+ 168, 168, 190, 168, 129, 168, 191, 92, 122, 177, 122, 177, 191, 194, 121, 168,
+ 168, 168, 161, 122, 190, 177, 168, 168, 164, 177, 121, 177, 161, 122, 169, 163,
+ 160, 177, 177, 166, 176, 168, 122, 164, 122, 160, 168, 122, 191, 177, 191, 122,
+ 168, 168, 177, 171, 168, 168, 168, 121, 177, 97, 161, 165, 161, 161, 122, 121,
+ 161, 168, 121, 191, 168, 161, 172, 168, 168, 168, 183, 164, 160, 162, 184, 202,
+ 181, 92, 113, 130, 161, 130, 179, 92, 168, 96, 161, 160, 113, 177, 168, 167,
+ 122, 161, 168, 177, 168, 92, 121, 168, 169, 177, 160, 168, 122, 121, 168, 165,
+ 177, 168, 122, 168, 168, 122, 168, 176, 161, 161, 122, 126, 161, 162, 177, 122,
+ 168, 192, 167, 177, 96, 160, 122, 167, 160, 168, 122, 174, 97, 167, 168, 177,
+ 177, 166, 122, 177, 121, 121, 168, 176, 177, 180, 177, 122, 121, 177, 191, 166,
+ 168, 122, 168, 122, 122, 169, 168, 130, 168, 160, 179, 160, 168, 172, 202, 130,
+ 130, 130, 170, 161, 130, 130, 173, 92, 179, 179, 92, 177, 142, 177, 177, 121,
+ 161, 168, 142, 161, 122, 168, 168, 142, 180, 166, 160, 177, 168, 177, 121, 121,
+ 168, 121, 122, 168, 163, 168, 122, 168, 177, 167, 177, 160, 163, 177, 168, 122,
+ 161, 196, 168, 169, 122, 122, 182, 160, 177, 168, 177, 164, 168, 161, 168, 168,
+ 122, 168, 121, 121, 170, 168, 177, 168, 161, 176, 176, 122, 121, 166, 168, 176,
+ 177, 122, 121, 176, 160, 168, 166, 168, 121, 168, 168, 177, 177, 160, 169, 121,
+ 168, 180, 161, 168, 160, 113, 130, 130, 161, 161, 161, 130, 161, 130, 168, 177,
+ 168, 188, 177, 177, 121, 168, 94, 191, 122, 164, 191, 121, 175, 177, 192, 121,
+ 97, 177, 192, 168, 121, 161, 169, 168, 162, 168, 168, 168, 177, 122, 122, 142,
+ 121, 161, 185, 168, 175, 161, 168, 168, 169, 160, 122, 168, 122, 191, 191, 168,
+ 142, 198, 178, 162, 122, 168, 142, 177, 190, 185, 160, 177, 166, 192, 122, 161,
+ 191, 181, 177, 177, 191, 168, 177, 121, 92, 161, 162, 92, 130, 160, 168, 163,
+ 171, 169, 168, 180, 121, 177, 171, 190, 177, 168, 178, 168, 168, 168, 191, 191,
+ 177, 121, 168, 122, 97, 163, 176, 161, 168, 122, 168, 160, 177, 168, 203, 168,
+ 122, 121, 122, 121, 168, 162, 178, 177, 177, 185, 191, 168, 168, 168, 168, 168,
+ 161, 130, 130, 160, 178, 121, 161, 161, 142, 160, 193, 142, 168, 168, 166, 121,
+ 122, 122, 168, 168, 121, 161, 168, 168, 177, 188, 161, 121, 121, 168, 169, 122,
+ 171, 121, 168, 181, 168, 164, 172, 168, 160, 162, 142, 168, 177, 164, 121, 168,
+ 177, 180, 161, 160, 168, 191, 188, 177, 161, 121, 168, 121, 168, 177, 168, 121,
+ 161, 122, 92, 161, 168, 121, 168, 177, 121, 168, 122, 122, 194, 121, 198, 121,
+ 177, 168, 168, 192, 168, 161, 178, 180, 126, 168, 168, 168, 172, 161, 161, 191,
+ 142, 168, 142, 168, 177, 185, 161, 191, 168, 166, 168, 168, 177, 161, 121, 168,
+ 168, 168, 168, 177, 177, 168, 168, 161, 177, 177, 177, 163, 122, 161, 162, 130,
+ 128, 121, 168, 161, 163, 177, 168, 168, 121, 161, 168, 168, 160, 191, 176, 168,
+ 168, 168, 168, 121, 171, 177, 168, 160, 168, 168, 168, 122, 90, 130, 164, 175,
+ 122, 168, 161, 161, 168, 174, 176, 161, 122, 160, 168, 161, 122, 121, 174, 170,
+ 130, 163, 168, 168, 168, 192, 177, 161, 161, 175, 122, 160, 161, 161, 122, 160,
+ 161, 168, 122, 168, 166, 176, 166, 162, 191, 122, 194, 162, 130, 130, 92, 168,
+ 160, 194, 161, 160, 188, 160, 160, 160, 161, 168, 161, 190, 122, 122, 169, 122,
+ 177, 166, 161, 122, 177, 168, 161, 192, 122, 186, 142, 179, 170, 170, 168, 161,
+ 170, 130, 130, 130, 160, 168, 168, 168, 122, 161, 176, 180, 160, 168, 168, 121,
+ 160, 177, 168, 177, 177, 163, 163, 168, 190, 122, 168, 173, 177, 180, 168, 186,
+ 168, 168, 168, 161, 176, 161, 130, 130, 130, 130, 161, 130, 130, 130, 161, 96,
+ 168, 198, 161, 168, 168, 160, 168, 185, 168, 122, 177, 168, 168, 122, 160, 168,
+ 168, 161, 168, 164, 191, 182, 177, 164, 161, 122, 96, 177, 191, 168, 168, 164,
+ 185, 161, 161, 185, 113, 130, 130, 168, 130, 122, 122, 168, 142, 160, 191, 168,
+ 177, 121, 168, 168, 161, 168, 122, 161, 168, 94, 161, 163, 160, 164, 168, 166,
+ 190, 166, 168, 160, 160, 160, 122, 161, 164, 161, 168, 160, 113, 161, 94, 161,
+ 94, 177, 168, 168, 168, 174, 171, 191, 161, 121, 209, 177, 122, 168, 122, 160,
+ 191, 160, 177, 168, 168, 113, 121, 164, 168, 121, 177, 161, 190, 168, 190, 168,
+ 177, 168, 178, 168, 122, 121, 122, 122, 176, 121, 168, 160, 121, 161, 122, 161,
+ 168, 160, 185, 170, 161, 160, 160, 160, 185, 162, 170, 168, 160, 122, 160, 161,
+ 177, 168, 168, 161, 122, 177, 168, 177, 172, 194, 122, 161, 163, 161, 160, 165,
+ 168, 161, 188, 161, 122, 113, 160, 168, 170, 122, 177, 177, 168, 168, 168, 122,
+ 166, 168, 193, 160, 168, 168, 161, 168, 169, 168, 168, 161, 122, 160, 161, 177,
+ 177, 121, 177, 166, 160, 185, 161, 160, 168, 122, 193, 161, 168, 168, 121, 177,
+ 177, 191, 168, 122, 171, 168, 168, 168, 121, 121, 168, 177, 164, 161, 122, 168,
+ 121, 160, 121, 164, 165, 122, 177, 113, 168, 171, 177, 168, 171, 160, 161, 121,
+ 169, 168, 168, 161, 168, 122, 121, 122, 168, 161, 161, 160, 142, 121, 122, 161,
+ 168, 168, 168, 161, 97, 153, 94, 92, 171, 167, 161, 121, 121, 168, 188, 180,
+ 204, 168, 168, 168, 161, 168, 122, 177, 164, 182, 168, 161, 168, 142, 160, 160,
+ 121, 161, 161, 177, 168, 160, 160, 163, 161, 168, 177, 121, 161, 166, 168, 177,
+ 161, 161, 168, 168, 163, 161, 168, 168, 169, 168, 122, 182, 122, 121, 160, 162,
+ 122, 130, 196, 92, 162, 122, 122, 130, 176, 176, 121, 122, 181, 122, 121, 167,
+ 198, 177, 177, 162, 168, 162, 121, 122, 122, 168, 168, 178, 122, 130, 164, 177,
+ 163, 161, 122, 177, 92, 163, 176, 160, 121, 122, 177, 122, 182, 122, 177, 122,
+ 171, 122, 122, 177, 161, 161, 179, 122, 164, 122, 168, 162, 168, 161, 166, 176,
+ 168, 162, 122, 168, 142, 130, 168, 177, 177, 122, 173, 177, 177, 121, 167, 166,
+ 122, 122, 172, 161, 176, 168, 168, 172, 168, 177, 130, 185, 168, 166, 177, 170,
+ 168, 168, 169, 177, 160, 168, 142, 168, 168, 161, 168, 171, 92, 168, 168, 170,
+ 113, 168, 121, 168, 168, 168, 168, 121, 177, 168, 168, 161, 122, 90, 177, 122,
+ 185, 164, 172, 92, 166, 168, 184, 130, 130, 184, 168, 161, 161, 168, 164, 168,
+ 126, 166, 122, 167, 122, 168, 178, 164, 130, 177, 168, 168, 177, 179, 122, 161,
+ 122, 168, 167, 161, 168, 162, 177, 122, 177, 122, 168, 181, 168, 92, 130, 177,
+ 169, 122, 172, 168, 168, 164, 168, 161, 185, 122, 168, 168, 184, 184, 130, 130,
+ 130, 130, 130, 166, 166, 161, 168, 169, 122, 121, 166, 166, 122, 121, 177, 168,
+ 168, 185, 163, 130, 182, 162, 161, 177, 168, 92, 165, 177, 168, 162, 173, 168,
+ 160, 168, 177, 176, 92, 130, 122, 167, 177, 171, 161, 122, 122, 165, 166, 113,
+ 92, 130, 166, 168, 164, 122, 168, 177, 163, 122, 186, 186, 174, 168, 175, 181,
+ 168, 166, 177, 168, 169, 177, 121, 122, 179, 170, 177, 177, 168, 162, 122, 122,
+ 168, 160, 168, 177, 121, 121, 161, 161, 160, 168, 168, 161, 168, 166, 142, 172,
+ 190, 168, 192, 161, 161, 161, 162, 122, 177, 168, 168, 168, 92, 177, 177, 177,
+ 166, 168, 168, 113, 92, 168, 177, 177, 121, 177, 180, 177, 166, 130, 177, 166,
+ 121, 163, 121, 168, 94, 121, 168, 171, 121, 162, 121, 121, 177, 168, 185, 168,
+ 171, 177, 168, 177, 122, 177, 188, 122, 168, 122, 168, 122, 161, 161, 192, 160,
+ 162, 130, 168, 177, 194, 177, 122, 191, 193, 92, 92, 130, 163, 168, 163, 190,
+ 177, 168, 166, 161, 168, 171, 177, 203, 97, 122, 163, 176, 168, 191, 130, 173,
+ 130, 92, 122, 122, 168, 177, 168, 176, 168, 191, 130, 169, 177, 164, 168, 177,
+ 122, 161, 165, 168, 161, 177, 177, 168, 167, 209, 122, 177, 191, 122, 172, 209,
+ 179, 130, 177, 177, 168, 160, 191, 168, 168, 192, 168, 168, 168, 191, 122, 161,
+ 122, 163, 160, 191, 203, 165, 193, 166, 168, 192, 121, 168, 161, 122, 142, 160,
+ 92, 113, 130, 160, 177, 177, 168, 193, 178, 193, 177, 163, 168, 191, 121, 177,
+ 177, 191, 161, 122, 177, 122, 122, 191, 168, 122, 176, 168, 168, 97, 92, 130,
+ 130, 182, 160, 183, 160, 160, 168, 160, 161, 160, 166, 190, 160, 168, 160, 160,
+ 194, 194, 122, 168, 177, 122, 190, 161, 190, 177, 190, 191, 192, 177, 192, 188,
+ 192, 177, 178, 122, 122, 122, 122, 94, 203, 163, 121, 161, 179, 161, 161, 121,
+ 191, 122, 168, 193, 191, 160, 177, 163, 160, 160, 168, 191, 161, 177, 168, 168,
+ 168, 177, 177, 160, 168, 122, 160, 192, 161, 122, 122, 122, 122, 163, 122, 122,
+ 198, 161, 191, 142, 121, 203, 164, 177, 193, 121, 121, 163, 160, 176, 177, 121,
+ 169, 177, 177, 178, 160, 168, 175, 130, 92, 168, 160, 161, 168, 168, 122, 168,
+ 176, 166, 203, 122, 161, 177, 177, 192, 168, 191, 168, 122, 160, 160, 130, 162,
+ 166, 162, 177, 161, 168, 168, 161, 168, 188, 163, 177, 160, 190, 161, 122, 188,
+ 177, 191, 181, 188, 160, 194, 171, 122, 190, 176, 191, 177, 161, 168, 164, 177,
+ 121, 177, 191, 161, 160, 191, 168, 168, 168, 204, 185, 177, 161, 121, 168, 188,
+ 168, 168, 168, 168, 161, 168, 183, 161, 163, 164, 121, 168, 163, 161, 161, 121,
+ 163, 161, 130, 163, 121, 168, 97, 168, 191, 168, 188, 177, 122, 168, 166, 177,
+ 122, 168, 122, 122, 176, 168, 122, 153, 177, 142, 162, 164, 168, 161, 165, 189,
+ 153, 153, 153, 161, 166, 168, 169, 122, 153, 161, 162, 177, 162, 168, 168, 166,
+ 168, 195, 168, 178, 122, 153, 164, 168, 168, 161, 161, 168, 142, 169, 172, 185,
+ 168, 165, 177, 167, 168, 121, 177, 177, 122, 170, 122, 195, 169, 168, 172, 122,
+ 162, 177, 97, 196, 164, 122, 121, 162, 122, 176, 177, 122, 122, 96, 168, 166,
+ 122, 122, 122, 122, 94, 170, 162, 122, 122, 177, 165, 175, 113, 171, 166, 177,
+ 166, 161, 160, 162, 181, 130, 172, 191, 166, 181, 172, 169, 122, 172, 176, 122,
+ 164, 205, 162, 128, 122, 160, 161, 164, 161, 122, 169, 165, 122, 121, 164, 177,
+ 153, 164, 121, 168, 178, 122, 122, 172, 161, 113, 122, 142, 168, 172, 160, 191,
+ 121, 164, 170, 113, 202, 183, 121, 178, 122, 166, 193, 162, 162, 177, 177, 122,
+ 168, 164, 113, 179, 168, 162, 122, 121, 92, 181, 121, 122, 168, 94, 198, 122,
+ 177, 122, 174, 164, 167, 177, 130, 130, 168, 176, 169, 161, 162, 122, 160, 130,
+ 130, 130, 171, 169, 176, 122, 161, 168, 161, 92, 168, 122, 130, 92, 130, 130,
+ 185, 186, 122, 122, 174, 122, 168, 92, 122, 122, 177, 168, 122, 122, 122, 177,
+ 177, 177, 122, 175, 166, 122, 162, 122, 170, 130, 169, 168, 177, 122, 177, 177,
+ 168, 168, 165, 161, 122, 122, 130, 177, 122, 121, 168, 122, 182, 168, 169, 177,
+ 171, 177, 122, 169, 166, 161, 185, 166, 130, 113, 130, 130, 162, 168, 164, 177,
+ 122, 176, 121, 142, 122, 168, 168, 168, 168, 166, 121, 168, 165, 168, 178, 169,
+ 190, 169, 163, 166, 162, 130, 92, 163, 177, 142, 166, 142, 166, 121, 161, 177,
+ 185, 168, 162, 171, 168, 166, 177, 130, 130, 192, 168, 166, 177, 177, 177, 122,
+ 122, 121, 122, 177, 122, 166, 190, 142, 168, 176, 130, 130, 160, 166, 92, 168,
+ 167, 168, 177, 166, 169, 166, 161, 161, 176, 162, 171, 198, 166, 168, 130, 130,
+ 90, 162, 121, 166, 164, 164, 142, 178, 178, 177, 162, 162, 122, 170, 203, 160,
+ 168, 160, 121, 168, 170, 162, 122, 168, 142, 177, 168, 161, 167, 92, 130, 171,
+ 168, 121, 142, 130, 191, 171, 94, 172, 181, 121, 178, 130, 121, 177, 171, 174,
+ 180, 171, 121, 160, 182, 168, 172, 161, 122, 168, 153, 122, 121, 122, 122, 168,
+ 181, 177, 96, 181, 122, 162, 122, 122, 169, 168, 168, 169, 162, 162, 122, 168,
+ 198, 130, 168, 122, 161, 177, 169, 161, 161, 167, 142, 177, 177, 177, 168, 162,
+ 162, 160, 162, 164, 166, 163, 177, 162, 162, 161, 177, 168, 92, 177, 122, 168,
+ 142, 130, 130, 161, 169, 168, 92, 172, 178, 181, 121, 168, 161, 177, 168, 122,
+ 161, 164, 122, 121, 168, 176, 122, 161, 122, 177, 122, 164, 163, 169, 176, 130,
+ 130, 130, 122, 168, 176, 161, 186, 184, 130, 164, 168, 122, 121, 168, 121, 122,
+ 162, 121, 161, 121, 121, 169, 177, 121, 162, 168, 142, 161, 177, 168, 122, 96,
+ 177, 166, 122, 168, 122, 168, 162, 168, 122, 176, 168, 178, 190, 161, 122, 161,
+ 162, 122, 92, 168, 165, 168, 164, 169, 165, 122, 177, 122, 153, 130, 163, 160,
+ 168, 168, 177, 168, 162, 177, 161, 162, 161, 166, 166, 178, 162, 168, 198, 169,
+ 122, 161, 166, 168, 172, 178, 175, 168, 176, 122, 161, 160, 92, 166, 162, 166,
+ 161, 168, 168, 168, 177, 166, 176, 122, 122, 177, 122, 168, 122, 177, 171, 161,
+ 186, 130, 164, 179, 168, 177, 177, 167, 161, 161, 177, 168, 168, 191, 177, 171,
+ 130, 130, 177, 161, 168, 168, 177, 162, 160, 168, 167, 122, 171, 161, 171, 177,
+ 177, 122, 176, 122, 164, 169, 122, 177, 169, 168, 171, 122, 176, 168, 168, 168,
+ 162, 161, 182, 162, 164, 161, 161, 160, 160, 122, 163, 160, 168, 176, 165, 122,
+ 166, 168, 168, 168, 176, 185, 92, 97, 168, 168, 161, 121, 176, 166, 169, 168,
+ 161, 122, 130, 94, 162, 177, 164, 168, 160, 168, 177, 168, 168, 168, 121, 176,
+ 169, 168, 166, 168, 161, 122, 161, 176, 168, 173, 176, 168, 122, 121, 162, 163,
+ 122, 177, 168, 122, 168, 166, 178, 168, 161, 172, 168, 122, 121, 169, 163, 122,
+ 161, 161, 168, 182, 168, 160, 161, 142, 92, 177, 168, 94, 168, 167, 168, 168,
+ 168, 164, 162, 97, 168, 177, 161, 122, 168, 177, 142, 122, 122, 161, 177, 164,
+ 177, 92, 122, 122, 162, 122, 163, 167, 168, 122, 162, 130, 166, 122, 122, 121,
+ 177, 177, 168, 122, 163, 161, 130, 168, 166, 168, 168, 177, 178, 96, 170, 130,
+ 130, 130, 122, 168, 161, 177, 177, 161, 160, 166, 161, 161, 169, 176, 177, 168,
+ 168, 166, 165, 168, 169, 181, 130, 130, 170, 161, 130, 161, 170, 176, 160, 96,
+ 142, 177, 177, 166, 161, 122, 165, 122, 168, 185, 168, 168, 211, 176, 177, 168,
+ 176, 168, 121, 168, 122, 177, 161, 176, 96, 170, 202, 130, 170, 160, 130, 113,
+ 130, 92, 160, 171, 182, 165, 161, 174, 177, 168, 168, 160, 166, 168, 176, 195,
+ 185, 160, 166, 160, 160, 130, 130, 130, 161, 92, 92, 92, 177, 122, 177, 161,
+ 177, 162, 168, 164, 177, 168, 160, 92, 177, 168, 166, 122, 122, 185, 166, 121,
+ 168, 168, 113, 92, 113, 92, 161, 130, 161, 168, 163, 168, 122, 161, 177, 97,
+ 168, 198, 161, 168, 168, 168, 178, 165, 160, 96, 164, 161, 122, 186, 122, 177,
+ 161, 122, 161, 169, 177, 178, 168, 122, 176, 168, 167, 130, 130, 162, 177, 176,
+ 168, 166, 168, 122, 177, 185, 161, 122, 177, 121, 178, 168, 177, 177, 161, 172,
+ 176, 174, 166, 176, 185, 113, 94, 161, 160, 170, 121, 191, 121, 162, 169, 162,
+ 161, 122, 161, 168, 168, 122, 181, 163, 177, 166, 122, 122, 177, 168, 191, 168,
+ 122, 178, 163, 163, 167, 176, 164, 94, 160, 130, 142, 177, 161, 168, 168, 177,
+ 177, 177, 168, 168, 162, 168, 162, 142, 122, 168, 177, 161, 122, 168, 160, 121,
+ 160, 160, 166, 177, 169, 128, 162, 176, 161, 168, 176, 191, 168, 178, 168, 177,
+ 162, 122, 168, 92, 168, 185, 163, 181, 161, 168, 161, 161, 177, 161, 121, 92,
+ 177, 178, 178, 185, 168, 161, 183, 168, 161, 142, 164, 168, 177, 168, 166, 162,
+ 164, 168, 161, 168, 185, 177, 142, 177, 168, 177, 121, 121, 121, 177, 160, 168,
+ 161, 177, 160, 94, 90, 177, 94, 161, 168, 168, 122, 90, 175, 177, 122, 177,
+ 122, 122, 168, 92, 177, 177, 176, 121, 122, 122, 177, 177, 168, 161, 92, 177,
+ 121, 177, 168, 167, 177, 142, 122, 122, 163, 160, 122, 192, 192, 122, 122, 169,
+ 122, 168, 175, 168, 168, 122, 161, 166, 122, 177, 168, 177, 161, 122, 161, 130,
+ 168, 160, 177, 168, 168, 161, 161, 202, 130, 177, 122, 162, 177, 168, 163, 121,
+ 175, 122, 168, 160, 184, 202, 160, 160, 168, 161, 167, 177, 162, 121, 121, 122,
+ 168, 201, 168, 177, 177, 177, 177, 168, 177, 160, 185, 177, 177, 172, 161, 160,
+ 168, 177, 168, 161, 168, 160, 121, 122, 177, 163, 121, 177, 168, 168, 121, 164,
+ 178, 188, 168, 122, 177, 161, 168, 168, 177, 122, 169, 166, 161, 122, 122, 121,
+ 122, 122, 162, 173, 163, 168, 179, 164, 171, 122, 204, 122, 160, 185, 168, 177,
+ 161, 122, 122, 161, 163, 165, 177, 161, 122, 161, 164, 161, 168, 177, 177, 122,
+ 177, 181, 163, 169, 122, 164, 122, 122, 161, 122, 177, 166, 178, 166, 168, 130,
+ 184, 163, 161, 161, 94, 161, 168, 168, 166, 161, 168, 122, 162, 130, 92, 161,
+ 122, 92, 166, 166, 168, 126, 170, 164, 121, 164, 177, 122, 177, 122, 184, 161,
+ 168, 177, 168, 168, 122, 177, 92, 165, 178, 180, 122, 177, 121, 161, 176, 121,
+ 122, 162, 168, 130, 92, 161, 168, 162, 168, 161, 161, 177, 161, 163, 121, 177,
+ 177, 121, 181, 130, 162, 162, 183, 122, 164, 166, 163, 122, 122, 122, 172, 122,
+ 121, 161, 181, 153, 177, 163, 122, 177, 177, 198, 168, 97, 171, 121, 121, 181,
+ 113, 130, 92, 161, 168, 162, 177, 122, 168, 162, 168, 168, 177, 162, 92, 177,
+ 171, 121, 121, 113, 161, 182, 161, 177, 168, 121, 164, 121, 168, 177, 168, 161,
+ 165, 168, 161, 161, 122, 177, 122, 130, 166, 122, 122, 168, 161, 198, 177, 122,
+ 166, 122, 164, 175, 122, 177, 166, 168, 122, 168, 177, 177, 168, 130, 92, 168,
+ 177, 174, 122, 196, 177, 122, 169, 169, 122, 168, 161, 92, 130, 130, 177, 122,
+ 176, 161, 168, 177, 161, 130, 130, 161, 185, 121, 121, 168, 166, 130, 121, 121,
+ 172, 168, 168, 166, 168, 177, 178, 168, 168, 162, 121, 163, 182, 161, 168, 169,
+ 168, 168, 160, 153, 121, 121, 162, 121, 172, 163, 121, 122, 164, 181, 162, 172,
+ 161, 177, 181, 172, 161, 181, 130, 183, 168, 122, 172, 163, 172, 198, 130, 122,
+ 122, 181, 172, 122, 168, 122, 167, 160, 162, 163, 198, 177, 164, 122, 168, 122,
+ 181, 164, 161, 161, 162, 161, 121, 168, 181, 122, 122, 177, 161, 176, 163, 122,
+ 168, 168, 113, 130, 167, 168, 169, 162, 167, 168, 167, 175, 94, 161, 168, 165,
+ 168, 122, 168, 168, 174, 130, 161, 161, 178, 122, 168, 122, 161, 168, 122, 163,
+ 122, 161, 168, 177, 185, 167, 122, 182, 169, 163, 166, 166, 122, 191, 176, 177,
+ 177, 166, 168, 167, 177, 178, 181, 161, 185, 205, 130, 168, 130, 162, 130, 162,
+ 177, 164, 160, 160, 168, 167, 121, 166, 178, 122, 168, 122, 165, 121, 177, 122,
+ 122, 122, 122, 161, 122, 163, 122, 161, 185, 161, 130, 130, 92, 202, 161, 92,
+ 190, 168, 179, 168, 177, 178, 177, 142, 161, 177, 162, 161, 198, 177, 122, 163,
+ 178, 167, 166, 177, 178, 122, 168, 176, 168, 173, 113, 170, 92, 183, 130, 92,
+ 130, 161, 168, 161, 171, 185, 181, 121, 168, 162, 168, 121, 168, 167, 177, 121,
+ 166, 177, 172, 161, 122, 122, 177, 122, 178, 178, 200, 177, 167, 122, 164, 181,
+ 171, 122, 170, 160, 168, 162, 130, 130, 130, 130, 202, 130, 166, 122, 161, 177,
+ 162, 122, 163, 161, 122, 177, 162, 168, 122, 168, 162, 162, 162, 162, 168, 161,
+ 121, 122, 164, 161, 121, 162, 122, 122, 162, 121, 177, 178, 169, 161, 168, 153,
+ 160, 130, 183, 130, 177, 168, 162, 162, 168, 176, 166, 171, 168, 167, 168, 168,
+ 121, 96, 168, 168, 121, 167, 169, 168, 177, 121, 166, 168, 161, 181, 130, 92,
+ 168, 185, 177, 178, 177, 162, 181, 169, 177, 177, 163, 168, 174, 168, 176, 168,
+ 178, 177, 177, 177, 162, 168, 177, 122, 161, 177, 168, 166, 176, 142, 177, 166,
+ 168, 142, 198, 113, 113, 94, 130, 113, 161, 177, 161, 163, 168, 168, 126, 167,
+ 177, 121, 168, 142, 161, 177, 166, 122, 177, 168, 122, 121, 177, 168, 161, 161,
+ 168, 162, 161, 177, 164, 160, 162, 142, 169, 177, 162, 168, 168, 121, 121, 122,
+ 169, 130, 160, 121, 160, 168, 162, 168, 168, 168, 177, 161, 121, 122, 161, 113,
+ 142, 163, 162, 177, 178, 162, 172, 168, 181, 177, 177, 177, 177, 163, 164, 142,
+ 121, 162, 161, 171, 121, 142, 168, 177, 161, 177, 168, 168, 121, 163, 171, 168,
+ 182, 161, 171, 122, 179, 178, 161, 161, 168, 177, 168, 179, 174, 176, 153, 168,
+ 168, 178, 113, 198, 168, 168, 163, 164, 168, 122, 168, 181, 168, 178, 160, 162,
+ 113, 185, 122, 161, 177, 122, 168, 122, 165, 161, 161, 181, 179, 130, 166, 122,
+ 164, 178, 167, 168, 184, 122, 163, 198, 178, 161, 130, 113, 94, 113, 186, 168,
+ 164, 122, 165, 122, 168, 97, 162, 164, 160, 122, 177, 177, 166, 169, 122, 177,
+ 113, 130, 172, 161, 164, 167, 161, 174, 166, 163, 122, 168, 185, 174, 142, 162,
+ 168, 168, 178, 163, 177, 176, 122, 166, 113, 176, 163, 161, 169, 171, 121, 122,
+ 122, 161, 142, 161, 92, 92, 163, 121, 185, 162, 168, 162, 168, 160, 168, 169,
+ 97, 168, 178, 160, 178, 163, 178, 168, 169, 94, 181, 122, 160, 168, 121, 161,
+ 121, 168, 121, 177, 121, 121, 121, 188, 191, 171, 122, 121, 168, 121, 168, 177,
+ 121, 177, 177, 177, 121, 142, 177, 121, 180, 121, 121, 121, 142, 177, 177, 168,
+ 122, 121, 122, 162, 161, 160, 162, 130, 168, 168, 162, 122, 180, 164, 121, 122,
+ 121, 171, 142, 121, 161, 180, 168, 161, 168, 121, 180, 168, 171, 177, 177, 178,
+ 171, 177, 121, 121, 121, 180, 121, 177, 164, 161, 168, 113, 181, 163, 178, 178,
+ 121, 177, 168, 177, 168, 97, 178, 164, 168, 164, 163, 142, 177, 163, 121, 168,
+ 161, 121, 121, 178, 161, 162, 121, 177, 121, 168, 191, 168, 161, 168, 122, 168,
+ 171, 121, 121, 121, 161, 181, 196, 130, 164, 121, 177, 177, 168, 178, 161, 191,
+ 168, 171, 162, 177, 168, 177, 177, 161, 177, 172, 161, 164, 177, 177, 194, 121,
+ 161, 171, 168, 121, 168, 161, 177, 163, 161, 181, 113, 113, 121, 177, 171, 178,
+ 126, 168, 121, 178, 160, 92, 166, 177, 160, 168, 177, 172, 121, 121, 167, 178,
+ 142, 121, 121, 163, 121, 121, 164, 177, 121, 177, 121, 121, 168, 121, 121, 121,
+ 168, 168, 177, 162, 177, 177, 177, 121, 161, 168, 121, 180, 177, 163, 177, 172,
+ 160, 181, 142, 160, 94, 113, 195, 177, 121, 171, 121, 168, 172, 121, 121, 168,
+ 121, 180, 164, 126, 172, 163, 177, 168, 121, 121, 177, 164, 121, 164, 168, 121,
+ 168, 177, 142, 168, 121, 163, 177, 168, 161, 171, 177, 121, 161, 160, 160, 161,
+ 164, 181, 161, 168, 113, 113, 92, 160, 171, 121, 121, 178, 168, 168, 168, 168,
+ 171, 171, 178, 168, 168, 191, 168, 177, 92, 161, 168, 121, 177, 188, 121, 180,
+ 177, 180, 178, 121, 168, 168, 181, 163, 162, 168, 168, 121, 164, 177, 121, 188,
+ 168, 121, 142, 177, 97, 142, 177, 121, 168, 142, 178, 167, 168, 121, 121, 171,
+ 168, 122, 168, 121, 177, 171, 121, 192, 97, 168, 113, 113, 168, 181, 162, 161,
+ 177, 168, 188, 168, 121, 121, 178, 168, 177, 142, 142, 161, 168, 181, 121, 177,
+ 168, 188, 177, 168, 161, 182, 181, 153, 168, 121, 121, 188, 161, 121, 163, 177,
+ 180, 161, 168, 171, 168, 168, 168, 168, 177, 121, 168, 178, 121, 142, 177, 172,
+ 168, 177, 122, 113, 161, 161, 177, 177, 178, 181, 177, 168, 121, 177, 172, 121,
+ 113, 177, 172, 121, 142, 177, 121, 168, 191, 168, 177, 165, 121, 162, 164, 170,
+ 130, 130, 130, 130, 170, 130, 130, 130, 130, 130, 130, 130, 170, 130, 92, 130,
+ 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 170, 92, 92, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 170, 130, 130, 130, 130, 130, 130, 130, 170,
+ 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 130, 170,
+ 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 170, 130, 130, 130, 92, 130, 130, 130, 130, 130,
+ 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 122, 94, 122, 168, 122, 164, 162, 171, 177, 177,
+ 160, 160, 130, 177, 176, 167, 161, 163, 97, 94, 168, 168, 121, 178, 172, 177,
+ 122, 167, 182, 182, 122, 122, 92, 130, 167, 161, 130, 177, 177, 177, 168, 169,
+ 178, 166, 173, 177, 162, 177, 177, 178, 167, 169, 122, 180, 168, 177, 122, 161,
+ 121, 174, 122, 168, 130, 121, 168, 121, 172, 122, 168, 168, 168, 177, 166, 177,
+ 162, 130, 113, 178, 161, 121, 178, 178, 121, 168, 122, 171, 122, 177, 122, 163,
+ 162, 177, 168, 160, 122, 168, 177, 163, 92, 161, 122, 168, 177, 167, 122, 130,
+ 168, 166, 177, 172, 122, 168, 177, 185, 121, 121, 162, 92, 168, 177, 172, 169,
+ 185, 168, 122, 168, 163, 168, 142, 168, 122, 122, 168, 168, 176, 122, 168, 176,
+ 177, 122, 168, 177, 161, 122, 181, 168, 162, 168, 165, 168, 122, 168, 190, 177,
+ 168, 168, 121, 161, 122, 122, 161, 168, 130, 92, 92, 177, 168, 160, 168, 190,
+ 122, 122, 168, 177, 92, 166, 167, 160, 177, 122, 168, 180, 177, 168, 176, 177,
+ 122, 96, 177, 169, 168, 168, 161, 168, 168, 121, 163, 169, 122, 177, 177, 177,
+ 122, 122, 160, 122, 169, 122, 122, 177, 163, 183, 164, 169, 122, 176, 177, 177,
+ 122, 171, 169, 162, 166, 122, 166, 122, 122, 169, 161, 168, 169, 163, 177, 177,
+ 90, 178, 130, 161, 177, 170, 176, 130, 169, 185, 185, 161, 177, 183, 163, 160,
+ 177, 170, 92, 122, 177, 166, 122, 166, 130, 177, 162, 175, 163, 122, 177, 122,
+ 164, 161, 130, 211, 164, 161, 122, 168, 168, 161, 122, 130, 130, 130, 161, 168,
+ 168, 168, 169, 161, 170, 92, 121, 161, 122, 161, 122, 160, 168, 168, 121, 181,
+ 164, 172, 153, 160, 177, 161, 163, 168, 181, 130, 173, 161, 168, 162, 161, 121,
+ 121, 176, 121, 121, 181, 177, 142, 121, 168, 178, 161, 161, 161, 121, 121, 122,
+ 170, 162, 168, 130, 122, 121, 122, 122, 162, 122, 168, 122, 122, 161, 164, 168,
+ 168, 161, 168, 169, 161, 168, 122, 161, 169, 168, 169, 122, 166, 122, 162, 179,
+ 130, 122, 122, 168, 173, 122, 164, 163, 161, 122, 122, 176, 181, 167, 185, 122,
+ 161, 122, 122, 161, 122, 168, 160, 170, 177, 162, 122, 161, 170, 170, 130, 130,
+ 130, 130, 185, 122, 122, 168, 175, 168, 177, 168, 168, 161, 122, 166, 122, 177,
+ 168, 168, 164, 161, 177, 177, 169, 166, 177, 167, 122, 122, 185, 169, 122, 161,
+ 177, 122, 161, 168, 122, 122, 168, 130, 130, 170, 130, 130, 170, 176, 164, 169,
+ 176, 122, 166, 176, 122, 168, 174, 161, 122, 177, 166, 168, 169, 122, 177, 161,
+ 168, 168, 122, 163, 161, 121, 122, 198, 121, 175, 122, 162, 94, 130, 170, 130,
+ 130, 130, 170, 130, 179, 168, 176, 163, 192, 168, 186, 180, 162, 168, 166, 168,
+ 162, 168, 168, 121, 171, 168, 92, 177, 161, 121, 160, 126, 166, 168, 161, 122,
+ 171, 184, 170, 113, 160, 162, 130, 94, 130, 121, 177, 161, 162, 168, 122, 92,
+ 161, 161, 160, 168, 168, 164, 169, 177, 179, 161, 166, 122, 176, 168, 121, 168,
+ 122, 122, 177, 169, 122, 122, 94, 162, 92, 170, 170, 168, 168, 161, 168, 181,
+ 166, 177, 168, 161, 168, 122, 121, 166, 162, 166, 161, 121, 161, 174, 169, 177,
+ 122, 122, 168, 97, 169, 161, 168, 177, 121, 122, 122, 130, 170, 173, 130, 122,
+ 122, 164, 169, 178, 163, 162, 177, 168, 122, 168, 122, 177, 168, 168, 162, 122,
+ 162, 130, 161, 172, 161, 178, 164, 168, 176, 168, 121, 176, 122, 122, 177, 168,
+ 121, 161, 177, 165, 113, 94, 185, 168, 122, 142, 179, 168, 168, 161, 177, 161,
+ 178, 168, 177, 122, 177, 180, 94, 168, 181, 168, 122, 166, 168, 121, 121, 121,
+ 122, 170, 122, 176, 168, 177, 122, 168, 172, 142, 166, 162, 185, 121, 164, 171,
+ 168, 178, 168, 113, 161, 177, 161, 177, 121, 178, 142, 177, 92, 177, 177, 121,
+ 178, 177, 97, 122, 182, 121, 168, 122, 121, 168, 122, 162, 176, 122, 168, 160,
+ 162, 162, 177, 122, 122, 162, 163, 168, 177, 177, 121, 122, 122, 162, 122, 177,
+ 176, 167, 169, 164, 185, 122, 130, 121, 121, 142, 121, 168, 122, 122, 181, 162,
+ 169, 168, 122, 164, 176, 168, 178, 113, 172, 164, 163, 122, 122, 177, 122, 122,
+ 168, 192, 176, 130, 161, 168, 94, 161, 176, 172, 122, 122, 122, 179, 113, 185,
+ 130, 130, 177, 167, 166, 122, 122, 122, 167, 122, 177, 130, 168, 168, 170, 168,
+ 180, 161, 168, 162, 166, 191, 162, 122, 161, 185, 161, 176, 161, 92, 177, 166,
+ 168, 177, 168, 168, 94, 168, 177, 168, 169, 121, 167, 168, 177, 113, 168, 167,
+ 162, 168, 172, 177, 180, 160, 121, 162, 167, 168, 181, 178, 168, 177, 122, 122,
+ 130, 121, 122, 130, 166, 168, 198, 142, 180, 170, 170, 163, 168, 166, 122, 166,
+ 177, 162, 130, 177, 166, 168, 161, 182, 130, 162, 166, 122, 161, 122, 192, 185,
+ 168, 166, 122, 168, 177, 161, 162, 130, 166, 122, 191, 177, 173, 122, 168, 122,
+ 177, 166, 168, 171, 166, 122, 186, 177, 166, 192, 174, 167, 122, 122, 192, 122,
+ 176, 122, 164, 122, 166, 168, 168, 190, 122, 122, 177, 121, 191, 122, 176, 197,
+ 168, 130, 168, 168, 179, 113, 162, 130, 130, 161, 170, 130, 130, 130, 130, 170,
+ 163, 122, 122, 169, 122, 192, 168, 122, 179, 178, 162, 122, 169, 161, 122, 122,
+ 166, 165, 163, 169, 166, 122, 122, 121, 177, 161, 177, 167, 168, 177, 160, 176,
+ 168, 122, 168, 178, 167, 168, 177, 174, 161, 167, 178, 167, 160, 193, 191, 94,
+ 177, 190, 122, 122, 122, 122, 169, 166, 166, 122, 162, 163, 185, 168, 184, 130,
+ 161, 130, 161, 92, 130, 130, 178, 122, 172, 168, 170, 166, 167, 163, 177, 164,
+ 168, 164, 177, 181, 168, 168, 168, 185, 122, 168, 168, 122, 166, 166, 162, 165,
+ 162, 122, 142, 166, 122, 122, 122, 177, 122, 122, 166, 168, 166, 182, 161, 168,
+ 122, 168, 177, 176, 177, 178, 173, 192, 168, 122, 121, 168, 168, 177, 177, 122,
+ 169, 192, 122, 177, 176, 162, 177, 163, 181, 92, 130, 130, 130, 92, 130, 130,
+ 130, 130, 160, 179, 130, 130, 170, 130, 130, 130, 130, 130, 130, 130, 130, 170,
+ 162, 161, 161, 180, 168, 178, 168, 122, 176, 161, 168, 122, 169, 166, 168, 177,
+ 164, 168, 162, 168, 164, 175, 176, 178, 168, 122, 121, 168, 168, 177, 122, 168,
+ 168, 160, 176, 169, 177, 177, 121, 168, 190, 177, 178, 166, 174, 177, 122, 181,
+ 169, 161, 121, 168, 168, 168, 177, 171, 167, 192, 165, 122, 182, 164, 168, 168,
+ 185, 202, 130, 130, 130, 113, 130, 173, 130, 170, 130, 92, 130, 122, 182, 177,
+ 166, 122, 168, 168, 168, 122, 168, 166, 168, 191, 122, 168, 122, 160, 178, 166,
+ 162, 177, 161, 198, 176, 168, 165, 168, 167, 168, 161, 168, 122, 166, 168, 169,
+ 169, 185, 168, 168, 168, 185, 161, 168, 177, 122, 166, 180, 168, 160, 168, 121,
+ 122, 122, 122, 168, 121, 168, 177, 113, 176, 192, 168, 178, 177, 122, 168, 168,
+ 161, 166, 161, 122, 122, 160, 166, 142, 161, 168, 188, 169, 122, 122, 122, 166,
+ 168, 166, 168, 178, 160, 162, 160, 161, 179, 162, 92, 168, 170, 130, 161, 161,
+ 153, 160, 113, 168, 170, 130, 170, 130, 130, 180, 181, 168, 121, 168, 160, 177,
+ 168, 122, 168, 168, 168, 142, 168, 168, 122, 177, 168, 168, 169, 122, 160, 168,
+ 168, 161, 168, 168, 168, 177, 169, 177, 163, 121, 163, 168, 168, 177, 178, 164,
+ 168, 166, 177, 160, 168, 160, 177, 122, 163, 166, 166, 122, 174, 168, 168, 168,
+ 177, 122, 172, 122, 163, 177, 121, 177, 168, 169, 162, 122, 122, 169, 178, 180,
+ 177, 175, 160, 166, 177, 122, 166, 142, 166, 178, 165, 161, 162, 177, 168, 160,
+ 160, 162, 169, 161, 181, 162, 168, 130, 170, 130, 92, 202, 130, 168, 185, 168,
+ 121, 168, 163, 163, 180, 164, 160, 185, 168, 122, 168, 168, 122, 168, 171, 178,
+ 168, 165, 168, 160, 168, 161, 162, 168, 177, 177, 177, 168, 168, 172, 168, 166,
+ 168, 177, 122, 161, 166, 161, 168, 161, 122, 167, 166, 180, 121, 174, 182, 122,
+ 188, 167, 191, 161, 122, 168, 121, 177, 164, 122, 169, 121, 177, 165, 168, 177,
+ 167, 122, 168, 176, 168, 161, 167, 168, 161, 113, 198, 168, 162, 130, 160, 130,
+ 130, 160, 160, 130, 160, 170, 130, 177, 168, 168, 177, 168, 122, 161, 121, 177,
+ 166, 177, 177, 168, 180, 161, 168, 177, 160, 168, 177, 177, 165, 177, 168, 169,
+ 178, 161, 177, 163, 161, 160, 142, 177, 168, 168, 168, 168, 166, 168, 177, 168,
+ 182, 122, 168, 122, 121, 178, 168, 122, 180, 168, 122, 161, 177, 168, 191, 167,
+ 168, 122, 162, 188, 177, 188, 178, 177, 168, 168, 177, 166, 122, 121, 168, 191,
+ 168, 168, 162, 163, 163, 181, 162, 130, 170, 130, 130, 185, 130, 122, 168, 204,
+ 178, 180, 160, 122, 168, 168, 177, 168, 169, 122, 169, 172, 160, 168, 180, 162,
+ 162, 177, 182, 191, 168, 178, 166, 178, 178, 190, 172, 168, 164, 177, 176, 164,
+ 177, 177, 177, 180, 166, 168, 168, 168, 122, 121, 121, 177, 168, 121, 168, 163,
+ 160, 168, 130, 160, 130, 168, 168, 178, 168, 166, 166, 166, 168, 162, 169, 164,
+ 178, 177, 168, 168, 122, 166, 177, 122, 178, 177, 142, 177, 177, 168, 168, 192,
+ 178, 121, 161, 164, 121, 168, 168, 181, 177, 178, 168, 122, 169, 177, 168, 177,
+ 177, 168, 177, 168, 167, 162, 121, 177, 122, 121, 122, 181, 181, 162, 202, 122,
+ 129, 168, 161, 168, 177, 168, 177, 166, 177, 169, 121, 161, 162, 177, 177, 177,
+ 168, 186, 177, 168, 168, 168, 168, 177, 168, 122, 162, 177, 161, 121, 191, 122,
+ 169, 168, 168, 130, 161, 122, 161, 168, 177, 168, 177, 161, 165, 121, 168, 177,
+ 182, 168, 168, 168, 122, 121, 177, 161, 177, 122, 121, 168, 168, 177, 160, 168,
+ 168, 168, 168, 162, 161, 161, 177, 121, 168, 142, 121, 122, 163, 168, 178, 192,
+ 177, 168, 198, 161, 177, 166, 121, 121, 161, 168, 121, 142, 168, 163, 162, 161,
+ 163, 176, 162, 181, 94, 161, 186, 121, 177, 177, 121, 177, 168, 161, 177, 168,
+ 168, 177, 178, 168, 168, 168, 168, 166, 160, 166, 168, 161, 168, 121, 168, 172,
+ 113, 168, 168, 168, 168, 168, 177, 161, 176, 168, 177, 168, 166, 164, 168, 121,
+ 177, 164, 163, 168, 92, 160, 177, 168, 168, 161, 161, 168, 168, 167, 122, 130,
+ 122, 130, 177, 177, 122, 121, 177, 164, 164, 177, 184, 126, 121, 164, 122, 121,
+ 162, 177, 166, 177, 177, 168, 92, 121, 168, 177, 168, 169, 174, 168, 185, 177,
+ 168, 169, 160, 168, 168, 164, 164, 177, 161, 122, 176, 169, 185, 173, 170, 130,
+ 130, 130, 130, 92, 161, 168, 168, 168, 162, 161, 122, 167, 122, 166, 168, 161,
+ 168, 177, 160, 122, 168, 167, 177, 168, 177, 168, 177, 161, 176, 185, 168, 161,
+ 160, 177, 168, 122, 122, 168, 164, 166, 166, 122, 169, 113, 130, 182, 161, 169,
+ 167, 176, 160, 177, 166, 176, 169, 177, 177, 177, 185, 168, 168, 168, 168, 177,
+ 176, 177, 168, 177, 169, 177, 169, 122, 168, 169, 130, 122, 168, 113, 202, 130,
+ 96, 166, 162, 168, 122, 164, 168, 177, 185, 122, 177, 122, 177, 168, 169, 122,
+ 162, 161, 168, 177, 122, 162, 168, 162, 168, 167, 168, 168, 178, 122, 184, 153,
+ 130, 130, 130, 130, 130, 168, 168, 168, 167, 169, 177, 142, 164, 164, 122, 161,
+ 122, 168, 122, 122, 177, 177, 142, 176, 122, 167, 169, 177, 168, 167, 177, 162,
+ 162, 178, 167, 176, 162, 173, 161, 130, 122, 177, 165, 168, 122, 161, 166, 162,
+ 168, 166, 96, 166, 168, 169, 168, 168, 177, 169, 168, 161, 168, 168, 166, 162,
+ 168, 166, 177, 168, 169, 168, 161, 169, 168, 164, 177, 169, 177, 164, 166, 169,
+ 177, 168, 168, 177, 92, 164, 168, 173, 130, 202, 161, 113, 169, 177, 165, 168,
+ 168, 168, 168, 169, 168, 121, 168, 122, 177, 169, 168, 168, 168, 177, 168, 180,
+ 169, 177, 168, 167, 166, 166, 121, 168, 121, 168, 178, 168, 168, 168, 167, 177,
+ 170, 163, 162, 168, 122, 168, 122, 168, 121, 168, 168, 166, 130, 179, 130, 113,
+ 92, 168, 122, 176, 177, 166, 182, 177, 166, 177, 161, 174, 182, 122, 161, 168,
+ 177, 168, 168, 166, 168, 162, 168, 166, 177, 164, 168, 168, 168, 168, 171, 122,
+ 162, 161, 121, 177, 168, 160, 92, 162, 130, 160, 168, 169, 166, 166, 177, 167,
+ 168, 163, 168, 122, 168, 166, 168, 168, 168, 168, 122, 142, 168, 167, 177, 177,
+ 169, 163, 168, 168, 180, 168, 169, 181, 171, 177, 166, 169, 168, 161, 163, 92,
+ 113, 96, 169, 185, 168, 164, 163, 168, 168, 177, 163, 185, 177, 168, 168, 177,
+ 122, 168, 177, 177, 177, 185, 168, 168, 168, 161, 166, 177, 126, 177, 179, 121,
+ 161, 162, 121, 177, 168, 160, 178, 178, 164, 122, 177, 121, 168, 161, 122, 177,
+ 168, 177, 168, 166, 94, 121, 177, 161, 168, 177, 166, 177, 168, 142, 181, 172,
+ 177, 178, 164, 166, 171, 169, 167, 168, 163, 177, 164, 166, 177, 168, 162, 188,
+ 168, 169, 122, 121, 168, 168, 168, 172, 177, 168, 168, 168, 168, 163, 177, 168,
+ 177, 121, 166, 168, 161, 177, 121, 168, 168, 169, 162, 121, 166, 168, 168, 168,
+ 122, 177, 172, 177, 167, 174, 198, 161, 177, 162, 177, 177, 122, 122, 177, 160,
+ 161, 162, 180, 121, 130, 177, 177, 122, 164, 122, 177, 121, 164, 121, 172, 164,
+ 182, 122, 122, 122, 90, 170, 161, 168, 122, 166, 168, 122, 130, 168, 179, 168,
+ 122, 177, 165, 161, 168, 178, 168, 122, 161, 171, 161, 164, 168, 169, 165, 165,
+ 177, 122, 122, 168, 179, 130, 92, 160, 122, 168, 161, 122, 168, 122, 168, 161,
+ 161, 168, 122, 168, 161, 168, 122, 180, 177, 178, 177, 177, 174, 92, 121, 177,
+ 163, 168, 167, 161, 167, 161, 161, 168, 177, 161, 177, 122, 168, 130, 153, 92,
+ 113, 169, 168, 92, 198, 172, 168, 167, 168, 168, 177, 161, 185, 177, 177, 172,
+ 177, 122, 122, 113, 113, 187, 130, 94, 92, 185, 171, 177, 177, 177, 166, 198,
+ 168, 162, 176, 162, 122, 122, 168, 168, 169, 122, 168, 177, 121, 121, 177, 122,
+ 161, 121, 130, 130, 130, 130, 160, 177, 122, 161, 161, 168, 168, 161, 168, 171,
+ 166, 166, 178, 122, 122, 193, 168, 177, 122, 169, 168, 168, 167, 121, 167, 160,
+ 160, 177, 169, 161, 113, 168, 177, 121, 92, 168, 169, 168, 178, 162, 177, 164,
+ 122, 168, 122, 122, 168, 171, 177, 168, 191, 192, 176, 173, 162, 113, 178, 168,
+ 162, 96, 168, 168, 160, 122, 177, 177, 162, 168, 122, 169, 168, 168, 168, 168,
+ 166, 177, 171, 168, 130, 177, 122, 168, 121, 164, 162, 121, 168, 97, 177, 161,
+ 164, 165, 177, 172, 122, 162, 177, 94, 161, 177, 161, 168, 178, 172, 161, 177,
+ 168, 168, 177, 168, 160, 92, 142, 177, 168, 168, 177, 177, 177, 168, 169, 122,
+ 142, 177, 177, 177, 121, 160, 167, 161, 92, 168, 121, 177, 97, 178, 177, 142,
+ 162, 168, 121, 177, 178, 162, 168, 153, 161, 168, 177, 166, 177, 164, 178, 122,
+ 94, 122, 168, 122, 161, 168, 122, 198, 178, 163, 172, 121, 161, 162, 92, 121,
+ 162, 160, 161, 121, 163, 177, 121, 178, 178, 92, 181, 177, 171, 168, 168, 177,
+ 162, 180, 168, 168, 168, 163, 142, 172, 92, 198, 121, 161, 142, 168, 168, 178,
+ 164, 161, 121, 181, 162, 164, 177, 177, 92, 168, 121, 161, 163, 121, 168, 178,
+ 121, 170, 130, 92, 130, 130, 170, 130, 130, 130, 130, 130, 130, 92, 130, 130,
+ 130, 130, 122, 168, 171, 177, 166, 162, 162, 168, 167, 168, 167, 178, 130, 168,
+ 168, 168, 168, 122, 168, 166, 167, 172, 168, 177, 161, 166, 168, 177, 161, 130,
+ 168, 177, 168, 166, 121, 161, 177, 168, 121, 162, 168, 168, 97, 162, 168, 177,
+ 122, 92, 121, 121, 177, 164, 161, 166, 121, 92, 121, 161, 121, 161, 121, 171,
+ 142, 171, 177, 121, 162, 171, 121, 121, 121, 161, 92, 121, 160, 121, 177, 121,
+ 164, 161, 171, 121, 162, 121, 164, 168, 161, 160, 121, 163, 177, 121, 161, 162,
+ 168, 121, 161, 113, 121, 164, 121, 162, 160, 168, 121, 121, 142, 163, 176, 168,
+ 177, 142, 161, 164, 168, 177, 142, 162, 167, 163, 168, 161, 168, 177, 177, 168,
+ 121, 178, 178, 162, 121, 121, 171, 177, 177, 168, 161, 121, 162, 164, 121, 92,
+ 121, 177, 121, 121, 161, 164, 121, 163, 97, 121, 161, 142, 142, 121, 121, 161,
+ 121, 121, 121, 121, 168, 191, 177, 177, 161, 190, 177, 171, 142, 161, 163, 177,
+ 164, 168, 178, 177, 178, 121, 177, 121, 161, 202, 130, 177, 121, 121, 161, 177,
+ 163, 142, 177, 122, 160, 121, 177, 162, 121, 177, 142, 161, 160, 161, 121, 164,
+ 121, 121, 161, 121, 121, 121, 121, 171, 121, 163, 126, 168, 181, 113, 162, 163,
+ 121, 161, 121, 164, 160, 161, 171, 164, 168, 121, 168, 177, 121, 168, 191, 121,
+ 168, 161, 121, 177, 121, 168, 177, 121, 177, 171, 164, 121, 181, 121, 161, 180,
+ 161, 177, 121, 177, 177, 177, 121, 177, 168, 168, 153, 121, 121, 177, 178, 177,
+ 178, 180, 178, 161, 178, 161, 121, 121, 168, 161, 203, 121, 164, 121, 121, 168,
+ 177, 121, 168, 142, 177, 177, 188, 121, 121, 161, 121, 168, 171, 161, 121, 177,
+ 121, 121, 121, 161, 121, 177, 177, 167, 168, 161, 171, 177, 172, 168, 121, 168,
+ 121, 177, 168, 168, 180, 168, 180, 121, 168, 121, 180, 121, 177, 121, 177, 163,
+ 121, 113, 168, 168, 168, 168, 167, 168, 121, 161, 168, 121, 121, 163, 168, 168,
+ 177, 168, 161, 180, 161, 168, 168, 177, 161, 121, 168, 168, 177, 168, 178, 160,
+ 168, 121, 177, 163, 162, 177, 171, 168, 177, 121, 168, 168, 172, 163, 121, 121,
+ 168, 168, 177, 177, 177, 168, 178, 168, 121, 171, 121, 113, 121, 168, 182, 142,
+ 168, 161, 160, 177, 161, 168, 122, 168, 168, 160, 168, 142, 122, 177, 161, 121,
+ 121, 181, 113, 161, 121, 161, 162, 121, 177, 177, 168, 168, 164, 121, 177, 168,
+ 121, 163, 168, 181, 177, 177, 168, 161, 168, 92, 121, 177, 178, 164, 178, 162,
+ 198, 161, 121, 121, 177, 177, 121, 161, 168, 178, 121, 160, 171, 161, 177, 177,
+ 170, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130,
+ 130, 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 170, 130,
+ 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 130,
+ 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 170, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 122, 162, 177, 181, 168, 168, 177, 177, 121,
+ 161, 122, 168, 168, 161, 177, 122, 166, 121, 176, 180, 177, 122, 168, 142, 177,
+ 142, 163, 161, 164, 171, 122, 168, 177, 164, 162, 122, 164, 168, 177, 161, 168,
+ 161, 122, 169, 164, 177, 168, 177, 161, 177, 177, 122, 122, 142, 171, 92, 168,
+ 168, 168, 168, 176, 161, 177, 177, 168, 167, 122, 122, 177, 181, 168, 164, 161,
+ 168, 168, 122, 161, 168, 167, 177, 164, 161, 169, 122, 162, 122, 142, 181, 168,
+ 177, 168, 177, 171, 167, 168, 161, 168, 167, 177, 168, 163, 177, 121, 121, 160,
+ 121, 121, 121, 168, 177, 168, 161, 121, 121, 121, 121, 121, 121, 172, 181, 121,
+ 180, 161, 142, 121, 121, 168, 121, 121, 121, 177, 177, 121, 121, 121, 168, 121,
+ 121, 121, 121, 121, 121, 171, 162, 121, 121, 164, 121, 162, 168, 172, 113, 177,
+ 161, 121, 97, 121, 160, 177, 163, 168, 161, 177, 180, 172, 121, 177, 121, 168,
+ 121, 171, 121, 121, 121, 168, 121, 168, 177, 160, 121, 160, 171, 121, 168, 164,
+ 177, 168, 163, 168, 126, 177, 161, 163, 171, 168, 142, 121, 121, 121, 177, 162,
+ 168, 162, 168, 163, 180, 121, 168, 180, 121, 177, 121, 172, 160, 121, 161, 142,
+ 178, 160, 163, 121, 178, 168, 121, 171, 160, 168, 161, 171, 160, 170, 130, 130,
+ 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 92, 92, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 92,
+ 130, 130, 130, 130, 122, 164, 122, 169, 168, 177, 92, 122, 177, 169, 177, 168,
+ 122, 181, 168, 122, 122, 130, 185, 122, 168, 168, 160, 168, 161, 168, 161, 164,
+ 168, 169, 163, 161, 166, 122, 161, 161, 164, 168, 122, 173, 168, 177, 168, 168,
+ 177, 166, 168, 168, 185, 171, 168, 161, 161, 121, 161, 168, 168, 161, 162, 176,
+ 177, 168, 161, 122, 161, 168, 163, 168, 121, 160, 168, 177, 177, 168, 168, 177,
+ 161, 130, 177, 122, 96, 166, 168, 177, 130, 177, 122, 164, 166, 161, 122, 185,
+ 163, 168, 178, 170, 130, 177, 190, 177, 177, 161, 164, 122, 122, 168, 176, 165,
+ 168, 176, 161, 168, 163, 177, 167, 166, 168, 177, 169, 122, 168, 122, 130, 169,
+ 168, 121, 168, 165, 176, 162, 97, 177, 122, 168, 169, 167, 166, 161, 168, 122,
+ 177, 177, 177, 122, 177, 202, 92, 130, 130, 130, 96, 130, 142, 166, 168, 178,
+ 168, 163, 168, 168, 177, 166, 177, 168, 181, 167, 165, 164, 130, 168, 94, 122,
+ 121, 177, 168, 168, 166, 168, 177, 168, 168, 168, 168, 168, 168, 169, 122, 169,
+ 177, 171, 176, 166, 168, 168, 177, 177, 160, 96, 186, 97, 130, 94, 185, 130,
+ 180, 176, 161, 177, 142, 122, 177, 162, 177, 176, 170, 161, 168, 166, 168, 168,
+ 166, 166, 122, 161, 122, 168, 160, 165, 122, 122, 122, 176, 178, 177, 177, 163,
+ 178, 130, 130, 168, 177, 142, 168, 168, 161, 122, 168, 177, 177, 177, 177, 121,
+ 180, 177, 177, 142, 142, 168, 96, 168, 160, 166, 168, 161, 176, 166, 92, 166,
+ 189, 182, 169, 168, 122, 160, 122, 160, 168, 162, 171, 177, 169, 92, 94, 130,
+ 94, 122, 171, 164, 178, 169, 168, 122, 168, 171, 121, 142, 168, 121, 168, 130,
+ 166, 142, 177, 142, 167, 177, 168, 168, 168, 181, 177, 162, 130, 177, 166, 168,
+ 168, 142, 164, 168, 168, 168, 168, 163, 168, 177, 121, 122, 122, 163, 162, 184,
+ 172, 181, 96, 164, 161, 162, 160, 161, 161, 161, 176, 162, 160, 168, 113, 161,
+ 188, 164, 168, 163, 162, 113, 181, 162, 113, 168, 121, 121, 121, 121, 170, 171,
+ 92, 177, 121, 168, 171, 161, 161, 168, 168, 161, 94, 142, 177, 168, 168, 121,
+ 168, 168, 153, 113, 160, 168, 168, 168, 177, 168, 161, 180, 168, 182, 177, 168,
+ 162, 177, 160, 161, 168, 168, 168, 177, 121, 177, 177, 121, 142, 181, 121, 168,
+ 177, 168, 177, 121, 161, 180, 168, 177, 177, 121, 142, 168, 113, 168, 168, 162,
+ 177, 168, 121, 121, 121, 121, 177, 177, 177, 172, 168, 121, 121, 121, 188, 121,
+ 177, 162, 161, 177, 168, 171, 121, 204, 162, 121, 121, 161, 177, 163, 177, 121,
+ 160, 161, 168, 121, 177, 177, 177, 177, 121, 180, 162, 121, 161, 161, 121, 121,
+ 177, 163, 142, 177, 121, 121, 178, 177, 168, 121, 160, 168, 113, 121, 121, 177,
+ 168, 177, 177, 177, 171, 177, 168, 178, 177, 168, 168, 168, 172, 191, 177, 121,
+ 168, 142, 180, 178, 178, 164, 170, 170, 130, 130, 92, 130, 130, 130, 170, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130,
+ 130, 130, 92, 170, 130, 130, 130, 130, 130, 130, 130, 122, 122, 164, 184, 169,
+ 163, 164, 161, 122, 164, 163, 188, 181, 122, 130, 161, 130, 161, 121, 142, 121,
+ 122, 122, 121, 160, 168, 163, 90, 153, 182, 179, 153, 153, 153, 130, 174, 178,
+ 162, 174, 122, 92, 169, 122, 171, 173, 130, 168, 163, 177, 160, 177, 122, 161,
+ 90, 122, 177, 166, 122, 166, 168, 168, 173, 173, 153, 130, 130, 130, 130, 130,
+ 177, 168, 169, 177, 176, 169, 122, 161, 176, 184, 122, 122, 92, 122, 166, 181,
+ 122, 164, 183, 130, 142, 177, 177, 122, 169, 186, 142, 177, 168, 122, 177, 168,
+ 122, 122, 192, 122, 166, 122, 122, 92, 193, 173, 130, 165, 177, 122, 181, 122,
+ 122, 165, 179, 181, 122, 121, 169, 122, 162, 121, 122, 176, 168, 122, 122, 122,
+ 122, 165, 122, 121, 168, 161, 130, 113, 164, 164, 164, 161, 164, 166, 122, 166,
+ 161, 121, 121, 182, 177, 122, 169, 163, 122, 113, 161, 173, 122, 168, 122, 177,
+ 161, 122, 122, 164, 166, 181, 161, 122, 161, 178, 121, 121, 163, 122, 121, 169,
+ 122, 122, 167, 122, 121, 121, 153, 130, 169, 121, 161, 176, 121, 188, 121, 161,
+ 121, 198, 176, 122, 94, 202, 162, 177, 169, 121, 161, 168, 182, 122, 122, 180,
+ 177, 161, 121, 168, 176, 122, 178, 121, 121, 177, 121, 168, 121, 122, 168, 122,
+ 122, 121, 122, 122, 121, 177, 168, 121, 190, 181, 121, 176, 162, 168, 162, 121,
+ 171, 122, 161, 173, 168, 190, 161, 166, 177, 192, 161, 166, 161, 130, 168, 168,
+ 177, 166, 190, 122, 161, 177, 122, 168, 198, 161, 122, 161, 130, 161, 170, 165,
+ 192, 122, 177, 166, 166, 122, 176, 161, 122, 173, 130, 170, 161, 177, 166, 168,
+ 161, 122, 161, 171, 174, 166, 161, 166, 177, 161, 122, 168, 162, 161, 169, 130,
+ 130, 130, 162, 130, 168, 177, 168, 166, 177, 177, 168, 167, 166, 176, 195, 177,
+ 168, 122, 169, 168, 178, 177, 130, 130, 122, 168, 168, 166, 168, 122, 161, 166,
+ 177, 168, 168, 168, 166, 121, 164, 181, 130, 168, 168, 168, 168, 122, 176, 177,
+ 177, 168, 122, 168, 166, 177, 177, 168, 177, 97, 161, 168, 161, 177, 168, 168,
+ 177, 168, 121, 161, 177, 195, 177, 171, 171, 122, 177, 168, 177, 168, 176, 168,
+ 177, 168, 166, 166, 168, 164, 168, 188, 168, 177, 168, 168, 168, 121, 177, 166,
+ 142, 176, 180, 168, 171, 168, 177, 164, 168, 176, 177, 168, 164, 164, 168, 168,
+ 168, 168, 92, 166, 168, 168, 185, 177, 171, 122, 122, 122, 122, 122, 165, 166,
+ 185, 160, 122, 177, 181, 168, 178, 176, 178, 163, 166, 162, 160, 130, 170, 168,
+ 168, 166, 165, 169, 166, 169, 92, 163, 168, 122, 122, 161, 122, 162, 185, 185,
+ 170, 130, 167, 178, 176, 122, 179, 122, 122, 166, 177, 164, 160, 130, 130, 130,
+ 168, 177, 178, 171, 168, 166, 177, 122, 161, 122, 177, 122, 179, 165, 163, 168,
+ 167, 166, 122, 177, 162, 164, 161, 113, 162, 168, 185, 185, 121, 168, 171, 168,
+ 168, 177, 167, 96, 113, 168, 162, 168, 177, 160, 167, 121, 188, 166, 190, 165,
+ 177, 188, 177, 177, 122, 165, 182, 168, 113, 168, 169, 163, 177, 177, 168, 164,
+ 121, 142, 177, 177, 160, 171, 142, 122, 113, 122, 130, 121, 122, 122, 122, 122,
+ 121, 122, 92, 177, 177, 168, 172, 188, 121, 171, 177, 181, 122, 121, 164, 172,
+ 161, 113, 168, 121, 177, 163, 142, 121, 168, 171, 191, 168, 177, 171, 177, 162,
+ 164, 177, 161, 168, 168, 121, 181, 177, 168, 177, 94, 162, 113, 177, 160, 178,
+ 177, 177, 168, 168, 177, 177, 177, 171, 160, 171, 177, 161, 177, 121, 172, 168,
+ 188, 121, 191, 163, 142, 142, 177, 194, 164, 168, 168, 161, 177, 162, 121, 92,
+ 161, 161, 161, 171, 177, 177, 177, 168, 182, 113, 94, 160, 113, 168, 177, 164,
+ 177, 168, 168, 177, 121, 163, 177, 142, 171, 171, 191, 161, 163, 97, 171, 121,
+ 188, 160, 162, 162, 172, 121, 177, 162, 178, 121, 177, 142, 168, 171, 177, 177,
+ 178, 171, 168, 168, 168, 160, 168, 121, 182, 164, 142, 121, 164, 163, 180, 160,
+ 177, 177, 198, 168, 121, 191, 180, 177, 162, 162, 161, 160, 168, 168, 163, 177,
+ 177, 113, 168, 161, 130, 162, 177, 182, 171, 177, 168, 171, 171, 177, 178, 177,
+ 121, 160, 168, 180, 160, 121, 168, 168, 177, 163, 177, 168, 168, 177, 166, 160,
+ 161, 121, 164, 121, 168, 178, 121, 177, 121, 177, 178, 178, 121, 168, 161, 162,
+ 177, 168, 168, 168, 177, 177, 168, 177, 171, 168, 168, 177, 97, 181, 179, 162,
+ 161, 160, 171, 126, 168, 168, 191, 121, 164, 198, 182, 171, 171, 162, 160, 163,
+ 177, 171, 177, 177, 168, 171, 177, 171, 166, 168, 168, 177, 191, 177, 177, 180,
+ 177, 168, 121, 177, 160, 177, 161, 177, 177, 177, 161, 160, 164, 177, 168, 177,
+ 177, 177, 161, 182, 121, 163, 168, 177, 177, 178, 121, 160, 182, 181, 177, 168,
+ 171, 168, 153, 172, 160, 161, 160, 168, 121, 177, 178, 177, 121, 160, 168, 177,
+ 177, 168, 177, 160, 126, 161, 178, 160, 177, 168, 161, 168, 168, 177, 168, 178,
+ 121, 162, 168, 168, 177, 171, 168, 161, 121, 142, 121, 168, 164, 177, 191, 191,
+ 121, 188, 121, 178, 191, 177, 121, 177, 121, 177, 177, 121, 172, 168, 121, 121,
+ 160, 160, 181, 171, 177, 178, 171, 162, 168, 168, 113, 113, 168, 92, 130, 161,
+ 94, 94, 160, 94, 153, 160, 168, 177, 193, 177, 126, 121, 168, 121, 168, 168,
+ 177, 177, 177, 161, 121, 177, 178, 177, 177, 168, 171, 121, 178, 161, 177, 160,
+ 178, 168, 160, 168, 177, 171, 160, 177, 160, 163, 166, 160, 142, 177, 198, 162,
+ 171, 177, 161, 163, 163, 121, 177, 168, 160, 168, 177, 168, 180, 163, 121, 164,
+ 177, 182, 171, 168, 94, 94, 160, 94, 177, 168, 171, 164, 180, 177, 168, 166,
+ 160, 168, 177, 161, 121, 177, 121, 142, 171, 168, 121, 177, 160, 168, 177, 168,
+ 160, 177, 97, 191, 177, 168, 177, 180, 177, 177, 168, 162, 121, 198, 142, 168,
+ 121, 168, 168, 97, 177, 177, 162, 168, 160, 113, 162, 160, 161, 160, 161, 94,
+ 168, 164, 168, 121, 177, 164, 163, 177, 142, 162, 166, 163, 177, 171, 168, 168,
+ 178, 121, 168, 163, 168, 168, 169, 142, 142, 177, 168, 160, 171, 142, 191, 171,
+ 160, 121, 171, 168, 121, 181, 177, 177, 142, 161, 161, 161, 168, 161, 168, 161,
+ 94, 160, 161, 160, 161, 168, 194, 177, 177, 177, 177, 177, 168, 171, 168, 168,
+ 168, 182, 164, 142, 193, 161, 168, 178, 163, 177, 168, 168, 168, 177, 177, 177,
+ 178, 168, 168, 178, 178, 177, 177, 163, 121, 178, 181, 160, 161, 94, 161, 164,
+ 168, 113, 161, 161, 160, 128, 94, 160, 168, 168, 168, 121, 168, 160, 171, 162,
+ 168, 177, 171, 171, 162, 121, 178, 168, 121, 168, 142, 177, 168, 177, 170, 177,
+ 168, 113, 160, 163, 121, 177, 168, 168, 177, 168, 177, 168, 177, 160, 161, 168,
+ 168, 121, 121, 113, 160, 177, 161, 168, 160, 162, 181, 198, 164, 168, 178, 164,
+ 142, 164, 178, 171, 97, 160, 161, 160, 177, 168, 142, 166, 160, 177, 177, 177,
+ 142, 177, 171, 168, 168, 178, 168, 142, 168, 94, 161, 160, 142, 121, 142, 121,
+ 168, 178, 168, 177, 164, 170, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 92, 130, 130, 130, 130, 92, 130, 92, 130, 130, 130, 130, 130, 130, 170,
+ 130, 130, 170, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 170, 130, 170, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 92,
+ 130, 130, 130, 92, 92, 130, 130, 130, 130, 130, 92, 130, 170, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 170, 130, 130, 130, 130, 92, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130,
+ 92, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 170, 130, 130,
+ 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130,
+ 130, 130, 130, 92, 130, 130, 130, 170, 92, 130, 130, 92, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130,
+ 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130,
+ 130, 130, 130, 130, 92, 92, 130, 121, 182, 164, 168, 168, 168, 168, 162, 170,
+ 121, 161, 142, 121, 162, 160, 168, 181, 177, 121, 113, 121, 177, 177, 171, 121,
+ 168, 121, 126, 121, 121, 161, 153, 160, 121, 172, 161, 168, 168, 162, 177, 177,
+ 153, 171, 172, 121, 121, 121, 182, 172, 121, 171, 94, 177, 177, 121, 168, 161,
+ 168, 126, 181, 161, 162, 168, 177, 168, 161, 178, 177, 121, 180, 177, 178, 177,
+ 168, 161, 161, 178, 161, 168, 171, 180, 171, 177, 121, 171, 142, 178, 161, 92,
+ 171, 177, 177, 177, 121, 121, 121, 161, 181, 162, 177, 168, 121, 164, 177, 177,
+ 177, 121, 121, 168, 177, 178, 162, 161, 170, 130, 130, 130, 92, 130, 130, 130,
+ 130, 130, 130, 130, 170, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92,
+ 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 92, 130, 130, 130, 130, 92, 130, 130, 92, 122, 174, 177, 130,
+ 168, 122, 166, 168, 177, 162, 164, 161, 178, 161, 122, 161, 171, 168, 122, 178,
+ 168, 176, 122, 174, 173, 130, 130, 164, 182, 177, 177, 122, 166, 166, 161, 122,
+ 122, 163, 122, 168, 122, 170, 130, 130, 130, 130, 168, 122, 122, 122, 168, 178,
+ 122, 168, 162, 168, 166, 130, 163, 162, 171, 161, 161, 122, 180, 121, 121, 165,
+ 161, 176, 122, 121, 122, 113, 113, 130, 130, 170, 122, 168, 169, 168, 164, 168,
+ 121, 168, 169, 121, 176, 122, 122, 122, 121, 161, 113, 163, 177, 121, 177, 164,
+ 168, 163, 164, 177, 171, 122, 122, 168, 167, 177, 121, 122, 161, 122, 121, 175,
+ 130, 177, 168, 168, 122, 121, 163, 167, 122, 122, 162, 121, 122, 164, 168, 164,
+ 181, 168, 168, 198, 177, 163, 162, 122, 121, 177, 121, 161, 168, 161, 177, 164,
+ 167, 121, 181, 166, 142, 161, 175, 196, 142, 169, 164, 121, 167, 179, 130, 168,
+ 122, 122, 168, 168, 122, 122, 122, 122, 168, 122, 171, 121, 122, 122, 165, 130,
+ 161, 181, 176, 168, 168, 122, 121, 168, 177, 121, 177, 121, 121, 177, 171, 177,
+ 130, 168, 121, 121, 161, 168, 161, 161, 122, 190, 122, 113, 161, 161, 161, 190,
+ 180, 177, 121, 130, 160, 168, 122, 122, 168, 122, 177, 121, 161, 168, 130, 168,
+ 122, 130, 177, 182, 169, 177, 122, 122, 167, 176, 181, 168, 161, 169, 169, 169,
+ 168, 121, 168, 122, 161, 161, 122, 161, 168, 180, 164, 163, 122, 177, 122, 168,
+ 168, 182, 177, 177, 142, 168, 168, 121, 177, 168, 169, 168, 168, 130, 168, 168,
+ 122, 163, 122, 164, 161, 168, 160, 161, 169, 122, 168, 161, 161, 121, 169, 168,
+ 160, 163, 121, 177, 121, 161, 178, 168, 121, 178, 162, 168, 92, 161, 162, 162,
+ 161, 203, 169, 130, 92, 164, 122, 182, 177, 184, 177, 176, 121, 160, 122, 160,
+ 169, 122, 122, 164, 181, 130, 142, 164, 142, 122, 177, 113, 168, 198, 177, 161,
+ 168, 153, 168, 166, 122, 92, 176, 191, 177, 181, 180, 177, 169, 177, 168, 177,
+ 177, 178, 168, 168, 178, 169, 113, 160, 168, 163, 168, 122, 161, 122, 168, 121,
+ 113, 130, 130, 161, 185, 162, 162, 177, 169, 177, 177, 160, 178, 168, 177, 163,
+ 122, 168, 177, 169, 168, 168, 142, 92, 180, 161, 168, 165, 177, 122, 177, 130,
+ 92, 163, 174, 178, 175, 164, 177, 168, 163, 177, 163, 168, 162, 160, 163, 177,
+ 160, 171, 94, 142, 177, 177, 121, 177, 172, 171, 164, 121, 171, 177, 177, 168,
+ 177, 162, 160, 121, 177, 168, 168, 177, 177, 177, 161, 162, 121, 177, 177, 168,
+ 182, 177, 161, 168, 164, 168, 170, 130, 92, 130, 130, 130, 130, 169, 172, 164,
+ 168, 177, 172, 122, 162, 175, 122, 162, 177, 97, 177, 121, 161, 168, 168, 121,
+ 194, 121, 121, 121, 168, 121, 121, 177, 121, 92, 188, 161, 121, 177, 177, 178,
+ 121, 121, 121, 121, 163, 160, 177, 121, 121, 164, 181, 168, 171, 168, 177, 160,
+ 177, 142, 161, 163, 142, 162, 177, 168, 168, 168, 161, 171, 113, 121, 163, 177,
+ 188, 161, 177, 163, 172, 177, 161, 142, 121, 126, 161, 121, 181, 181, 162, 161,
+ 161, 168, 161, 168, 177, 168, 121, 163, 168, 168, 177, 172, 121, 121, 121, 142,
+ 168, 177, 177, 171, 196, 181, 164, 177, 121, 177, 197, 142, 168, 168, 121, 168,
+ 168, 161, 177, 177, 168, 188, 163, 121, 161, 168, 177, 121, 163, 161, 161, 121,
+ 142, 142, 168, 178, 178, 170, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 92, 130,
+ 130, 130, 92, 130, 130, 92, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 92, 130, 130, 130, 130, 121, 168, 113, 162, 168, 177, 177, 121,
+ 162, 121, 168, 97, 182, 161, 142, 163, 177, 160, 171, 177, 97, 168, 168, 177,
+ 168, 168, 177, 172, 121, 162, 178, 203, 163, 168, 160, 168, 177, 161, 170, 92,
+ 92, 130, 130, 130, 92, 130, 92, 92, 130, 130, 130, 121, 198, 161, 170, 122,
+ 94, 193, 121, 177, 161, 177, 163, 176, 130, 142, 171, 178, 160, 121, 200, 121,
+ 161, 160, 142, 164, 121, 160, 177, 161, 161, 168, 168, 92, 121, 121, 121, 161,
+ 168, 161, 177, 121, 92, 142, 161, 177, 177, 121, 121, 92, 121, 130, 160, 92,
+ 122, 177, 142, 121, 178, 177, 177, 177, 121, 160, 171, 171, 163, 181, 121, 177,
+ 196, 142, 164, 161, 178, 168, 162, 177, 121, 168, 168, 177, 178, 168, 169, 168,
+ 168, 177, 177, 177, 162, 171, 161, 94, 160, 163, 177, 163, 177, 142, 142, 97,
+ 163, 177, 172, 168, 161, 121, 162, 177, 177, 121, 94, 180, 180, 193, 177, 161,
+ 178, 121, 121, 168, 192, 169, 168, 121, 177, 177, 161, 177, 171, 160, 171, 177,
+ 162, 168, 94, 170, 92, 130, 92, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 92, 130, 130, 130, 130, 92, 92, 130, 92, 130, 130, 92, 130,
+ 130, 130, 92, 92, 130, 130, 130, 130, 130, 92, 130, 130, 92, 130, 92, 130,
+ 130, 130, 130, 130, 130, 130, 122, 167, 167, 122, 161, 182, 168, 191, 168, 162,
+ 161, 168, 161, 168, 160, 122, 177, 168, 122, 161, 160, 168, 121, 121, 121, 168,
+ 177, 188, 177, 121, 121, 177, 161, 161, 160, 191, 177, 168, 172, 177, 161, 164,
+ 161, 121, 168, 177, 172, 153, 113, 168, 181, 177, 161, 168, 168, 168, 168, 168,
+ 121, 121, 121, 177, 177, 121, 168, 168, 178, 188, 163, 142, 177, 121, 164, 121,
+ 161, 160, 142, 168, 168, 168, 160, 177, 161, 168, 177, 164, 177, 121, 178, 161,
+ 177, 121, 113, 161, 177, 163, 168, 168, 178, 177, 168, 178, 168, 177, 177, 121,
+ 161, 121, 177, 177, 177, 178, 168, 168, 195, 168, 168, 177, 163, 168, 121, 180,
+ 163, 177, 113, 113, 168, 168, 171, 161, 161, 121, 168, 168, 168, 168, 177, 160,
+ 177, 160, 177, 177, 177, 168, 160, 177, 113, 168, 168, 121, 168, 177, 177, 160,
+ 121, 168, 168, 162, 168, 171, 191, 121, 177, 168, 168, 160, 160, 168, 142, 168,
+ 121, 177, 178, 121, 177, 121, 168, 162, 168, 168, 177, 162, 177, 121, 177, 168,
+ 168, 164, 168, 168, 177, 121, 177, 121, 160, 168, 121, 121, 160, 162, 168, 121,
+ 168, 161, 121, 160, 178, 121, 168, 168, 168, 180, 121, 178, 170, 130, 130, 130,
+ 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 92, 130, 130, 130, 130, 130, 92, 130, 130, 130, 92, 92, 170,
+ 130, 130, 130, 130, 92, 92, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 92, 130, 122, 161, 162, 168, 162, 178, 162, 171,
+ 169, 185, 182, 168, 177, 164, 174, 96, 122, 177, 170, 177, 169, 160, 177, 177,
+ 167, 176, 185, 162, 181, 130, 177, 168, 164, 161, 168, 130, 130, 168, 164, 142,
+ 177, 169, 171, 122, 121, 177, 171, 163, 122, 161, 161, 162, 177, 161, 181, 167,
+ 163, 96, 172, 178, 164, 204, 169, 177, 161, 164, 181, 167, 177, 169, 121, 169,
+ 92, 178, 177, 177, 172, 164, 168, 178, 161, 166, 177, 169, 168, 177, 168, 182,
+ 164, 177, 163, 176, 177, 177, 142, 161, 166, 163, 168, 177, 177, 171, 177, 170,
+ 177, 168, 177, 130, 160, 168, 177, 168, 178, 177, 121, 162, 162, 161, 168, 167,
+ 177, 161, 142, 169, 168, 142, 164, 121, 142, 178, 198, 177, 161, 163, 178, 167,
+ 161, 121, 169, 177, 163, 177, 92, 177, 161, 182, 177, 167, 122, 164, 168, 168,
+ 160, 122, 122, 165, 122, 122, 168, 130, 166, 173, 168, 177, 177, 169, 142, 122,
+ 160, 169, 168, 161, 122, 177, 177, 164, 142, 168, 121, 177, 92, 161, 162, 168,
+ 168, 177, 92, 164, 168, 162, 177, 168, 177, 160, 162, 164, 177, 162, 162, 121,
+ 168, 168, 161, 162, 178, 177, 168, 171, 162, 162, 168, 168, 168, 168, 168, 182,
+ 177, 94, 168, 172, 164, 177, 177, 177, 168, 164, 162, 163, 161, 182, 198, 163,
+ 177, 121, 178, 178, 164, 168, 113, 153, 161, 161, 177, 168, 92, 163, 177, 198,
+ 178, 168, 168, 161, 168, 168, 177, 162, 178, 162, 142, 121, 162, 142, 121, 168,
+ 182, 162, 162, 92, 113, 168, 168, 162, 177, 178, 92, 164, 162, 168, 162, 177,
+ 142, 177, 161, 168, 168, 161, 178, 177, 171, 121, 142, 161, 161, 161, 162, 153,
+ 162, 113, 181, 168, 178, 168, 121, 177, 162, 168, 168, 142, 168, 182, 168, 164,
+ 168, 178, 178, 181, 180, 177, 168, 171, 121, 160, 177, 177, 168, 94, 161, 162,
+ 178, 153, 113, 162, 94, 113, 161, 177, 177, 164, 162, 161, 161, 171, 161, 163,
+ 164, 92, 163, 92, 181, 168, 178, 168, 178, 178, 172, 177, 172, 121, 168, 162,
+ 198, 162, 180, 142, 178, 198, 162, 168, 162, 162, 162, 172, 177, 168, 162, 160,
+ 94, 178, 162, 177, 178, 121, 182, 164, 177, 177, 162, 168, 168, 142, 181, 153,
+ 113, 171, 180, 168, 168, 163, 177, 177, 161, 178, 172, 121, 168, 177, 142, 168,
+ 168, 177, 92, 162, 177, 163, 178, 200, 178, 188, 177, 168, 168, 168, 177, 163,
+ 177, 161, 178, 163, 171, 168, 171, 121, 177, 168, 113, 162, 162, 163, 177, 171,
+ 178, 161, 168, 177, 92, 161, 168, 178, 177, 162, 162, 162, 161, 168, 177, 161,
+ 162, 168, 182, 168, 168, 177, 181, 171, 142, 168, 168, 163, 170, 92, 92, 130,
+ 92, 130, 130, 92, 92, 130, 130, 130, 130, 92, 92, 130, 92, 130, 130, 92,
+ 130, 130, 130, 92, 130, 130, 92, 92, 92, 92, 130, 130, 130, 92, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 92, 130, 130, 92,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130, 130, 130, 92, 92,
+ 92, 92, 92, 130, 130, 130, 130, 130, 92, 92, 130, 130, 130, 130, 130, 130,
+ 130, 92, 92, 130, 130, 130, 130, 130, 130, 130, 92, 92, 130, 130, 130, 130,
+ 92, 92, 130, 92, 92, 121, 177, 180, 161, 121, 168, 181, 181, 168, 161, 161,
+ 113, 168, 177, 121, 121, 168, 121, 177, 161, 177, 168, 168, 168, 168, 161, 168,
+ 168, 161, 163, 142, 168, 168, 142, 178, 178, 121, 161, 162, 160, 161, 113, 161,
+ 168, 162, 142, 161, 168, 142, 160, 177, 177, 168, 161, 121, 162, 177, 177, 178,
+ 168, 160, 168, 142, 161, 168, 121, 161, 121, 168, 181, 113, 113, 168, 168, 177,
+ 177, 168, 162, 177, 182, 161, 168, 168, 168, 160, 162, 121, 162, 177, 178, 142,
+ 168, 178, 177, 177, 172, 177, 113, 162, 113, 160, 177, 168, 168, 161, 160, 168,
+ 172, 121, 168, 177, 177, 161, 168, 168, 168, 178, 168, 168, 178, 121, 172, 177,
+ 121, 121, 162, 164, 113, 162, 161, 168, 168, 177, 171, 177, 121, 160, 160, 178,
+ 177, 168, 121, 168, 168, 168, 164, 177, 168, 168, 181, 177, 182, 168, 163, 168,
+ 168, 168, 168, 163, 177, 168, 177, 178, 168, 142, 177, 168, 168, 162, 162, 113,
+ 168, 161, 177, 182, 168, 164, 177, 177, 177, 168, 178, 168, 168, 168, 168, 168,
+ 168, 177, 168, 168, 178, 160, 168, 168, 168, 180, 177, 153, 177, 168, 164, 121,
+ 161, 177, 178, 168, 121, 177, 168, 168, 142, 177, 178, 178, 177, 160, 168, 177,
+ 94, 178, 142, 177, 198, 168, 113, 177, 168, 182, 177, 168, 168, 168, 168, 178,
+ 168, 168, 168, 142, 182, 177, 177, 188, 168, 178, 177, 168, 168, 168, 177, 177,
+ 162, 168, 168, 168, 168, 171, 178, 162, 168, 177, 92, 177, 168, 178, 177, 178,
+ 177, 92, 180, 177, 177, 168, 168, 168, 180, 121, 121, 168, 160, 178, 177, 168,
+ 168, 168, 177, 168, 168, 168, 168, 177, 161, 168, 182, 168, 94, 168, 163, 168,
+ 177, 177, 177, 168, 168, 177, 164, 168, 160, 177, 121, 142, 163, 177, 121, 170,
+ 130, 130, 130, 130, 92, 130, 130, 92, 130, 130, 130, 130, 130, 130, 92, 130,
+ 92, 130, 130, 130, 92, 130, 130, 130, 130, 130, 130, 92, 92, 130, 130, 130,
+ 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 92, 130, 130,
+ 92, 130, 92, 92, 92, 130, 92, 130, 130, 92, 130, 130, 130, 92, 130, 92,
+ 92, 92, 92, 130, 130, 92, 130, 130, 130, 130, 130, 130, 130, 130, 92, 92,
+ 130, 130, 92, 130, 92, 121, 92, 92, 113, 121, 177, 163, 171, 121, 130, 122,
+ 177, 172, 176, 177, 163, 163, 168, 166, 167, 168, 168, 169, 178, 168, 177, 162,
+ 160, 178, 122, 122, 168, 172, 182, 121, 163, 168, 168, 177, 168, 122, 163, 122,
+ 168, 168, 160, 161, 177, 121, 175, 168, 182, 142, 172, 160, 163, 178, 177, 163,
+ 177, 160, 161, 162, 190, 188, 168, 168, 202, 113, 113, 122, 142, 179, 122, 153,
+ 168, 160, 168, 126, 175, 161, 163, 94, 177, 130, 161, 162, 142, 122, 122, 169,
+ 178, 129, 181, 168, 122, 177, 168, 161, 122, 113, 168, 122, 122, 169, 121, 166,
+ 169, 92, 170, 161, 177, 167, 168, 166, 121, 130, 130, 168, 162, 177, 177, 169,
+ 177, 163, 177, 168, 121, 177, 178, 142, 182, 167, 168, 167, 167, 178, 179, 177,
+ 168, 168, 163, 164, 161, 161, 168, 121, 198, 177, 168, 130, 92, 130, 122, 177,
+ 166, 162, 177, 122, 164, 142, 177, 174, 168, 176, 177, 177, 168, 161, 168, 162,
+ 122, 113, 166, 168, 168, 168, 163, 160, 168, 168, 177, 177, 169, 168, 168, 176,
+ 168, 177, 177, 168, 171, 168, 168, 166, 168, 174, 162, 122, 162, 166, 169, 162,
+ 168, 177, 168, 177, 90, 163, 177, 177, 168, 168, 121, 121, 168, 168, 180, 178,
+ 179, 130, 121, 163, 178, 177, 177, 177, 177, 168, 163, 168, 97, 177, 177, 121,
+ 178, 121, 153, 142, 168, 168, 142, 121, 162, 163, 121, 168, 121, 162, 177, 177,
+ 177, 177, 142, 162, 168, 177, 178, 121, 168, 168, 177, 168, 161, 162, 168, 170,
+ 130, 92, 92, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 121, 160, 162,
+ 188, 177, 177, 161, 171, 180, 162, 164, 168, 170, 130, 130, 212, 181, 162, 170,
+ 167, 164, 177, 164, 168, 163, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 98, 98, 98, 98, 0, 0, 0, 0, 0,
+ 98, 98, 98, 98, 98, 98, 98, 98, 0, 98, 98, 98, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 98, 0, 0, 98, 98, 98, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 0, 98, 0, 0, 98,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 98,
+ 98, 98, 0, 98, 0, 98, 98, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 98, 98, 98, 98, 0, 0, 0, 0, 98, 98, 98, 0, 98,
+ 0, 98, 98, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 98, 0, 0, 0, 98, 0, 98, 98, 98, 0,
+ 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 98, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 98, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 98, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 98, 98, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 0, 98, 0, 98, 98, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 98, 0, 98, 0, 98, 0,
+ 0, 0, 0, 98, 98, 98, 0, 98, 0, 98, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 0, 98, 0, 0, 98,
+ 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 98, 98,
+ 0, 98, 0, 98, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 0, 0, 0,
+ 98, 0, 98, 98, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 98, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 98, 98, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 98, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 98, 0, 0, 0, 98, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 98, 0, 98, 98, 98, 0, 98, 0, 0, 98, 98, 98, 98, 98,
+ 0, 0, 0, 98, 98, 98, 0, 98, 98, 98, 98, 98, 0, 0, 0, 98,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 98, 0, 98, 0, 0, 98, 98, 0, 98, 98,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 98, 0, 0, 98, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 98, 0,
+ 98, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 98, 0, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 98, 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 98, 98, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 98, 0, 0, 0, 98, 98, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 98, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 98, 0, 0, 98, 98, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 98, 98,
+ 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 98, 0,
+ 0, 98, 0, 98, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 98, 0,
+ 0, 0, 0, 98, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 98, 98, 98, 0, 98, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 0, 0, 0,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 98, 0, 98, 0, 0, 98, 98, 98, 98, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 98, 0, 98,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 98,
+ 0, 98, 0, 0, 98, 98, 98, 98, 98, 0, 0, 98, 98, 98, 98, 98,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 98, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 98, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 98, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98,
+ 98, 98, 0, 0, 0, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 98, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 98, 98, 98, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 98, 98, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 98, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 98, 98, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 0, 0, 98, 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 98, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 98,
+ 98, 0, 0, 98, 98, 0, 98, 98, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 98, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 0,
+ 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 98, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 98,
+ 0, 98, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 98, 0, 98, 98, 0, 98, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 98, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 98, 98, 0, 98, 98, 98, 0,
+ 0, 0, 0, 98, 98, 98, 0, 98, 98, 98, 0, 0, 0, 98, 98, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 98, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 98, 0, 98, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 98, 0, 98, 98, 98, 98, 0,
+ 0, 0, 0, 0, 98, 98, 98, 98, 98, 98, 98, 0, 98, 0, 98, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 0,
+ 98, 0, 0, 0, 98, 0, 98, 98, 0, 0, 0, 0, 98, 98, 98, 98,
+ 98, 98, 0, 0, 0, 98, 98, 98, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 98, 98, 0,
+ 98, 0, 0, 98, 98, 98, 0, 98, 0, 98, 0, 98, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 98, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 98, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 98, 0, 98, 98, 0, 98,
+ 0, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 98, 98, 0,
+ 0, 0, 0, 98, 98, 98, 0, 98, 98, 98, 98, 0, 0, 0, 98, 0,
+ 98, 98, 0, 0, 98, 0, 98, 98, 98, 0, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 98, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 98, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 98, 98, 0, 0, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 98, 0, 0, 98, 98, 0, 98, 98, 0, 0,
+ 98, 0, 98, 0, 98, 0, 0, 98, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 98, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 98, 98, 0, 0, 0, 0, 98, 98, 98, 0, 0, 98, 0, 98, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 98, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 98, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 98, 0,
+ 98, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 98, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 98, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 98,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 98, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 98, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 98, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 98, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 98, 0, 0, 98, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 98, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0, 98, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 98, 0, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 0, 98, 0, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0,
+ 98, 98, 0, 98, 0, 98, 0, 0, 0, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0,
+ 0, 98, 0, 0, 0, 0, 0, 0, 98, 98, 0, 0, 98, 0, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 98, 98, 0, 98, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 94, 92, 94, 94, 92, 92, 92, 92, 92, 94, 94, 92, 94, 92, 94, 92,
+ 92, 92, 94, 94, 94, 94, 94, 92, 94, 92, 94, 94, 94, 94, 94, 92,
+ 94, 92, 94, 94, 92, 94, 92, 92, 92, 92, 92, 92, 92, 94, 94, 92,
+ 94, 92, 94, 94, 94, 94, 94, 94, 94, 92, 92, 94, 94, 92, 92, 92,
+ 92, 92, 92, 92, 92, 94, 92, 92, 92, 92, 92, 92, 94, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 94, 92, 94, 92, 92, 94,
+ 94, 94, 92, 92, 94, 92, 94, 92, 92, 92, 92, 92, 94, 92, 92, 92,
+ 92, 94, 92, 92, 94, 94, 92, 92, 94, 92, 92, 92, 92, 94, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 94, 92, 94, 94, 92, 94, 92, 92, 92,
+ 92, 92, 92, 94, 94, 92, 92, 92, 92, 94, 94, 92, 94, 94, 94, 92,
+ 92, 92, 92, 92, 92, 92, 94, 94, 92, 94, 92, 94, 92, 92, 94, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 94, 92, 94, 92, 94, 92,
+ 92, 92, 92, 94, 92, 94, 92, 94, 94, 92, 94, 92, 92, 92, 92, 92,
+ 94, 92, 92, 92, 94, 94, 92, 92, 92, 92, 92, 92, 94, 92, 92, 94,
+ 92, 92, 94, 94, 94, 94, 92, 94, 94, 94, 92, 94, 94, 92, 94, 92,
+ 92, 92, 94, 92, 92, 92, 92, 92, 94, 94, 92, 94, 92, 94, 92, 92,
+ 92, 92, 92, 94, 92, 92, 94, 92, 92, 94, 94, 94, 92, 92, 92, 92,
+ 94, 92, 92, 92, 94, 94, 92, 92, 92, 92, 92, 92, 94, 94, 92, 92,
+ 92, 94, 92, 92, 92, 92, 94, 94, 94, 92, 92, 92, 92, 92, 92, 92,
+ 94, 94, 92, 92, 92, 92, 94, 92, 92, 94, 92, 92, 92, 92, 92, 92,
+ 92, 94, 94, 92, 92, 94, 92, 94, 94, 92, 94, 92, 92, 94, 92, 92,
+ 94, 92, 92, 92, 94, 94, 94, 94, 92, 94, 94, 92, 92, 94, 92, 92,
+ 92, 92, 94, 92, 92, 92, 92, 92, 94, 94, 94, 92, 92, 92, 92, 92,
+ 92, 94, 94, 92, 92, 94, 92, 92, 94, 94, 92, 94, 94, 92, 92, 94,
+ 94, 92, 92, 92, 92, 94, 92, 94, 92, 94, 92, 94, 92, 92, 92, 94,
+ 94, 92, 92, 94, 92, 94, 94, 92, 92, 92, 92, 92, 92, 92, 92, 94,
+ 94, 92, 92, 92, 94, 92, 94, 92, 92, 92, 94, 92, 92, 92, 94, 92,
+ 94, 94, 92, 94, 94, 92, 94, 92, 94, 92, 92, 94, 94, 94, 94, 94,
+ 92, 94, 92, 92, 94, 94, 92, 92, 94, 92, 92, 92, 94, 94, 92, 92,
+ 92, 92, 92, 92, 94, 94, 92, 94, 92, 92, 94, 92, 92, 94, 92, 92,
+ 92, 92, 94, 92, 92, 92, 94, 92, 92, 92, 92, 94, 92, 92, 92, 94,
+ 94, 92, 94, 92, 92, 92, 92, 94, 92, 92, 94, 92, 92, 92, 94, 92,
+ 94, 94, 94, 92, 92, 94, 92, 94, 92, 92, 94, 94, 94, 92, 92, 92,
+ 94, 92, 94, 94, 94, 94, 94, 92, 92, 94, 92, 94, 94, 92, 92, 94,
+ 94, 94, 92, 92, 92, 92, 94, 94, 94, 92, 94, 92, 92, 92, 92, 94,
+ 92, 94, 92, 94, 92, 92, 92, 94, 92, 92, 92, 94, 92, 94, 94, 92,
+ 92, 92, 92, 92, 92, 94, 92, 92, 94, 92, 94, 94, 94, 94, 94, 94,
+ 92, 94, 94, 94, 94, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 94, 92, 92, 92, 92, 92, 92, 94, 92, 92, 94, 92, 94, 94, 94,
+ 92, 94, 92, 92, 92, 92, 92, 92, 92, 92, 94, 92, 92, 94, 92, 92,
+ 92, 92, 94, 92, 92, 92, 92, 92, 94, 94, 92, 94, 92, 92, 92, 92,
+ 94, 94, 92, 92, 94, 94, 94, 92, 92, 94, 94, 94, 92, 92, 92, 94,
+ 92, 94, 92, 92, 94, 92, 94, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 94, 94, 94, 94, 92, 94, 94, 92, 94, 92, 92, 92, 94, 94,
+ 92, 94, 92, 92, 92, 92, 92, 94, 92, 94, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 94, 92, 92, 92, 94, 94, 92, 92, 92, 92, 94, 92,
+ 94, 94, 94, 92, 92, 92, 92, 94, 92, 94, 92, 94, 94, 94, 92, 92,
+ 94, 94, 92, 92, 92, 92, 92, 92, 94, 92, 92, 92, 94, 92, 92, 94,
+ 94, 94, 92, 92, 92, 92, 94, 92, 94, 92, 92, 92, 94, 92, 92, 94,
+ 92, 94, 92, 94, 92, 94, 92, 92, 94, 92, 92, 94, 94, 92, 92, 94,
+ 92, 92, 92, 92, 92, 94, 92, 92, 92, 92, 92, 92, 94, 92, 92, 92,
+ 94, 94, 92, 92, 92, 94, 94, 92, 92, 92, 92, 94, 92, 94, 92, 92,
+ 92, 92, 94, 92, 92, 94, 92, 92, 94, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 94, 92, 94, 92, 92, 92, 92, 92, 92, 94, 94, 92, 92, 92,
+ 94, 92, 94, 92, 94, 94, 92, 92, 92, 92, 92, 92, 92, 92, 92, 94,
+ 92, 92, 94, 92, 94, 94, 92, 94, 92, 94, 92, 94, 92, 92, 92, 92,
+ 92, 94, 94, 92, 92, 92, 94, 92, 94, 94, 94, 92, 92, 94, 92, 92,
+ 92, 94, 92, 94, 94, 92, 94, 92, 94, 92, 94, 94, 92, 92, 94, 94,
+ 94, 92, 94, 92, 92, 94, 94, 94, 94, 94, 92, 92, 94, 92, 92, 92,
+ 92, 94, 94, 92, 94, 94, 92, 92, 92, 94, 94, 94, 94, 94, 92, 92,
+ 92, 92, 92, 94, 92, 92, 92, 92, 94, 92, 92, 92, 94, 94, 92, 94,
+ 92, 92, 92, 92, 92, 94, 92, 92, 94, 94, 94, 92, 92, 92, 92, 92,
+ 92, 94, 92, 94, 92, 92, 92, 94, 92, 92, 92, 92, 92, 94, 94, 92,
+ 94, 92, 94, 94, 94, 92, 92, 92, 94, 92, 94, 92, 92, 94, 92, 94,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 94, 94, 94, 92, 92, 92, 92,
+ 92, 92, 92, 92, 94, 92, 92, 92, 92, 92, 92, 94, 92, 94, 94, 92,
+ 92, 92, 92, 94, 92, 94, 94, 92, 94, 92, 92, 92, 94, 94, 92, 92,
+ 92, 92, 94, 92, 92, 92, 94, 92, 92, 92, 94, 94, 94, 92, 94, 92,
+ 94, 94, 92, 92, 94, 92, 92, 92, 94, 92, 92, 92, 94, 94, 94, 92,
+ 94, 94, 92, 92, 92, 92, 92, 92, 92, 94, 94, 92, 92, 94, 94, 92,
+ 92, 94, 94, 94, 92, 94, 92, 94, 94, 94, 94, 92, 94, 92, 94, 94,
+ 92, 94, 94, 92, 94, 92, 94, 92, 92, 92, 92, 92, 92, 92, 94, 94,
+ 92, 92, 92, 92, 94, 92, 94, 94, 94, 94, 94, 92, 92, 94, 94, 92,
+ 92, 94, 94, 92, 92, 94, 94, 94, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 94, 94, 94, 94, 92, 92, 92, 92, 92, 92, 94, 92, 92, 92, 94,
+ 92, 92, 92, 94, 94, 94, 94, 94, 94, 94, 94, 92, 92, 92, 92, 92,
+ 92, 94, 92, 92, 92, 92, 94, 92, 92, 94, 92, 92, 92, 94, 94, 92,
+ 92, 92, 92, 92, 92, 92, 94, 92, 92, 94, 92, 92, 94, 94, 92, 92,
+ 92, 92, 92, 92, 94, 92, 94, 94, 94, 92, 92, 92, 92, 92, 94, 94,
+ 92, 92, 92, 92, 92, 92, 94, 92, 94, 94, 92, 92, 92, 92, 92, 94,
+ 92, 94, 94, 92, 92, 94, 92, 92, 92, 92, 94, 92, 92, 94, 92, 94,
+ 92, 92, 94, 92, 94, 92, 94, 92, 92, 92, 94, 92, 94, 94, 94, 94,
+ 94, 94, 92, 92, 94, 92, 92, 92, 94, 94, 94, 94, 94, 92, 94, 94,
+ 92, 92, 92, 92, 92, 92, 92, 94, 92, 92, 92, 92, 92, 92, 94, 92,
+ 92, 92, 92, 94, 92, 92, 92, 92, 92, 92, 92, 94, 92, 92, 92, 92,
+ 92, 92, 92, 92, 94, 94, 92, 94, 94, 94, 92, 94, 94, 92, 94, 94,
+ 92, 92, 94, 92, 92, 92, 94, 94, 92, 92, 92, 92, 92, 94, 94, 92,
+ 94, 92, 94, 94, 92, 94, 94, 94, 92, 94, 94, 92, 94, 94, 94, 92,
+ 94, 92, 94, 94, 94, 94, 94, 92, 94, 92, 92, 94, 94, 94, 94, 94,
+ 94, 92, 94, 94, 94, 92, 92, 92, 92, 92, 94, 92, 92, 94, 94, 94,
+ 94, 94, 92, 92, 94, 92, 94, 94, 94, 92, 94, 92, 92, 92, 92, 94,
+ 92, 94, 94, 92, 92, 94, 92, 94, 94, 92, 94, 94, 92, 92, 94, 94,
+ 94, 92, 94, 92, 92, 92, 92, 92, 94, 94, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 94, 94, 94, 92, 94, 94, 92, 92, 94,
+ 92, 94, 94, 94, 92, 94, 94, 92, 92, 94, 92, 92, 92, 92, 94, 94,
+ 94, 94, 92, 94, 92, 92, 92, 92, 92, 92, 92, 94, 94, 92, 92, 92,
+ 94, 92, 94, 92, 94, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 94,
+ 94, 94, 94, 92, 92, 92, 92, 92, 92, 94, 94, 94, 94, 92, 92, 92,
+ 92, 94, 92, 94, 94, 92, 92, 94, 92, 92, 92, 94, 92, 92, 92, 92,
+ 92, 92, 94, 94, 94, 92, 92, 94, 94, 92, 94, 92, 94, 92, 92, 94,
+ 94, 94, 94, 92, 92, 94, 94, 92, 94, 92, 92, 94, 92, 92, 94, 94,
+ 92, 92, 94, 94, 94, 94, 92, 94, 94, 94, 92, 92, 92, 94, 94, 94,
+ 94, 92, 94, 94, 92, 94, 94, 94, 94, 92, 94, 92, 92, 92, 94, 94,
+ 92, 94, 92, 92, 92, 92, 94, 94, 94, 94, 92, 94, 94, 94, 92, 94,
+ 94, 92, 92, 94, 94, 94, 94, 94, 94, 92, 94, 94, 94, 92, 94, 94,
+ 94, 92, 94, 92, 92, 92, 94, 94, 92, 94, 94, 92, 94, 92, 94, 94,
+ 92, 94, 94, 92, 92, 92, 94, 92, 92, 92, 92, 92, 94, 94, 92, 92,
+ 92, 92, 94, 92, 92, 92, 92, 92, 92, 94, 94, 92, 92, 94, 94, 92,
+ 94, 94, 92, 92, 92, 94, 92, 94, 92, 92, 94, 92, 92, 92, 92, 92,
+ 92, 94, 94, 92, 92, 92, 92, 94, 94, 92, 94, 94, 92, 94, 94, 94,
+ 94, 94, 92, 92, 94, 94, 94, 92, 92, 92, 92, 92, 92, 92, 94, 92,
+ 92, 92, 94, 94, 92, 92, 92, 94, 92, 92, 94, 94, 94, 92, 92, 94,
+ 92, 94, 94, 92, 92, 92, 94, 94, 92, 94, 94, 92, 94, 92, 92, 92,
+ 94, 94, 92, 94, 92, 92, 92, 94, 94, 92, 94, 94, 92, 94, 92, 92,
+ 92, 92, 92, 92, 94, 94, 92, 92, 92, 92, 92, 94, 92, 92, 92, 94,
+ 92, 92, 92, 94, 94, 94, 94, 94, 92, 92, 92, 92, 94, 94, 92, 92,
+ 94, 94, 94, 92, 94, 92, 92, 94, 92, 92, 92, 92, 92, 94, 94, 94,
+ 92, 94, 94, 92, 92, 92, 92, 92, 92, 92, 92, 94, 94, 94, 92, 94,
+ 92, 94, 94, 92, 94, 94, 92, 94, 94, 94, 92, 92, 93, 94, 94, 92,
+ 94, 92, 92, 92, 92, 94, 92, 94, 94, 92, 94, 92, 94, 94, 92, 92,
+ 92, 92, 92, 92, 94, 92, 94, 92, 92, 94, 92, 94, 92, 94, 92, 92,
+ 94, 92, 94, 92, 94, 92, 94, 94, 92, 94, 92, 92, 92, 92, 92, 92,
+ 92, 92, 94, 92, 94, 94, 94, 94, 94, 94, 92, 92, 92, 92, 92, 92,
+ 92, 94, 92, 92, 94, 92, 92, 92, 94, 92, 92, 92, 94, 92, 92, 92,
+ 92, 92, 92, 92, 94, 92, 92, 92, 0, 92, 94, 92, 92, 92, 94, 92,
+ 92, 94, 92, 92, 92, 92, 92, 92, 94, 92, 94, 92, 94, 94, 92, 92,
+ 92, 92, 92, 92, 94, 92, 92, 93, 93, 93, 0, 93, 0, 93, 93, 93,
+ 0, 93, 93, 93, 92, 92, 92, 92, 94, 92, 92, 94, 94, 92, 92, 94,
+ 94, 94, 94, 92, 92, 92, 92, 92, 94, 92, 92, 92, 94, 92, 94, 94,
+ 92, 94, 92, 94, 92, 0, 94, 94, 94, 0, 93, 0, 0, 0, 92, 0,
+ 0, 93, 0, 0, 0, 0, 92, 93, 93, 0, 0, 92, 92, 93, 0, 93,
+ 0, 92, 92, 0, 0, 93, 0, 93, 93, 0, 93, 94, 0, 0, 0, 0,
+ 0, 93, 93, 92, 0, 0, 0, 0, 0, 0, 0, 93, 0, 93, 93, 0,
+ 0, 93, 0, 0, 92, 94, 93, 93, 93, 0, 0, 93, 93, 93, 0, 0,
+ 93, 93, 93, 0, 92, 93, 93, 93, 0, 93, 93, 0, 93, 0, 0, 0,
+ 0, 93, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 93, 93, 93,
+ 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 93,
+ 0, 93, 93, 0, 93, 93, 0, 0, 0, 0, 93, 0, 0, 93, 0, 0,
+ 93, 93, 0, 93, 93, 93, 93, 93, 0, 93, 93, 0, 93, 93, 93, 93,
+ 93, 0, 0, 0, 0, 93, 93, 0, 93, 0, 0, 0, 0, 93, 93, 93,
+ 93, 93, 93, 93, 0, 93, 0, 93, 0, 0, 0, 93, 0, 93, 93, 0,
+ 93, 93, 0, 93, 0, 93, 93, 0, 93, 93, 93, 0, 0, 93, 0, 93,
+ 93, 93, 0, 0, 0, 93, 93, 0, 93, 93, 93, 0, 0, 93, 0, 0,
+ 0, 93, 93, 0, 0, 93, 0, 0, 0, 0, 0, 93, 0, 0, 93, 0,
+ 93, 0, 0, 93, 0, 0, 0, 93, 93, 0, 0, 0, 93, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 93, 93, 0, 0, 0, 93, 0, 93, 93,
+ 93, 93, 93, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 0, 93, 93,
+ 0, 0, 0, 93, 93, 93, 93, 0, 93, 0, 93, 0, 93, 93, 93, 0,
+ 0, 93, 0, 0, 93, 93, 0, 0, 93, 0, 0, 0, 0, 93, 0, 0,
+ 93, 0, 93, 93, 93, 93, 0, 93, 93, 0, 93, 0, 93, 93, 93, 0,
+ 93, 93, 0, 0, 93, 0, 0, 93, 93, 0, 0, 0, 0, 0, 93, 93,
+ 0, 0, 0, 93, 93, 93, 0, 93, 93, 0, 93, 93, 0, 93, 0, 0,
+ 0, 93, 93, 0, 0, 0, 0, 93, 0, 0, 93, 0, 0, 0, 93, 0,
+ 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,
+ 93, 93, 0, 0, 0, 93, 0, 0, 0, 93, 93, 93, 93, 0, 0, 93,
+ 93, 93, 0, 93, 93, 0, 93, 93, 93, 93, 93, 0, 93, 0, 93, 93,
+ 93, 93, 93, 93, 0, 0, 0, 93, 93, 93, 93, 93, 93, 0, 93, 0,
+ 93, 93, 93, 0, 93, 93, 93, 0, 93, 93, 93, 93, 0, 0, 93, 93,
+ 93, 0, 93, 93, 93, 93, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93,
+ 0, 93, 93, 0, 0, 93, 0, 0, 93, 93, 93, 93, 93, 93, 0, 93,
+ 93, 93, 0, 93, 0, 93, 0, 93, 0, 0, 93, 0, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 93, 93, 93,
+ 0, 93, 0, 93, 93, 0, 93, 0, 0, 0, 93, 93, 93, 93, 93, 93,
+ 93, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 93, 0, 93,
+ 0, 93, 93, 93, 0, 93, 0, 93, 93, 93, 0, 93, 0, 93, 0, 93,
+ 93, 93, 0, 93, 93, 0, 93, 93, 93, 0, 93, 0, 0, 0, 93, 93,
+ 93, 93, 0, 93, 93, 93, 0, 0, 93, 93, 93, 0, 93, 93, 93, 93,
+ 93, 0, 0, 93, 0, 93, 0, 93, 93, 93, 93, 93, 0, 0, 0, 93,
+ 93, 0, 93, 93, 0, 93, 93, 0, 93, 0, 93, 93, 0, 93, 93, 93,
+ 93, 0, 93, 93, 93, 0, 93, 0, 0, 93, 0, 0, 93, 93, 0, 93,
+ 0, 0, 93, 0, 0, 93, 93, 93, 93, 0, 93, 0, 93, 93, 93, 0,
+ 93, 0, 0, 93, 0, 93, 0, 93, 93, 0, 93, 93, 0, 93, 0, 93,
+ 0, 93, 0, 0, 93, 0, 0, 93, 93, 93, 0, 93, 93, 0, 93, 93,
+ 0, 93, 93, 0, 0, 93, 93, 0, 0, 93, 93, 93, 0, 93, 93, 0,
+ 0, 0, 0, 0, 0, 93, 93, 0, 93, 93, 0, 0, 93, 0, 93, 93,
+ 93, 0, 0, 93, 93, 0, 0, 93, 93, 93, 93, 93, 93, 93, 0, 0,
+ 93, 0, 93, 0, 93, 0, 93, 0, 0, 0, 93, 93, 93, 93, 93, 93,
+ 0, 93, 93, 0, 0, 93, 0, 93, 0, 0, 0, 93, 93, 0, 0, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 93, 93, 0, 0, 93,
+ 0, 0, 93, 0, 93, 0, 93, 93, 93, 0, 93, 0, 93, 93, 0, 93,
+ 93, 0, 93, 93, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 0, 93, 93, 0, 0, 93, 0, 93, 0, 0, 93, 0,
+ 93, 0, 0, 0, 93, 0, 93, 0, 0, 0, 0, 0, 0, 93, 93, 0,
+ 0, 93, 93, 93, 93, 93, 93, 0, 93, 93, 93, 93, 0, 93, 93, 0,
+ 93, 0, 0, 93, 93, 0, 0, 93, 93, 0, 0, 93, 0, 93, 0, 93,
+ 0, 0, 0, 0, 93, 0, 93, 0, 0, 93, 93, 93, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,
+ 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 93, 93, 0, 93, 93,
+ 93, 93, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 93, 0, 93, 0, 0, 93, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0,
+ 0, 0, 0, 0, 93, 0, 0, 93, 0, 0, 93, 0, 93, 93, 93, 93,
+ 93, 93, 0, 93, 0, 93, 93, 93, 93, 0, 93, 0, 93, 93, 93, 0,
+ 0, 0, 93, 0, 93, 93, 93, 93, 0, 93, 93, 0, 93, 93, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 93, 0, 0,
+ 0, 93, 93, 0, 0, 93, 0, 93, 0, 0, 93, 93, 0, 93, 93, 93,
+ 0, 93, 93, 93, 93, 0, 0, 93, 93, 0, 0, 0, 0, 0, 0, 93,
+ 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0,
+ 0, 93, 93, 0, 0, 93, 0, 93, 93, 0, 93, 0, 0, 0, 0, 0,
+ 0, 93, 0, 0, 93, 93, 93, 0, 93, 93, 93, 93, 0, 0, 93, 0,
+ 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 93,
+ 0, 93, 0, 0, 0, 0, 0, 93, 0, 0, 93, 93, 0, 93, 0, 0,
+ 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0,
+ 0, 93, 0, 0, 0, 93, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0,
+ 93, 0, 93, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0,
+ 93, 93, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 93, 0, 93, 0, 0,
+ 93, 0, 0, 0, 93, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 93, 0, 93, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0,
+ 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 93, 93, 93, 93,
+ 93, 93, 0, 0, 93, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 93, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 93, 0, 93, 0, 0, 0, 93, 93, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 93, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 0, 93, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0,
+ 93, 93, 93, 0, 93, 0, 93, 0, 93, 93, 0, 93, 0, 93, 0, 0,
+ 93, 93, 93, 0, 93, 93, 93, 93, 0, 0, 93, 93, 93, 93, 93, 93,
+ 0, 93, 93, 93, 0, 93, 93, 0, 0, 93, 0, 0, 93, 93, 93, 93,
+ 0, 0, 0, 0, 93, 0, 0, 93, 93, 93, 0, 93, 93, 93, 93, 0,
+ 93, 93, 0, 93, 93, 93, 0, 0, 93, 0, 0, 93, 0, 93, 93, 93,
+ 93, 93, 0, 0, 0, 0, 0, 93, 93, 0, 0, 93, 0, 0, 93, 0,
+ 0, 0, 0, 0, 93, 93, 93, 93, 0, 93, 93, 0, 0, 93, 0, 93,
+ 93, 0, 93, 93, 93, 0, 0, 93, 0, 0, 93, 93, 93, 93, 93, 93,
+ 93, 93, 0, 93, 93, 93, 0, 93, 93, 93, 93, 0, 93, 93, 93, 93,
+ 0, 93, 93, 93, 93, 93, 0, 93, 0, 93, 93, 93, 93, 93, 93, 93,
+ 93, 0, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 93,
+ 0, 0, 93, 93, 0, 0, 0, 0, 93, 0, 0, 0, 93, 0, 93, 93,
+ 93, 93, 0, 93, 0, 93, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 0, 93, 93, 93, 93, 0, 93, 93, 93, 93, 93, 93, 0, 93,
+ 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 93, 0, 0, 0, 0, 0,
+ 0, 0, 0, 93, 93, 0, 0, 0, 0, 0, 93, 93, 0, 93, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0,
+ 0, 0, 0, 93, 0, 0, 93, 0, 0, 93, 93, 0, 0, 0, 93, 0,
+ 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0,
+ 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0,
+ 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 93, 93, 0, 93, 0, 93, 93, 0, 93, 93, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 183, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 183, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 183, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 183, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 183, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 137, 137, 92, 92,
+ 0, 92, 0, 92, 92, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 92,
+ 92, 92, 0, 92, 92, 0, 0, 92, 92, 92, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 97, 97, 213, 137, 137, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 110, 110, 110, 110, 97, 97, 97, 97, 97, 97, 137,
+ 97, 134, 97, 110, 97, 97, 97, 97, 110, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 110, 134, 97, 97, 97, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 0,
+ 0, 122, 214, 122, 122, 122, 122, 214, 122, 122, 122, 122, 122, 129, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 215, 129, 215, 123, 122,
+ 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 132, 0,
+ 0, 216, 216, 216, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 218, 218, 128, 123, 94, 219, 98, 0, 0, 0, 0, 0, 0, 93, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
+};
diff --git a/trunk/modules/basic/tables-small.i b/trunk/modules/basic/tables-small.i
new file mode 100644
index 00000000..98abb3a4
--- /dev/null
+++ b/trunk/modules/basic/tables-small.i
@@ -0,0 +1,603 @@
+/* NOTE: This file has not been maintained, and is out
+ * of date with respect to the rest of the code.
+ */
+enum {
+ ENC_ISO_8859_1 = 1 << 0,
+ ENC_ISO_8859_2 = 1 << 1,
+ ENC_ISO_8859_3 = 1 << 2,
+ ENC_ISO_8859_4 = 1 << 3,
+ ENC_ISO_8859_5 = 1 << 4,
+ ENC_ISO_8859_6 = 1 << 5,
+ ENC_ISO_8859_7 = 1 << 6,
+ ENC_ISO_8859_8 = 1 << 7,
+ ENC_ISO_8859_9 = 1 << 8,
+ ENC_ISO_10646 = 1 << 12
+};
+
+static Charset charsets[] = {
+ { 0, NULL, "iso8859-1", conv_ucs4 },
+ { 1, "ISO-8859-2", "iso8859-2", conv_8bit },
+ { 2, "ISO-8859-3", "iso8859-3", conv_8bit },
+ { 3, "ISO-8859-4", "iso8859-4", conv_8bit },
+ { 4, "ISO-8859-5", "iso8859-5", conv_8bit },
+ { 5, "ISO-8859-6", "iso8859-6", conv_8bit },
+ { 6, "ISO-8859-7", "iso8859-7", conv_8bit },
+ { 7, "ISO-8859-8", "iso8859-8", conv_8bit },
+ { 8, "ISO-8859-9", "iso8859-9", conv_8bit },
+ { 9, NULL, "iso10646-1", conv_ucs4 }
+};
+
+static PangoEngineRange basic_ranges[] = {
+ { 0x0000, 0x02af, "*" },
+ { 0x02b0, 0x02ff, "" },
+ { 0x0380, 0x058f, "*" },
+ { 0x0591, 0x05f4, "*" }, /* Hebrew */
+ { 0x060c, 0x06f9, "" }, /* Arabic */
+ { 0x2015, 0x2017, "*" },
+};
+
+static const guint32 char_mask_map[] = {
+ 0,
+ ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_6|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_5|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_3|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_6|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_7|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_4|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_3|ENC_ISO_8859_8|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_3|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_9,
+ ENC_ISO_8859_1,
+ ENC_ISO_8859_1|ENC_ISO_8859_3|ENC_ISO_8859_4|ENC_ISO_8859_9,
+ ENC_ISO_8859_1|ENC_ISO_8859_2,
+ ENC_ISO_8859_4,
+ ENC_ISO_8859_2,
+ ENC_ISO_8859_2|ENC_ISO_8859_4,
+ ENC_ISO_8859_3,
+ ENC_ISO_8859_3|ENC_ISO_8859_9,
+ ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_9,
+ ENC_ISO_8859_2|ENC_ISO_8859_3,
+ ENC_ISO_8859_7,
+ ENC_ISO_8859_2|ENC_ISO_8859_3|ENC_ISO_8859_4,
+ ENC_ISO_8859_5,
+ ENC_ISO_8859_8,
+ ENC_ISO_8859_6
+};
+
+static const guchar char_masks[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 3, 4, 5, 6, 4, 7, 2, 8, 7, 3, 7, 7, 1, 4, 9,
+ 8, 7, 5, 5, 10, 11, 4, 5, 10, 4, 3, 7, 4, 5, 4, 3,
+ 12, 13, 13, 9, 13, 9, 9, 14, 12, 13, 12, 13, 12, 13, 13, 12,
+ 15, 12, 12, 14, 13, 9, 13, 10, 9, 12, 13, 16, 13, 17, 15, 13,
+ 12, 13, 13, 9, 13, 9, 9, 14, 12, 13, 12, 13, 12, 13, 13, 12,
+ 15, 12, 12, 14, 13, 9, 13, 10, 9, 12, 13, 16, 13, 17, 15, 3,
+ 18, 18, 19, 19, 20, 20, 19, 19, 21, 21, 21, 21, 20, 20, 19, 19,
+ 20, 20, 18, 18, 0, 0, 18, 18, 20, 20, 19, 19, 21, 21, 22, 22,
+ 21, 21, 18, 18, 21, 21, 21, 21, 18, 18, 18, 18, 0, 0, 18, 18,
+ 22, 22, 0, 0, 21, 21, 18, 18, 18, 19, 19, 18, 18, 19, 19, 0,
+ 0, 19, 19, 19, 19, 18, 18, 19, 19, 0, 18, 18, 18, 18, 0, 0,
+ 19, 19, 0, 0, 19, 19, 18, 18, 19, 19, 19, 19, 21, 21, 23, 23,
+ 20, 20, 19, 19, 19, 19, 18, 18, 18, 18, 18, 18, 21, 21, 19, 19,
+ 19, 19, 18, 18, 0, 0, 0, 0, 0, 19, 19, 24, 24, 20, 20, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 24, 26, 0, 20, 0, 19, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 25, 25, 25, 0, 25, 25, 25, 0, 25, 0, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 27, 27,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 29,
+ 0, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 0, 0, 0, 0,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 25, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 27,
+};
diff --git a/trunk/modules/hangul/Makefile.am b/trunk/modules/hangul/Makefile.am
new file mode 100644
index 00000000..3b3c52fa
--- /dev/null
+++ b/trunk/modules/hangul/Makefile.am
@@ -0,0 +1,24 @@
+include $(top_srcdir)/modules/Module.mk
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_HANGUL_FC
+noinst_LTLIBRARIES += libpango-hangul-fc.la
+else
+if DYNAMIC_HANGUL_FC
+module_LTLIBRARIES += pango-hangul-fc.la
+endif
+endif
+endif
+
+fc_sources = hangul-fc.c hangul-defs.h
+
+pango_hangul_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_hangul_fc_la_LIBADD = $(pangoft2libs)
+pango_hangul_fc_la_SOURCES = $(fc_sources)
+libpango_hangul_fc_la_SOURCES = $(fc_sources)
+libpango_hangul_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_hangul_fc
+
+
+EXTRA_DIST = \
+ tables-jamos.i
diff --git a/trunk/modules/hangul/hangul-defs.h b/trunk/modules/hangul/hangul-defs.h
new file mode 100644
index 00000000..8cef8ba8
--- /dev/null
+++ b/trunk/modules/hangul/hangul-defs.h
@@ -0,0 +1,91 @@
+/* Pango
+ * hangul-defs.h:
+ *
+ * Copyright (C) 2002-2006 Changwoo Ryu
+ * Author: Changwoo Ryu <cwryu@debian.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* See 3.12 "Conjoining Jamo Behavior" in the Unicode Book for more
+ * information
+ */
+
+/* The start of the Hangul Syllables (U+AC00-U+D7A3) */
+#define SBASE 0xAC00
+#define SCOUNT 11172
+
+/* The starts/ends of the leading consonants (choseong), the vowels
+ * (jungseong) and the trailing consonants (jongseong).
+ */
+#define LBASE 0x1100
+#define VBASE 0x1161
+#define TBASE 0x11A7
+#define LEND 0x115F
+#define VEND 0x11A7
+#define TEND 0x11FF
+
+/* Number of modern jamos */
+#define LCOUNT 19
+#define VCOUNT 21
+#define TCOUNT 28
+#define NCOUNT (VCOUNT * TCOUNT) /* number of syllables of a given choseong */
+
+/* choseong and jungseong filler */
+#define LFILL 0x115F
+#define VFILL 0x1160
+
+/* Old tone marks. */
+#define HTONE1 0x302E
+#define HTONE2 0x302F
+
+/* Useful macros
+ */
+
+#define IS_JAMO(wc) ((wc) >= LBASE && (wc) <= TEND)
+#define IS_L(wc) ((wc) >= LBASE && (wc) <= LEND)
+#define IS_V(wc) ((wc) >= VFILL && (wc) <= VEND)
+#define IS_T(wc) ((wc) > TBASE && (wc) <= TEND)
+#define IS_M(wc) ((wc) == HTONE1 || (wc) == HTONE2)
+#define IS_S(wc) (SBASE <= (wc) && (wc) < (SBASE + SCOUNT))
+
+/* jamo which can be composited as a precomposed syllable */
+#define IS_L_S(wc) ((wc) >= LBASE && (wc) < (LBASE + LCOUNT))
+#define IS_V_S(wc) ((wc) >= VBASE && (wc) < (VBASE + VCOUNT))
+#define IS_T_S(wc) ((wc) > TBASE && (wc) < (TBASE + TCOUNT))
+
+/* if a syllable has a jongseong */
+#define S_HAS_T(s) (((s) - SBASE) % TCOUNT)
+
+/* non hangul */
+#define IS_HANGUL(wc) (IS_S(wc) || IS_JAMO(wc) || IS_M(wc))
+
+/* syllable boundary condition */
+#define IS_BOUNDARY(prev,next) \
+ ((!IS_L(prev) && IS_S(wc)) || \
+ !IS_HANGUL(next) || \
+ (IS_S(prev) && S_HAS_T(prev) && IS_L(next)) || \
+ (IS_T(prev) && (IS_L(next) || IS_V(next))) || \
+ (IS_S(prev) && !S_HAS_T(prev) && IS_L(next)) || \
+ (IS_V(prev) && IS_L(next)) || \
+ IS_M(prev))
+
+/* composing/decomposing */
+#define S_FROM_LVT(l,v,t) (SBASE + (((l) - LBASE) * VCOUNT + ((v) - VBASE)) * TCOUNT + ((t) - TBASE))
+#define S_FROM_LV(l,v) (SBASE + (((l) - LBASE) * VCOUNT + ((v) - VBASE)) * TCOUNT)
+#define L_FROM_S(s) (LBASE + (((s) - SBASE) / NCOUNT))
+#define V_FROM_S(s) (VBASE + (((s) - SBASE) % NCOUNT) / TCOUNT)
+#define T_FROM_S(s) (TBASE + (((s) - SBASE) % TCOUNT))
diff --git a/trunk/modules/hangul/hangul-fc.c b/trunk/modules/hangul/hangul-fc.c
new file mode 100644
index 00000000..32470fe4
--- /dev/null
+++ b/trunk/modules/hangul/hangul-fc.c
@@ -0,0 +1,498 @@
+/* Pango
+ * hangul-fc.c: Hangul shaper for FreeType based backends
+ *
+ * Copyright (C) 2002-2006 Changwoo Ryu
+ * Author: Changwoo Ryu <cwryu@debian.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "pango-engine.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+
+#include "hangul-defs.h"
+#include "tables-jamos.i"
+
+/* No extra fields needed */
+typedef PangoEngineShape HangulEngineFc;
+typedef PangoEngineShapeClass HangulEngineFcClass ;
+
+#define SCRIPT_ENGINE_NAME "HangulScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+static PangoEngineScriptInfo hangul_scripts[] = {
+ { PANGO_SCRIPT_HANGUL, "*" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ hangul_scripts, G_N_ELEMENTS(hangul_scripts)
+ }
+};
+
+static void
+set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGlyph glyph)
+{
+ PangoRectangle logical_rect;
+
+ glyphs->glyphs[i].glyph = glyph;
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+ glyphs->log_clusters[i] = offset;
+
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+}
+
+/* Add a Hangul tone mark glyph in a glyph string.
+ * Non-spacing glyph works pretty much automatically.
+ * Spacing-glyph takes some care:
+ * 1. Make a room for a tone mark at the beginning(leftmost end) of a cluster
+ * to attach it to.
+ * 2. Adjust x_offset so that it is drawn to the left of a cluster.
+ * 3. Set the logical width to zero.
+ */
+
+static void
+set_glyph_tone (PangoFont *font, PangoGlyphString *glyphs, int i,
+ int offset, PangoGlyph glyph)
+{
+ PangoRectangle logical_rect, ink_rect;
+ PangoRectangle logical_rect_cluster;
+
+ glyphs->glyphs[i].glyph = glyph;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+ glyphs->log_clusters[i] = offset;
+
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph,
+ &ink_rect, &logical_rect);
+
+ /* tone mark is not the first in a glyph string. We have info. on the
+ * preceding glyphs in a glyph string
+ */
+ {
+ int j = i - 1;
+ /* search for the beg. of the preceding cluster */
+ while (j >= 0 && glyphs->log_clusters[j] == glyphs->log_clusters[i - 1])
+ j--;
+
+ /* In .._extents_range(...,start,end,...), to my surprise start is
+ * inclusive but end is exclusive !!
+ */
+ pango_glyph_string_extents_range (glyphs, j + 1, i, font,
+ NULL, &logical_rect_cluster);
+
+ /* logical_rect_cluster.width is all the offset we need so that the
+ * inherent x_offset in the glyph (ink_rect.x) should be canceled out.
+ */
+ glyphs->glyphs[i].geometry.x_offset = - logical_rect_cluster.width
+ - ink_rect.x ;
+
+
+ /* make an additional room for a tone mark if it has a spacing glyph
+ * because that's likely to be an indication that glyphs for other
+ * characters in the font are not designed for combining with tone marks.
+ */
+ if (logical_rect.width)
+ {
+ glyphs->glyphs[i].geometry.x_offset -= ink_rect.width;
+ glyphs->glyphs[j + 1].geometry.width += ink_rect.width;
+ glyphs->glyphs[j + 1].geometry.x_offset += ink_rect.width;
+ }
+ }
+
+ glyphs->glyphs[i].geometry.width = 0;
+}
+
+
+#define find_char(font,wc) \
+ pango_fc_font_get_glyph((PangoFcFont *)font, wc)
+
+static void
+render_tone (PangoFont *font, gunichar tone, PangoGlyphString *glyphs,
+ int *n_glyphs, int cluster_offset)
+{
+ int index;
+
+ index = find_char (font, tone);
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ if (index)
+ {
+ set_glyph_tone (font, glyphs, *n_glyphs, cluster_offset, index);
+ }
+ else
+ {
+ /* fall back : HTONE1(0x302e) => middle-dot, HTONE2(0x302f) => colon */
+ index = find_char (font, tone == HTONE1 ? 0x00b7 : 0x003a);
+ if (index)
+ {
+ set_glyph_tone (font, glyphs, *n_glyphs, cluster_offset, index);
+ }
+ else
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+ PANGO_GET_UNKNOWN_GLYPH (tone));
+ }
+ (*n_glyphs)++;
+}
+
+/* This is a fallback for when we get a tone mark not preceded
+ * by a syllable.
+ */
+static void
+render_isolated_tone (PangoFont *font, gunichar tone, PangoGlyphString *glyphs,
+ int *n_glyphs, int cluster_offset)
+{
+#if 0 /* FIXME: what kind of hack is it? it draws dummy glyphs. */
+ /* Find a base character to render the mark on
+ */
+ int index = find_char (font, 0x25cc); /* DOTTED CIRCLE */
+ if (!index)
+ index = find_char (font, 0x25cb); /* WHITE CIRCLE, in KSC-5601 */
+ if (!index)
+ index = find_char (font, ' '); /* Space */
+ if (!index) /* Unknown glyph box with 0000 in it */
+ index = find_char (font, PANGO_GET_UNKNOWN_GLYPH (0));
+
+ /* Add the base character
+ */
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ (*n_glyphs)++;
+#endif
+
+ /* And the tone mark
+ */
+ render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+}
+
+static void
+render_syllable (PangoFont *font, const char *str, int length,
+ PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
+{
+ int n_prev_glyphs = *n_glyphs;
+ int index;
+ gunichar wc = 0, tone = 0, text[4];
+ int i, j, composed = 0;
+ const char *p;
+
+ /* Normalize it only when the entire sequence is equivalent to a
+ * precomposed syllable. It's usually better than prefix
+ * normalization both for poor-featured fonts and for smart fonts.
+ * I have seen no smart font which can render S+T as a syllable
+ * form.
+ */
+
+ if (length == 3 || length == 4)
+ {
+ p = str;
+ text[0] = g_utf8_get_char(p);
+ p = g_utf8_next_char(p);
+ text[1] = g_utf8_get_char(p);
+ p = g_utf8_next_char(p);
+ text[2] = g_utf8_get_char(p);
+
+ if (length == 4 && !IS_M(g_utf8_get_char(g_utf8_next_char(p))))
+ goto lvt_out; /* draw the tone mark later */
+
+ if (IS_L_S(text[0]) && IS_V_S(text[1]) && IS_T_S(text[2]))
+ {
+ composed = 3;
+ wc = S_FROM_LVT(text[0], text[1], text[2]);
+ str = g_utf8_next_char(p);
+ goto normalize_out;
+ }
+ }
+ lvt_out:
+
+ if (length == 2 || length == 3)
+ {
+ p = str;
+ text[0] = g_utf8_get_char(p);
+ p = g_utf8_next_char(p);
+ text[1] = g_utf8_get_char(p);
+
+ if (length == 3 && !IS_M(g_utf8_get_char(g_utf8_next_char(p))))
+ goto lv_out; /* draw the tone mark later */
+ if (IS_L_S(text[0]) && IS_V_S(text[1]))
+ {
+ composed = 2;
+ wc = S_FROM_LV(text[0], text[1]);
+ str = g_utf8_next_char(p);
+ }
+ else if (IS_S(text[0] && !S_HAS_T(text[0]) && IS_T_S(text[1])))
+ {
+ composed = 2;
+ wc = text[0] + (text[1] - TBASE);
+ str = g_utf8_next_char(p);
+ goto normalize_out;
+ }
+ }
+ lv_out:
+ normalize_out:
+
+ if (composed)
+ {
+ index = find_char (font, wc);
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ if (!index)
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+ PANGO_GET_UNKNOWN_GLYPH (wc));
+ else
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ (*n_glyphs)++;
+ length -= composed;
+ }
+
+ /* Render the remaining text as uncomposed forms as a fallback. */
+ for (i = 0; i < length; i++, str = g_utf8_next_char(str))
+ {
+ int jindex;
+ int oldlen;
+
+ wc = g_utf8_get_char(str);
+
+ if (wc == LFILL || wc == VFILL)
+ continue;
+
+ if (IS_M(wc))
+ {
+ tone = wc;
+ break;
+ }
+
+ if (IS_S(wc))
+ {
+ oldlen = *n_glyphs;
+
+ text[0] = L_FROM_S(wc);
+ text[1] = V_FROM_S(wc);
+ if (S_HAS_T(wc))
+ {
+ text[2] = T_FROM_S(wc);
+ composed = 3;
+ }
+ else
+ composed = 2;
+
+ for (j = 0; j < composed; j++)
+ {
+ index = find_char (font, text[j]);
+ if (index)
+ {
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ (*n_glyphs)++;
+ }
+ else
+ goto decompose_cancel;
+ }
+
+ continue;
+
+ decompose_cancel:
+ /* The font doesn't have jamos. Cancel it. */
+ *n_glyphs = oldlen;
+ pango_glyph_string_set_size (glyphs, *n_glyphs);
+ }
+
+ index = find_char (font, wc);
+ if (index)
+ {
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ (*n_glyphs)++;
+ continue;
+ }
+ else if (IS_S(wc))
+ {
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+ PANGO_GET_UNKNOWN_GLYPH (wc));
+ (*n_glyphs)++;
+ continue;
+ }
+
+ /* This font has no glyphs on the Hangul Jamo area! Find a
+ fallback from the Hangul Compatibility Jamo area. */
+ jindex = wc - LBASE;
+ oldlen = *n_glyphs;
+ for (j = 0; j < 3 && (__jamo_to_ksc5601[jindex][j] != 0); j++)
+ {
+ wc = __jamo_to_ksc5601[jindex][j] - KSC_JAMOBASE + UNI_JAMOBASE;
+ index = (wc >= 0x3131) ? find_char (font, wc) : 0;
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ if (!index)
+ {
+ *n_glyphs = oldlen;
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+ PANGO_GET_UNKNOWN_GLYPH (text[i]));
+ (*n_glyphs)++;
+ break;
+ }
+ else
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ (*n_glyphs)++;
+ }
+ }
+ if (n_prev_glyphs == *n_glyphs)
+ {
+ index = find_char (font, 0x3164); /* U+3164 HANGUL FILLER */
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ if (!index)
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+ PANGO_GET_UNKNOWN_GLYPH (index));
+ else
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ glyphs->log_clusters[*n_glyphs] = cluster_offset;
+ (*n_glyphs)++;
+ }
+ if (tone)
+ render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+}
+
+static void
+render_basic (PangoFont *font, gunichar wc,
+ PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
+{
+ int index;
+
+ if (wc == 0xa0) /* non-break-space */
+ wc = 0x20;
+
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+
+ if (pango_is_zero_width (wc))
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, PANGO_GLYPH_EMPTY);
+ else
+ {
+ index = find_char (font, wc);
+ if (index)
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ else
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, PANGO_GET_UNKNOWN_GLYPH (wc));
+ }
+ (*n_glyphs)++;
+}
+
+static void
+hangul_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ int n_chars = g_utf8_strlen (text, length);
+ int n_glyphs;
+ int i;
+ const char *p, *start;
+
+ int n_jamos;
+ gunichar prev = 0;
+
+ n_glyphs = 0;
+ start = p = text;
+ n_jamos = 0;
+
+ for (i = 0; i < n_chars; i++)
+ {
+ gunichar wc;
+
+ wc = g_utf8_get_char (p);
+
+ /* Check syllable boundaries. */
+ if (n_jamos && IS_BOUNDARY (prev, wc))
+ {
+ if (n_jamos == 1 && IS_S (prev))
+ /* common case which the most people use */
+ render_basic (font, prev, glyphs, &n_glyphs, start - text);
+ else
+ /* possibly complex composition */
+ render_syllable (font, start, n_jamos, glyphs,
+ &n_glyphs, start - text);
+ n_jamos = 0;
+ start = p;
+ }
+
+ prev = wc;
+
+ if (!IS_HANGUL (wc))
+ {
+ render_basic (font, wc, glyphs, &n_glyphs, start - text);
+ start = g_utf8_next_char (p);
+ }
+ else if (IS_M (wc) && !n_jamos)
+ {
+ /* Tone mark not following syllable */
+ render_isolated_tone (font, wc, glyphs, &n_glyphs, start - text);
+ start = g_utf8_next_char (p);
+ }
+ else
+ n_jamos++;
+ p = g_utf8_next_char (p);
+ }
+
+ if (n_jamos == 1 && IS_S (prev))
+ render_basic (font, prev, glyphs, &n_glyphs, start - text);
+ else if (n_jamos > 0)
+ render_syllable (font, start, n_jamos, glyphs, &n_glyphs,
+ start - text);
+}
+
+static void
+hangul_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = hangul_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (HangulEngineFc, hangul_engine_fc,
+ hangul_engine_fc_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ hangul_engine_fc_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (hangul_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/hangul/tables-jamos.i b/trunk/modules/hangul/tables-jamos.i
new file mode 100644
index 00000000..e5ea5942
--- /dev/null
+++ b/trunk/modules/hangul/tables-jamos.i
@@ -0,0 +1,401 @@
+/* -*-c-*- */
+
+#define KSC_JAMOBASE 0x2420
+#define UNI_JAMOBASE 0x3130
+
+#define KSC_KIYEOK 0x2421
+#define KSC_SSANGKIYEOK 0x2422
+#define KSC_KIYEOK_SIOS 0x2423
+#define KSC_NIEUN 0x2424
+#define KSC_NIEUN_CIEUC 0x2425
+#define KSC_NIEUN_HIEUH 0x2426
+#define KSC_TIKEUT 0x2427
+#define KSC_SSANGTIKEUT 0x2428
+#define KSC_RIEUL 0x2429
+#define KSC_RIEUL_KIYEOK 0x242a
+#define KSC_RIEUL_MIEUM 0x242b
+#define KSC_RIEUL_PIEUP 0x242c
+#define KSC_RIEUL_SIOS 0x242d
+#define KSC_RIEUL_THIEUTH 0x242e
+#define KSC_RIEUL_PHIEUPH 0x242f
+#define KSC_RIEUL_HIEUH 0x2430
+#define KSC_MIEUM 0x2431
+#define KSC_PIEUP 0x2432
+#define KSC_SSANGPIEUP 0x2433
+#define KSC_PIEUP_SIOS 0x2434
+#define KSC_SIOS 0x2435
+#define KSC_SSANGSIOS 0x2436
+#define KSC_IEUNG 0x2437
+#define KSC_CIEUC 0x2438
+#define KSC_SSANGCIEUC 0x2439
+#define KSC_CHIEUCH 0x243a
+#define KSC_KHIEUKH 0x243b
+#define KSC_THIEUTH 0x243c
+#define KSC_PHIEUPH 0x243d
+#define KSC_HIEUH 0x243e
+
+#define KSC_A 0x243f
+#define KSC_AE 0x2440
+#define KSC_YA 0x2441
+#define KSC_YAE 0x2442
+#define KSC_EO 0x2443
+#define KSC_E 0x2444
+#define KSC_YEO 0x2445
+#define KSC_YE 0x2446
+#define KSC_O 0x2447
+#define KSC_WA 0x2448
+#define KSC_WAE 0x2449
+#define KSC_OE 0x244a
+#define KSC_YO 0x244b
+#define KSC_U 0x244c
+#define KSC_WEO 0x244d
+#define KSC_WE 0x244e
+#define KSC_WI 0x244f
+#define KSC_YU 0x2450
+#define KSC_EU 0x2451
+#define KSC_YI 0x2452
+#define KSC_I 0x2453
+
+#define KSC_SSANGNIEUN 0x2455
+#define KSC_NIEUN_TIKEUT 0x2456
+#define KSC_NIEUN_SIOS 0x2457
+#define KSC_NIEUN_PANSIOS 0x2458
+#define KSC_RIEUL_KIYEOK_SIOS 0x2459
+#define KSC_RIEUL_TIKEUT 0x245a
+#define KSC_RIEUL_PIEUP_SIOS 0x245b
+#define KSC_RIEUL_PANSIOS 0x245c
+#define KSC_RIEUL_YEORINHIEUH 0x245d
+#define KSC_MIEUM_PIEUP 0x245e
+#define KSC_MIEUM_SIOS 0x245f
+#define KSC_MIEUM_PANSIOS 0x2460
+#define KSC_KAPYEOUNMIEUM 0x2461
+#define KSC_PIEUP_KIYEOK 0x2462
+#define KSC_PIEUP_TIKEUT 0x2463
+#define KSC_PIEUP_SIOS_KIYEOK 0x2464
+#define KSC_PIEUP_SIOS_TIKEUT 0x2465
+#define KSC_PIEUP_CIEUC 0x2466
+#define KSC_PIEUP_THIEUTH 0x2467
+#define KSC_KAPYEOUNPIEUP 0x2468
+#define KSC_KAPYEOUNSSANGPIEUP 0x2469
+#define KSC_SIOS_KIYEOK 0x246a
+#define KSC_SIOS_NIEUN 0x246b
+#define KSC_SIOS_TIKEUT 0x246c
+#define KSC_SIOS_PIEUP 0x246d
+#define KSC_SIOS_CIEUC 0x246e
+#define KSC_PANSIOS 0x246f
+#define KSC_SSANGIEUNG 0x2470
+#define KSC_YESIEUNG 0x2471
+#define KSC_IEUNG_CIEUC 0x2472
+#define KSC_IEUNG_PANSIOS 0x2473
+#define KSC_KAPYEOUNPHIEUPH 0x2474
+#define KSC_SSANGHIEUH 0x2475
+#define KSC_YEORINHIEUH 0x2476
+#define KSC_YO_YA 0x2477
+#define KSC_YO_YAE 0x2478
+#define KSC_YO_I 0x2479
+#define KSC_YU_YEO 0x247a
+#define KSC_YU_YE 0x247b
+#define KSC_YU_I 0x247c
+#define KSC_ARAEA 0x247d
+#define KSC_ARAEA_I 0x247e
+
+/*
+ * Some jamos are not representable with KSC5601. These are ugly
+ * fallbacks:
+ *
+ * CHITUEUMSIOS: 0x233c (less than)
+ * CEONGCHITUEUMSIOS: 0x233e (greater than)
+ * CHITUEUMCIEUC 0x237b (left bracket)
+ * CEONGEUMCIEUC 0x237d (right bracket)
+ * CHITUEUMCHIEUCH 0x237b (left brace)
+ * CEONGEUMCHIEUCH 0x237d (right brace)
+ */
+#define KSC_CHITUEUMSIOS 0x233c
+#define KSC_CEONGCHITUEUMSIOS 0x233e
+#define KSC_CHITUEUMCIEUC 0x235b
+#define KSC_CEONGEUMCIEUC 0x235d
+#define KSC_CHITUEUMCHIEUCH 0x237b
+#define KSC_CEONGEUMCHIEUCH 0x237d
+
+static const guint16 __jamo_to_ksc5601[0x100][3] =
+{
+ /*
+ * CHOSEONG
+ */
+ /* CHOSEONG 0x1100 -- 0x1112 : matched to each ksc5601 Jamos extactly. */
+ {KSC_KIYEOK, 0, 0},
+ {KSC_SSANGKIYEOK, 0, 0},
+ {KSC_NIEUN, 0, 0},
+ {KSC_TIKEUT, 0, 0},
+ {KSC_SSANGTIKEUT, 0, 0},
+ {KSC_RIEUL, 0, 0},
+ {KSC_MIEUM, 0, 0},
+ {KSC_PIEUP, 0, 0},
+ {KSC_SSANGPIEUP, 0, 0},
+ {KSC_SIOS, 0, 0},
+ {KSC_SSANGSIOS, 0, 0},
+ {KSC_IEUNG, 0, 0},
+ {KSC_CIEUC, 0, 0},
+ {KSC_SSANGCIEUC, 0, 0},
+ {KSC_CHIEUCH, 0, 0},
+ {KSC_KHIEUKH, 0, 0},
+ {KSC_THIEUTH, 0, 0},
+ {KSC_PHIEUPH, 0, 0},
+ {KSC_HIEUH, 0, 0},
+ /* Some of the following are representable as a glyph, the others not. */
+ {KSC_NIEUN, KSC_KIYEOK, 0},
+ {KSC_SSANGNIEUN, 0, 0},
+ {KSC_NIEUN_TIKEUT, 0, 0},
+ {KSC_NIEUN, KSC_PIEUP, 0},
+ {KSC_TIKEUT, KSC_KIYEOK, 0},
+ {KSC_RIEUL, KSC_NIEUN, 0},
+ {KSC_RIEUL, KSC_RIEUL, 0},
+ {KSC_RIEUL_HIEUH, 0, 0},
+ {KSC_RIEUL, KSC_IEUNG, 0},
+ {KSC_MIEUM_PIEUP, 0, 0},
+ {KSC_KAPYEOUNMIEUM, 0, 0},
+ {KSC_PIEUP_KIYEOK, 0, 0},
+ {KSC_PIEUP, KSC_NIEUN, 0},
+ {KSC_PIEUP_TIKEUT, 0, 0},
+ {KSC_PIEUP_SIOS, 0, 0},
+ {KSC_PIEUP_SIOS_KIYEOK, 0, 0},
+ {KSC_PIEUP_SIOS_TIKEUT, 0, 0},
+ {KSC_PIEUP, KSC_SIOS, KSC_PIEUP},
+ {KSC_PIEUP, KSC_SIOS, KSC_SIOS},
+ {KSC_PIEUP, KSC_SIOS, KSC_CIEUC},
+ {KSC_PIEUP_CIEUC, 0, 0},
+ {KSC_PIEUP, KSC_CHIEUCH, 0},
+ {KSC_PIEUP_THIEUTH, 0, 0},
+ {KSC_PIEUP, KSC_PHIEUPH, 0},
+ {KSC_KAPYEOUNPIEUP, 0, 0},
+ {KSC_KAPYEOUNSSANGPIEUP, 0, 0},
+ {KSC_SIOS_KIYEOK, 0, 0},
+ {KSC_SIOS_NIEUN, 0, 0},
+ {KSC_SIOS_TIKEUT, 0, 0},
+ {KSC_SIOS, KSC_RIEUL, 0},
+ {KSC_SIOS, KSC_MIEUM, 0},
+ {KSC_SIOS_PIEUP, 0, 0},
+ {KSC_SIOS, KSC_PIEUP, KSC_KIYEOK},
+ {KSC_SIOS, KSC_SIOS, KSC_SIOS},
+ {KSC_SIOS, KSC_IEUNG, 0},
+ {KSC_SIOS_CIEUC, 0, 0},
+ {KSC_SIOS, KSC_CHIEUCH, 0},
+ {KSC_SIOS, KSC_KHIEUKH, 0},
+ {KSC_SIOS, KSC_THIEUTH, 0},
+ {KSC_SIOS, KSC_PHIEUPH, 0},
+ {KSC_SIOS, KSC_HIEUH, 0},
+ {KSC_CHITUEUMSIOS, 0, 0},
+ {KSC_CHITUEUMSIOS, KSC_CHITUEUMSIOS, 0},
+ {KSC_CEONGCHITUEUMSIOS, 0, 0},
+ {KSC_CEONGCHITUEUMSIOS, KSC_CEONGCHITUEUMSIOS, 0},
+ {KSC_PANSIOS, 0, 0},
+ {KSC_IEUNG, KSC_KIYEOK, 0},
+ {KSC_IEUNG, KSC_TIKEUT, 0},
+ {KSC_IEUNG, KSC_MIEUM, 0},
+ {KSC_IEUNG, KSC_PIEUP, 0},
+ {KSC_IEUNG, KSC_SIOS, 0},
+ {KSC_IEUNG_PANSIOS, 0, 0},
+ {KSC_SSANGIEUNG, 0, 0},
+ {KSC_IEUNG_CIEUC, 0, 0},
+ {KSC_IEUNG, KSC_CHIEUCH, 0},
+ {KSC_IEUNG, KSC_THIEUTH, 0},
+ {KSC_IEUNG, KSC_PHIEUPH, 0},
+ {KSC_YESIEUNG, 0, 0},
+ {KSC_CIEUC, KSC_IEUNG, 0},
+ {KSC_CHITUEUMCIEUC, 0, 0},
+ {KSC_CHITUEUMCIEUC, KSC_CHITUEUMCIEUC, 0},
+ {KSC_CEONGEUMCIEUC, 0, 0},
+ {KSC_CEONGEUMCIEUC, KSC_CEONGEUMCIEUC, 0},
+ {KSC_CHIEUCH, KSC_KHIEUKH, 0},
+ {KSC_CHIEUCH, KSC_HIEUH, 0},
+ {KSC_CHITUEUMCHIEUCH, 0, 0},
+ {KSC_CEONGEUMCHIEUCH, 0, 0},
+ {KSC_PHIEUPH, KSC_PIEUP, 0},
+ {KSC_KAPYEOUNPHIEUPH, 0, 0},
+ {KSC_SSANGHIEUH, 0, 0},
+ {KSC_YEORINHIEUH, 0, 0},
+ /* 0x115A ~ 0x115E -- reserved */
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ /* CHOSEONG FILLER */
+ {0, 0, 0},
+
+ /*
+ * JUNGSEONG
+ */
+ /*
+ * JUNGSEONG
+ */
+ {0, 0, 0}, /* JUNGSEONG FILL */
+ /* JUNGSEONG 0x1161 -- 0x1175 : matched to each ksc5601 Jamos extactly. */
+ {KSC_A, 0, 0},
+ {KSC_AE, 0, 0},
+ {KSC_YA, 0, 0},
+ {KSC_YAE, 0, 0},
+ {KSC_EO, 0, 0},
+ {KSC_E, 0, 0},
+ {KSC_YEO, 0, 0},
+ {KSC_YE, 0, 0},
+ {KSC_O, 0, 0},
+ {KSC_WA, 0, 0},
+ {KSC_WAE, 0, 0},
+ {KSC_OE, 0, 0},
+ {KSC_YO, 0, 0},
+ {KSC_U, 0, 0},
+ {KSC_WEO, 0, 0},
+ {KSC_WE, 0, 0},
+ {KSC_WI, 0, 0},
+ {KSC_YU, 0, 0},
+ {KSC_EU, 0, 0},
+ {KSC_YI, 0, 0},
+ {KSC_I, 0, 0},
+ /* Some of the following are representable as a glyph, the others not. */
+ {KSC_A, KSC_O, 0},
+ {KSC_A, KSC_U, 0},
+ {KSC_YA, KSC_O, 0},
+ {KSC_YA, KSC_YO, 0},
+ {KSC_EO, KSC_O, 0},
+ {KSC_EO, KSC_U, 0},
+ {KSC_EO, KSC_EU, 0},
+ {KSC_YEO, KSC_O, 0},
+ {KSC_YEO, KSC_U, 0},
+ {KSC_O, KSC_EO, 0},
+ {KSC_O, KSC_E, 0},
+ {KSC_O, KSC_YE, 0},
+ {KSC_O, KSC_O, 0},
+ {KSC_O, KSC_U, 0},
+ {KSC_YO_YA, 0, 0},
+ {KSC_YO_YAE, 0, 0},
+ {KSC_YO, KSC_YEO, 0},
+ {KSC_YO, KSC_O, 0},
+ {KSC_YO_I, 0, 0},
+ {KSC_U, KSC_A, 0},
+ {KSC_U, KSC_AE, 0},
+ {KSC_U, KSC_EO, KSC_EU},
+ {KSC_U, KSC_YE, 0},
+ {KSC_U, KSC_U, 0},
+ {KSC_YU, KSC_A, 0},
+ {KSC_YU, KSC_EO, 0},
+ {KSC_YU, KSC_E, 0},
+ {KSC_YU_YEO, 0, 0},
+ {KSC_YU_YE, 0, 0},
+ {KSC_YU, KSC_U, 0},
+ {KSC_YU_I, 0, 0},
+ {KSC_EU, KSC_U, 0},
+ {KSC_EU, KSC_EU, 0},
+ {KSC_YI, KSC_U, 0},
+ {KSC_I, KSC_A, 0},
+ {KSC_I, KSC_YA, 0},
+ {KSC_I, KSC_O, 0},
+ {KSC_I, KSC_U, 0},
+ {KSC_I, KSC_EU, 0},
+ {KSC_I, KSC_ARAEA, 0},
+ {KSC_ARAEA, 0, 0},
+ {KSC_ARAEA, KSC_EO, 0},
+ {KSC_ARAEA, KSC_U, 0},
+ {KSC_ARAEA, KSC_I, 0},
+ {KSC_ARAEA, KSC_ARAEA, 0},
+ /* 0x11A3 ~ 0x11A7 -- reserved */
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}, /* (INTERNAL) JONGSEONG FILL */
+
+ /*
+ * JONGSEONG
+ */
+ {KSC_KIYEOK, 0, 0},
+ {KSC_SSANGKIYEOK, 0, 0},
+ {KSC_KIYEOK_SIOS, 0, 0},
+ {KSC_NIEUN, 0, 0},
+ {KSC_NIEUN_CIEUC, 0, 0},
+ {KSC_NIEUN_HIEUH, 0, 0},
+ {KSC_TIKEUT, 0, 0},
+ {KSC_RIEUL, 0, 0},
+ {KSC_RIEUL_KIYEOK, 0, 0},
+ {KSC_RIEUL_MIEUM, 0, 0},
+ {KSC_RIEUL_PIEUP, 0, 0},
+ {KSC_RIEUL_SIOS, 0, 0},
+ {KSC_RIEUL_TIKEUT, 0, 0},
+ {KSC_RIEUL_PHIEUPH, 0, 0},
+ {KSC_RIEUL_HIEUH, 0, 0},
+ {KSC_MIEUM, 0, 0},
+ {KSC_PIEUP, 0, 0},
+ {KSC_PIEUP_SIOS, 0, 0},
+ {KSC_SIOS, 0, 0},
+ {KSC_SSANGSIOS, 0, 0},
+ {KSC_IEUNG, 0, 0},
+ {KSC_CIEUC, 0, 0},
+ {KSC_CHIEUCH, 0, 0},
+ {KSC_KHIEUKH, 0, 0},
+ {KSC_THIEUTH, 0, 0},
+ {KSC_PHIEUPH, 0, 0},
+ {KSC_HIEUH, 0, 0},
+ {KSC_KIYEOK, KSC_RIEUL, 0},
+ {KSC_KIYEOK, KSC_SIOS, KSC_KIYEOK},
+ {KSC_NIEUN, KSC_KIYEOK, 0},
+ {KSC_NIEUN_TIKEUT, 0, 0},
+ {KSC_NIEUN_SIOS, 0, 0},
+ {KSC_NIEUN_PANSIOS, 0, 0},
+ {KSC_NIEUN, KSC_THIEUTH, 0},
+ {KSC_TIKEUT, KSC_KIYEOK, 0},
+ {KSC_TIKEUT, KSC_RIEUL, 0},
+ {KSC_RIEUL_KIYEOK_SIOS, 0, 0},
+ {KSC_RIEUL, KSC_NIEUN, 0},
+ {KSC_RIEUL_TIKEUT, 0, 0},
+ {KSC_RIEUL, KSC_TIKEUT, KSC_HIEUH},
+ {KSC_RIEUL, KSC_RIEUL, 0},
+ {KSC_RIEUL, KSC_MIEUM, KSC_KIYEOK},
+ {KSC_RIEUL, KSC_MIEUM, KSC_SIOS},
+ {KSC_RIEUL_PIEUP_SIOS, 0, 0},
+ {KSC_RIEUL, KSC_PHIEUPH, KSC_HIEUH},
+ {KSC_RIEUL, KSC_KAPYEOUNPIEUP, 0},
+ {KSC_RIEUL, KSC_SIOS, KSC_SIOS},
+ {KSC_RIEUL_PANSIOS, 0, 0},
+ {KSC_RIEUL, KSC_KHIEUKH, 0},
+ {KSC_RIEUL_YEORINHIEUH, 0, 0},
+ {KSC_MIEUM, KSC_KIYEOK, 0},
+ {KSC_MIEUM, KSC_RIEUL, 0},
+ {KSC_MIEUM_PIEUP, 0, 0},
+ {KSC_MIEUM_SIOS, 0, 0},
+ {KSC_MIEUM, KSC_SIOS, KSC_SIOS},
+ {KSC_MIEUM_PANSIOS, 0, 0},
+ {KSC_MIEUM, KSC_CHIEUCH, 0},
+ {KSC_MIEUM, KSC_HIEUH, 0},
+ {KSC_KAPYEOUNMIEUM, 0, 0},
+ {KSC_PIEUP, KSC_RIEUL, 0},
+ {KSC_PIEUP, KSC_PHIEUPH, 0},
+ {KSC_PIEUP, KSC_HIEUH, 0},
+ {KSC_KAPYEOUNPIEUP, 0, 0},
+ {KSC_SIOS_KIYEOK, 0, 0},
+ {KSC_SIOS_TIKEUT, 0, 0},
+ {KSC_SIOS, KSC_RIEUL, 0},
+ {KSC_SIOS_PIEUP, 0, 0},
+ {KSC_PANSIOS, 0, 0},
+ {KSC_IEUNG, KSC_KIYEOK, 0},
+ {KSC_IEUNG, KSC_KIYEOK, KSC_KIYEOK},
+ {KSC_SSANGIEUNG, 0, 0},
+ {KSC_IEUNG, KSC_KHIEUKH, 0},
+ {KSC_YESIEUNG, 0, 0},
+ {KSC_YESIEUNG, KSC_SIOS, 0},
+ {KSC_YESIEUNG, KSC_PANSIOS, 0},
+ {KSC_PHIEUPH, KSC_PIEUP, 0},
+ {KSC_KAPYEOUNPHIEUPH, 0, 0},
+ {KSC_HIEUH, KSC_NIEUN, 0},
+ {KSC_HIEUH, KSC_RIEUL, 0},
+ {KSC_HIEUH, KSC_MIEUM, 0},
+ {KSC_HIEUH, KSC_PIEUP, 0},
+ {KSC_YEORINHIEUH, 0, 0},
+ /* reserved */
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}
+};
+
diff --git a/trunk/modules/hebrew/Makefile.am b/trunk/modules/hebrew/Makefile.am
new file mode 100644
index 00000000..e7a7b76b
--- /dev/null
+++ b/trunk/modules/hebrew/Makefile.am
@@ -0,0 +1,22 @@
+include $(top_srcdir)/modules/Module.mk
+
+common_sources = hebrew-shaper.c hebrew-shaper.h
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_HEBREW_FC
+noinst_LTLIBRARIES += libpango-hebrew-fc.la
+else
+if DYNAMIC_HEBREW_FC
+module_LTLIBRARIES += pango-hebrew-fc.la
+endif
+endif
+endif
+
+hebrew_fc_sources = $(common_sources) hebrew-fc.c
+
+pango_hebrew_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_hebrew_fc_la_LIBADD = $(pangoft2libs)
+pango_hebrew_fc_la_SOURCES = $(hebrew_fc_sources)
+libpango_hebrew_fc_la_SOURCES = $(hebrew_fc_sources)
+libpango_hebrew_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_hebrew_fc
diff --git a/trunk/modules/hebrew/hebrew-fc.c b/trunk/modules/hebrew/hebrew-fc.c
new file mode 100644
index 00000000..6ab83816
--- /dev/null
+++ b/trunk/modules/hebrew/hebrew-fc.c
@@ -0,0 +1,358 @@
+/* Pango
+ * hebrew-fc.h: Hebrew shaper for FreeType-based backends
+ *
+ * Copyright (C) 2000, 2007 Red Hat Software
+ * Authors:
+ * Owen Taylor <otaylor@redhat.com>
+ * Dov Grobgeld <dov.grobgeld@weizmann.ac.il>
+ * Behdad Esfahbod <behdad@behdad.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <pango/pango-ot.h>
+#include "pango-engine.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+#include "hebrew-shaper.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape HebrewEngineFc;
+typedef PangoEngineShapeClass HebrewEngineFcClass ;
+
+#define MAX_CLUSTER_CHRS 20
+
+static PangoEngineScriptInfo hebrew_scripts[] = {
+ { PANGO_SCRIPT_HEBREW, "*" }
+};
+
+#define SCRIPT_ENGINE_NAME "HebrewScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ hebrew_scripts, G_N_ELEMENTS(hebrew_scripts)
+ }
+};
+
+static void
+get_cluster_glyphs(PangoFont *font,
+ gunichar cluster[],
+ gint cluster_size,
+ gboolean do_mirror,
+ /* output */
+ gint glyph_num[],
+ PangoGlyph glyph[],
+ gint widths[],
+ PangoRectangle ink_rects[])
+{
+ int i;
+ for (i=0; i<cluster_size; i++)
+ {
+ PangoRectangle logical_rect;
+ gunichar wc = cluster[i];
+ gunichar mirrored_ch;
+
+ if (do_mirror)
+ if (pango_get_mirror_char (wc, &mirrored_ch))
+ wc = mirrored_ch;
+
+ if (pango_is_zero_width (wc))
+ glyph_num[i] = PANGO_GLYPH_EMPTY;
+ else
+ {
+ glyph_num[i] = pango_fc_font_get_glyph ((PangoFcFont *)font, wc);
+
+ if (!glyph_num[i])
+ glyph_num[i] = PANGO_GET_UNKNOWN_GLYPH ( wc);
+ }
+
+ glyph[i] = glyph_num[i];
+
+ pango_font_get_glyph_extents (font,
+ glyph[i], &ink_rects[i], &logical_rect);
+
+ /* Assign the base char width to the last character in the cluster */
+ if (i==0)
+ {
+ widths[i] = 0;
+ widths[cluster_size-1] = logical_rect.width;
+ }
+ else if (i < cluster_size-1)
+ widths[i] = 0;
+ }
+}
+
+static void
+add_glyph (PangoGlyphString *glyphs,
+ gint cluster_start,
+ PangoGlyph glyph,
+ gboolean is_combining,
+ gint width,
+ gint x_offset,
+ gint y_offset
+ )
+{
+ gint index = glyphs->num_glyphs;
+
+ pango_glyph_string_set_size (glyphs, index + 1);
+
+ glyphs->glyphs[index].glyph = glyph;
+ glyphs->glyphs[index].attr.is_cluster_start = is_combining ? 0 : 1;
+
+ glyphs->log_clusters[index] = cluster_start;
+
+ glyphs->glyphs[index].geometry.x_offset = x_offset;
+ glyphs->glyphs[index].geometry.y_offset = y_offset;
+ glyphs->glyphs[index].geometry.width = width;
+}
+
+static void
+add_cluster(PangoFont *font,
+ PangoGlyphString *glyphs,
+ int cluster_size,
+ int cluster_start,
+ int glyph_num[],
+ PangoGlyph glyph[],
+ int width[],
+ int x_offset[],
+ int y_offset[])
+{
+ int i;
+
+ for (i=0; i<cluster_size; i++)
+ {
+ add_glyph (glyphs, cluster_start, glyph[i],
+ i == 0 ? FALSE : TRUE, width[i], x_offset[i], y_offset[i]);
+ }
+}
+
+static void
+fallback_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ const char *p;
+ const char *log_cluster;
+ gunichar cluster[MAX_CLUSTER_CHRS];
+ gint cluster_size;
+ gint glyph_num[MAX_CLUSTER_CHRS];
+ gint glyph_width[MAX_CLUSTER_CHRS], x_offset[MAX_CLUSTER_CHRS], y_offset[MAX_CLUSTER_CHRS];
+ PangoRectangle ink_rects[MAX_CLUSTER_CHRS];
+ PangoGlyph glyph[MAX_CLUSTER_CHRS];
+
+ pango_glyph_string_set_size (glyphs, 0);
+
+ p = text;
+ while (p < text + length)
+ {
+ log_cluster = p;
+ p = hebrew_shaper_get_next_cluster (p, text + length - p,
+ /* output */
+ cluster, &cluster_size);
+ get_cluster_glyphs(font,
+ cluster,
+ cluster_size,
+ analysis->level % 2,
+ /* output */
+ glyph_num,
+ glyph,
+ glyph_width,
+ ink_rects);
+
+ /* Kern the glyphs! */
+ hebrew_shaper_get_cluster_kerning(cluster,
+ cluster_size,
+ /* Input and output */
+ ink_rects,
+ glyph_width,
+ /* output */
+ x_offset,
+ y_offset);
+
+ add_cluster(font,
+ glyphs,
+ cluster_size,
+ log_cluster - text,
+ glyph_num,
+ glyph,
+ glyph_width,
+ x_offset,
+ y_offset);
+
+ }
+
+ if (analysis->level % 2)
+ hebrew_shaper_bidi_reorder(glyphs);
+}
+
+static const PangoOTFeatureMap gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"rlig", PANGO_OT_ALL_GLYPHS},
+ /* 'dlig' should be turned-on/off-able. lets turn off for now. */
+ /* {"dlig", PANGO_OT_ALL_GLYPHS}, */
+};
+
+static const PangoOTFeatureMap gpos_features[] =
+{
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
+
+static void
+hebrew_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ PangoFcFont *fc_font;
+ FT_Face face;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ guint n_gpos_features = 0;
+ glong n_chars;
+ const char *p;
+ int cluster = 0;
+ int i;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return;
+
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
+ desc.static_gsub_features = gsub_features;
+ desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
+ desc.static_gpos_features = gpos_features;
+
+ /* TODO populate other_features from analysis->extra_attrs */
+ desc.n_other_features = 0;
+ desc.other_features = NULL;
+
+ ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
+
+ pango_ot_ruleset_get_feature_count (ruleset, NULL, &n_gpos_features);
+ if (n_gpos_features == 0)
+ {
+ fallback_shape (engine, font, text, length, analysis, glyphs);
+ goto out;
+ }
+
+ buffer = pango_ot_buffer_new (fc_font);
+ pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
+
+ n_chars = g_utf8_strlen (text, length);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ gunichar wc;
+ PangoGlyph glyph;
+
+ wc = g_utf8_get_char (p);
+
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
+
+ if (pango_is_zero_width (wc))
+ glyph = PANGO_GLYPH_EMPTY;
+ else
+ {
+ gunichar c = wc;
+
+ if (analysis->level % 2)
+ g_unichar_get_mirror_char (c, &c);
+
+ glyph = pango_fc_font_get_glyph (fc_font, c);
+ }
+
+ if (!glyph)
+ glyph = PANGO_GET_UNKNOWN_GLYPH (wc);
+
+ pango_ot_buffer_add_glyph (buffer, glyph, 0, cluster);
+
+ p = g_utf8_next_char (p);
+ }
+
+ pango_ot_ruleset_substitute (ruleset, buffer);
+ pango_ot_ruleset_position (ruleset, buffer);
+ pango_ot_buffer_output (buffer, glyphs);
+
+ pango_ot_buffer_destroy (buffer);
+
+ out:
+ pango_fc_font_unlock_face (fc_font);
+}
+
+static void
+hebrew_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = hebrew_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (HebrewEngineFc, hebrew_engine_fc,
+ hebrew_engine_fc_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ hebrew_engine_fc_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (hebrew_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/hebrew/hebrew-shaper.c b/trunk/modules/hebrew/hebrew-shaper.c
new file mode 100644
index 00000000..72566758
--- /dev/null
+++ b/trunk/modules/hebrew/hebrew-shaper.c
@@ -0,0 +1,477 @@
+/* Pango
+ * hebrew-shaper.c:
+ *
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
+ *
+ * Hebrew points positioning improvements 2001
+ * Author: Dov Grobgeld <dov@imagic.weizmann.ac.il>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Note March 9, 2003: I fixed a crash with regards to precomposed
+ * characters, by wraping all of them to be considered as ALEF as
+ * far as consideration about composability is concerned. The rendering
+ * with regards to precomposed characters AND nikud comes out really
+ * bad though, and should be fixed, once I have more time.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include "pango-engine.h"
+#include "hebrew-shaper.h"
+
+/* Wrap all characters above 0xF00 to ALEF. */
+#define ishebrew(wc) ((wc)>0x590 && (wc)<0x600)
+#define ucs2iso8859_8(wc) ((unsigned int)((unsigned int)(wc) - 0x0590 + 0x10))
+#define iso8859_8_2uni(c) ((gunichar)(c) - 0x10 + 0x0590)
+
+#define MAX_CLUSTER_CHRS 256
+
+/* Define Hebrew character classes */
+#define _ND 0
+#define _SP 1
+#define _NS (1<<1)
+#define _DA (1<<2) /* only for dagesh... */
+
+#define NoDefine _ND
+#define SpacingLetter _SP
+#define NonSpacingPunc _NS
+
+/* Define Hebrew character types */
+#define __ND 0
+#define __SP 1
+#define __NS 2
+#define __DA 3
+
+/* Unicode definitions needed in logics below... */
+#define UNI_ALEF 0x05D0
+#define UNI_BET 0x05D1
+#define UNI_GIMMEL 0x05d2
+#define UNI_DALED 0x05D3
+#define UNI_KAF 0x05DB
+#define UNI_FINAL_KAF 0x05DA
+#define UNI_VAV 0x05D5
+#define UNI_YOD 0x05D9
+#define UNI_RESH 0x05E8
+#define UNI_LAMED 0x05DC
+#define UNI_SHIN 0x05E9
+#define UNI_FINAL_PE 0x05E3
+#define UNI_PE 0x05E4
+#define UNI_QOF 0x05E7
+#define UNI_TAV 0x05EA
+#define UNI_SHIN_DOT 0x05C1
+#define UNI_SIN_DOT 0x05C2
+#define UNI_MAPIQ 0x05BC
+#define UNI_SHEVA 0x05B0
+#define UNI_HOLAM 0x05B9
+#define UNI_QUBUTS 0x05BB
+#define UNI_HATAF_SEGOL 0x05B1
+#define UNI_HATAF_QAMATZ 0x05B3
+#define UNI_TSERE 0x05B5
+#define UNI_QAMATS 0x05B8
+#define UNI_QUBUTS 0x05BB
+
+/*======================================================================
+// In the tables below all Hebrew characters are categorized to
+// one of the following four classes:
+//
+// non used entries Not defined (ND)
+// accents, points Non spacing (NS)
+// punctuation and characters Spacing characters (SP)
+// dagesh "Dagesh" (DA)
+//----------------------------------------------------------------------*/
+static const gint char_class_table[128] = {
+ /* 0, 1, 2, 3, 4, 5, 6, 7 */
+
+ /*00*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+
+ /*10*/ _ND, _NS, _NS, _NS, _NS, _NS, _NS, _NS,
+ _NS, _NS, _NS, _NS, _NS, _NS, _NS, _NS,
+ /*20*/ _NS, _NS, _ND, _NS, _NS, _NS, _NS, _NS,
+ _NS, _NS, _NS, _NS, _NS, _NS, _NS, _NS,
+ /*30*/ _NS, _NS, _NS, _NS, _NS, _NS, _NS, _NS,
+ _NS, _NS, _ND, _NS, _DA, _NS, _SP, _NS,
+ /*40*/ _SP, _NS, _NS, _SP, _NS, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ /*50*/ _SP, _SP, _SP, _SP, _SP, _SP, _SP, _SP,
+ _SP, _SP, _SP, _SP, _SP, _SP, _SP, _SP,
+ /*60*/ _SP, _SP, _SP, _SP, _SP, _SP, _SP, _SP,
+ _SP, _SP, _SP, _ND, _ND, _ND, _ND, _ND,
+ /*70*/ _SP, _SP, _SP, _SP, _SP, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+};
+
+static const gint char_type_table[128] = {
+ /* 0, 1, 2, 3, 4, 5, 6, 7 */
+
+ /*00*/ __ND, __ND, __ND, __ND, __ND, __ND, __ND, __ND,
+ __ND, __ND, __ND, __ND, __ND, __ND, __ND, __ND,
+
+ /*10*/ __ND, __NS, __NS, __NS, __NS, __NS, __NS, __NS,
+ __NS, __NS, __NS, __NS, __NS, __NS, __NS, __NS,
+ /*20*/ __NS, __NS, __ND, __NS, __NS, __NS, __NS, __NS,
+ __NS, __NS, __NS, __NS, __NS, __NS, __NS, __NS,
+ /*30*/ __NS, __NS, __NS, __NS, __NS, __NS, __NS, __NS,
+ __NS, __NS, __ND, __NS, __DA, __NS, __SP, __NS,
+ /*40*/ __SP, __NS, __NS, __SP, __NS, __ND, __ND, __ND,
+ __ND, __ND, __ND, __ND, __ND, __ND, __ND, __ND,
+ /*50*/ __SP, __SP, __SP, __SP, __SP, __SP, __SP, __SP,
+ __SP, __SP, __SP, __SP, __SP, __SP, __SP, __SP,
+ /*60*/ __SP, __SP, __SP, __SP, __SP, __SP, __SP, __SP,
+ __SP, __SP, __SP, __ND, __ND, __ND, __ND, __ND,
+ /*70*/ __SP, __SP, __SP, __SP, __SP, __ND, __ND, __ND,
+ __ND, __ND, __ND, __ND, __ND, __ND, __ND, __ND,
+};
+
+/*======================================================================
+// The following table answers the question whether two characters
+// are composible or not. The decision is made by looking at the
+// char_type_table values for the first character in a cluster
+// vs a following charactrer. The only three combinations that
+// are composible in Hebrew according to the table are:
+//
+// 1. a spacing character followed by non-spacing character
+// 2. a spacing character followed by a dagesh.
+// 3. a dagesh followed by a non-spacing character.
+//
+// Note that a spacing character may be followed by several non-spacing
+// accents, as the decision is always made on the base character of
+// a combination.
+//----------------------------------------------------------------------*/
+static const gboolean compose_table[4][4] = {
+ /* Cn */ /* 0, 1, 2, 3, */
+/* Cn-1 00 */ { FALSE, FALSE, FALSE, FALSE },
+ /* 10 */ { FALSE, FALSE, TRUE, TRUE },
+ /* 20 */ { FALSE, FALSE, FALSE, FALSE },
+ /* 30 */ { FALSE, FALSE, TRUE, FALSE },
+};
+
+/* Treat all characters above 0xF000 as characters */
+#define is_hebrew(wc) ((wc) >= 0x590 && (wc) < 0x600)
+#define is_char_class(wc, mask) (char_class_table[ucs2iso8859_8 ((wc))] & (mask))
+#define is_composible(cur_wc, nxt_wc) (compose_table[char_type_table[ucs2iso8859_8 (cur_wc)]]\
+ [char_type_table[ucs2iso8859_8 (nxt_wc)]])
+
+G_CONST_RETURN char *
+hebrew_shaper_get_next_cluster(const char *text,
+ gint length,
+ gunichar *cluster,
+ gint *num_chrs)
+{
+ const char *p;
+ gint n_chars = 0;
+
+ p = text;
+
+ while (p < text + length && n_chars < MAX_CLUSTER_CHRS)
+ {
+ gunichar current = g_utf8_get_char (p);
+
+ if (!ishebrew (current) ||
+ (n_chars == 0 && is_char_class(current, ~(NoDefine|SpacingLetter))))
+ {
+ /* Not a legal Hebrew cluster */
+
+ if (n_chars == 0)
+ {
+ cluster[n_chars++] = current;
+ p = g_utf8_next_char (p);
+ }
+ break;
+ }
+ else if (n_chars == 0 ||
+ is_composible (cluster[0], current))
+ {
+ cluster[n_chars++] = current;
+ p = g_utf8_next_char (p);
+ }
+ else
+ break;
+ }
+
+ *num_chrs = n_chars;
+ return p;
+}
+
+void
+hebrew_shaper_get_cluster_kerning(gunichar *cluster,
+ gint cluster_length,
+ PangoRectangle ink_rect[],
+
+ /* input and output */
+ gint width[],
+ gint x_offset[],
+ gint y_offset[])
+{
+ int i;
+ int base_ink_x_offset, base_ink_y_offset, base_ink_width, base_ink_height;
+ gunichar base_char = cluster[0];
+
+ x_offset[0] = 0;
+ y_offset[0] = 0;
+
+ if (cluster_length == 1)
+ {
+ /* Make lone 'vav dot' have zero width */
+ if (base_char == UNI_SHIN_DOT
+ || base_char == UNI_SIN_DOT
+ || base_char == UNI_HOLAM
+ ) {
+ x_offset[0] = -ink_rect[0].x - ink_rect[0].width;
+ width[0] = 0;
+ }
+
+ return;
+ }
+
+ base_ink_x_offset = ink_rect[0].x;
+ base_ink_y_offset = ink_rect[0].y;
+ base_ink_width = ink_rect[0].width;
+ base_ink_height = ink_rect[0].height;
+
+ /* Do heuristics */
+ for (i=1; i<cluster_length; i++)
+ {
+ int gl = cluster[i];
+ x_offset[i] = 0;
+ y_offset[i] = 0;
+
+ /* Check if it is a point */
+ if (gl < 0x5B0 || gl >= 0x05D0)
+ continue;
+
+ /* Center dot of VAV */
+ if (gl == UNI_MAPIQ && base_char == UNI_VAV)
+ {
+ x_offset[i] = base_ink_x_offset - ink_rect[i].x;
+
+ /* If VAV is a vertical bar without a roof, then we
+ need to make room for the dot by increasing the
+ cluster width. But how can I check if that is the
+ case??
+ */
+ /* This is wild, but it does the job of differentiating
+ between two M$ fonts... Base the decision on the
+ aspect ratio of the vav...
+ */
+ if (base_ink_height > base_ink_width * 3.5)
+ {
+ int j;
+ double space = 0.7;
+ double kern = 0.5;
+
+ /* Shift all characters to make place for the mapiq */
+ for (j=0; j<i; j++)
+ x_offset[j] += ink_rect[i].width*(1+space-kern);
+
+ width[cluster_length-1] += ink_rect[i].width*(1+space-kern);
+ x_offset[i] -= ink_rect[i].width*(kern);
+ }
+ }
+
+ /* Dot over SHIN */
+ else if (gl == UNI_SHIN_DOT && base_char == UNI_SHIN)
+ {
+ x_offset[i] = base_ink_x_offset + base_ink_width
+ - ink_rect[i].x - ink_rect[i].width;
+ }
+
+ /* Dot over SIN */
+ else if (gl == UNI_SIN_DOT && base_char == UNI_SHIN)
+ {
+ x_offset[i] = base_ink_x_offset - ink_rect[i].x;
+ }
+
+ /* VOWEL DOT above to any other character than
+ SHIN or VAV should stick out a bit to the left. */
+ else if ((gl == UNI_SIN_DOT || gl == UNI_HOLAM)
+ && base_char != UNI_SHIN && base_char != UNI_VAV)
+ {
+ x_offset[i] = base_ink_x_offset -ink_rect[i].x - ink_rect[i].width * 3/ 2;
+ }
+
+ /* VOWELS under resh or vav are right aligned, if they are
+ narrower than the characters. Otherwise they are centered.
+ */
+ else if ((base_char == UNI_VAV
+ || base_char == UNI_RESH
+ || base_char == UNI_YOD
+ || base_char == UNI_DALED
+ )
+ && ((gl >= UNI_SHEVA && gl <= UNI_QAMATS) ||
+ gl == UNI_QUBUTS)
+ && ink_rect[i].width < base_ink_width
+ )
+ {
+ x_offset[i] = base_ink_x_offset + base_ink_width
+ - ink_rect[i].x - ink_rect[i].width;
+ }
+
+ /* VOWELS under FINAL KAF are offset centered and offset in
+ y */
+ else if ((base_char == UNI_FINAL_KAF
+ )
+ && ((gl >= UNI_SHEVA && gl <= UNI_QAMATS) ||
+ gl == UNI_QUBUTS))
+ {
+ /* x are at 1/3 to take into accoun the stem */
+ x_offset[i] = base_ink_x_offset - ink_rect[i].x
+ + base_ink_width * 1/3 - ink_rect[i].width/2;
+
+ /* Center in y */
+ y_offset[i] = base_ink_y_offset - ink_rect[i].y
+ + base_ink_height * 1/2 - ink_rect[i].height/2;
+ }
+
+
+ /* MAPIQ in PE or FINAL PE */
+ else if (gl == UNI_MAPIQ
+ && (base_char == UNI_PE || base_char == UNI_FINAL_PE))
+ {
+ x_offset[i]= base_ink_x_offset - ink_rect[i].x
+ + base_ink_width * 2/3 - ink_rect[i].width/2;
+
+ /* Another option is to offset the MAPIQ in y...
+ glyphs->glyphs[cluster_start_idx+i].geometry.y_offset
+ -= base_ink_height/5; */
+ }
+
+ /* MAPIQ in SHIN should be moved a bit to the right */
+ else if (gl == UNI_MAPIQ
+ && base_char == UNI_SHIN)
+ {
+ x_offset[i]= base_ink_x_offset - ink_rect[i].x
+ + base_ink_width * 3/5 - ink_rect[i].width/2;
+ }
+
+ /* MAPIQ in YUD is right aligned */
+ else if (gl == UNI_MAPIQ
+ && base_char == UNI_YOD)
+ {
+ x_offset[i]= base_ink_x_offset - ink_rect[i].x;
+
+ /* Lower left in y */
+ y_offset[i] = base_ink_y_offset - ink_rect[i].y
+ + base_ink_height - ink_rect[i].height*1.75;
+
+ if (base_ink_height > base_ink_width * 2)
+ {
+ int j;
+ double space = 0.7;
+ double kern = 0.5;
+
+ /* Shift all cluster characters to make space for mapiq */
+ for (j=0; j<i; j++)
+ x_offset[j] += ink_rect[i].width*(1+space-kern);
+
+ width[cluster_length-1] += ink_rect[i].width*(1+space-kern);
+ }
+
+ }
+
+ /* VOWEL DOT next to any other character */
+ else if ((gl == UNI_SIN_DOT || gl == UNI_HOLAM)
+ && (base_char != UNI_VAV))
+ {
+ x_offset[i] = base_ink_x_offset -ink_rect[i].x;
+ }
+
+ /* Move nikud of taf a bit ... */
+ else if (base_char == UNI_TAV && gl == UNI_MAPIQ)
+ {
+ x_offset[i] = base_ink_x_offset - ink_rect[i].x
+ + base_ink_width * 5/8 - ink_rect[i].width/2;
+ }
+
+ /* Move center dot of characters with a right stem and no
+ left stem. */
+ else if (gl == UNI_MAPIQ &&
+ (base_char == UNI_BET
+ || base_char == UNI_DALED
+ || base_char == UNI_KAF
+ || base_char == UNI_GIMMEL
+ ))
+ {
+ x_offset[i] = base_ink_x_offset - ink_rect[i].x
+ + base_ink_width * 3/8 - ink_rect[i].width/2;
+ }
+
+ /* Right align wide nikud under QOF */
+ else if (base_char == UNI_QOF &&
+ ( (gl >= UNI_HATAF_SEGOL
+ && gl <= UNI_HATAF_QAMATZ)
+ || (gl >= UNI_TSERE
+ && gl<= UNI_QAMATS)
+ || (gl == UNI_QUBUTS)))
+ {
+ x_offset[i] = base_ink_x_offset + base_ink_width
+ - ink_rect[i].x - ink_rect[i].width;
+ }
+
+ /* Center by default */
+ else
+ {
+ x_offset[i] = base_ink_x_offset - ink_rect[i].x
+ + base_ink_width/2 - ink_rect[i].width/2;
+ }
+ }
+
+}
+
+void
+hebrew_shaper_swap_range (PangoGlyphString *glyphs,
+ int start,
+ int end)
+{
+ int i, j;
+
+ for (i = start, j = end - 1; i < j; i++, j--)
+ {
+ PangoGlyphInfo glyph_info;
+ gint log_cluster;
+
+ glyph_info = glyphs->glyphs[i];
+ glyphs->glyphs[i] = glyphs->glyphs[j];
+ glyphs->glyphs[j] = glyph_info;
+
+ log_cluster = glyphs->log_clusters[i];
+ glyphs->log_clusters[i] = glyphs->log_clusters[j];
+ glyphs->log_clusters[j] = log_cluster;
+ }
+}
+
+void
+hebrew_shaper_bidi_reorder(PangoGlyphString *glyphs)
+{
+ int start, end;
+
+ /* Swap all glyphs */
+ hebrew_shaper_swap_range (glyphs, 0, glyphs->num_glyphs);
+
+ /* Now reorder glyphs within each cluster back to LTR */
+ for (start = 0; start < glyphs->num_glyphs;)
+ {
+ end = start;
+ while (end < glyphs->num_glyphs &&
+ glyphs->log_clusters[end] == glyphs->log_clusters[start])
+ end++;
+
+ hebrew_shaper_swap_range (glyphs, start, end);
+ start = end;
+ }
+}
diff --git a/trunk/modules/hebrew/hebrew-shaper.h b/trunk/modules/hebrew/hebrew-shaper.h
new file mode 100644
index 00000000..24603433
--- /dev/null
+++ b/trunk/modules/hebrew/hebrew-shaper.h
@@ -0,0 +1,50 @@
+/* Pango
+ * hebrew-shaper.h: Hebrew shaper internal functions
+ *
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef HEBREW_SHAPER_H
+#define HEBREW_SHAPER_H
+
+const char *
+hebrew_shaper_get_next_cluster(const char *text,
+ gint length,
+ gunichar *cluster,
+ gint *num_chrs);
+
+void
+hebrew_shaper_get_cluster_kerning(gunichar *cluster,
+ gint cluster_length,
+ PangoRectangle ink_rect[],
+
+ /* input and output */
+ gint width[],
+ gint x_offset[],
+ gint y_offset[]);
+
+void
+hebrew_shaper_swap_range (PangoGlyphString *glyphs,
+ int start,
+ int end);
+
+void
+hebrew_shaper_bidi_reorder(PangoGlyphString *glyphs);
+
+#endif
diff --git a/trunk/modules/indic/Makefile.am b/trunk/modules/indic/Makefile.am
new file mode 100644
index 00000000..76494e3c
--- /dev/null
+++ b/trunk/modules/indic/Makefile.am
@@ -0,0 +1,44 @@
+include $(top_srcdir)/modules/Module.mk
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_INDIC_FC
+noinst_LTLIBRARIES += libpango-indic-fc.la
+else
+if DYNAMIC_INDIC_FC
+module_LTLIBRARIES += pango-indic-fc.la
+endif
+endif
+endif
+
+fc_sources = \
+ indic-fc.c \
+ indic-ot-class-tables.c \
+ indic-ot.c \
+ indic-ot.h \
+ mprefixups.c \
+ mprefixups.h
+
+pango_indic_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_indic_fc_la_LIBADD = $(pangoft2libs)
+pango_indic_fc_la_SOURCES = $(fc_sources)
+libpango_indic_fc_la_SOURCES = $(fc_sources)
+libpango_indic_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_indic_fc
+
+
+if INCLUDE_INDIC_LANG
+noinst_LTLIBRARIES += libpango-indic-lang.la
+else
+if DYNAMIC_INDIC_LANG
+module_LTLIBRARIES += pango-indic-lang.la
+endif
+endif
+
+lang_sources = \
+ indic-lang.c
+
+pango_indic_lang_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_indic_lang_la_LIBADD = $(pangolibs)
+pango_indic_lang_la_SOURCES = $(lang_sources)
+libpango_indic_lang_la_SOURCES = $(lang_sources)
+libpango_indic_lang_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_indic_lang
diff --git a/trunk/modules/indic/indic-fc.c b/trunk/modules/indic/indic-fc.c
new file mode 100644
index 00000000..d73b94dc
--- /dev/null
+++ b/trunk/modules/indic/indic-fc.c
@@ -0,0 +1,347 @@
+/* Pango
+ * indic-xft.c:
+ *
+ * Copyright (C) 2001, 2002 IBM Corporation
+ * Author: Eric Mader <mader@jtcsv.com>
+ * Based on arabic-xft.c by Owen Taylor <otaylor@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "indic-ot.h"
+
+#include "pango-engine.h"
+#include "pango-ot.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+
+typedef struct _PangoIndicInfo PangoIndicInfo;
+
+typedef struct _IndicEngineFc IndicEngineFc;
+typedef PangoEngineShapeClass IndicEngineFcClass ; /* No extra fields needed */
+
+struct _IndicEngineFc
+{
+ PangoEngineShape shapeEngine;
+ const IndicOTClassTable *classTable;
+};
+
+#define ENGINE_SUFFIX "ScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+#define INDIC_ENGINE_INFO(script) {#script ENGINE_SUFFIX, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, script##_scripts, G_N_ELEMENTS(script##_scripts)}
+
+#define INDIC_OT_CLASS_TABLE(script) &script##_class_table
+
+static PangoEngineScriptInfo deva_scripts[] = {
+ { PANGO_SCRIPT_DEVANAGARI, "*" }
+};
+
+static PangoEngineScriptInfo beng_scripts[] = {
+ {PANGO_SCRIPT_BENGALI, "*" }
+};
+
+static PangoEngineScriptInfo guru_scripts[] = {
+ { PANGO_SCRIPT_GURMUKHI, "*" }
+};
+
+static PangoEngineScriptInfo gujr_scripts[] = {
+ { PANGO_SCRIPT_GUJARATI, "*" }
+};
+
+static PangoEngineScriptInfo orya_scripts[] = {
+ { PANGO_SCRIPT_ORIYA, "*" }
+};
+
+static PangoEngineScriptInfo taml_scripts[] = {
+ { PANGO_SCRIPT_TAMIL, "*" }
+};
+
+static PangoEngineScriptInfo telu_scripts[] = {
+ { PANGO_SCRIPT_TELUGU, "*" }
+};
+
+static PangoEngineScriptInfo knda_scripts[] = {
+ { PANGO_SCRIPT_KANNADA, "*" }
+};
+
+static PangoEngineScriptInfo mlym_scripts[] = {
+ { PANGO_SCRIPT_MALAYALAM, "*" }
+};
+
+static PangoEngineScriptInfo sinh_scripts[] = {
+ { PANGO_SCRIPT_SINHALA, "*" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ INDIC_ENGINE_INFO(deva), INDIC_ENGINE_INFO(beng), INDIC_ENGINE_INFO(guru),
+ INDIC_ENGINE_INFO(gujr), INDIC_ENGINE_INFO(orya), INDIC_ENGINE_INFO(taml),
+ INDIC_ENGINE_INFO(telu), INDIC_ENGINE_INFO(knda), INDIC_ENGINE_INFO(mlym),
+ INDIC_ENGINE_INFO(sinh)
+};
+
+/*
+ * WARNING: These entries need to be in the same order as the entries
+ * in script_engines[].
+ *
+ * FIXME: remove this requirement, either by encapsulating the order
+ * in a macro that calls a body macro that can be redefined, or by
+ * putting the pointers to the PangoEngineInfo in PangoIndicInfo...
+ */
+static const IndicOTClassTable *indic_ot_class_tables[] = {
+ INDIC_OT_CLASS_TABLE(deva), INDIC_OT_CLASS_TABLE(beng), INDIC_OT_CLASS_TABLE(guru),
+ INDIC_OT_CLASS_TABLE(gujr), INDIC_OT_CLASS_TABLE(orya), INDIC_OT_CLASS_TABLE(taml),
+ INDIC_OT_CLASS_TABLE(telu), INDIC_OT_CLASS_TABLE(knda), INDIC_OT_CLASS_TABLE(mlym),
+ INDIC_OT_CLASS_TABLE(sinh)
+};
+
+static const PangoOTFeatureMap gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"init", init},
+ {"nukt", nukt},
+ {"akhn", akhn},
+ {"rphf", rphf},
+ {"blwf", blwf},
+ {"half", half},
+ {"pstf", pstf},
+ {"vatu", vatu},
+ {"pres", pres},
+ {"blws", blws},
+ {"abvs", abvs},
+ {"psts", psts},
+ {"haln", haln},
+ {"calt", PANGO_OT_ALL_GLYPHS}
+};
+
+static const PangoOTFeatureMap gpos_features[] =
+{
+ {"blwm", blwm},
+ {"abvm", abvm},
+ {"dist", dist},
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
+
+static void
+set_glyphs (PangoFont *font,
+ const gunichar *wcs,
+ gulong *tags,
+ glong n_glyphs,
+ PangoOTBuffer *buffer,
+ gboolean process_zwj)
+{
+ gint i;
+ PangoFcFont *fc_font;
+
+ g_assert (font);
+
+ fc_font = PANGO_FC_FONT (font);
+
+ for (i = 0; i < n_glyphs; i++)
+ {
+ guint glyph;
+
+ if (pango_is_zero_width (wcs[i]) &&
+ (!process_zwj || wcs[i] != 0x200D))
+ glyph = PANGO_GLYPH_EMPTY;
+ else
+ {
+ glyph = pango_fc_font_get_glyph (fc_font, wcs[i]);
+
+ if (!glyph)
+ glyph = PANGO_GET_UNKNOWN_GLYPH ( wcs[i]);
+ }
+ pango_ot_buffer_add_glyph (buffer, glyph, tags[i], i);
+ }
+}
+
+/*
+ * FIXME: should this check for null pointers, etc.?
+ */
+static gunichar *
+expand_text(const gchar *text, glong length, glong **offsets, glong *n_chars)
+{
+ const gchar *p;
+ gunichar *wcs, *wco;
+ glong i, *oo;
+
+ *n_chars = g_utf8_strlen (text, length);
+ wcs = g_new (gunichar, *n_chars);
+ *offsets = g_new (glong, *n_chars + 1);
+
+ p = text;
+ wco = wcs;
+ oo = *offsets;
+ for (i = 0; i < *n_chars; i++)
+ {
+ *wco++ = g_utf8_get_char (p);
+ *oo++ = p - text;
+
+ p = g_utf8_next_char (p);
+ }
+
+ *oo = p - text;
+
+ return wcs;
+}
+
+
+/* analysis->shape_engine has the PangoEngine... */
+static void
+indic_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ PangoFcFont *fc_font;
+ FT_Face face;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ glong i, n_chars, n_glyphs;
+ gulong *tags = NULL;
+ gunichar *wc_in = NULL, *wc_out = NULL;
+ glong *utf8_offsets = NULL;
+ glong *indices = NULL;
+ IndicEngineFc *indic_shape_engine = NULL;
+ MPreFixups *mprefixups;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return;
+
+ indic_shape_engine = (IndicEngineFc *) engine;
+
+ wc_in = expand_text (text, length, &utf8_offsets, &n_chars);
+
+ n_glyphs = indic_ot_reorder (wc_in, utf8_offsets, n_chars, indic_shape_engine->classTable, NULL, NULL, NULL, NULL);
+
+ wc_out = g_new (gunichar, n_glyphs);
+ indices = g_new (glong, n_glyphs);
+ tags = g_new (gulong, n_glyphs);
+
+ n_glyphs = indic_ot_reorder (wc_in, utf8_offsets, n_chars, indic_shape_engine->classTable, wc_out, indices, tags, &mprefixups);
+
+ pango_glyph_string_set_size (glyphs, n_glyphs);
+ buffer = pango_ot_buffer_new (fc_font);
+
+ set_glyphs(font, wc_out, tags, n_glyphs, buffer,
+ (indic_shape_engine->classTable->scriptFlags & SF_PROCESS_ZWJ) != 0);
+
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
+ desc.static_gsub_features = gsub_features;
+ desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
+ desc.static_gpos_features = gpos_features;
+
+ /* TODO populate other_features from analysis->extra_attrs */
+ desc.n_other_features = 0;
+ desc.other_features = NULL;
+
+ ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
+
+ /* do gsub processing */
+ pango_ot_ruleset_substitute (ruleset, buffer);
+
+ /* Fix pre-modifiers for some scripts before base consonant */
+ if (mprefixups)
+ {
+ indic_mprefixups_apply (mprefixups, buffer);
+ indic_mprefixups_free (mprefixups);
+ }
+
+ /* do gpos processing */
+ pango_ot_ruleset_position (ruleset, buffer);
+
+ pango_ot_buffer_output (buffer, glyphs);
+
+ /* Get the right log_clusters values */
+ for (i = 0; i < glyphs->num_glyphs; i += 1)
+ glyphs->log_clusters[i] = indices[glyphs->log_clusters[i]];
+
+ pango_fc_font_unlock_face (fc_font);
+
+ pango_ot_buffer_destroy (buffer);
+ g_free (tags);
+ g_free (indices);
+ g_free (wc_out);
+ g_free (wc_in);
+ g_free (utf8_offsets);
+}
+
+static void
+indic_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = indic_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (IndicEngineFc, indic_engine_fc,
+ indic_engine_fc_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ indic_engine_fc_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS(script_engines); i += 1)
+ {
+ if (!strcmp(id, script_engines[i].id))
+ {
+ IndicEngineFc *engine = g_object_new (indic_engine_fc_type, NULL);
+ engine->classTable = indic_ot_class_tables[i];
+
+ return (PangoEngine *)engine;
+ }
+ }
+
+ return NULL;
+}
diff --git a/trunk/modules/indic/indic-lang.c b/trunk/modules/indic/indic-lang.c
new file mode 100644
index 00000000..132bedc8
--- /dev/null
+++ b/trunk/modules/indic/indic-lang.c
@@ -0,0 +1,253 @@
+/* Pango
+ * indic-lang.c:
+ *
+ * Copyright (C) 2006 Red Hat Software
+ * Author: Akira TAGOH <tagoh@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "pango-engine.h"
+#include "pango-break.h"
+
+typedef PangoEngineLang IndicEngineLang;
+typedef PangoEngineLangClass IndicEngineLangClass;
+
+#define ENGINE_SUFFIX "IndicScriptEngineLang"
+#define RENDER_TYPE PANGO_RENDER_TYPE_NONE
+#define INDIC_ENGINE_INFO(script) \
+ {#script ENGINE_SUFFIX, PANGO_ENGINE_TYPE_LANG, RENDER_TYPE, script##_scripts, G_N_ELEMENTS(script##_scripts)}
+
+
+static PangoEngineScriptInfo deva_scripts[] = {
+ { PANGO_SCRIPT_DEVANAGARI, "*" }
+};
+
+static PangoEngineScriptInfo beng_scripts[] = {
+ { PANGO_SCRIPT_BENGALI, "*" }
+};
+
+static PangoEngineScriptInfo guru_scripts[] = {
+ { PANGO_SCRIPT_GURMUKHI, "*" }
+};
+
+static PangoEngineScriptInfo gujr_scripts[] = {
+ { PANGO_SCRIPT_GUJARATI, "*" }
+};
+
+static PangoEngineScriptInfo orya_scripts[] = {
+ { PANGO_SCRIPT_ORIYA, "*" }
+};
+
+static PangoEngineScriptInfo taml_scripts[] = {
+ { PANGO_SCRIPT_TAMIL, "*" }
+};
+
+static PangoEngineScriptInfo telu_scripts[] = {
+ { PANGO_SCRIPT_TELUGU, "*" }
+};
+
+static PangoEngineScriptInfo knda_scripts[] = {
+ { PANGO_SCRIPT_KANNADA, "*" }
+};
+
+static PangoEngineScriptInfo mlym_scripts[] = {
+ { PANGO_SCRIPT_MALAYALAM, "*" }
+};
+
+static PangoEngineScriptInfo sinh_scripts[] = {
+ { PANGO_SCRIPT_SINHALA, "*" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ INDIC_ENGINE_INFO(deva), INDIC_ENGINE_INFO(beng), INDIC_ENGINE_INFO(guru),
+ INDIC_ENGINE_INFO(gujr), INDIC_ENGINE_INFO(orya), INDIC_ENGINE_INFO(taml),
+ INDIC_ENGINE_INFO(telu), INDIC_ENGINE_INFO(knda), INDIC_ENGINE_INFO(mlym),
+ INDIC_ENGINE_INFO(sinh)
+};
+
+
+static void
+indic_engine_break (PangoEngineLang *engine,
+ const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len)
+{
+ const gchar *p, *next = NULL, *next_next;
+ gunichar prev_wc, this_wc, next_wc, next_next_wc;
+ gboolean makes_rephaya_syllable = FALSE;
+ int i;
+
+ for (p = text, prev_wc = 0, i = 0;
+ p != NULL && p < (text + length);
+ p = next, prev_wc = this_wc, i++)
+ {
+ this_wc = g_utf8_get_char (p);
+ next = g_utf8_next_char (p);
+ if (next != NULL && next < (text + length))
+ {
+ next_wc = g_utf8_get_char (next);
+ next_next = g_utf8_next_char (next);
+ }
+ else
+ {
+ next_wc = 0;
+ next_next = NULL;
+ }
+ if (next_next != NULL && next_next < (text + length))
+ next_next_wc = g_utf8_get_char (next_next);
+ else
+ next_next_wc = 0;
+
+ if (prev_wc != 0 && this_wc == 0x0DBB &&
+ next_wc == 0x0DCA && next_next_wc == 0x200D)
+ {
+ /* Determine whether or not this forms a Rephaya syllable.
+ * SINHALA LETTER + U+0DBB U+0DCA U+200D + SINHALA LETTER is
+ * the kind of Rephaya.
+ */
+ makes_rephaya_syllable = TRUE;
+ attrs[i].is_cursor_position = FALSE;
+ attrs[i].is_char_break = FALSE;
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+ }
+ else if (prev_wc == 0x200D &&
+ (makes_rephaya_syllable || this_wc == 0x0DBB || this_wc == 0x0DBA))
+ {
+ /* fixes the cursor break in Sinhala.
+ * SINHALA LETTER + SINHALA VOWEL + ZWJ + 0x0DBB/0x0DBA is
+ * the kind of Rakaransaya/Yansaya. these characters has to
+ * be dealt as one character.
+ */
+ attrs[i].is_cursor_position = FALSE;
+ attrs[i].is_char_break = FALSE;
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+ makes_rephaya_syllable = FALSE;
+ }
+ else if (this_wc == 0x200D &&
+ ((makes_rephaya_syllable && next_wc != 0) ||
+ (next_wc == 0x0DBB || next_wc == 0x0DBA)))
+ {
+ attrs[i].is_cursor_position = FALSE;
+ attrs[i].is_char_break = FALSE;
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+ }
+ else if (prev_wc != 0 && (this_wc == 0x200D || this_wc == 0x200C))
+ {
+ if (next_wc != 0)
+ {
+ if (next_next_wc == 0)
+ {
+ attrs[i].is_cursor_position = FALSE;
+ attrs[i].is_char_break = FALSE;
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+
+ i++;
+
+ attrs[i].is_cursor_position = FALSE;
+ attrs[i].is_char_break = FALSE;
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+ }
+ else if ((next_next_wc != 0) &&
+ (next_wc == 0x09CD || /* Bengali */
+ next_wc == 0x0ACD || /* Gujarati */
+ next_wc == 0x094D || /* Hindi */
+ next_wc == 0x0CCD || /* Kannada */
+ next_wc == 0x0D4D || /* Malayalam */
+ next_wc == 0x0B4D || /* Oriya */
+ next_wc == 0x0A4D || /* Punjabi */
+ next_wc == 0x0BCD || /* Tamil */
+ next_wc == 0x0C4D || /* Telugu */
+ next_wc == 0x0DCA)) /*Sinhala*/
+ {
+ attrs[i].is_cursor_position = FALSE;
+ attrs[i].is_char_break = FALSE;
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+
+ i++;
+
+ attrs[i].is_cursor_position = FALSE;
+ attrs[i].is_char_break = FALSE;
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+
+ i++;
+ attrs[i].is_cursor_position = FALSE;
+ }
+ }
+ else
+ {
+ attrs[i].is_cursor_position = FALSE;
+ attrs[i].is_char_break = FALSE;
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+ }
+ }
+ }
+}
+
+static void
+indic_engine_lang_class_init (PangoEngineLangClass *klass)
+{
+ klass->script_break = indic_engine_break;
+}
+
+PANGO_ENGINE_LANG_DEFINE_TYPE (IndicEngineLang, indic_engine_lang,
+ indic_engine_lang_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ indic_engine_lang_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS(script_engines); i++)
+ {
+ if (!strcmp (id, script_engines[i].id))
+ return g_object_new (indic_engine_lang_type, NULL);
+ }
+
+ return NULL;
+}
diff --git a/trunk/modules/indic/indic-ot-class-tables.c b/trunk/modules/indic/indic-ot-class-tables.c
new file mode 100644
index 00000000..963dcfa5
--- /dev/null
+++ b/trunk/modules/indic/indic-ot-class-tables.c
@@ -0,0 +1,522 @@
+/* Pango
+ * indic-ot-class-tables.c:
+ *
+ * Copyright (C) 2001, 2002 IBM Corporation. All Rights Reserved.
+ * Author: Eric Mader <mader@jtcsv.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished
+ * to do so, provided that the above copyright notice(s) and this
+ * permission notice appear in all copies of the Software and that
+ * both the above copyright notice(s) and this permission notice
+ * appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR
+ * ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
+ * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written
+ * authorization of the copyright holder.
+ */
+
+#include <config.h>
+
+#include "indic-ot.h"
+
+
+/*
+ * Split matra table indices
+ */
+#define _x1 (1 << CF_INDEX_SHIFT)
+#define _x2 (2 << CF_INDEX_SHIFT)
+#define _x3 (3 << CF_INDEX_SHIFT)
+#define _x4 (4 << CF_INDEX_SHIFT)
+#define _x5 (5 << CF_INDEX_SHIFT)
+#define _x6 (6 << CF_INDEX_SHIFT)
+#define _x7 (7 << CF_INDEX_SHIFT)
+#define _x8 (8 << CF_INDEX_SHIFT)
+#define _x9 (9 << CF_INDEX_SHIFT)
+
+/*
+ * Simple classes
+ */
+#define _xx (CC_RESERVED)
+#define _ma (CC_MODIFYING_MARK_ABOVE)
+#define _mp (CC_MODIFYING_MARK_POST)
+#define _iv (CC_INDEPENDENT_VOWEL)
+#define _ct (CC_CONSONANT | CF_CONSONANT)
+#define _cn (CC_CONSONANT_WITH_NUKTA | CF_CONSONANT)
+#define _nu (CC_NUKTA)
+#define _dv (CC_DEPENDENT_VOWEL)
+#define _dl (_dv | CF_MATRA_PRE)
+#define _db (_dv | CF_MATRA_BELOW)
+#define _da (_dv | CF_MATRA_ABOVE)
+#define _dr (_dv | CF_MATRA_POST)
+#define _lm (_dv | CF_LENGTH_MARK)
+#define _vr (CC_VIRAMA)
+#define _al (CC_AL_LAKUNA)
+
+/*
+ * Split matras
+ */
+#define _s1 (_dv | _x1)
+#define _s2 (_dv | _x2)
+#define _s3 (_dv | _x3)
+#define _s4 (_dv | _x4)
+#define _s5 (_dv | _x5)
+#define _s6 (_dv | _x6)
+#define _s7 (_dv | _x7)
+#define _s8 (_dv | _x8)
+#define _s9 (_dv | _x9)
+
+/*
+ * consonants with special forms
+ * NOTE: this assumes that no consonants with nukta have
+ * special forms... (Bengali RA?)
+ */
+#define _bb (_ct | CF_BELOW_BASE)
+#define _pb (_ct | CF_POST_BASE)
+#define _vt (_bb | CF_VATTU)
+#define _rv (_vt | CF_REPH)
+#define _rp (_pb | CF_REPH)
+#define _rb (_bb | CF_REPH)
+
+
+/*
+ * Character class tables
+ */
+static const IndicOTCharClass devaCharClasses[] =
+{
+ _xx, _ma, _ma, _mp, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, /* 0900 - 090F */
+ _iv, _iv, _iv, _iv, _iv, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, /* 0910 - 091F */
+ _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _cn, _ct, _ct, _ct, _ct, _ct, _ct, /* 0920 - 092F */
+ _rv, _cn, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _xx, _xx, _nu, _xx, _dr, _dl, /* 0930 - 093F */
+ _dr, _db, _db, _db, _db, _da, _da, _da, _da, _dr, _dr, _dr, _dr, _vr, _xx, _xx, /* 0940 - 094F */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _cn, _cn, _cn, _cn, _cn, _cn, _cn, _cn, /* 0950 - 095F */
+ _iv, _iv, _db, _db, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0960 - 096F */
+ _xx /* 0970 */
+};
+
+/* As a hack, BENGALI LETTER A (U+0985) and BENGALI LETTER E (U+098F)
+ * are marked as consonants below; this gives approximately the
+ * right behavior for the sequences "a halant ya aa" and
+ * "e halant ya aa".
+ */
+static const IndicOTCharClass bengCharClasses[] =
+{
+ _xx, _ma, _mp, _mp, _xx, _ct, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _xx, _ct, /* 0980 - 098F */
+ _iv, _xx, _xx, _iv, _iv, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, /* 0990 - 099F */
+ _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _xx, _ct, _ct, _bb, _ct, _ct, _pb, /* 09A0 - 09AF */
+ _rv, _xx, _ct, _xx, _xx, _xx, _ct, _ct, _ct, _ct, _xx, _xx, _nu, _xx, _dr, _dl, /* 09B0 - 09BF */
+ _dr, _db, _db, _db, _db, _xx, _xx, _dl, _dl, _xx, _xx, _s1, _s2, _vr, _xx, _xx, /* 09C0 - 09CF */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _dr, _xx, _xx, _xx, _xx, _cn, _cn, _xx, _cn, /* 09D0 - 09DF */
+ _iv, _iv, _dv, _dv, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 09E0 - 09EF */
+ _rv, _ct, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx /* 09F0 - 09FA */
+};
+
+static const IndicOTCharClass guruCharClasses[] =
+{
+ _xx, _ma, _ma, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _xx, _xx, _xx, _iv, /* 0A00 - 0A0F */
+ _iv, _xx, _xx, _iv, _iv, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, /* 0A10 - 0A1F */
+ _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _xx, _ct, _ct, _ct, _ct, _ct, _bb, /* 0A20 - 0A2F */
+ _vt, _xx, _ct, _cn, _xx, _bb, _cn, _xx, _ct, _bb, _xx, _xx, _nu, _xx, _dr, _dl, /* 0A30 - 0A3F */
+ _dr, _db, _db, _xx, _xx, _xx, _xx, _da, _da, _xx, _xx, _da, _da, _vr, _xx, _xx, /* 0A40 - 0A4F */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _cn, _cn, _cn, _ct, _xx, _cn, _xx, /* 0A50 - 0A5F */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0A60 - 0A6F */
+ _ma, _ma, _ct, _ct, _xx /* 0A70 - 0A74 */
+};
+
+static const IndicOTCharClass gujrCharClasses[] =
+{
+ _xx, _ma, _ma, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _iv, _xx, _iv, /* 0A80 - 0A8F */
+ _iv, _iv, _xx, _iv, _iv, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, /* 0A90 - 0A9F */
+ _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _xx, _ct, _ct, _ct, _ct, _ct, _ct, /* 0AA0 - 0AAF */
+ _rv, _xx, _ct, _ct, _xx, _ct, _ct, _ct, _ct, _ct, _xx, _xx, _nu, _xx, _dr, _dl, /* 0AB0 - 0ABF */
+ _dr, _db, _db, _db, _db, _da, _xx, _da, _da, _dr, _xx, _dr, _dr, _vr, _xx, _xx, /* 0AC0 - 0ACF */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0AD0 - 0ADF */
+ _iv, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx /* 0AE0 - 0AEF */
+};
+
+static const IndicOTCharClass oryaCharClasses[] =
+{
+ _xx, _ma, _mp, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _xx, _iv, /* 0B00 - 0B0F */
+ _iv, _xx, _xx, _iv, _iv, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _ct, _bb, /* 0B10 - 0B1F */
+ _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _xx, _bb, _bb, _bb, _bb, _bb, _pb, /* 0B20 - 0B2F */
+ _rb, _xx, _bb, _bb, _xx, _bb, _bb, _bb, _bb, _bb, _xx, _xx, _nu, _xx, _dr, _da, /* 0B30 - 0B3F */
+ _dr, _db, _db, _db, _xx, _xx, _xx, _dl, _s1, _xx, _xx, _s2, _s3, _vr, _xx, _xx, /* 0B40 - 0B4F */
+ _xx, _xx, _xx, _xx, _xx, _xx, _da, _dr, _xx, _xx, _xx, _xx, _cn, _cn, _xx, _pb, /* 0B50 - 0B5F */
+ _iv, _iv, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0B60 - 0B6F */
+ _xx, _bb /* 0B70 - 0B71 */
+};
+
+static const IndicOTCharClass tamlCharClasses[] =
+{
+ _xx, _xx, _ma, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _xx, _xx, _iv, _iv, /* 0B80 - 0B8F */
+ _iv, _xx, _iv, _iv, _iv, _ct, _xx, _xx, _xx, _ct, _ct, _xx, _ct, _xx, _ct, _ct, /* 0B90 - 0B9F */
+ _xx, _xx, _xx, _ct, _ct, _xx, _xx, _xx, _ct, _ct, _ct, _xx, _xx, _xx, _ct, _ct, /* 0BA0 - 0BAF */
+ _ct, _ct, _ct, _ct, _ct, _ct, _xx, _ct, _ct, _ct, _xx, _xx, _xx, _xx, _dr, _dr, /* 0BB0 - 0BBF */
+ _da, _dr, _dr, _xx, _xx, _xx, _dl, _dl, _dl, _xx, _s1, _s2, _s3, _vr, _xx, _xx, /* 0BC0 - 0BCF */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _dr, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0BD0 - 0BDF */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0BE0 - 0BEF */
+ _xx, _xx, _xx /* 0BF0 - 0BF2 */
+};
+
+/* FIXME: Should some of the bb's be pb's? (KA, NA, MA, YA, VA, etc. (approx 13)) */
+static const IndicOTCharClass teluCharClasses[] =
+{
+ _xx, _mp, _mp, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _iv, _iv, /* 0C00 - 0C0F */
+ _iv, _xx, _iv, _iv, _iv, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, /* 0C10 - 0C1F */
+ _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _xx, _bb, _bb, _bb, _bb, _bb, _bb, /* 0C20 - 0C2F */
+ _bb, _bb, _bb, _bb, _xx, _bb, _bb, _bb, _bb, _bb, _xx, _xx, _xx, _xx, _da, _da, /* 0C30 - 0C3F */
+ _da, _dr, _dr, _dr, _dr, _xx, _da, _da, _s1, _xx, _da, _da, _da, _vr, _xx, _xx, /* 0C40 - 0C4F */
+ _xx, _xx, _xx, _xx, _xx, _da, _db, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0C50 - 0C5F */
+ _iv, _iv, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx /* 0C60 - 0C6F */
+};
+
+/* U+CC3 and U+CC4 are _lm here not _dr since the Kannada rendering
+ * rules want them below and to the right of the entire cluster. They
+ * aren't, strictly speaking, length marks, however.
+ *
+ * There's some information about this in:
+ *
+ * http://brahmi.sourceforge.net/docs/KannadaComputing.html
+ */
+static const IndicOTCharClass kndaCharClasses[] =
+{
+ _xx, _xx, _mp, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _iv, /* 0C80 - 0C8F */
+ _iv, _xx, _iv, _iv, _iv, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, /* 0C90 - 0C9F */
+ _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _xx, _bb, _bb, _bb, _bb, _bb, _bb, /* 0CA0 - 0CAF */
+ _rb, _ct, _bb, _bb, _xx, _bb, _bb, _bb, _bb, _bb, _xx, _xx, _xx, _xx, _dr, _da, /* 0CB0 - 0CBF */
+ _s1, _dr, _dr, _lm, _lm, _xx, _da, _s2, _s3, _xx, _s4, _s5, _da, _vr, _xx, _xx, /* 0CC0 - 0CCF */
+ _xx, _xx, _xx, _xx, _xx, _lm, _lm, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _ct, _xx, /* 0CD0 - 0CDF */
+ _iv, _iv, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx /* 0CE0 - 0CEF */
+};
+
+/*
+ * FIXME: this is correct for old-style Malayalam (MAL) but not for reformed Malayalam (MLR)
+ * FIXME: should there be a REPH for old-style Malayalam?
+ */
+static const IndicOTCharClass mlymCharClasses[] =
+{
+ _xx, _xx, _mp, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _iv, _iv, /* 0D00 - 0D0F */
+ _iv, _xx, _iv, _iv, _iv, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, /* 0D10 - 0D1F */
+ _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _xx, _ct, _ct, _ct, _ct, _ct, _pb, /* 0D20 - 0D2F */
+ _cn, _cn, _ct, _ct, _ct, _pb, _ct, _ct, _ct, _ct, _xx, _xx, _xx, _xx, _dr, _dr, /* 0D30 - 0D3F */
+ _dr, _dr, _dr, _dr, _xx, _xx, _dl, _dl, _dl, _xx, _s1, _s2, _s3, _vr, _xx, _xx, /* 0D40 - 0D4F */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _dr, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0D50 - 0D5F */
+ _iv, _iv, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx /* 0D60 - 0D6F */
+};
+
+static const IndicOTCharClass sinhCharClasses[] =
+{
+ _xx, _xx, _mp, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, /* 0D80 - 0D8F */
+ _iv, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _xx, _xx, _ct, _ct, _ct, _ct, _ct, _ct, /* 0D90 - 0D9F */
+ _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, /* 0DA0 - 0DAF */
+ _ct, _ct, _xx, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _ct, _xx, _ct, _xx, _xx, /* 0DB0 - 0DBF */
+ _ct, _ct, _ct, _ct, _ct, _ct, _ct, _xx, _xx, _xx, _al, _xx, _xx, _xx, _xx, _dr, /* 0DC0 - 0DCF */
+ _dr, _dr, _da, _da, _db, _xx, _db, _xx, _dr, _dl, _s1, _dl, _s2, _s3, _s4, _dr, /* 0DD0 - 0DDF */
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0DE0 - 0DEF */
+ _xx, _xx, _dr, _dr, _xx /* 0DF0 - 0DF4 */
+};
+
+
+/*
+ * Split matra tables
+ */
+static const IndicOTSplitMatra bengSplitTable[] = {{0x09C7, 0x09BE}, {0x09C7, 0x09D7}};
+
+static const IndicOTSplitMatra oryaSplitTable[] = {{0x0B47, 0x0B56}, {0x0B47, 0x0B3E}, {0x0B47, 0x0B57}};
+
+static const IndicOTSplitMatra tamlSplitTable[] = {{0x0BC6, 0x0BBE}, {0x0BC7, 0x0BBE}, {0x0BC6, 0x0BD7}};
+
+static const IndicOTSplitMatra teluSplitTable[] = {{0x0C46, 0x0C56}};
+
+static const IndicOTSplitMatra kndaSplitTable[] = {{0x0CBF, 0x0CD5}, {0x0CC6, 0x0CD5}, {0x0CC6, 0x0CD6}, {0x0CC6, 0x0CC2},
+ {0x0CC6, 0x0CC2, 0x0CD5}};
+
+static const IndicOTSplitMatra mlymSplitTable[] = {{0x0D46, 0x0D3E}, {0x0D47, 0x0D3E}, {0x0D46, 0x0D57}};
+
+static const IndicOTSplitMatra sinhSplitTable[] = {{0x0DD9, 0x0DCA}, {0x0DD9, 0x0DCF}, {0x0DD9, 0x0DCF, 0x0DCA},
+ {0x0DD9, 0x0DDF} };
+
+
+/*
+ * Script Flags
+ */
+
+/*
+ * FIXME: post 'GSUB' reordering of MATRA_PRE's for Malayalam and Tamil
+ * FIXME: reformed Malayalam needs to reorder VATTU to before base glyph...
+ * FIXME: eyelash RA only for Devanagari??
+ */
+#define DEVA_SCRIPT_FLAGS (SF_EYELASH_RA | SF_NO_POST_BASE_LIMIT)
+#define BENG_SCRIPT_FLAGS (SF_REPH_AFTER_BELOW | SF_NO_POST_BASE_LIMIT)
+#define GURU_SCRIPT_FLAGS (SF_NO_POST_BASE_LIMIT)
+#define GUJR_SCRIPT_FLAGS (SF_NO_POST_BASE_LIMIT)
+#define ORYA_SCRIPT_FLAGS (SF_REPH_AFTER_BELOW | SF_NO_POST_BASE_LIMIT)
+#define TAML_SCRIPT_FLAGS (SF_MPRE_FIXUP | SF_NO_POST_BASE_LIMIT)
+#define TELU_SCRIPT_FLAGS (SF_MATRAS_AFTER_BASE | 3)
+#define KNDA_SCRIPT_FLAGS (SF_MATRAS_AFTER_BASE | 3)
+#define MLYM_SCRIPT_FLAGS (SF_MPRE_FIXUP | SF_NO_POST_BASE_LIMIT )
+#define SINH_SCRIPT_FLAGS (SF_MPRE_FIXUP | SF_NO_POST_BASE_LIMIT | SF_PROCESS_ZWJ)
+
+/*
+ * Indic Class Tables
+ */
+/* Add a little macro to compute lastChar based on size of the charClasses * table */
+#define INDIC_OT_CLASS_TABLE_DEFINE(name, firstChar, worstCaseExpansion, scriptFlags, charClasses, splitMatraTable) \
+ const IndicOTClassTable name = {firstChar, firstChar + G_N_ELEMENTS (charClasses) - 1, \
+ worstCaseExpansion, scriptFlags, charClasses, splitMatraTable}
+INDIC_OT_CLASS_TABLE_DEFINE (deva_class_table, 0x0900, 2, DEVA_SCRIPT_FLAGS, devaCharClasses, NULL);
+INDIC_OT_CLASS_TABLE_DEFINE (beng_class_table, 0x0980, 3, BENG_SCRIPT_FLAGS, bengCharClasses, bengSplitTable);
+INDIC_OT_CLASS_TABLE_DEFINE (guru_class_table, 0x0A00, 2, GURU_SCRIPT_FLAGS, guruCharClasses, NULL);
+INDIC_OT_CLASS_TABLE_DEFINE (gujr_class_table, 0x0A80, 2, GUJR_SCRIPT_FLAGS, gujrCharClasses, NULL);
+INDIC_OT_CLASS_TABLE_DEFINE (orya_class_table, 0x0B00, 3, ORYA_SCRIPT_FLAGS, oryaCharClasses, oryaSplitTable);
+INDIC_OT_CLASS_TABLE_DEFINE (taml_class_table, 0x0B80, 3, TAML_SCRIPT_FLAGS, tamlCharClasses, tamlSplitTable);
+INDIC_OT_CLASS_TABLE_DEFINE (telu_class_table, 0x0C00, 3, TELU_SCRIPT_FLAGS, teluCharClasses, teluSplitTable);
+INDIC_OT_CLASS_TABLE_DEFINE (knda_class_table, 0x0C80, 4, KNDA_SCRIPT_FLAGS, kndaCharClasses, kndaSplitTable);
+INDIC_OT_CLASS_TABLE_DEFINE (mlym_class_table, 0x0D00, 3, MLYM_SCRIPT_FLAGS, mlymCharClasses, mlymSplitTable);
+INDIC_OT_CLASS_TABLE_DEFINE (sinh_class_table, 0x0D80, 4, SINH_SCRIPT_FLAGS, sinhCharClasses, sinhSplitTable);
+
+const IndicOTSplitMatra *indic_ot_get_split_matra(const IndicOTClassTable *class_table, IndicOTCharClass char_class)
+{
+ gint32 index = (char_class & CF_INDEX_MASK) >> CF_INDEX_SHIFT;
+
+ return &class_table->splitMatraTable[index - 1];
+}
+
+gboolean indic_ot_is_vm_above(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_VM_ABOVE(char_class);
+}
+
+gboolean indic_ot_is_vm_post(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_VM_POST(char_class);
+}
+
+gboolean indic_ot_is_consonant(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_CONSONANT(char_class);
+}
+
+gboolean indic_ot_is_reph(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_REPH(char_class);
+}
+
+gboolean indic_ot_is_virama(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return (IS_VIRAMA(char_class) || IS_AL_LAKUNA(char_class));
+}
+
+gboolean indic_ot_is_al_lakuna(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_AL_LAKUNA(char_class);
+}
+
+gboolean indic_ot_is_nukta(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_NUKTA(char_class);
+}
+
+gboolean indic_ot_is_vattu(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_VATTU(char_class);
+}
+
+gboolean indic_ot_is_matra(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_MATRA(char_class);
+}
+
+gboolean indic_ot_is_split_matra(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_SPLIT_MATRA(char_class);
+}
+
+gboolean indic_ot_is_m_pre(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_M_PRE(char_class);
+}
+
+gboolean indic_ot_is_m_below(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_M_BELOW(char_class);
+}
+
+gboolean indic_ot_is_m_above(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_M_ABOVE(char_class);
+}
+
+gboolean indic_ot_is_m_post(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_M_POST(char_class);
+}
+
+gboolean indic_ot_is_length_mark(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return IS_LENGTH_MARK(char_class);
+}
+
+gboolean indic_ot_has_post_or_below_base_form(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return HAS_POST_OR_BELOW_BASE_FORM(char_class);
+}
+
+gboolean indic_ot_has_post_base_form(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return HAS_POST_BASE_FORM(char_class);
+}
+
+gboolean indic_ot_has_below_base_form(const IndicOTClassTable *class_table, gunichar ch)
+{
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, ch);
+
+ return HAS_BELOW_BASE_FORM(char_class);
+}
+
+IndicOTCharClass indic_ot_get_char_class(const IndicOTClassTable *class_table, gunichar ch)
+{
+ if (ch == C_SIGN_ZWJ) {
+ return CF_CONSONANT | CC_ZERO_WIDTH_MARK;
+ }
+
+ if (ch == C_SIGN_ZWNJ) {
+ return CC_ZERO_WIDTH_MARK;
+ }
+
+ if (ch < class_table->firstChar || ch > class_table->lastChar) {
+ return CC_RESERVED;
+ }
+
+ return class_table->charClasses[ch - class_table->firstChar];
+}
+
+static const gint8 stateTable[][CC_COUNT] =
+{
+/* xx ma mp iv ct cn nu dv vr zw al */
+ { 1, 1, 1, 5, 3, 2, 1, 1, 1, 1, 1},
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {-1, 6, 1, -1, -1, -1, -1, 5, 4, -1, -1},
+ {-1, 6, 1, -1, -1, -1, 2, 5, 4, 10, 9},
+ {-1, -1, -1, -1, 3, 2, -1, -1, -1, 8, -1},
+ {-1, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {-1, 7, 1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {-1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, 3, 2, -1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1},
+ {-1, -1, -1, -1, -1, -1, -1, -1, 8, -1, 8}
+
+};
+
+glong indic_ot_find_syllable(const IndicOTClassTable *class_table, const gunichar *chars, glong prev, glong char_count)
+{
+ glong cursor = prev;
+ gint8 state = 0;
+
+ while (cursor < char_count) {
+ IndicOTCharClass char_class = indic_ot_get_char_class(class_table, chars[cursor]);
+
+ state = stateTable[state][char_class & CF_CLASS_MASK];
+
+ /*for the components of split matra*/
+ if ((char_count >= cursor + 3) &&
+ (chars[cursor] == 0x0DD9 && chars[cursor + 1] == 0x0DCF && chars[cursor + 2] == 0x0DCA)) { /*for 3 split matra of Sinhala*/
+ return cursor + 3;
+ }
+ else if ((char_count >= cursor + 3) &&
+ (chars[cursor] == 0x0CC6 && chars[cursor + 1] == 0x0CC2 && chars[cursor + 2] == 0x0CD5)) { /*for 3 split matra of Kannada*/
+ return cursor + 3;
+ }
+ /*for 2 split matra*/
+ else if (char_count >= cursor + 2) {
+ /*for Bengali*/
+ if ((chars[cursor] == 0x09C7 && chars[cursor + 1] == 0x09BE) ||
+ (chars[cursor] == 0x09C7 && chars[cursor + 1] == 0x09D7) ||
+ /*for Oriya*/
+ (chars[cursor] == 0x0B47 && chars[cursor + 1] == 0x0B3E) ||
+ (chars[cursor] == 0x0B47 && chars[cursor + 1] == 0x0B56) ||
+ (chars[cursor] == 0x0B47 && chars[cursor + 1] == 0x0B57) ||
+ /*for Tamil*/
+ (chars[cursor] == 0x0BC6 && chars[cursor + 1] == 0x0BBE) ||
+ (chars[cursor] == 0x0BC6 && chars[cursor + 1] == 0x0BD7) ||
+ (chars[cursor] == 0x0BC7 && chars[cursor + 1] == 0x0BBE) ||
+ /*for Malayalam*/
+ (chars[cursor] == 0x0D46 && chars[cursor + 1] == 0x0D3E) ||
+ (chars[cursor] == 0x0D46 && chars[cursor + 1] == 0x0D57) ||
+ (chars[cursor] == 0x0D47 && chars[cursor + 1] == 0x0D3E) ||
+ /*for Sinhala*/
+ (chars[cursor] == 0x0DD9 && chars[cursor + 1] == 0x0DCA) ||
+ (chars[cursor] == 0x0DD9 && chars[cursor + 1] == 0x0DCF) ||
+ (chars[cursor] == 0x0DD9 && chars[cursor + 1] == 0x0DDF) ||
+ (chars[cursor] == 0x0DDC && chars[cursor + 1] == 0x0DCA) ||
+ /*for Telugu*/
+ (chars[cursor] == 0x0C46 && chars[cursor + 1] == 0x0C56) ||
+ /*for Kannada*/
+ (chars[cursor] == 0x0CBF && chars[cursor + 1] == 0x0CD5) ||
+ (chars[cursor] == 0x0CC6 && chars[cursor + 1] == 0x0CD5) ||
+ (chars[cursor] == 0x0CC6 && chars[cursor + 1] == 0x0CD6) ||
+ (chars[cursor] == 0x0CC6 && chars[cursor + 1] == 0x0CC2) ||
+ (chars[cursor] == 0x0CCA && chars[cursor + 1] == 0x0CD5))
+ return cursor + 2;
+ }
+
+ if (state < 0) {
+ break;
+ }
+
+ cursor += 1;
+ }
+
+ return cursor;
+}
+
diff --git a/trunk/modules/indic/indic-ot.c b/trunk/modules/indic/indic-ot.c
new file mode 100644
index 00000000..ca3ca7f0
--- /dev/null
+++ b/trunk/modules/indic/indic-ot.c
@@ -0,0 +1,535 @@
+/* Pango
+ * indic-ot.c:
+ *
+ * Copyright (C) 2001, 2002 IBM Corporation. All Rights Reserved.
+ * Author: Eric Mader <mader@jtcsv.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished
+ * to do so, provided that the above copyright notice(s) and this
+ * permission notice appear in all copies of the Software and that
+ * both the above copyright notice(s) and this permission notice
+ * appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR
+ * ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
+ * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written
+ * authorization of the copyright holder.
+ */
+
+#include <config.h>
+
+#include "indic-ot.h"
+#include "mprefixups.h"
+/*
+ * FIXME: should the IndicOutput stuff be moved
+ * to a separate .h and .c file just to keep the
+ * clutter down here? (it's not really usefull
+ * anyplace else, is it?)
+ */
+struct _Output
+{
+ glong fOutIndex;
+
+ const glong *fOriginalOffsets;
+
+ gunichar *fOutChars;
+ glong *fCharIndices;
+ gulong *fCharTags;
+
+ gunichar fMpre;
+ gunichar fMbelow;
+ gunichar fMabove;
+ gunichar fMpost;
+ gunichar fLengthMark;
+ gunichar fAlLakuna; /* to handle Al-Lakuna in sinhala split matras */
+ glong fMatraIndex;
+ gulong fMatraTags;
+ gboolean fMatraWordStart;
+ glong fMPreOutIndex;
+
+ MPreFixups *fMPreFixups;
+};
+
+typedef struct _Output Output;
+
+static void initOutput(Output *output, const glong *originalOffsets, gunichar *outChars, glong *charIndices, gulong *charTags, MPreFixups *mpreFixups)
+{
+ output->fOriginalOffsets = originalOffsets;
+
+ output->fOutChars = outChars;
+ output->fCharIndices = charIndices;
+ output->fCharTags = charTags;
+
+ output->fOutIndex = 0;
+ output->fMatraTags = 0;
+
+ output->fMpre = output->fMbelow = output->fMabove = output->fMpost = output->fLengthMark = output->fAlLakuna = 0;
+
+ output->fMPreOutIndex = -1;
+ output->fMPreFixups = mpreFixups;
+}
+
+static void saveMatra(Output *output, gunichar matra, IndicOTCharClass matraClass)
+{
+ /* FIXME: check if already set, or if not a matra... */
+ if (IS_M_PRE(matraClass)) {
+ output->fMpre = matra;
+ } else if (IS_M_BELOW(matraClass)) {
+ output->fMbelow = matra;
+ } else if (IS_M_ABOVE(matraClass)) {
+ output->fMabove = matra;
+ } else if (IS_M_POST(matraClass)) {
+ output->fMpost = matra;
+ } else if (IS_LENGTH_MARK(matraClass)) {
+ output->fLengthMark = matra;
+ } else if (IS_AL_LAKUNA(matraClass)) {
+ output->fAlLakuna = matra;
+ }
+}
+
+static void initMatra(Output *output, guint32 matraIndex, gulong matraTags, gboolean wordStart)
+{
+ output->fMpre = output->fMbelow = output->fMabove = output->fMpost = output->fLengthMark = output->fAlLakuna = 0;
+ output->fMPreOutIndex = -1;
+ output->fMatraIndex = matraIndex;
+ output->fMatraTags = matraTags;
+ output->fMatraWordStart = wordStart;
+}
+
+static gboolean noteMatra(Output *output, const IndicOTClassTable *classTable, gunichar matra)
+{
+ IndicOTCharClass matraClass = indic_ot_get_char_class(classTable, matra);
+
+ if (IS_MATRA(matraClass)) {
+ if (IS_SPLIT_MATRA(matraClass)) {
+ const IndicOTSplitMatra *splitMatra = indic_ot_get_split_matra(classTable, matraClass);
+ int i;
+
+ for (i = 0; i < 3 && (*splitMatra)[i] != 0; i += 1) {
+ gunichar piece = (*splitMatra)[i];
+ IndicOTCharClass pieceClass = indic_ot_get_char_class(classTable, piece);
+
+ saveMatra(output, piece, pieceClass);
+ }
+ } else {
+ saveMatra(output, matra, matraClass);
+ }
+
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+static void noteBaseConsonant(Output *output)
+{
+ if (output->fMPreFixups && output->fMPreOutIndex >= 0) {
+ indic_mprefixups_add(output->fMPreFixups, output->fOutIndex, output->fMPreOutIndex);
+ }
+}
+
+static void swapChars(Output *output, int a, int b)
+{
+ if (output->fOutChars != NULL) {
+ gunichar temp_char;
+ guint32 temp_index;
+ gulong temp_tag;
+
+ temp_char = output->fOutChars[output->fOutIndex + b];
+ temp_index = output->fCharIndices[output->fOutIndex + b];
+ temp_tag = output->fCharTags[output->fOutIndex + b];
+
+ output->fOutChars[output->fOutIndex + b] = output->fOutChars[output->fOutIndex + a];
+ output->fCharIndices[output->fOutIndex + b] = output->fCharIndices[output->fOutIndex + a];
+ output->fCharTags[output->fOutIndex + b] = pstf_p;
+
+ output->fOutChars[output->fOutIndex + a] = temp_char;
+ output->fCharIndices[output->fOutIndex + a] = temp_index;
+ output->fCharTags[output->fOutIndex + a] = temp_tag;
+ }
+}
+
+static void writeChar(Output *output, gunichar ch, guint32 charIndex, gulong charTags)
+{
+ if (output->fOutChars != NULL) {
+ output->fOutChars[output->fOutIndex] = ch;
+ output->fCharIndices[output->fOutIndex] = output->fOriginalOffsets[charIndex];
+ output->fCharTags[output->fOutIndex] = charTags;
+ }
+
+ output->fOutIndex += 1;
+}
+
+static void writeMpre(Output *output)
+{
+ if (output->fMpre != 0) {
+ gulong tags = output->fMatraTags;
+ if (output->fMatraWordStart)
+ tags &= ~init;
+
+ output->fMPreOutIndex = output->fOutIndex;
+ writeChar(output, output->fMpre, output->fMatraIndex, tags);
+ }
+}
+
+static void writeMbelow(Output *output)
+{
+ if (output->fMbelow != 0) {
+ writeChar(output, output->fMbelow, output->fMatraIndex, output->fMatraTags);
+ }
+}
+
+static void writeMabove(Output *output)
+{
+ if (output->fMabove != 0) {
+ writeChar(output, output->fMabove, output->fMatraIndex, output->fMatraTags);
+ }
+}
+
+static void writeMpost(Output *output)
+{
+ if (output->fMpost != 0) {
+ writeChar(output, output->fMpost, output->fMatraIndex, output->fMatraTags);
+ }
+}
+
+static void writeLengthMark(Output *output)
+{
+ if (output->fLengthMark != 0) {
+ writeChar(output, output->fLengthMark, output->fMatraIndex, output->fMatraTags);
+ }
+}
+
+static void writeAlLakuna(Output *output)
+{
+ if (output->fAlLakuna != 0) {
+ writeChar(output, output->fAlLakuna, output->fMatraIndex, output->fMatraTags);
+ }
+}
+
+static glong getOutputIndex(Output *output)
+{
+ return output->fOutIndex;
+}
+
+#define false 0
+#define true 1
+
+glong indic_ot_reorder(const gunichar *chars, const glong *utf8_offsets, glong char_count, const IndicOTClassTable *class_table, gunichar *out_chars, glong *char_indices, gulong *char_tags, MPreFixups **outMPreFixups)
+{
+ MPreFixups *mpreFixups = NULL;
+ Output output;
+ glong i, prev = 0;
+ gboolean last_in_word = FALSE;
+
+ if (outMPreFixups && (class_table->scriptFlags & SF_MPRE_FIXUP)) {
+ mpreFixups = indic_mprefixups_new (char_count);
+ }
+
+ initOutput(&output, utf8_offsets, out_chars, char_indices, char_tags, mpreFixups);
+
+ while (prev < char_count) {
+ glong syllable = indic_ot_find_syllable(class_table, chars, prev, char_count);
+ glong matra, vmabove, vmpost = syllable;
+
+ while (vmpost > prev && indic_ot_is_vm_post(class_table, chars[vmpost - 1])) {
+ vmpost -= 1;
+ }
+
+ vmabove = vmpost;
+ while (vmabove > prev && indic_ot_is_vm_above(class_table, chars[vmabove - 1])) {
+ vmabove -= 1;
+ }
+
+ matra = vmabove - 1;
+ initMatra(&output, prev, blwf_p, !last_in_word);
+ while (noteMatra(&output, class_table, chars[matra]) &&
+ matra != prev)
+ matra--;
+
+ last_in_word = TRUE;
+ switch (indic_ot_get_char_class(class_table, chars[prev]) & CF_CLASS_MASK) {
+ case CC_RESERVED:
+ last_in_word = FALSE;
+ /* Fall through */
+ case CC_INDEPENDENT_VOWEL:
+ case CC_ZERO_WIDTH_MARK:
+ for (i = prev; i < syllable; i += 1) {
+ writeChar(&output, chars[i], /*i*/ prev, blwf_p);
+ }
+
+ break;
+
+ case CC_MODIFYING_MARK_ABOVE:
+ case CC_MODIFYING_MARK_POST:
+ case CC_NUKTA:
+ case CC_VIRAMA:
+ case CC_AL_LAKUNA:
+ writeChar(&output, C_DOTTED_CIRCLE, prev, blwf_p);
+ writeChar(&output, chars[prev], prev, blwf_p);
+ break;
+
+ case CC_DEPENDENT_VOWEL:
+ writeMpre(&output);
+ writeChar(&output, C_DOTTED_CIRCLE, prev, blwf_p);
+ writeMbelow(&output);
+ writeMabove(&output);
+ writeMpost(&output);
+ writeLengthMark(&output);
+ writeAlLakuna(&output);
+ break;
+
+ case CC_CONSONANT:
+ case CC_CONSONANT_WITH_NUKTA:
+ {
+ guint32 length = vmabove - prev;
+ glong lastConsonant = vmabove - 1;
+ glong baseLimit = prev;
+ glong baseConsonant, postBase, postBaseLimit;
+ gboolean seenVattu, seenBelowBaseForm, supressVattu;
+ glong bcSpan;
+
+ /* Check for REPH at front of syllable */
+ if (length > 2 && indic_ot_is_reph(class_table, chars[prev]) && indic_ot_is_virama(class_table, chars[prev + 1])) {
+ baseLimit += 2;
+
+ /* Check for eyelash RA, if the script supports it */
+ if ((class_table->scriptFlags & SF_EYELASH_RA) != 0 &&
+ chars[baseLimit] == C_SIGN_ZWJ) {
+ if (length > 3) {
+ baseLimit += 1;
+ } else {
+ baseLimit -= 2;
+ }
+ }
+ }
+
+ while (lastConsonant > baseLimit && !indic_ot_is_consonant(class_table, chars[lastConsonant])) {
+ lastConsonant -= 1;
+ }
+
+ baseConsonant = lastConsonant;
+ postBase = lastConsonant + 1;
+
+ postBaseLimit = class_table->scriptFlags & SF_POST_BASE_LIMIT_MASK;
+ seenVattu = false;
+ seenBelowBaseForm = false;
+ supressVattu = true;
+
+ while (baseConsonant > baseLimit) {
+ IndicOTCharClass charClass = indic_ot_get_char_class(class_table, chars[baseConsonant]);
+
+ if (IS_CONSONANT(charClass)) {
+ if (postBaseLimit == 0 || seenVattu ||
+ (baseConsonant > baseLimit && !indic_ot_is_virama(class_table, chars[baseConsonant - 1])) ||
+ !HAS_POST_OR_BELOW_BASE_FORM(charClass)) {
+ break;
+ }
+
+ seenVattu = IS_VATTU(charClass);
+
+ if (HAS_POST_BASE_FORM(charClass)) {
+ if (seenBelowBaseForm) {
+ break;
+ }
+
+ postBase = baseConsonant;
+ } else if (HAS_BELOW_BASE_FORM(charClass)) {
+ seenBelowBaseForm = true;
+ }
+
+ postBaseLimit -= 1;
+ }
+
+ baseConsonant -= 1;
+ }
+
+ /* Write Mpre */
+ writeMpre(&output);
+
+ /* Write eyelash RA */
+ /* NOTE: baseLimit == prev + 3 iff eyelash RA present... */
+ if (baseLimit == prev + 3) {
+ writeChar(&output, chars[prev], prev, half_p);
+ writeChar(&output, chars[prev + 1], prev /*+ 1*/, half_p);
+ writeChar(&output, chars[prev + 2], prev /*+ 2*/, half_p);
+ }
+
+ /* write any pre-base consonants */
+ supressVattu = true;
+
+ for (i = baseLimit; i < baseConsonant; i += 1) {
+ gunichar ch = chars[i];
+ /* Applying blwf to the first consonant doesn't makes sense
+ * since the below-form follows the consonant that it is
+ * put under */
+ gulong tag = (i == baseLimit) ? half_p : blwf_p;
+ IndicOTCharClass charClass = indic_ot_get_char_class(class_table, ch);
+
+ if (IS_CONSONANT(charClass)) {
+ if (IS_VATTU(charClass) && supressVattu) {
+ tag = nukt_p;
+ }
+ else if ((i + 2 < baseConsonant) && (chars[i + 2] == C_SIGN_ZWNJ)) {
+ tag = nukt_p;
+ }
+
+ supressVattu = IS_VATTU(charClass);
+ } else if (IS_VIRAMA(charClass) && chars[i + 1] == C_SIGN_ZWNJ)
+ {
+ tag = nukt_p;
+ }
+
+ writeChar(&output, ch, /*i*/ prev, tag);
+ }
+
+ bcSpan = baseConsonant + 1;
+
+ if (bcSpan < vmabove && indic_ot_is_nukta(class_table, chars[bcSpan])) {
+ bcSpan += 1;
+ }
+
+ if (baseConsonant == lastConsonant && bcSpan < vmabove && indic_ot_is_virama(class_table, chars[bcSpan])) {
+ bcSpan += 1;
+
+ if (bcSpan < vmabove && chars[bcSpan] == C_SIGN_ZWNJ) {
+ bcSpan += 1;
+ }
+ }
+
+ /* note the base consonant for post-GSUB fixups */
+ noteBaseConsonant(&output);
+
+ /* write base consonant */
+ for (i = baseConsonant; i < bcSpan; i += 1) {
+ writeChar(&output, chars[i], /*i*/ prev, nukt_p);
+ }
+
+ if ((class_table->scriptFlags & SF_MATRAS_AFTER_BASE) != 0) {
+ gboolean is_for_0C48 = FALSE;
+ if (output.fOutChars != NULL) { /*for 0x0C48 of Telugu*/
+ int t;
+ for (t = prev; t < syllable; t++) {
+ if (chars[t] == 0x0C48) {
+ writeMabove(&output);
+ writeMbelow(&output);
+ writeMpost(&output);
+
+ is_for_0C48 = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!is_for_0C48) {
+ writeMbelow(&output);
+ writeMabove(&output);
+ writeMpost(&output);
+ }
+ }
+
+ /* write below-base consonants */
+ if (baseConsonant != lastConsonant) {
+ for (i = bcSpan + 1; i < postBase; i += 1) {
+ writeChar(&output, chars[i], /*i*/ prev, blwf_p);
+ }
+
+ if (postBase > lastConsonant) {
+ /* write halant that was after base consonant */
+ writeChar(&output, chars[bcSpan], /*bcSpan*/ prev, blwf_p);
+ }
+ }
+
+ /* write Mbelow, Mabove */
+ if ((class_table->scriptFlags & SF_MATRAS_AFTER_BASE) == 0) {
+ writeMbelow(&output);
+ writeMabove(&output);
+ }
+
+ if ((class_table->scriptFlags & SF_REPH_AFTER_BELOW) != 0) {
+ if (baseLimit == prev + 2) {
+ writeChar(&output, chars[prev], prev, rphf_p);
+ writeChar(&output, chars[prev + 1], prev /*+ 1*/, rphf_p);
+ }
+
+ /* write VMabove */
+ for (i = vmabove; i < vmpost; i += 1) {
+ writeChar(&output, chars[i], /*i*/ prev, blwf_p);
+ }
+ }
+
+ /* write post-base consonants */
+ if (baseConsonant != lastConsonant) {
+ if (postBase <= lastConsonant) {
+ for (i = postBase; i <= lastConsonant; i += 1) {
+ writeChar(&output, chars[i], /*i*/ prev, pstf_p);
+ }
+
+ /* write halant that was after base consonant */
+ writeChar(&output, chars[bcSpan], /*bcSpan*/ prev, blwf_p);
+ }
+
+ /* write the training halant, if there is one */
+ if (lastConsonant < matra && indic_ot_is_virama(class_table, chars[matra])) {
+ writeChar(&output, chars[matra], /*matra*/ prev, nukt_p);
+ }
+ }
+
+ /* write Mpost */
+ if ((class_table->scriptFlags & SF_MATRAS_AFTER_BASE) == 0) {
+ writeMpost(&output);
+ }
+
+ writeLengthMark(&output);
+ writeAlLakuna(&output);
+
+ /* write reph */
+ if ((class_table->scriptFlags & SF_REPH_AFTER_BELOW) == 0) {
+ if (baseLimit == prev + 2) {
+ writeChar(&output, chars[prev], prev, rphf_p);
+ writeChar(&output, chars[prev + 1], prev /*+ 1*/, rphf_p);
+ }
+
+ /* write VMabove */
+ for (i = vmabove; i < vmpost; i += 1) {
+ writeChar(&output, chars[i], /*i*/ prev, blwf_p);
+ }
+ }
+
+ /* write VMpost */
+ for (i = vmpost; i < syllable; i += 1) {
+ writeChar(&output, chars[i], /*i*/ prev, blwf_p);
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+
+ prev = syllable;
+ }
+
+ if (outMPreFixups) {
+ *outMPreFixups = mpreFixups;
+ }
+
+ return getOutputIndex(&output);
+}
diff --git a/trunk/modules/indic/indic-ot.h b/trunk/modules/indic/indic-ot.h
new file mode 100644
index 00000000..47dd39f2
--- /dev/null
+++ b/trunk/modules/indic/indic-ot.h
@@ -0,0 +1,238 @@
+/* Pango
+ * indic-ot.h:
+ *
+ * Copyright (C) 2001, 2002 IBM Corporation. All Rights Reserved.
+ * Author: Eric Mader <mader@jtcsv.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished
+ * to do so, provided that the above copyright notice(s) and this
+ * permission notice appear in all copies of the Software and that
+ * both the above copyright notice(s) and this permission notice
+ * appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR
+ * ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
+ * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written
+ * authorization of the copyright holder.
+ */
+
+#ifndef __INDIC_OT_H__
+#define __INDIC_OT_H__
+
+#include <pango/pango-glyph.h>
+#include <pango/pango-types.h>
+#include "mprefixups.h"
+
+G_BEGIN_DECLS
+
+#ifdef PANGO_ENABLE_ENGINE
+
+/* Characters that get refered to by name... */
+#define C_SIGN_ZWNJ 0x200C
+#define C_SIGN_ZWJ 0x200D
+#define C_DOTTED_CIRCLE 0x25CC
+
+/*
+ * The characters that a split matra splits into.
+ * Unused characters will be zero.
+ */
+typedef gunichar IndicOTSplitMatra[3];
+
+/*
+ * Character class values
+ */
+typedef enum
+{
+ CC_RESERVED,
+ CC_MODIFYING_MARK_ABOVE,
+ CC_MODIFYING_MARK_POST,
+ CC_INDEPENDENT_VOWEL,
+ CC_CONSONANT,
+ CC_CONSONANT_WITH_NUKTA,
+ CC_NUKTA,
+ CC_DEPENDENT_VOWEL,
+ CC_VIRAMA,
+ CC_ZERO_WIDTH_MARK,
+ CC_AL_LAKUNA,
+ CC_COUNT
+} IndicOTCharClassValues;
+
+/*
+ * Character class flags
+ */
+#define CF_CLASS_MASK 0x0000FFFFU
+
+#define CF_CONSONANT 0x80000000U
+
+#define CF_REPH 0x40000000U
+#define CF_VATTU 0x20000000U
+#define CF_BELOW_BASE 0x10000000U
+#define CF_POST_BASE 0x08000000U
+
+#define CF_MATRA_PRE 0x04000000U
+#define CF_MATRA_BELOW 0x02000000U
+#define CF_MATRA_ABOVE 0x01000000U
+#define CF_MATRA_POST 0x00800000U
+#define CF_LENGTH_MARK 0x00400000U
+
+#define CF_INDEX_MASK 0x000F0000U
+#define CF_INDEX_SHIFT 16
+
+/*
+ * Character class: a character class value
+ * ORed with character class flags.
+ */
+typedef glong IndicOTCharClass;
+
+/*
+ * Script flags
+ */
+#define SF_MATRAS_AFTER_BASE 0x80000000U
+#define SF_REPH_AFTER_BELOW 0x40000000U
+#define SF_EYELASH_RA 0x20000000U
+#define SF_MPRE_FIXUP 0x10000000U
+#define SF_PROCESS_ZWJ 0x08000000U
+
+#define SF_POST_BASE_LIMIT_MASK 0x0000FFFFU
+#define SF_NO_POST_BASE_LIMIT 0x00007FFFU
+
+typedef guint32 IndicOTScriptFlags;
+
+/*
+ * Bit flags for the indic feature tags
+ */
+enum indic_glyph_feature_
+{
+ nukt = 0x0001,
+ akhn = 0x0002,
+ rphf = 0x0004,
+ blwf = 0x0008,
+ half = 0x0010,
+ pstf = 0x0020,
+ vatu = 0x0040,
+ pres = 0x0080,
+ blws = 0x0100,
+ abvs = 0x0200,
+ psts = 0x0400,
+ haln = 0x0800,
+ blwm = 0x1000,
+ abvm = 0x2000,
+ dist = 0x4000,
+ junk = 0x8000,
+ init = 0x10000
+};
+
+/*
+ * Complement of the feature flags that
+ * will be assigned to specific glyphs.
+ *
+ * The names come from the ICU implementation,
+ * which listed the actual tags in an order
+ * such that tags could be assigned using the
+ * address of the first one: &tags[0], &tags[1],
+ * &tags[2], &tags[3]. The name of each set here
+ * is the name of the first tag in the ICU list.
+ */
+enum indic_glyph_property_
+{
+ rphf_p = (junk | dist | init),
+ blwf_p = (junk | dist | init | rphf),
+ half_p = (junk | dist | init | rphf | blwf),
+ pstf_p = (junk | dist | init | rphf | blwf | half),
+ nukt_p = (junk | dist | init | rphf | blwf | half | pstf)
+};
+
+/*
+ * Macros to test the charClass flags for various things.
+ */
+#define IS_VM_ABOVE(charClass) ((charClass & CF_CLASS_MASK) == CC_MODIFYING_MARK_ABOVE)
+#define IS_VM_POST(charClass) ((charClass & CF_CLASS_MASK) == CC_MODIFYING_MARK_POST)
+#define IS_CONSONANT(charClass) ((charClass & CF_CONSONANT) != 0)
+#define IS_REPH(charClass) ((charClass & CF_REPH) != 0)
+#define IS_NUKTA(charClass) ((charClass & CF_CLASS_MASK) == CC_NUKTA)
+#define IS_VIRAMA(charClass) ((charClass & CF_CLASS_MASK) == CC_VIRAMA)
+#define IS_AL_LAKUNA(charClass) ((charClass & CF_CLASS_MASK) == CC_AL_LAKUNA)
+#define IS_VATTU(charClass) ((charClass & CF_VATTU) != 0)
+#define IS_MATRA(charClass) ((charClass & CF_CLASS_MASK) == CC_DEPENDENT_VOWEL)
+#define IS_SPLIT_MATRA(charClass) ((charClass & CF_INDEX_MASK) != 0)
+#define IS_M_PRE(charClass) ((charClass & CF_MATRA_PRE) != 0)
+#define IS_M_BELOW(charClass) ((charClass & CF_MATRA_BELOW) != 0)
+#define IS_M_ABOVE(charClass) ((charClass & CF_MATRA_ABOVE) != 0)
+#define IS_M_POST(charClass) ((charClass & CF_MATRA_POST) != 0)
+#define IS_LENGTH_MARK(charClass) ((charClass & CF_LENGTH_MARK) != 0)
+#define HAS_POST_OR_BELOW_BASE_FORM(charClass) ((charClass & (CF_POST_BASE | CF_BELOW_BASE)) != 0)
+#define HAS_POST_BASE_FORM(charClass) ((charClass & CF_POST_BASE) != 0)
+#define HAS_BELOW_BASE_FORM(charClass) ((charClass & CF_BELOW_BASE) != 0)
+
+struct _IndicOTClassTable
+{
+ gunichar firstChar;
+ gunichar lastChar;
+ glong worstCaseExpansion;
+ IndicOTScriptFlags scriptFlags;
+
+ const IndicOTCharClass *charClasses;
+ const IndicOTSplitMatra *splitMatraTable;
+};
+
+typedef struct _IndicOTClassTable IndicOTClassTable;
+
+extern const IndicOTClassTable deva_class_table;
+extern const IndicOTClassTable beng_class_table;
+extern const IndicOTClassTable guru_class_table;
+extern const IndicOTClassTable gujr_class_table;
+extern const IndicOTClassTable orya_class_table;
+extern const IndicOTClassTable taml_class_table;
+extern const IndicOTClassTable telu_class_table;
+extern const IndicOTClassTable knda_class_table;
+extern const IndicOTClassTable mlym_class_table;
+extern const IndicOTClassTable sinh_class_table;
+
+const IndicOTSplitMatra *indic_ot_get_split_matra(const IndicOTClassTable *class_table, IndicOTCharClass char_class);
+
+IndicOTCharClass indic_ot_get_char_class(const IndicOTClassTable *class_table, gunichar ch);
+
+gboolean indic_ot_is_vm_above(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_vm_post(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_consonant(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_reph(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_virama(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_al_lakuna(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_nukta(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_vattu(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_matra(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_split_matra(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_m_pre(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_m_below(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_m_above(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_m_post(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_is_length_mark(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_has_post_or_below_base_form(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_has_post_base_form(const IndicOTClassTable *class_table, gunichar ch);
+gboolean indic_ot_has_below_base_form(const IndicOTClassTable *class_table, gunichar ch);
+
+glong indic_ot_find_syllable(const IndicOTClassTable *class_table, const gunichar *chars, glong prev, glong char_count);
+
+glong indic_ot_reorder(const gunichar *chars, const glong *utf8_offsets, glong char_count, const IndicOTClassTable *class_table, gunichar *out_chars, glong *char_indices, gulong *char_tags, MPreFixups **outMPreFixups);
+
+#endif /* PANGO_ENABLE_ENGINE */
+
+G_END_DECLS
+
+#endif /* __INDIC_OT_H__ */
diff --git a/trunk/modules/indic/mprefixups.c b/trunk/modules/indic/mprefixups.c
new file mode 100644
index 00000000..60517d88
--- /dev/null
+++ b/trunk/modules/indic/mprefixups.c
@@ -0,0 +1,116 @@
+/*
+ * mprefixups.h: Handle left matra placement
+ *
+ * Author: Sivaraj Doddannan
+ * Ported from IBM's ICU engine. Original copyright:
+ * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <pango/pango-types.h>
+#include "mprefixups.h"
+#include <stdio.h>
+
+struct _FixupData
+{
+ glong fBaseIndex;
+ glong fMPreIndex;
+};
+
+MPreFixups *indic_mprefixups_new(glong char_count)
+{
+ MPreFixups *mprefixups = g_new (MPreFixups, 1);
+ mprefixups->fFixupCount = 0;
+ mprefixups->fFixupData = g_new (FixupData, char_count);
+
+ return mprefixups;
+}
+
+void indic_mprefixups_free (MPreFixups *mprefixups)
+{
+ g_free (mprefixups->fFixupData);
+ g_free (mprefixups);
+}
+
+void indic_mprefixups_add (MPreFixups *mprefixups, glong baseIndex, glong mpreIndex)
+{
+ /* NOTE: don't add the fixup data if the mpre is right
+ * before the base consonant glyph.
+ */
+ if (baseIndex - mpreIndex > 1) {
+ mprefixups->fFixupData[mprefixups->fFixupCount].fBaseIndex = baseIndex;
+ mprefixups->fFixupData[mprefixups->fFixupCount].fMPreIndex = mpreIndex;
+
+ mprefixups->fFixupCount += 1;
+ }
+}
+
+void indic_mprefixups_apply(MPreFixups *mprefixups, PangoOTBuffer *buffer)
+{
+ glong fixup;
+
+ for (fixup = 0; fixup < mprefixups->fFixupCount; fixup += 1) {
+ gulong baseIndex = mprefixups->fFixupData[fixup].fBaseIndex;
+ gulong mpreIndex = mprefixups->fFixupData[fixup].fMPreIndex;
+ glong baseGlyph = -1;
+ glong mpreGlyph = -1;
+ glong mpreLimit = -1;
+ glong mpreCount, moveCount, mpreDest;
+ glong i;
+ PangoOTGlyph *glyphs;
+ int n_glyphs;
+ PangoOTGlyph *mpreSave;
+
+ /* determine post GSUB location of baseIndex and mpreIndex */
+
+ pango_ot_buffer_get_glyphs (buffer, &glyphs, &n_glyphs);
+
+ for (i = 0; i < n_glyphs; i++) {
+ if (baseGlyph < 0 && glyphs[i].cluster == baseIndex)
+ baseGlyph = i;
+ if (glyphs[i].cluster == mpreIndex) {
+ if (mpreGlyph < 0)
+ mpreGlyph = i;
+ mpreLimit = i + 1;
+ }
+ }
+ if (baseGlyph < 0 || mpreGlyph < 0 || mpreLimit >= baseGlyph) {
+ continue;
+ }
+
+ mpreCount = mpreLimit - mpreGlyph;
+ moveCount = baseGlyph - mpreLimit;
+ mpreDest = baseGlyph - mpreCount;
+
+ mpreSave = g_new (PangoOTGlyph, mpreCount);
+
+ for (i = 0; i < mpreCount; i += 1) {
+ mpreSave[i] = glyphs[mpreGlyph + i];
+ }
+
+ for (i = 0; i < moveCount; i += 1) {
+ glyphs[mpreGlyph + i] = glyphs[mpreLimit + i];
+ }
+
+ for (i = 0; i < mpreCount; i += 1) {
+ glyphs[mpreDest + i] = mpreSave[i];
+ }
+
+ g_free(mpreSave);
+ }
+}
diff --git a/trunk/modules/indic/mprefixups.h b/trunk/modules/indic/mprefixups.h
new file mode 100644
index 00000000..22336dba
--- /dev/null
+++ b/trunk/modules/indic/mprefixups.h
@@ -0,0 +1,51 @@
+/*
+ * mprefixups.c: Handle left matra placement
+ *
+ * Author: Sivaraj Doddannan
+ * Ported from IBM's ICU engine. Original copyright:
+ * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MPREFIXUPS_H
+#define __MPREFIXUPS_H
+
+#include <pango/pango-types.h>
+#include <pango/pango-glyph.h>
+#include <pango/pango-ot.h>
+
+G_BEGIN_DECLS
+
+typedef struct _FixupData FixupData;
+
+struct _MPreFixups {
+ glong fFixupCount;
+ FixupData *fFixupData;
+};
+
+typedef struct _MPreFixups MPreFixups;
+
+MPreFixups *indic_mprefixups_new(glong char_count);
+void indic_mprefixups_free(MPreFixups *mprefixups);
+void indic_mprefixups_add(MPreFixups *mprefixups, glong baseIndex, glong mpreIndex);
+void indic_mprefixups_apply(MPreFixups *mprefixups, PangoOTBuffer *buffer);
+
+
+G_END_DECLS
+
+#endif
+
diff --git a/trunk/modules/khmer/Makefile.am b/trunk/modules/khmer/Makefile.am
new file mode 100644
index 00000000..c1618c9b
--- /dev/null
+++ b/trunk/modules/khmer/Makefile.am
@@ -0,0 +1,21 @@
+include $(top_srcdir)/modules/Module.mk
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_KHMER_FC
+noinst_LTLIBRARIES += libpango-khmer-fc.la
+else
+if DYNAMIC_KHMER_FC
+module_LTLIBRARIES += pango-khmer-fc.la
+endif
+endif
+endif
+
+fc_sources = \
+ khmer-fc.c
+
+pango_khmer_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_khmer_fc_la_LIBADD = $(pangoft2libs)
+pango_khmer_fc_la_SOURCES = $(fc_sources)
+libpango_khmer_fc_la_SOURCES = $(fc_sources)
+libpango_khmer_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_khmer_fc
diff --git a/trunk/modules/khmer/khmer-fc.c b/trunk/modules/khmer/khmer-fc.c
new file mode 100644
index 00000000..7c2486cd
--- /dev/null
+++ b/trunk/modules/khmer/khmer-fc.c
@@ -0,0 +1,720 @@
+/* Pango
+ * khmer-fc.c: Shaper for Khmer script
+ *
+ * Copyright (C) 2004 Open Forum of Cambodia (www.forum.org.kh / www.khmeros.info)
+ * Authors: Jens Herden <jens@khmeros.info> and Javier Sola <javier@khmeros.info>
+ *
+ * Based on code from other shapers
+ * Copyright (C) 1999-2004 Red Hat Software
+ * Author: Owen Taylor <otaylor@redhat.com>
+
+ * Partially based on Indic shaper
+ * Copyright (C) 2001, 2002 IBM Corporation
+ * Author: Eric Mader <mader@jtcsv.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * The license on the original Indic shaper code is as follows:
+ *
+ * * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished
+ * to do so, provided that the above copyright notice(s) and this
+ * permission notice appear in all copies of the Software and that
+ * both the above copyright notice(s) and this permission notice
+ * appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR
+ * ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
+ * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written
+ * authorization of the copyright holder.
+ */
+#include <config.h>
+#include <string.h>
+
+#include "pango-engine.h"
+#include "pango-ot.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+
+
+#define SCRIPT_ENGINE_NAME "KhmerScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+
+typedef PangoEngineShape KhmerEngineFc;
+typedef PangoEngineShapeClass KhmerEngineFcClass ;
+
+
+static PangoEngineScriptInfo khmer_scripts[] =
+{
+ { PANGO_SCRIPT_KHMER, "*" }
+};
+
+static PangoEngineInfo script_engines[] =
+{
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ khmer_scripts, G_N_ELEMENTS (khmer_scripts)
+ }
+};
+
+
+/* Vocabulary
+ * Base -> A consonant or an independent vowel in its full (not subscript) form. It is the
+ * center of the syllable, it can be surrounded by coeng (subscript) consonants, vowels,
+ * split vowels, signs... but there is only one base in a syllable, it has to be coded as
+ * the first character of the syllable.
+ * split vowel --> vowel that has two parts placed separately (e.g. Before and after the consonant).
+ * Khmer language has five of them. Khmer split vowels either have one part before the
+ * base and one after the base or they have a part before the base and a part above the base.
+ * The first part of all Khmer split vowels is the same character, identical to
+ * the glyph of Khmer dependent vowel SRA EI
+ * coeng --> modifier used in Khmer to construct coeng (subscript) consonants
+ * Differently than indian languages, the coeng modifies the consonant that follows it,
+ * not the one preceding it Each consonant has two forms, the base form and the subscript form
+ * the base form is the normal one (using the consonants code-point), the subscript form is
+ * displayed when the combination coeng + consonant is encountered.
+ * Consonant of type 1 -> A consonant which has subscript for that only occupies space under a base consonant
+ * Consonant of type 2.-> Its subscript form occupies space under and before the base (only one, RO)
+ * Consonant of Type 3 -> Its subscript form occupies space under and after the base (KHO, CHHO, THHO, BA, YO, SA)
+ * Consonant shifter -> Khmer has to series of consonants. The same dependent vowel has different sounds
+ * if it is attached to a consonant of the first series or a consonant of the second series
+ * Most consonants have an equivalent in the other series, but some of theme exist only in
+ * one series (for example SA). If we want to use the consonant SA with a vowel sound that
+ * can only be done with a vowel sound that corresponds to a vowel accompanying a consonant
+ * of the other series, then we need to use a consonant shifter: TRIISAP or MUSIKATOAN
+ * x17C9 y x17CA. TRIISAP changes a first series consonant to second series sound and
+ * MUSIKATOAN a second series consonant to have a first series vowel sound.
+ * Consonant shifter are both normally supercript marks, but, when they are followed by a
+ * superscript, they change shape and take the form of subscript dependent vowel SRA U.
+ * If they are in the same syllable as a coeng consonant, Unicode 3.0 says that they
+ * should be typed before the coeng. Unicode 4.0 breaks the standard and says that it should
+ * be placed after the coeng consonant.
+ * Dependent vowel -> In khmer dependent vowels can be placed above, below, before or after the base
+ * Each vowel has its own position. Only one vowel per syllable is allowed.
+ * Signs -> Khmer has above signs and post signs. Only one above sign and/or one post sign are
+ * Allowed in a syllable.
+ *
+ *
+ * order is important here! This order must be the same that is found in each horizontal
+ * line in the statetable for Khmer (see khmerStateTable) .
+ */
+enum KhmerCharClassValues
+{
+ CC_RESERVED = 0,
+ CC_CONSONANT = 1, /* Consonant of type 1 or independent vowel */
+ CC_CONSONANT2 = 2, /* Consonant of type 2 */
+ CC_CONSONANT3 = 3, /* Consonant of type 3 */
+ CC_ZERO_WIDTH_NJ_MARK = 4, /* Zero Width non joiner character (0x200C) */
+ CC_CONSONANT_SHIFTER = 5,
+ CC_ROBAT = 6, /* Khmer special diacritic accent -treated differently in state table */
+ CC_COENG = 7, /* Subscript consonant combining character */
+ CC_DEPENDENT_VOWEL = 8,
+ CC_SIGN_ABOVE = 9,
+ CC_SIGN_AFTER = 10,
+ CC_ZERO_WIDTH_J_MARK = 11, /* Zero width joiner character */
+ CC_COUNT = 12 /* This is the number of character classes */
+};
+
+
+enum KhmerCharClassFlags
+{
+ CF_CLASS_MASK = 0x0000FFFF,
+
+ CF_CONSONANT = 0x01000000, /* flag to speed up comparing */
+ CF_SPLIT_VOWEL = 0x02000000, /* flag for a split vowel -> the first part is added in front of the syllable */
+ CF_DOTTED_CIRCLE = 0x04000000, /* add a dotted circle if a character with this flag is the first in a syllable */
+ CF_COENG = 0x08000000, /* flag to speed up comparing */
+ CF_SHIFTER = 0x10000000, /* flag to speed up comparing */
+ CF_ABOVE_VOWEL = 0x20000000, /* flag to speed up comparing */
+
+ /* position flags */
+ CF_POS_BEFORE = 0x00080000,
+ CF_POS_BELOW = 0x00040000,
+ CF_POS_ABOVE = 0x00020000,
+ CF_POS_AFTER = 0x00010000,
+ CF_POS_MASK = 0x000f0000
+};
+
+
+/* Characters that get refrered to by name */
+enum KhmerChar
+{
+ C_SIGN_ZWNJ = 0x200C,
+ C_SIGN_ZWJ = 0x200D,
+ C_DOTTED_CIRCLE = 0x25CC,
+ C_RO = 0x179A,
+ C_VOWEL_AA = 0x17B6,
+ C_SIGN_NIKAHIT = 0x17C6,
+ C_VOWEL_E = 0x17C1,
+ C_COENG = 0x17D2
+};
+
+
+enum
+{
+ /* simple classes, they are used in the state table (in this file) to control the length of a syllable
+ * they are also used to know where a character should be placed (location in reference to the base character)
+ * and also to know if a character, when independently displayed, should be displayed with a dotted-circle to
+ * indicate error in syllable construction
+ */
+ _xx = CC_RESERVED,
+ _sa = CC_SIGN_ABOVE | CF_DOTTED_CIRCLE | CF_POS_ABOVE,
+ _sp = CC_SIGN_AFTER | CF_DOTTED_CIRCLE| CF_POS_AFTER,
+ _c1 = CC_CONSONANT | CF_CONSONANT,
+ _c2 = CC_CONSONANT2 | CF_CONSONANT,
+ _c3 = CC_CONSONANT3 | CF_CONSONANT,
+ _rb = CC_ROBAT | CF_POS_ABOVE | CF_DOTTED_CIRCLE,
+ _cs = CC_CONSONANT_SHIFTER | CF_DOTTED_CIRCLE | CF_SHIFTER,
+ _dl = CC_DEPENDENT_VOWEL | CF_POS_BEFORE | CF_DOTTED_CIRCLE,
+ _db = CC_DEPENDENT_VOWEL | CF_POS_BELOW | CF_DOTTED_CIRCLE,
+ _da = CC_DEPENDENT_VOWEL | CF_POS_ABOVE | CF_DOTTED_CIRCLE | CF_ABOVE_VOWEL,
+ _dr = CC_DEPENDENT_VOWEL | CF_POS_AFTER | CF_DOTTED_CIRCLE,
+ _co = CC_COENG | CF_COENG | CF_DOTTED_CIRCLE,
+
+ /* split vowel */
+ _va = _da | CF_SPLIT_VOWEL,
+ _vr = _dr | CF_SPLIT_VOWEL
+};
+
+
+/* Character class: a character class value
+ * ORed with character class flags.
+ */
+typedef glong KhmerCharClass;
+
+
+/* Character class tables
+ * _xx character does not combine into syllable, such as numbers, puntuation marks, non-Khmer signs...
+ * _sa Sign placed above the base
+ * _sp Sign placed after the base
+ * _c1 Consonant of type 1 or independent vowel (independent vowels behave as type 1 consonants)
+ * _c2 Consonant of type 2 (only RO)
+ * _c3 Consonant of type 3
+ * _rb Khmer sign robat u17CC. combining mark for subscript consonants
+ * _cd Consonant-shifter
+ * _dl Dependent vowel placed before the base (left of the base)
+ * _db Dependent vowel placed below the base
+ * _da Dependent vowel placed above the base
+ * _dr Dependent vowel placed behind the base (right of the base)
+ * _co Khmer combining mark COENG u17D2, combines with the consonant or independent vowel following
+ * it to create a subscript consonant or independent vowel
+ * _va Khmer split vowel in wich the first part is before the base and the second one above the base
+ * _vr Khmer split vowel in wich the first part is before the base and the second one behind (right of) the base
+ */
+static const KhmerCharClass khmerCharClasses[] =
+{
+ _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, /* 1780 - 178F */
+ _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c2, _c1, _c1, _c1, _c3, _c3, /* 1790 - 179F */
+ _c1, _c3, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, /* 17A0 - 17AF */
+ _c1, _c1, _c1, _c1, _dr, _dr, _dr, _da, _da, _da, _da, _db, _db, _db, _va, _vr, /* 17B0 - 17BF */
+ _vr, _dl, _dl, _dl, _vr, _vr, _sa, _sp, _sp, _cs, _cs, _sa, _rb, _sa, _sa, _sa, /* 17C0 - 17CF */
+ _sa, _sa, _co, _sa, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _sa, _xx, _xx, /* 17D0 - 17DF */
+};
+
+/* this define must reflect the range of khmerCharClasses */
+#define firstChar 0x1780
+#define lastChar 0x17df
+
+
+
+/* The stateTable is used to calculate the end (the length) of a well
+ * formed Khmer Syllable.
+ *
+ * Each horizontal line is ordered exactly the same way as the values in KhmerClassTable
+ * CharClassValues. This coincidence of values allows the follow up of the table.
+ *
+ * Each line corresponds to a state, which does not necessarily need to be a type
+ * of component... for example, state 2 is a base, with is always a first character
+ * in the syllable, but the state could be produced a consonant of any type when
+ * it is the first character that is analysed (in ground state).
+ *
+ * Differentiating 3 types of consonants is necessary in order to
+ * forbid the use of certain combinations, such as having a second
+ * coeng after a coeng RO,
+ * The inexistent possibility of having a type 3 after another type 3 is permitted,
+ * eliminating it would very much complicate the table, and it does not create typing
+ * problems, as the case above.
+ *
+ * The table is quite complex, in order to limit the number of coeng consonants
+ * to 2 (by means of the table).
+ *
+ * There a peculiarity, as far as Unicode is concerned:
+ * - The consonant-shifter is considered in two possible different
+ * locations, the one considered in Unicode 3.0 and the one considered in
+ * Unicode 4.0. (there is a backwards compatibility problem in this standard).
+ *
+ *
+ * xx independent character, such as a number, punctuation sign or non-khmer char
+ *
+ * c1 Khmer consonant of type 1 or an independent vowel
+ * that is, a letter in which the subscript for is only under the
+ * base, not taking any space to the right or to the left
+ *
+ * c2 Khmer consonant of type 2, the coeng form takes space under
+ * and to the left of the base (only RO is of this type)
+ *
+ * c3 Khmer consonant of type 3. Its subscript form takes space under
+ * and to the right of the base.
+ *
+ * cs Khmer consonant shifter
+ *
+ * rb Khmer robat
+ *
+ * co coeng character (u17D2)
+ *
+ * dv dependent vowel (including split vowels, they are treated in the same way).
+ * even if dv is not defined above, the component that is really tested for is
+ * KhmerClassTable::CC_DEPENDENT_VOWEL, which is common to all dependent vowels
+ *
+ * zwj Zero Width joiner
+ *
+ * zwnj Zero width non joiner
+ *
+ * sa above sign
+ *
+ * sp post sign
+ *
+ * there are lines with equal content but for an easier understanding
+ * (and maybe change in the future) we did not join them
+ */
+static const gint8 khmerStateTable[][CC_COUNT] =
+{
+/* xx c1 c2 c3 zwnj cs rb co dv sa sp zwj */
+ { 1, 2, 2, 2, 1, 1, 1, 6, 1, 1, 1, 2}, /* 0 - ground state */
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 1 - exit state (or sign to the right of the syllable) */
+ {-1, -1, -1, -1, 3, 4, 5, 6, 16, 17, 1, -1}, /* 2 - Base consonant */
+ {-1, -1, -1, -1, -1, 4, -1, -1, 16, -1, -1, -1}, /* 3 - First ZWNJ before a register shifter
+ It can only be followed by a shifter or a vowel */
+ {-1, -1, -1, -1, 15, -1, -1, 6, 16, 17, 1, 14}, /* 4 - First register shifter */
+ {-1, -1, -1, -1, -1, -1, -1, -1, 20, -1, 1, -1}, /* 5 - Robat */
+ {-1, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1}, /* 6 - First Coeng */
+ {-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, /* 7 - First consonant of type 1 after coeng */
+ {-1, -1, -1, -1, 12, 13, -1, -1, 16, 17, 1, 14}, /* 8 - First consonant of type 2 after coeng */
+ {-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, /* 9 - First consonant or type 3 after ceong */
+ {-1, 11, 11, 11, -1, -1, -1, -1, -1, -1, -1, -1}, /* 10 - Second Coeng (no register shifter before) */
+ {-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, /* 11 - Second coeng consonant (or ind. vowel) no register shifter before */
+ {-1, -1, -1, -1, -1, 13, -1, -1, 16, -1, -1, -1}, /* 12 - Second ZWNJ before a register shifter */
+ {-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, /* 13 - Second register shifter */
+ {-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, /* 14 - ZWJ before vowel */
+ {-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, /* 15 - ZWNJ before vowel */
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 1, 18}, /* 16 - dependent vowel */
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 18}, /* 17 - sign above */
+ {-1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1}, /* 18 - ZWJ after vowel */
+ {-1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19 - Third coeng */
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, /* 20 - dependent vowel after a Robat */
+};
+
+
+enum property_flags
+{
+ abvf = 0x0001,
+ pref = 0x0002,
+ pstf = 0x0004,
+ blwf = 0x0008,
+
+ pres = 0x0010,
+ blws = 0x0020,
+ abvs = 0x0040,
+ psts = 0x0080,
+ clig = 0x0100,
+
+ dist = 0x0200,
+ blwm = 0x0400,
+ abvm = 0x0800,
+};
+
+
+enum properties
+{
+ blwf_p = /*(blwf | blws | clig | dist | blwm)*/ (abvf | pref | pstf | pres | abvs | psts | abvm),
+ pstf_p = /*(blwf | blws | pref | pres | pstf | psts | clig | dist | blwm)*/ (abvf | abvs | abvm),
+ abvf_p = /*(abvf | abvs | clig | dist | abvm)*/ (pref | pstf | blwf | pres | blws | psts | blwm),
+ pref_p = /*(pref | pres | clig | dist)*/ (abvf | pstf | blwf | blws | abvs | psts | blwm | abvm),
+ default_p = /*(pres | blws | clig | dist | abvm | blwm)*/ (pref | blwf |abvf | pstf | abvs | psts)
+};
+
+
+/* Below we define how a character in the input string is either in the khmerCharClasses table
+ * (in which case we get its type back), a ZWJ or ZWNJ (two characters that may appear
+ * within the syllable, but are not in the table) we also get their type back, or an unknown object
+ * in which case we get _xx (CC_RESERVED) back
+ */
+static KhmerCharClass
+get_char_class (gunichar ch)
+{
+ if (ch == C_SIGN_ZWJ)
+ return CC_ZERO_WIDTH_J_MARK;
+
+ if (ch == C_SIGN_ZWNJ)
+ return CC_ZERO_WIDTH_NJ_MARK;
+
+ if (ch < firstChar || ch > lastChar)
+ return CC_RESERVED;
+
+ return khmerCharClasses[ch - firstChar];
+}
+
+
+/* Given an input string of characters and a location in which to start looking
+ * calculate, using the state table, which one is the last character of the syllable
+ * that starts in the starting position.
+ */
+static glong
+find_syllable (const gunichar *chars,
+ glong start,
+ glong char_count)
+{
+ glong cursor = start;
+ gint8 state = 0;
+ KhmerCharClass charClass;
+
+ while (cursor < char_count)
+ {
+ charClass = get_char_class (chars[cursor]) & CF_CLASS_MASK;
+ state = khmerStateTable[state][charClass];
+
+ if (state < 0)
+ break;
+
+ cursor += 1;
+ }
+
+ return cursor;
+}
+
+static const PangoOTFeatureMap gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"pref", pref},
+ {"blwf", blwf},
+ {"abvf", abvf},
+ {"pstf", pstf},
+ {"pres", pres},
+ {"blws", blws},
+ {"abvs", abvs},
+ {"psts", psts},
+ {"clig", clig},
+ {"calt", PANGO_OT_ALL_GLYPHS}
+};
+
+static const PangoOTFeatureMap gpos_features[] =
+{
+ {"dist", dist},
+ {"blwm", blwm},
+ {"abvm", abvm},
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
+
+static PangoGlyph
+get_index (PangoFcFont *fc_font, gunichar wc)
+{
+ PangoGlyph index = pango_fc_font_get_glyph (fc_font, wc);
+ if (!index)
+ index = PANGO_GET_UNKNOWN_GLYPH ( wc);
+ return index;
+}
+
+
+static void
+khmer_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ PangoFcFont *fc_font;
+ FT_Face face;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ glong n_chars;
+ gunichar *wcs;
+ const char *p;
+ int i;
+ glong syllable;
+ KhmerCharClass charClass;
+ glong cursor = 0;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return;
+
+ buffer = pango_ot_buffer_new (fc_font);
+
+ wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);
+
+ p = text;
+ /* This loop only exits when we reach the end of a run, which may contain
+ * several syllables.
+ */
+ while (cursor < n_chars)
+ {
+ /* write a pre vowel or the pre part of a split vowel first
+ * and look out for coeng + ro. RO is the only vowel of type 2, and
+ * therefore the only one that requires saving space before the base.
+ */
+ glong coengRo = -1; /* There is no Coeng Ro, if found this value will change */
+
+ syllable = find_syllable (wcs, cursor, n_chars);
+
+ for (i = cursor; i < syllable; i += 1)
+ {
+ charClass = get_char_class (wcs[i]);
+
+ /* if a split vowel, write the pre part. In Khmer the pre part
+ * is the same for all split vowels, same glyph as pre vowel C_VOWEL_E
+ */
+ if (charClass & CF_SPLIT_VOWEL)
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_VOWEL_E), pref_p, p - text);
+ break; /* there can be only one vowel */
+ }
+
+ /* if a vowel with pos before write it out */
+ if (charClass & CF_POS_BEFORE)
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pref_p, p - text);
+ break; /* there can be only one vowel */
+ }
+
+ /* look for coeng + ro and remember position
+ * works because coeng + ro is always in front of a vowel (if there is a vowel)
+ * and because CC_CONSONANT2 is enough to identify it, as it is the only consonant
+ * with this flag
+ */
+ if ((charClass & CF_COENG) && (i + 1 < syllable) &&
+ ((get_char_class (wcs[i + 1]) & CF_CLASS_MASK) == CC_CONSONANT2))
+ {
+ coengRo = i;
+ }
+ }
+
+ /* write coeng + ro if found */
+ if (coengRo > -1)
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_COENG), pref_p, p - text);
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_RO), pref_p, p - text);
+ }
+
+ /* shall we add a dotted circle?
+ * If in the position in which the base should be (first char in the string) there is
+ * a character that has the Dotted circle flag (a character that cannot be a base)
+ * then write a dotted circle
+ */
+ if (get_char_class (wcs[cursor]) & CF_DOTTED_CIRCLE)
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_DOTTED_CIRCLE), default_p, p - text);
+ }
+
+ /* copy what is left to the output, skipping before vowels and
+ * coeng Ro if they are present
+ */
+ for (i = cursor; i < syllable; i += 1)
+ {
+ charClass = get_char_class (wcs[i]);
+
+ /* skip a before vowel, it was already processed */
+ if (charClass & CF_POS_BEFORE)
+ {
+ p = g_utf8_next_char (p);
+ continue;
+ }
+
+ /* skip coeng + ro, it was already processed */
+ if (i == coengRo)
+ {
+ p = g_utf8_next_char (p);
+ i += 1;
+ p = g_utf8_next_char (p);
+ continue;
+ }
+
+ switch (charClass & CF_POS_MASK)
+ {
+ case CF_POS_ABOVE :
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), abvf_p, p - text);
+ break;
+
+ case CF_POS_AFTER :
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text);
+ break;
+
+ case CF_POS_BELOW :
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
+ break;
+
+ default:
+ /* assign the correct flags to a coeng consonant
+ * Consonants of type 3 are taged as Post forms and those type 1 as below forms
+ */
+ if ((charClass & CF_COENG) && i + 1 < syllable)
+ {
+ if ((get_char_class (wcs[i + 1]) & CF_CLASS_MASK) == CC_CONSONANT3)
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text);
+ p = g_utf8_next_char (p);
+ i += 1;
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text);
+ break;
+ }
+ else
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
+ p = g_utf8_next_char (p);
+ i += 1;
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
+ break;
+ }
+ }
+
+ /* if a shifter is followed by an above vowel change the shifter to below form,
+ * an above vowel can have two possible positions i + 1 or i + 3
+ * (position i+1 corresponds to unicode 3, position i+3 to Unicode 4)
+ * and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two
+ * different positions, right after the shifter or after a vowel (Unicode 4)
+ */
+ if ((charClass & CF_SHIFTER) && (i + 1 < syllable))
+ {
+ if (get_char_class (wcs[i + 1]) & CF_ABOVE_VOWEL)
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
+ break;
+ }
+ if (i + 2 < syllable &&
+ (wcs[i + 1] == C_VOWEL_AA) &&
+ (wcs[i + 2] == C_SIGN_NIKAHIT) )
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
+ break;
+ }
+ if (i + 3 < syllable && (get_char_class (wcs[i + 3]) & CF_ABOVE_VOWEL) )
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
+ break;
+ }
+ if (i + 4 < syllable &&
+ (wcs[i + 3] == C_VOWEL_AA) &&
+ (wcs[i + 4] == C_SIGN_NIKAHIT) )
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
+ break;
+ }
+
+ }
+
+ /* default - any other characters */
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), default_p, p - text);
+ break;
+ } /* switch */
+ p = g_utf8_next_char (p);
+ } /* for */
+
+ cursor = syllable; /* move the pointer to the start of next syllable */
+ } /* while */
+
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
+ desc.static_gsub_features = gsub_features;
+ desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
+ desc.static_gpos_features = gpos_features;
+
+ /* TODO populate other_features from analysis->extra_attrs */
+ desc.n_other_features = 0;
+ desc.other_features = NULL;
+
+ ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
+
+ pango_ot_ruleset_substitute (ruleset, buffer);
+ pango_ot_ruleset_position (ruleset, buffer);
+ pango_ot_buffer_output (buffer, glyphs);
+
+ g_free (wcs);
+ pango_ot_buffer_destroy (buffer);
+
+ pango_fc_font_unlock_face (fc_font);
+}
+
+
+static void
+khmer_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = khmer_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (KhmerEngineFc, khmer_engine_fc,
+ khmer_engine_fc_class_init, NULL)
+
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ khmer_engine_fc_register_type (module);
+}
+
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (khmer_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/makefile.msc b/trunk/modules/makefile.msc
new file mode 100644
index 00000000..c4fd7e6f
--- /dev/null
+++ b/trunk/modules/makefile.msc
@@ -0,0 +1,63 @@
+# modles for the ft2 backend, don't include 'basic'
+# here it is built-in pangoft.dll, see ../pango/makefile.msc
+MODULES = arabic hangul hebrew indic syriac thai khmer
+
+!IFNDEF MODULE
+
+# The main target
+all : sub-all
+
+sub-all:
+ for %d in ($(MODULES)) do nmake -nologo -f makefile.msc sub-one THIS=%d
+
+sub-one:
+ cd $(THIS)
+ nmake -nologo -f ..\makefile.msc libpango-$(THIS)-fc.dll MODULE=$(THIS) OBJ_$(THIS)=1
+ cd ..
+
+clean:
+ for %d in ($(MODULE)) do nmake -nologo -f makefile.msc sub-clean THIS=%d
+
+!ELSE
+
+TOP = ..\..\..
+!INCLUDE $(TOP)\glib\build\win32\make.msc
+
+!IFDEF OBJ_arabic
+OBJECTS = arabic-fc.obj arabic-ot.obj
+!ENDIF
+
+!IFDEF OBJ_hebrew
+OBJECTS = hebrew-fc.obj hebrew-shaper.obj
+!ENDIF
+
+!IFDEF OBJ_indic
+OBJECTS = indic-fc.obj indic-ot.obj indic-ot-class-tables.obj mprefixups.obj
+!ENDIF
+
+!IFDEF OBJ_khmer
+OBJECTS = khmer_fc.obj
+!ENDIF
+
+!IFDEF OBJ_syriac
+OBJECTS = syriac-fc.obj syriac-ot.obj
+!ENDIF
+
+!IFDEF OBJ_thai
+OBJECTS = thai-fc.obj thai-shaper.obj
+!ENDIF
+
+!IFNDEF OBJECTS
+OBJECTS = $(MODULE)-fc.obj
+!ENDIF
+
+INCLUDES = -I ..\.. -I ..\..\pango $(GLIB_CFLAGS) $(FREETYPE2_CFLAGS)
+DEFINES = -DPANGO_ENABLE_ENGINE
+LINKS = $(FREETYPE_LIBS) $(GLIB_LIBS) \
+ ..\..\pango\pango-1.0.lib ..\..\pango\pangoft2-1.0.lib
+
+libpango-$(MODULE)-fc.dll : $(OBJECTS) ..\module.def
+ $(CC) $(CFLAGS) -LD -Fe$@ $(OBJECTS) $(LINKS) $(LDFLAGS) /def:..\module.def
+
+# MODULE
+!ENDIF
diff --git a/trunk/modules/module.def b/trunk/modules/module.def
new file mode 100644
index 00000000..6e673874
--- /dev/null
+++ b/trunk/modules/module.def
@@ -0,0 +1,5 @@
+EXPORTS
+ script_engine_create
+ script_engine_list
+ script_engine_init
+ script_engine_exit
diff --git a/trunk/modules/pangorc b/trunk/modules/pangorc
new file mode 100644
index 00000000..3b60eceb
--- /dev/null
+++ b/trunk/modules/pangorc
@@ -0,0 +1,8 @@
+#
+# pangorc file for uninstalled operation.
+# We set the path as ../modules, such that it works from any of
+# top level build subdirs.
+#
+
+[Pango]
+ModuleFiles = ../modules/pango.modules
diff --git a/trunk/modules/syriac/Makefile.am b/trunk/modules/syriac/Makefile.am
new file mode 100644
index 00000000..fd9b2a97
--- /dev/null
+++ b/trunk/modules/syriac/Makefile.am
@@ -0,0 +1,23 @@
+include $(top_srcdir)/modules/Module.mk
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_SYRIAC_FC
+noinst_LTLIBRARIES += libpango-syriac-fc.la
+else
+if DYNAMIC_SYRIAC_FC
+module_LTLIBRARIES += pango-syriac-fc.la
+endif
+endif
+endif
+
+fc_sources = \
+ syriac-fc.c \
+ syriac-ot.c \
+ syriac-ot.h
+
+pango_syriac_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_syriac_fc_la_LIBADD = $(pangoft2libs)
+pango_syriac_fc_la_SOURCES = $(fc_sources)
+libpango_syriac_fc_la_SOURCES = $(fc_sources)
+libpango_syriac_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_syriac_fc
diff --git a/trunk/modules/syriac/syriac-fc.c b/trunk/modules/syriac/syriac-fc.c
new file mode 100644
index 00000000..0e0837d0
--- /dev/null
+++ b/trunk/modules/syriac/syriac-fc.c
@@ -0,0 +1,212 @@
+/* Pango
+ * syriac-fc.h:
+ *
+ * Copyright (C) 2000, 2003, 2007 Red Hat Software
+ * Copyright (C) 2004 Emil Soleyman-Zomalan
+ * Authors:
+ * Owen Taylor <otaylor@redhat.com>
+ * Emil Soleyman-Zomalan <emil@soleyman.com>
+ * Behdad Esfahbod <behdad@behdad.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#include <string.h>
+
+#include "syriac-ot.h"
+
+#include "pango-engine.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape SyriacEngineFc;
+typedef PangoEngineShapeClass SyriacEngineFcClass ;
+
+#define SCRIPT_ENGINE_NAME "SyriacScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+static PangoEngineScriptInfo syriac_scripts[] = {
+ { PANGO_SCRIPT_SYRIAC, "*" },
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ syriac_scripts, G_N_ELEMENTS(syriac_scripts)
+ }
+};
+
+static const PangoOTFeatureMap gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"isol", isolated},
+ {"fina", final},
+ {"fin2", final2},
+ {"fin3", final3},
+ {"medi", medial},
+ {"med2", medial2},
+ {"init", initial},
+ {"rlig", PANGO_OT_ALL_GLYPHS},
+ {"calt", PANGO_OT_ALL_GLYPHS},
+ {"liga", PANGO_OT_ALL_GLYPHS},
+ /* 'dlig' should be turned-on/off-able. lets turn off for now. */
+ /* {"dlig", PANGO_OT_ALL_GLYPHS}, */
+};
+
+static const PangoOTFeatureMap gpos_features[] =
+{
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
+
+static void
+syriac_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ PangoFcFont *fc_font;
+ FT_Face face;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ gulong *properties = NULL;
+ glong n_chars;
+ gunichar *wcs;
+ const char *p;
+ int cluster = 0;
+ int i;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return;
+
+ buffer = pango_ot_buffer_new (fc_font);
+ pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
+ pango_ot_buffer_set_zero_width_marks (buffer, TRUE);
+
+ wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);
+ properties = g_new0 (gulong, n_chars);
+
+ syriac_assign_properties (wcs, properties, n_chars);
+
+ g_free (wcs);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ gunichar wc;
+ PangoGlyph glyph;
+
+ wc = g_utf8_get_char (p);
+
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
+
+ if (pango_is_zero_width (wc))
+ glyph = PANGO_GLYPH_EMPTY;
+ else
+ {
+ gunichar c = wc;
+
+ if (analysis->level % 2)
+ g_unichar_get_mirror_char (c, &c);
+
+ glyph = pango_fc_font_get_glyph (fc_font, c);
+ }
+
+ if (!glyph)
+ glyph = PANGO_GET_UNKNOWN_GLYPH (wc);
+
+ pango_ot_buffer_add_glyph (buffer, glyph, properties[i], cluster);
+
+ p = g_utf8_next_char (p);
+ }
+
+ g_free (properties);
+
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
+ desc.static_gsub_features = gsub_features;
+ desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
+ desc.static_gpos_features = gpos_features;
+
+ /* TODO populate other_features from analysis->extra_attrs */
+ desc.n_other_features = 0;
+ desc.other_features = NULL;
+
+ ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
+
+ pango_ot_ruleset_substitute (ruleset, buffer);
+ pango_ot_ruleset_position (ruleset, buffer);
+ pango_ot_buffer_output (buffer, glyphs);
+
+ pango_ot_buffer_destroy (buffer);
+
+ pango_fc_font_unlock_face (fc_font);
+}
+
+static void
+syriac_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = syriac_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (SyriacEngineFc, syriac_engine_fc,
+ syriac_engine_fc_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ syriac_engine_fc_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (syriac_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/syriac/syriac-ot.c b/trunk/modules/syriac/syriac-ot.c
new file mode 100644
index 00000000..30995021
--- /dev/null
+++ b/trunk/modules/syriac/syriac-ot.c
@@ -0,0 +1,361 @@
+/* Pango
+ * syriac-ot.h: Determine what OpenType features to apply to characters based
+ * on the rules for Syriac from the OpenType standard.
+ *
+ * Copyright (C) 2004 Emil Soleyman-Zomalan
+ * Author: Emil Soleyman-Zomalan <emil@soleyman.com>
+ *
+ * This file is based on the Arabic shaping code from FreeType 1 tree; original
+ * copyright notice:
+ *
+ * The FreeType project -- a free and portable quality TrueType renderer.
+ *
+ * Copyright 1996-2000 by
+ * D. Turner, R.Wilhelm, and W. Lemberg
+ *
+ * The code, like the FreeType code it is derived from is dual-licensed
+ * under the GNU General Public License and the FreeType license. See
+ * pango/opentype/COPYING for full details of this licensing scheme.
+ */
+#include <config.h>
+#include "syriac-ot.h"
+
+/* Here a table of the joining classes for characters in the range
+ * U+0700 - U+074F.
+ *
+ * The following character also has a joining class:
+ *
+ * U+200C ZERO WIDTH NON-JOINER -> causing
+ *
+ * All other characters are given the joining class `none'.
+ */
+static const JoiningClass syriac[] =
+{
+ /* U+0700 */
+ none, none, none, none,
+ none, none, none, none,
+ none, none, none, none,
+ none, none, none, transparent,
+
+ /* U+0710 */
+ right, none, dual, dual,
+ dual, right, right, right,
+ right, right, dual, dual,
+ dual, dual, right, dual,
+
+ /* U+0720 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ right, dual, right, dual,
+ right, none, none, none,
+
+ /* U+0730 */
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+
+ /* U+0740 */
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, none,
+ none, right, dual, dual
+};
+
+/* `direction' can be -1, 0, or 1 to indicate the last non-transparent
+ * glyph, the current glyph, and the next non-transparent glyph,
+ * respectively.
+ */
+static JoiningClass
+Get_Joining_Class (gunichar* string,
+ int pos,
+ int length,
+ int direction)
+{
+ JoiningClass j;
+
+ while (1)
+ {
+ if (pos == 0 && direction < 0)
+ return none;
+
+ pos += direction;
+
+ if (pos >= length)
+ return none;
+
+ if (string[pos] < 0x0700 ||
+ string[pos] >= 0x074F)
+ {
+ if (string[pos] == 0x200C)
+ return causing;
+ else
+ return none;
+ }
+ else
+ j = syriac[string[pos] - 0x0700];
+
+ if (!direction || j != transparent)
+ return j;
+ }
+}
+
+
+/* The rules here are roughly based on the Arabic rules from the Unicode
+ * 2.0 standard (which differ from the Unicode-4.0 rules), augmented
+ * with the Syriac rules from the Unicode-4.0 standard. The numbers
+ * R1...R11 below do not correspond to either the Arabic or the Syriac
+ * rule numbering from the Unicode standard.
+ *
+ * Characters are here specified as appearing in the byte stream, i.e.
+ * *not* in visual order. Joining classes are given in angle brackets,
+ * glyph forms in square brackets. Glyphs affected by a specific rule are
+ * enclosed with vertical bars.
+ *
+ *
+ * Glyphs: 0x0715 (Dalath), 0x0716 (Dalath Rish), 0x072A (Rish),
+ * 0x0722 (Nun), 0x071F (Kaph)
+ *
+ *
+ * R1: <anything1> <transparent> <anything2>
+ *
+ * apply joining rules for
+ * <anything1> <anything2> -> [shape1] [shape2]
+ * -> [shape1] [isolated] [shape2]
+ *
+ *
+ * R2: <causing|right> <0x0722|0x071F> <!(causing|right|dual)>
+ * -> [isolated]
+ *
+ * The Nun and Kaph characters each have 3 different glyphs
+ * with two of those glyphs coming at the final position.
+ * However, one of those final glyphs should really be of the
+ * isolated glyph form where the preceding character cannot be
+ * joined to and there is no next character.
+ *
+ * This rule exists to combine similar exception for both
+ * characters without increasing the complexity in the other
+ * rules.
+ *
+ *
+ * R3: <causing|right|dual> && <!(0x0715|0x0716|0x072A)> |<alaph>|
+ *
+ * -> [final2]
+ *
+ * If the preceding glyph cannot be joined to the current
+ * glyph and the preceding character is not a Dalath, Rish,
+ * or Dotless Dalath Rish, then the Alaph takes this contextual
+ * position.
+ *
+ * The [final2] joining rule is placed ahead of the [final] to
+ * give it greater precedence when choosing the correct glyph.
+ * If it comes after the [final] rule, the incorrect glyph is
+ * inserted into position.
+ *
+ *
+ * R4: <0x0715|0x0715|0x072A> |<alaph>|
+ *
+ * -> [final3]
+ *
+ * If the previous glyph is a Dalath, Rish, or Dotless Dalath
+ * Rish, then the Alaph takes this contextual position.
+ *
+ * The [final3] joining rule is placed ahead of the [final] to
+ * give it greater precedence when choosing the correct glyph.
+ * If it comes after the [final] rule, the incorrect glyph is
+ * inserted into position.
+ *
+ *
+ * R5: <causing|right|dual> |<right>|
+ *
+ * -> [final]
+ *
+ *
+ * R6: <causing|right|dual> |<dual>| <!(causing|right|dual)>
+ *
+ * -> [final]
+ *
+ *
+ * R7: <causing|left|dual> |<dual>| <causing|right|dual>
+ *
+ * -> [medial]
+ *
+ *
+ * R8: <causing|right> |<alaph>| <causing|right|dual>
+ *
+ * -> [medial2]
+ *
+ * If the Alaph glyph falls in the middle of a Syriac word and
+ * the preceding character cannot be joined to, then the Alaph
+ * takes this contextual position.
+ *
+ *
+ * R9: |<left>| <causing|right|dual>
+ *
+ * -> [initial]
+ *
+ *
+ * R10: <!(causing|left|dual)> |<dual>| <causing|right|dual>
+ *
+ * -> [initial]
+ *
+ *
+ * R11: <anything> -> [isolated]
+ *
+ * This joining rule is placed at the end of these features
+ * because when it is placed at the beginning of all of them
+ * it tends to break the cursive nature of Syriac writing --
+ * it inserts the isolated glyph of each character into that
+ * position with no joining occurring all throughout a text
+ * document.
+ */
+
+FT_Error
+syriac_assign_properties (gunichar *string,
+ gulong *properties,
+ int length)
+{
+ JoiningClass previous, current, next;
+ int i;
+
+ if (!string || !properties || length == 0)
+ return FT_Err_Invalid_Argument;
+
+ for (i = 0; i < length; i++)
+ {
+ previous = Get_Joining_Class (string, i, length, -1);
+ current = Get_Joining_Class (string, i, length, 0);
+ next = Get_Joining_Class (string, i, length, 1);
+
+ /* R1 */
+
+ if (current == transparent)
+ {
+ properties[i] |= isolated_p;
+ continue;
+ }
+
+ /* R2 */
+
+ if (string[i] == 0x0722 ||
+ string[i] == 0x071F)
+ if (previous == causing ||
+ previous == right)
+ if (!(next == causing ||
+ next == right ||
+ next == dual))
+ {
+ properties[i] |= isolated_p;
+ continue;
+ }
+
+ /* R3 */
+
+ if (string[i] == 0x0710)
+ if (previous == causing ||
+ previous == right)
+ if (!(string[i - 1] == 0x0715 ||
+ string[i - 1] == 0x0716 ||
+ string[i - 1] == 0x072A))
+ {
+ properties[i] |= final2_p;
+ continue;
+ }
+
+ /* R4 */
+
+ if (string[i] == 0x0710)
+ if (previous == causing ||
+ previous == right)
+ if (string[i - 1] == 0x0715 ||
+ string[i - 1] == 0x0716 ||
+ string[i - 1] == 0x072A)
+ {
+ properties[i] |= final3_p;
+ continue;
+ }
+
+ /* R5 */
+
+ if (previous == causing ||
+ previous == right ||
+ previous == dual)
+ if (current == right)
+ {
+ properties[i] |= final_p;
+ continue;
+ }
+
+ /* R6 */
+
+ if (previous == causing ||
+ previous == right ||
+ previous == dual)
+ if (current == dual)
+ if (!(next == causing ||
+ next == right ||
+ next == dual ))
+ {
+ properties[i] |= final_p;
+ continue;
+ }
+
+ /* R7 */
+
+ if (previous == causing ||
+ previous == left ||
+ previous == dual)
+ if (current == dual)
+ if (next == causing ||
+ next == right ||
+ next == dual )
+ {
+ properties[i] |= medial_p;
+ continue;
+ }
+
+ /* R8 */
+
+ if (string[i] == 0x0710)
+ if (previous == causing ||
+ previous == right)
+ if (next == causing ||
+ next == right ||
+ next == dual)
+ {
+ properties[i] |= medial2_p;
+ continue;
+ }
+
+ /* R9 */
+
+ if (current == left)
+ if (next == causing ||
+ next == right ||
+ next == dual)
+ {
+ properties[i] |= initial_p;
+ continue;
+ }
+
+ /* R10 */
+
+ if (!(previous == causing ||
+ previous == left ||
+ previous == dual ))
+ if (current == dual)
+ if (next == causing ||
+ next == right ||
+ next == dual)
+ {
+ properties[i] |= initial_p;
+ continue;
+ }
+
+ /* R11 */
+
+ properties[i] |= isolated_p;
+ }
+
+ return FT_Err_Ok;
+}
diff --git a/trunk/modules/syriac/syriac-ot.h b/trunk/modules/syriac/syriac-ot.h
new file mode 100644
index 00000000..e9aea543
--- /dev/null
+++ b/trunk/modules/syriac/syriac-ot.h
@@ -0,0 +1,69 @@
+/* Pango
+ * syriac-ot.h: Determine what OpenType features to apply to characters based
+ * on the rules for Syriac from the OpenType standard.
+ *
+ * Copyright (C) 2004 Emil Soleyman-Zomalan
+ * Author: Emil Soleyman-Zomalan <emil@soleyman.com>
+ *
+ * This file is based on the Arabic shaping code from FreeType 1 tree; original
+ * copyright notice:
+ *
+ * The FreeType project -- a free and portable quality TrueType renderer.
+ *
+ * Copyright 1996-2000 by
+ * D. Turner, R.Wilhelm, and W. Lemberg
+ *
+ * The code, like the FreeType code it is derived from is dual-licensed
+ * under the GNU Public License and the FreeType license. See see
+ * pango/opentype/FT-license.txt for full details of the FreeType
+ * license.
+ */
+
+#ifndef __SYRIAC_OT_H__
+#define __SYRIAC_OT_H__
+
+#include <pango/pango-ot.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ isolated = 1 << 0, /* nominal */
+ final = 1 << 1, /* right_joining */
+ initial = 1 << 2, /* left_joining */
+ medial = 1 << 3, /* double_joining */
+ medial2 = 1 << 4, /* double_joining, applies to Alaph only */
+ final2 = 1 << 5, /* right_joining, applies to Alaph only */
+ final3 = 1 << 6 /* right_joining, applies to Alaph only */
+} JoiningType;
+
+/* A glyph's property value as needed by e.g. TT_GSUB_Apply_String()
+ specifies which features should *not* be applied */
+typedef enum
+{
+ isolated_p = final | initial | medial | medial2 | final2 | final3,
+ final_p = isolated | initial | medial | medial2 | final2 | final3,
+ initial_p = isolated | final | medial | medial2 | final2 | final3,
+ medial_p = isolated | final | initial | medial2 | final2 | final3,
+ medial2_p = isolated | final | initial | medial | final2 | final3,
+ final2_p = isolated | final | initial | medial | medial2 | final3,
+ final3_p = isolated | final | initial | medial | medial2 | final2
+} SyriacGlyphForm;
+
+typedef enum
+{
+ right,
+ left, /* not used */
+ dual,
+ causing,
+ none,
+ transparent
+} JoiningClass;
+
+FT_Error syriac_assign_properties (gunichar *string,
+ gulong *properties,
+ int length);
+
+G_END_DECLS
+
+#endif /* __SYRIAC_OT_H__ */
diff --git a/trunk/modules/thai/Makefile.am b/trunk/modules/thai/Makefile.am
new file mode 100644
index 00000000..e46f2573
--- /dev/null
+++ b/trunk/modules/thai/Makefile.am
@@ -0,0 +1,41 @@
+include $(top_srcdir)/modules/Module.mk
+
+shaper_sources = thai-charprop.c thai-charprop.h thai-shaper.c thai-shaper.h
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_THAI_FC
+noinst_LTLIBRARIES += libpango-thai-fc.la
+else
+if DYNAMIC_THAI_FC
+module_LTLIBRARIES += pango-thai-fc.la
+endif
+endif
+endif
+
+thai_fc_sources = $(shaper_sources) thai-fc.c
+
+pango_thai_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_thai_fc_la_LIBADD = $(pangoft2libs)
+pango_thai_fc_la_SOURCES = $(thai_fc_sources)
+libpango_thai_fc_la_SOURCES = $(thai_fc_sources)
+libpango_thai_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_thai_fc
+
+
+if INCLUDE_THAI_LANG
+noinst_LTLIBRARIES += libpango-thai-lang.la
+else
+if DYNAMIC_THAI_LANG
+module_LTLIBRARIES += pango-thai-lang.la
+endif
+endif
+
+lang_sources = \
+ thai-lang.c
+
+pango_thai_lang_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_thai_lang_la_LIBADD = $(pangolibs) $(LIBTHAI_LIBS)
+pango_thai_lang_la_SOURCES = $(lang_sources)
+libpango_thai_lang_la_SOURCES = $(lang_sources)
+libpango_thai_lang_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_thai_lang $(LIBTHAI_CFLAGS)
+libpango_thai_lang_la_LIBADD = $(LIBTHAI_LIBS)
diff --git a/trunk/modules/thai/thai-charprop.c b/trunk/modules/thai/thai-charprop.c
new file mode 100644
index 00000000..26e13318
--- /dev/null
+++ b/trunk/modules/thai/thai-charprop.c
@@ -0,0 +1,164 @@
+/* Pango
+ * thai-charprop.c: character property tables
+ *
+ * Copyright (C) 2004 Theppitak Karoonboonyanan
+ * Copyright (C) 2002 Software and Language Engineering Laboratory, NECTEC
+ * Author: Theppitak Karoonboonyanan <thep@linux.thai.net>
+ *
+ * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
+ * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#include "thai-charprop.h"
+
+const gshort thai_char_type[256] = {
+ /* 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, A, B, C, D, E, F */
+
+ /* CL1 */
+ /*00*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ /*10*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+
+ /* Lao zone: [U+0E80..U+0EDF] */
+ /*20*/ _ND, _NC, _NC, _ND, _NC, _ND, _ND, _NC,
+ _NC, _ND, _NC, _ND, _ND, _NC, _ND, _ND,
+ /*30*/ _ND, _ND, _ND, _ND, _NC, _NC, _NC, _NC,
+ _ND, _NC, _NC, _UC, _NC, _UC, _NC, _UC,
+ /*40*/ _ND, _NC, _UC, _NC, _ND, _NC, _ND, _NC,
+ _ND, _ND, _NC, _NC, _ND, _NC, _NC, _ND,
+ /*50*/ _ND, _AV, _ND, _AM, _AV, _AV, _AV, _AV,
+ _BV, _BV, _ND, _AV, _BD, _NC, _ND, _ND,
+ /*60*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _AD,
+ _TN, _TN, _TN, _TN, _AD, _AD, _ND, _ND,
+ /*70*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _NC, _NC, _ND, _ND,
+
+ /* CL2 */
+ /*80*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ /*90*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+
+ /* Thai zone: [U+0E00..U+0E5F] */
+ /*A0*/ _ND, _NC, _NC, _NC, _NC, _NC, _NC, _NC,
+ _NC, _NC, _NC, _NC, _NC, _SC, _BC, _BC,
+ /*B0*/ _SC, _NC, _NC, _NC, _NC, _NC, _NC, _NC,
+ _NC, _NC, _NC, _UC, _NC, _UC, _NC, _UC,
+ /*C0*/ _NC, _NC, _NC, _NC, _ND, _NC, _ND, _NC,
+ _NC, _NC, _NC, _NC, _UC, _NC, _NC, _ND,
+ /*D0*/ _ND, _AV, _ND, _AM, _AV, _AV, _AV, _AV,
+ _BV, _BV, _BD, _ND, _ND, _ND, _ND, _ND,
+ /*E0*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _AD,
+ _TN, _TN, _TN, _TN, _AD, _AD, _AD, _ND,
+ /*F0*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+};
+
+const gshort thai_TAC_char_class[256] = {
+ /* 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, A, B, C, D, E, F */
+
+ /* CL1 */
+ /*00*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+ /*10*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+
+ /* Lao zone: [U+0E80..U+0EDF] */
+ /*20*/ NON,CONS,CONS, NON,CONS, NON, NON,CONS,
+ CONS, NON,CONS, NON, NON,CONS, NON, NON,
+ /*30*/ NON, NON, NON, NON,CONS,CONS,CONS,CONS,
+ NON,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+ /*40*/ NON,CONS,CONS,CONS, NON,CONS, NON,CONS,
+ NON, NON,CONS,CONS, NON,CONS,CONS, NON,
+ /*50*/ FV1, AV2, FV1, AM, AV1, AV3, AV2, AV3,
+ BV1, BV2, NON, AV2,BCON, FV3, NON, NON,
+ /*60*/ LV, LV, LV, LV, LV, NON, NON, NON,
+ TONE,TONE,TONE,TONE, AD1, AD4, NON, NON,
+ /*70*/ NON, NON, NON, NON, NON, NON, NON, NON,
+ NON, NON, NON, NON,CONS,CONS, NON,CTRL,
+
+ /* CL2 */
+ /*80*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+ /*90*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+
+ /* Thai zone: [U+0E00..U+0E5F] */
+ /*A0*/ NON,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+ CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+ /*B0*/ CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+ CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+ /*C0*/ CONS,CONS,CONS,CONS, FV3,CONS, FV3,CONS,
+ CONS,CONS,CONS,CONS,CONS,CONS,CONS, NON,
+ /*D0*/ FV1, AV2, FV1, AM, AV1, AV3, AV2, AV3,
+ BV1, BV2, BD, NON, NON, NON, NON, NON,
+ /*E0*/ LV, LV, LV, LV, LV, FV2, NON, AD2,
+ TONE,TONE,TONE,TONE, AD1, AD4, AD3, NON,
+ /*F0*/ NON, NON, NON, NON, NON, NON, NON, NON,
+ NON, NON, NON, NON, NON, NON, NON,CTRL,
+};
+
+const gchar thai_TAC_compose_input[20][20] = {
+ /* row: Cn-1, column: Cn */
+ /*CTRL NON CONS LV FV1 FV2 FV3 AM BV1 BV2
+ * BD TONE AD1 AD2 AD3 AD4 AV1 AV2 AV3 BCON*/
+/*CTRL*/{'X','A','A','A','A','A','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*NON */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*CONS*/{'X','A','A','A','A','S','A','C','C','C',
+ 'C','C','C','C','C','C','C','C','C','C'},
+/*LV */{'X','S','A','S','S','S','S','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*FV1 */{'X','A','A','A','A','S','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*FV2 */{'X','A','A','A','A','S','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*FV3 */{'X','A','A','A','S','A','S','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*AM */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*BV1 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','C','C','R','R','C','R','R','R','R'},
+/*BV2 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','C','R','R','R','R','R','R','R','R'},
+/*BD */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*TONE*/{'X','A','A','A','A','A','A','C','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*AD1 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*AD2 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*AD3 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','R','R','R','R','R','R','R','R','R'},
+/*AD4 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','C','R','R','R','R','R','R','R','R'},
+/*AV1 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','C','C','R','R','C','R','R','R','R'},
+/*AV2 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','C','R','R','R','R','R','R','R','R'},
+/*AV3 */{'X','A','A','A','S','S','A','R','R','R',
+ 'R','C','R','C','R','R','R','R','R','R'},
+/*BCON*/{'X','A','A','A','A','S','A','C','C','C',
+ 'R','C','R','R','R','C','C','C','C','R'},
+};
+
diff --git a/trunk/modules/thai/thai-charprop.h b/trunk/modules/thai/thai-charprop.h
new file mode 100644
index 00000000..98a8f8d2
--- /dev/null
+++ b/trunk/modules/thai/thai-charprop.h
@@ -0,0 +1,99 @@
+/* Pango
+ * thai-charprop.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Author: Owen Taylor <otaylor@redhat.com>
+ *
+ * Copyright (C) 2004 Theppitak Karoonboonyanan
+ * Copyright (C) 2002 Software and Language Engineering Laboratory, NECTEC
+ * Author: Theppitak Karoonboonyanan <thep@linux.thai.net>
+ *
+ * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
+ * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __THAI_CHARPROP_H__
+#define __THAI_CHARPROP_H__
+
+#include <glib.h>
+
+#define isthai(wc) (0x0E00 <= (wc) && (wc) < 0x0E60)
+#define islao(wc) (0x0E80 <= (wc) && (wc) < 0x0EE0)
+/* ucs2tis()
+ * Lao: [0x0E80..0x0EDF] -> [0x20..0x7F]
+ * Thai: [0x0E00..0x0E5F] -> [0xA0..0xFF]
+ */
+#define ucs2tis(wc) (((wc) - 0x0E00 + 0x20)^0x80)
+
+/* Define TACTIS character classes */
+#define CTRL 0
+#define NON 1
+#define CONS 2
+#define LV 3
+#define FV1 4
+#define FV2 5
+#define FV3 6
+#define AM 7
+#define BV1 8
+#define BV2 9
+#define BD 10
+#define TONE 11
+#define AD1 12
+#define AD2 13
+#define AD3 14
+#define AD4 15
+#define AV1 16
+#define AV2 17
+#define AV3 18
+#define BCON 19
+
+#define _ND 0
+#define _NC 1
+#define _UC (1<<1)
+#define _BC (1<<2)
+#define _SC (1<<3)
+#define _AV (1<<4)
+#define _BV (1<<5)
+#define _TN (1<<6)
+#define _AD (1<<7)
+#define _BD (1<<8)
+#define _AM (1<<9)
+
+#define NoTailCons _NC
+#define UpTailCons _UC
+#define BotTailCons _BC
+#define SpltTailCons _SC
+#define Cons (NoTailCons|UpTailCons|BotTailCons|SpltTailCons)
+#define AboveVowel _AV
+#define BelowVowel _BV
+#define Tone _TN
+#define AboveDiac _AD
+#define BelowDiac _BD
+#define SaraAm _AM
+
+#define is_char_type(wc, mask) (thai_char_type[ucs2tis ((wc))] & (mask))
+#define TAC_char_class(wc) \
+ (isthai(wc)||islao(wc) ? thai_TAC_char_class[ucs2tis (wc)] : NON)
+#define TAC_compose_input(wc1,wc2) \
+ thai_TAC_compose_input[TAC_char_class(wc1)][TAC_char_class(wc2)]
+
+extern const gshort thai_char_type[256];
+extern const gshort thai_TAC_char_class[256];
+extern const gchar thai_TAC_compose_input[20][20];
+
+#endif /* __THAI_CHARPROP_H__ */
diff --git a/trunk/modules/thai/thai-fc.c b/trunk/modules/thai/thai-fc.c
new file mode 100644
index 00000000..7fe2492c
--- /dev/null
+++ b/trunk/modules/thai/thai-fc.c
@@ -0,0 +1,355 @@
+/* Pango
+ * thai-fc.c:
+ *
+ * Copyright (C) 1999, 2007 Red Hat Software
+ * Copyright (C) 2002 NECTEC
+ * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
+ * Authors:
+ * Owen Taylor <otaylor@redhat.com>
+ * Theppitak Karoonboonyanan <thep@links.nectec.or.th>
+ * Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
+ * Behdad Esfahbod <behdad@behdad.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <config.h>
+#include <string.h>
+
+#include <glib.h>
+#include "pango-ot.h"
+#include "pango-engine.h"
+#include "pangofc-font.h"
+
+#include "thai-shaper.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape ThaiEngineFc;
+typedef PangoEngineShapeClass ThaiEngineFcClass ;
+
+#define SCRIPT_ENGINE_NAME "ThaiScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+/* We handle the range U+0e01 to U+0e5b exactly
+ */
+static PangoEngineScriptInfo thai_scripts[] = {
+ { PANGO_SCRIPT_THAI, "*" },
+ { PANGO_SCRIPT_LAO, "*" },
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ thai_scripts, G_N_ELEMENTS(thai_scripts)
+ }
+};
+
+/* TIS-to-Unicode glyph maps for characters 0x80-0xff
+ */
+static const int tis620_0[128] = {
+ /**/ 0, 0, 0, 0, 0, 0, 0, 0,
+ /**/ 0, 0, 0, 0, 0, 0, 0, 0,
+ /**/ 0, 0, 0, 0, 0, 0, 0, 0,
+ /**/ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x0020, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
+ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
+ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
+ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
+ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
+ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
+ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
+ 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
+ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
+ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
+ 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0, 0, 0, 0
+};
+
+static const int tis620_1[128] = {
+ 0xf89e, 0, 0, 0xf88c, 0xf88f, 0xf892, 0xf895, 0xf898,
+ 0xf88b, 0xf88e, 0xf891, 0xf894, 0xf897, 0, 0, 0xf899,
+ 0xf89a, 0, 0xf884, 0xf889, 0xf885, 0xf886, 0xf887, 0xf888,
+ 0xf88a, 0xf88d, 0xf890, 0xf893, 0xf896, 0, 0, 0,
+ /**/ 0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
+ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
+ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
+ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
+ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
+ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
+ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
+ 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
+ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0, 0x0e4f,
+ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
+ 0x0e58, 0x0e59, 0, 0, 0xf89b, 0xf89c, 0xf89d, 0
+};
+
+static const int tis620_2[128] = {
+ 0xf700, 0xf701, 0xf702, 0xf703, 0xf704, 0x2026, 0xf705, 0xf706,
+ 0xf707, 0xf708, 0xf709, 0xf70a, 0xf70b, 0xf70c, 0xf70d, 0xf70e,
+ 0xf70f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+ 0xf710, 0xf711, 0xf712, 0xf713, 0xf714, 0xf715, 0xf716, 0xf717,
+ 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
+ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
+ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
+ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
+ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
+ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
+ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
+ 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
+ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
+ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
+ 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xf718, 0xf719, 0xf71a, 0
+};
+
+static const int lao_0[128] = {
+ /**/ 0, 0, 0, 0, 0, 0, 0, 0,
+ /**/ 0, 0, 0, 0, 0, 0, 0, 0,
+ /**/ 0, 0, 0, 0, 0, 0, 0, 0,
+ /**/ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x0020, 0x0e81, 0x0e82, 0, 0x0e84, 0, 0, 0x0e87,
+ 0x0e88, 0, 0x0e8a, 0, 0, 0x0e8d, 0, 0,
+ 0, 0, 0, 0, 0x0e94, 0x0e95, 0x0e96, 0x0e97,
+ /**/ 0, 0x0e99, 0x0e9a, 0x0e9b, 0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f,
+ /**/ 0, 0x0ea1, 0x0ea2, 0x0ea3, 0, 0x0ea5, 0, 0x0ea7,
+ /**/ 0, 0, 0x0eaa, 0x0eab, 0, 0x0ead, 0x0eae, 0x0eaf,
+ 0x0eb0, 0x0eb1, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7,
+ 0x0eb8, 0x0eb9, 0, 0x0ebb, 0x0ebc, 0x0ebd, 0, 0,
+ 0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0, 0x0ec6, 0,
+ 0x0ec8, 0x0ec9, 0x0eca, 0x0ecb, 0x0ecc, 0x0ecd, 0, 0,
+ 0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7,
+ 0x0ed8, 0x0ed9, 0, 0, 0x0edc, 0x0edd, 0, 0
+};
+static int
+contain_glyphs(PangoFont *font, const int glyph_map[128])
+{
+ PangoFcFont *fc_font = (PangoFcFont *)font;
+ unsigned char c;
+
+ for (c = 0; c < 0x80; c++)
+ {
+ if (glyph_map[c])
+ {
+ if (!pango_fc_font_has_char (fc_font, glyph_map[c]))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Returns a structure with information we will use to rendering given the
+ * #PangoFont. This is computed once per font and cached for later retrieval.
+ */
+static ThaiFontInfo *
+thai_get_font_info (PangoFont *font,
+ const PangoOTRuleset *ruleset)
+{
+ ThaiFontInfo *font_info;
+ static GQuark info_id = 0;
+
+ if (G_UNLIKELY (!info_id))
+ info_id = g_quark_from_string ("thai-font-info");
+
+ font_info = g_object_get_qdata (G_OBJECT (font), info_id);
+
+ if (G_UNLIKELY (!font_info))
+ {
+ /* No cached information not found, so we need to compute it
+ * from scratch
+ */
+ font_info = g_new (ThaiFontInfo, 1);
+ font_info->font = font;
+
+ /* detect font set by determining availibility of OT ruleset & glyphs */
+ if (pango_ot_ruleset_get_feature_count (ruleset, NULL, NULL))
+ font_info->font_set = THAI_FONT_TIS;
+ else if (contain_glyphs(font, tis620_2))
+ font_info->font_set = THAI_FONT_TIS_WIN;
+ else if (contain_glyphs(font, tis620_1))
+ font_info->font_set = THAI_FONT_TIS_MAC;
+ else
+ font_info->font_set = THAI_FONT_TIS;
+
+ g_object_set_qdata_full (G_OBJECT (font), info_id, font_info, (GDestroyNotify)g_free);
+ }
+
+ return font_info;
+}
+
+static gunichar
+get_glyph_index_tis (ThaiFontInfo *font_info, guchar c)
+{
+ if (!(c & 0x80))
+ return lao_0[c];
+
+ switch (font_info->font_set) {
+ case THAI_FONT_TIS: return tis620_0[c & 0x7f];
+ case THAI_FONT_TIS_MAC: return tis620_1[c & 0x7f];
+ case THAI_FONT_TIS_WIN: return tis620_2[c & 0x7f];
+ default: return 0;
+ }
+}
+
+PangoGlyph
+thai_get_glyph_tis (ThaiFontInfo *font_info, guchar c)
+{
+ return thai_get_glyph_uni (font_info, get_glyph_index_tis (font_info, c));
+}
+
+PangoGlyph
+thai_make_glyph_tis (ThaiFontInfo *font_info, guchar c)
+{
+ return thai_make_glyph_uni (font_info, get_glyph_index_tis (font_info, c));
+}
+
+PangoGlyph
+thai_get_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
+{
+ return pango_fc_font_get_glyph ((PangoFcFont *)font_info->font, uc);
+}
+
+PangoGlyph
+thai_make_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
+{
+ PangoGlyph result;
+ PangoFcFont *fc_font = (PangoFcFont *)font_info->font;
+
+ result = pango_fc_font_get_glyph (fc_font, uc);
+ if (result)
+ return result;
+ else
+ return PANGO_GET_UNKNOWN_GLYPH ( uc);
+}
+
+static const PangoOTFeatureMap gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"liga", PANGO_OT_ALL_GLYPHS},
+};
+
+static const PangoOTFeatureMap gpos_features[] =
+{
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
+
+static void
+thai_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ PangoFcFont *fc_font;
+ FT_Face face;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ gint i;
+ ThaiFontInfo *font_info;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return;
+
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
+ desc.static_gsub_features = gsub_features;
+ desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
+ desc.static_gpos_features = gpos_features;
+
+ /* TODO populate other_features from analysis->extra_attrs */
+ desc.n_other_features = 0;
+ desc.other_features = NULL;
+
+ ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
+
+ font_info = thai_get_font_info (font, ruleset);
+
+ thai_set_glyphs (font_info, text, length, analysis->script, glyphs);
+
+ buffer = pango_ot_buffer_new (PANGO_FC_FONT (font));
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ pango_ot_buffer_add_glyph (buffer,
+ glyphs->glyphs[i].glyph,
+ 0,
+ glyphs->log_clusters[i]);
+
+ pango_ot_ruleset_substitute (ruleset, buffer);
+ pango_ot_ruleset_position (ruleset, buffer);
+
+ pango_ot_buffer_output (buffer, glyphs);
+ pango_ot_buffer_destroy (buffer);
+}
+
+PangoGlyph
+thai_make_unknown_glyph (ThaiFontInfo *font_info, gunichar uc)
+{
+ return PANGO_GET_UNKNOWN_GLYPH (uc);
+}
+
+static void
+thai_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = thai_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (ThaiEngineFc, thai_engine_fc,
+ thai_engine_fc_class_init, NULL)
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ thai_engine_fc_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (thai_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/modules/thai/thai-lang.c b/trunk/modules/thai/thai-lang.c
new file mode 100644
index 00000000..83d16428
--- /dev/null
+++ b/trunk/modules/thai/thai-lang.c
@@ -0,0 +1,139 @@
+/* Pango
+ * thai-lang.c:
+ *
+ * Copyright (C) 2003 Theppitak Karoonboonyanan <thep@linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include <string.h>
+#include <glib.h>
+#include <pango/pango-engine.h>
+#include <pango/pango-break.h>
+#include <thai/thwchar.h>
+#include <thai/thbrk.h>
+
+/* No extra fields needed */
+typedef PangoEngineLang ThaiEngineLang;
+typedef PangoEngineLangClass ThaiEngineLangClass;
+
+#define SCRIPT_ENGINE_NAME "ThaiScriptEngineLang"
+
+static PangoEngineScriptInfo thai_scripts[] = {
+ { PANGO_SCRIPT_THAI, "*" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_LANG,
+ PANGO_RENDER_TYPE_NONE,
+ thai_scripts, G_N_ELEMENTS(thai_scripts)
+ }
+};
+
+static thchar_t *
+utf8_to_tis (const char *text, int len)
+{
+ thchar_t *tis_text;
+ thchar_t *tis_p;
+ const char *text_p;
+
+ if (len < 0)
+ len = strlen (text);
+
+ tis_text = g_new (thchar_t, g_utf8_strlen (text, len) + 1);
+ if (!tis_text)
+ return NULL;
+
+ tis_p = tis_text;
+ for (text_p = text; text_p < text + len; text_p = g_utf8_next_char (text_p))
+ *tis_p++ = th_uni2tis (g_utf8_get_char (text_p));
+ *tis_p = '\0';
+
+ return tis_text;
+}
+
+static void
+thai_engine_break (PangoEngineLang *engine,
+ const char *text,
+ int len,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len)
+{
+ thchar_t *tis_text;
+
+ tis_text = utf8_to_tis (text, len);
+ if (tis_text)
+ {
+ int brk_len = strlen ((const char*)tis_text) + 1;
+ int *brk_pnts = g_new (int, brk_len);
+ int brk_n;
+ int i;
+
+ /* find line break positions */
+ brk_n = th_brk (tis_text, brk_pnts, brk_len);
+ for (i = 0; i < brk_n; i++)
+ {
+ attrs[brk_pnts[i]].is_line_break = TRUE;
+ attrs[brk_pnts[i]].is_word_start = TRUE;
+ attrs[brk_pnts[i]].is_word_end = TRUE;
+ }
+
+ g_free (brk_pnts);
+ g_free (tis_text);
+ }
+}
+
+static void
+thai_engine_lang_class_init (PangoEngineLangClass *class)
+{
+ class->script_break = thai_engine_break;
+}
+
+PANGO_ENGINE_LANG_DEFINE_TYPE (ThaiEngineLang, thai_engine_lang,
+ thai_engine_lang_class_init, NULL);
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ thai_engine_lang_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines, gint *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+/* Load a particular engine given the ID for the engine
+ */
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (thai_engine_lang_type, NULL);
+ else
+ return NULL;
+}
+
diff --git a/trunk/modules/thai/thai-shaper.c b/trunk/modules/thai/thai-shaper.c
new file mode 100644
index 00000000..580f1462
--- /dev/null
+++ b/trunk/modules/thai/thai-shaper.c
@@ -0,0 +1,548 @@
+/* Pango
+ * thai-shaper.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Author: Owen Taylor <otaylor@redhat.com>
+ *
+ * Copyright (C) 2005 Theppitak Karoonboonyanan
+ * Copyright (C) 2002 Software and Language Engineering Laboratory, NECTEC
+ * Author: Theppitak Karoonboonyanan <thep@links.nectec.or.th>
+ *
+ * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
+ * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#include <string.h>
+
+#include <glib.h>
+#include "pango-engine.h"
+#include "thai-charprop.h"
+#include "thai-shaper.h"
+
+#define MAX_CLUSTER_CHRS 256
+#define MAX_GLYPHS 256
+
+
+typedef struct {
+ guchar Start_TONE_AD, Start_AV, Start_BV_BD, Start_TailCutCons;
+
+ guchar ShiftDown_TONE_AD[8];
+ guchar ShiftDownLeft_TONE_AD[8];
+ guchar ShiftLeft_TONE_AD[8];
+ guchar ShiftLeft_AV[7];
+ guchar ShiftDown_BV_BD[3];
+ guchar TailCutCons[4];
+
+ guchar AmComp[2]; /* Sara Am components */
+} ThaiShapeTable;
+
+#define shiftdown_tone_ad(c,tbl) \
+ ((tbl)->ShiftDown_TONE_AD[(c)-(tbl)->Start_TONE_AD])
+#define shiftdownleft_tone_ad(c,tbl) \
+ ((tbl)->ShiftDownLeft_TONE_AD[(c)-(tbl)->Start_TONE_AD])
+#define shiftleft_tone_ad(c,tbl) \
+ ((tbl)->ShiftLeft_TONE_AD[(c)-(tbl)->Start_TONE_AD])
+#define shiftleft_av(c,tbl) \
+ ((tbl)->ShiftLeft_AV[(c)-(tbl)->Start_AV])
+#define shiftdown_bv_bd(c,tbl) \
+ ((tbl)->ShiftDown_BV_BD[(c)-(tbl)->Start_BV_BD])
+#define tailcutcons(c,tbl) \
+ ((tbl)->TailCutCons[(c)-(tbl)->Start_TailCutCons])
+
+/* No adjusted vowel/tonemark glyphs (tis620-0)
+ */
+static const ThaiShapeTable tis620_0_shape_table = {
+ 0xE7, 0xD1, 0xD8, 0xAD,
+ { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE },
+ { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE },
+ { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE },
+ { 0xD1, 0x00, 0x00, 0xD4, 0xD5, 0xD6, 0xD7 },
+ { 0xD8, 0xD9, 0xDA },
+ { 0xAD, 0x00, 0x00, 0xB0 },
+ { 0xED, 0xD2 }
+};
+
+/* Macintosh
+ */
+static const ThaiShapeTable Mac_shape_table = {
+ 0xE7, 0xD1, 0xD8, 0xAD,
+ { 0xE7, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0xED, 0xEE },
+ { 0x93, 0x83, 0x84, 0x85, 0x86, 0x87, 0x8F, 0xEE },
+ { 0x93, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x8F, 0xEE },
+ { 0x92, 0x00, 0x00, 0x94, 0x95, 0x96, 0x97 },
+ { 0xFC, 0xFD, 0xFE },
+ { 0x90, 0x00, 0x00, 0x80 },
+ { 0xED, 0xD2 }
+};
+
+/* Microsoft Window
+ */
+static const ThaiShapeTable Win_shape_table = {
+ 0xE7, 0xD1, 0xD8, 0xAD,
+ { 0xE7, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0xED, 0xEE },
+ { 0x9A, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x99, 0xEE },
+ { 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0x99, 0xEE },
+ { 0x98, 0x00, 0x00, 0x81, 0x82, 0x83, 0x84 },
+ { 0xFC, 0xFD, 0xFE },
+ { 0x90, 0x00, 0x00, 0x80 },
+ { 0xED, 0xD2 }
+};
+
+static const ThaiShapeTable Lao_shape_table = {
+ 0x67, 0x51, 0x58, 0x2D,
+ { 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E },
+ { 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E },
+ { 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E },
+ { 0x51, 0x00, 0x00, 0x54, 0x55, 0x56, 0x57 },
+ { 0x58, 0x59, 0x00 },
+ { 0x2D, 0x00, 0x00, 0x30 },
+ { 0x6D, 0x52 }
+};
+
+static void
+add_glyph (ThaiFontInfo *font_info,
+ PangoGlyphString *glyphs,
+ gint cluster_start,
+ PangoGlyph glyph,
+ gboolean combining)
+{
+ PangoRectangle ink_rect, logical_rect;
+ gint index = glyphs->num_glyphs;
+
+ pango_glyph_string_set_size (glyphs, index + 1);
+
+ glyphs->glyphs[index].glyph = glyph;
+ glyphs->glyphs[index].attr.is_cluster_start = combining ? 0 : 1;
+
+ glyphs->log_clusters[index] = cluster_start;
+
+ pango_font_get_glyph_extents (font_info->font,
+ glyphs->glyphs[index].glyph, &ink_rect, &logical_rect);
+
+ if (combining || logical_rect.width > 0)
+ {
+ glyphs->glyphs[index].geometry.x_offset = 0;
+ glyphs->glyphs[index].geometry.width = logical_rect.width;
+ }
+ else
+ {
+ glyphs->glyphs[index].geometry.x_offset = ink_rect.width;
+ glyphs->glyphs[index].geometry.width = ink_rect.width;
+ }
+ glyphs->glyphs[index].geometry.y_offset = 0;
+}
+
+static PangoGlyph
+get_null_base_glyph (ThaiFontInfo *font_info)
+{
+ return thai_get_glyph_uni (font_info, 0x25cc);
+}
+
+static gint
+get_adjusted_glyphs_list (ThaiFontInfo *font_info,
+ gunichar *cluster,
+ gint num_chrs,
+ PangoGlyph *glyph_lists,
+ const ThaiShapeTable *shaping_table)
+{
+ switch (num_chrs)
+ {
+ case 1:
+ if (is_char_type (cluster[0],
+ BelowVowel|BelowDiac|AboveVowel|AboveDiac|Tone|SaraAm))
+ {
+ gint n;
+ glyph_lists[0] = get_null_base_glyph (font_info);
+ n = glyph_lists[0] ? 1 : 0;
+ glyph_lists[n++] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ return n;
+ }
+ else
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ return 1;
+ }
+ break;
+
+ case 2:
+ if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
+ is_char_type (cluster[1], SaraAm))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info, shaping_table->AmComp[0]);
+ glyph_lists[2] = thai_make_glyph_tis (font_info, shaping_table->AmComp[1]);
+ return 3;
+ }
+ else if (is_char_type (cluster[0], UpTailCons) &&
+ is_char_type (cluster[1], SaraAm))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info,
+ shiftleft_tone_ad (shaping_table->AmComp[0], shaping_table));
+ glyph_lists[2] = thai_make_glyph_tis (font_info, shaping_table->AmComp[1]);
+ return 3;
+ }
+ else if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
+ is_char_type (cluster[1], AboveVowel))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ return 2;
+ }
+ else if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
+ is_char_type (cluster[1], AboveDiac|Tone))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info,
+ shiftdown_tone_ad (ucs2tis (cluster[1]), shaping_table));
+ return 2;
+ }
+ else if (is_char_type (cluster[0], UpTailCons) &&
+ is_char_type (cluster[1], AboveVowel))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info,
+ shiftleft_av (ucs2tis (cluster[1]), shaping_table));
+ return 2;
+ }
+ else if (is_char_type (cluster[0], UpTailCons) &&
+ is_char_type (cluster[1], AboveDiac|Tone))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info,
+ shiftdownleft_tone_ad (ucs2tis (cluster[1]), shaping_table));
+ return 2;
+ }
+ else if (is_char_type (cluster[0], NoTailCons|UpTailCons) &&
+ is_char_type (cluster[1], BelowVowel|BelowDiac))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ return 2;
+ }
+ else if (is_char_type (cluster[0], BotTailCons) &&
+ is_char_type (cluster[1], BelowVowel|BelowDiac))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ thai_make_glyph_tis (font_info,
+ shiftdown_bv_bd (ucs2tis (cluster[1]), shaping_table));
+ return 2;
+ }
+ else if (is_char_type (cluster[0], SpltTailCons) &&
+ is_char_type (cluster[1], BelowVowel|BelowDiac))
+ {
+ glyph_lists[0] = thai_make_glyph_tis (font_info,
+ tailcutcons (ucs2tis (cluster[0]), shaping_table));
+ glyph_lists[1] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ return 2;
+ }
+ else
+ {
+ gint n;
+ glyph_lists[0] = get_null_base_glyph (font_info);
+ n = glyph_lists[0] ? 1 : 0;
+ glyph_lists[n++] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[n++] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ return n;
+ }
+ break;
+
+ case 3:
+ if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
+ is_char_type (cluster[1], Tone) &&
+ is_char_type (cluster[2], SaraAm))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info, shaping_table->AmComp[0]);
+ glyph_lists[2] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ glyph_lists[3] = thai_make_glyph_tis (font_info, shaping_table->AmComp[1]);
+ return 4;
+ }
+ else if (is_char_type (cluster[0], UpTailCons) &&
+ is_char_type (cluster[1], Tone) &&
+ is_char_type (cluster[2], SaraAm))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info,
+ shiftleft_tone_ad (shaping_table->AmComp[0], shaping_table));
+ glyph_lists[2] = thai_make_glyph_tis (font_info,
+ shiftleft_tone_ad (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[3] = thai_make_glyph_tis (font_info, shaping_table->AmComp[1]);
+ return 4;
+ }
+ else if (is_char_type (cluster[0], UpTailCons) &&
+ is_char_type (cluster[1], AboveVowel) &&
+ is_char_type (cluster[2], AboveDiac|Tone))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info,
+ shiftleft_av (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[2] = thai_make_glyph_tis (font_info,
+ shiftleft_tone_ad (ucs2tis (cluster[2]), shaping_table));
+ return 3;
+ }
+ else if (is_char_type (cluster[0], UpTailCons) &&
+ is_char_type (cluster[1], BelowVowel) &&
+ is_char_type (cluster[2], AboveDiac|Tone))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ glyph_lists[2] = thai_make_glyph_tis (font_info,
+ shiftdownleft_tone_ad (ucs2tis (cluster[2]), shaping_table));
+ return 3;
+ }
+ else if (is_char_type (cluster[0], NoTailCons) &&
+ is_char_type (cluster[1], BelowVowel) &&
+ is_char_type (cluster[2], AboveDiac|Tone))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ glyph_lists[2] =
+ thai_make_glyph_tis (font_info,
+ shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table));
+ return 3;
+ }
+ else if (is_char_type (cluster[0], SpltTailCons) &&
+ is_char_type (cluster[1], BelowVowel) &&
+ is_char_type (cluster[2], AboveDiac|Tone))
+ {
+ glyph_lists[0] = thai_make_glyph_tis (font_info,
+ tailcutcons (ucs2tis (cluster[0]), shaping_table));
+ glyph_lists[1] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ glyph_lists[2] = thai_make_glyph_tis (font_info,
+ shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table));
+ return 3;
+ }
+ else if (is_char_type (cluster[0], BotTailCons) &&
+ is_char_type (cluster[1], BelowVowel) &&
+ is_char_type (cluster[2], AboveDiac|Tone))
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] = thai_make_glyph_tis (font_info,
+ shiftdown_bv_bd (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[2] = thai_make_glyph_tis (font_info,
+ shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table));
+ return 3;
+ }
+ else
+ {
+ glyph_lists[0] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
+ glyph_lists[2] =
+ thai_make_glyph_tis (font_info, ucs2tis (cluster[2]));
+ return 3;
+ }
+ break;
+
+ default: /* e.g. Lao cluster with below cons + upper/lower vowel + tone */
+ {
+ gint i;
+ for (i = 0; i < num_chrs; i++)
+ glyph_lists[i] = thai_make_glyph_tis (font_info, ucs2tis (cluster[i]));
+ return num_chrs;
+ }
+ }
+
+ return 0;
+}
+
+static gint
+get_glyphs_list (ThaiFontInfo *font_info,
+ PangoScript script,
+ gunichar *cluster,
+ gint num_chrs,
+ PangoGlyph *glyph_lists)
+{
+ gint i;
+
+ switch (script)
+ {
+ case PANGO_SCRIPT_THAI:
+ switch (font_info->font_set)
+ {
+ default:
+ case THAI_FONT_NONE:
+ for (i=0; i < num_chrs; i++)
+ glyph_lists[i] = thai_make_unknown_glyph (font_info, cluster[i]);
+ return num_chrs;
+
+ case THAI_FONT_TIS:
+ /* TIS620-0 + Wtt2.0 Extension
+ */
+ return get_adjusted_glyphs_list (font_info, cluster,
+ num_chrs, glyph_lists, &tis620_0_shape_table);
+
+ case THAI_FONT_TIS_MAC:
+ /* MacIntosh Extension
+ */
+ return get_adjusted_glyphs_list (font_info, cluster,
+ num_chrs, glyph_lists, &Mac_shape_table);
+
+ case THAI_FONT_TIS_WIN:
+ /* Microsoft Extension
+ */
+ return get_adjusted_glyphs_list (font_info, cluster,
+ num_chrs, glyph_lists, &Win_shape_table);
+ }
+ break;
+
+ case PANGO_SCRIPT_LAO:
+ return get_adjusted_glyphs_list (font_info, cluster,
+ num_chrs, glyph_lists, &Lao_shape_table);
+
+ default:
+ for (i=0; i < num_chrs; i++)
+ glyph_lists[i] = thai_make_unknown_glyph (font_info, cluster[i]);
+ return num_chrs;
+ }
+
+ return 0; /* Quiet GCC */
+}
+
+static void
+add_cluster (ThaiFontInfo *font_info,
+ PangoScript script,
+ PangoGlyphString *glyphs,
+ gint cluster_start,
+ gunichar *cluster,
+ gint num_chrs)
+{
+ PangoGlyph glyphs_list[MAX_GLYPHS];
+ gint num_glyphs;
+ gint i;
+
+ if (isthai (cluster[0]))
+ {
+ num_glyphs = get_glyphs_list(font_info, script, cluster, num_chrs, glyphs_list);
+ for (i=0; i<num_glyphs; i++)
+ add_glyph (font_info, glyphs, cluster_start, glyphs_list[i],
+ i == 0 ? FALSE : TRUE);
+ }
+ else if (islao (cluster[0]))
+ {
+ num_glyphs = get_glyphs_list(font_info, script, cluster, num_chrs, glyphs_list);
+ for (i=0; i<num_glyphs; i++)
+ add_glyph (font_info, glyphs, cluster_start, glyphs_list[i],
+ i == 0 ? FALSE : TRUE);
+ }
+ else
+ {
+ g_assert (num_chrs == 1);
+ add_glyph (font_info, glyphs, cluster_start,
+ thai_make_glyph_uni (font_info, cluster[0]),
+ FALSE);
+ }
+}
+
+static gboolean
+is_wtt_composible (gunichar cur_wc, gunichar nxt_wc)
+{
+ switch (TAC_compose_input(cur_wc, nxt_wc))
+ {
+ case 'A':
+ case 'S':
+ case 'R':
+ case 'X':
+ return FALSE;
+
+ case 'C':
+ return TRUE;
+ }
+
+ g_assert_not_reached ();
+ return FALSE;
+}
+
+static const char *
+get_next_cluster(const char *text,
+ gint length,
+ gunichar *cluster,
+ gint *num_chrs)
+{
+ PangoScript cluster_script = PANGO_SCRIPT_INVALID_CODE, cur_script;
+ const char *p;
+ gint n_chars = 0;
+ gunichar current;
+
+ for (p = text; p < text + length; p = g_utf8_next_char (p))
+ {
+ current = g_utf8_get_char (p);
+ cur_script = pango_script_for_unichar (current);
+ if (cluster_script == PANGO_SCRIPT_INVALID_CODE)
+ cluster_script = cur_script;
+ if (cur_script != cluster_script ||
+ (n_chars > 0 &&
+ !is_wtt_composible (cluster[n_chars - 1], current)))
+ break;
+ cluster[n_chars++] = current;
+ }
+
+ *num_chrs = n_chars;
+ return p;
+}
+
+void
+thai_set_glyphs (ThaiFontInfo *font_info,
+ const char *text,
+ gint length,
+ PangoScript script,
+ PangoGlyphString *glyphs)
+{
+ gint n_chars;
+ const char *p;
+ const char *log_cluster;
+ gunichar cluster[MAX_CLUSTER_CHRS];
+
+ pango_glyph_string_set_size (glyphs, 0);
+
+ p = text;
+ while (p < text + length)
+ {
+ log_cluster = p;
+ p = get_next_cluster (p, text + length - p, cluster, &n_chars);
+ add_cluster (font_info, script, glyphs, log_cluster - text, cluster, n_chars);
+ }
+}
diff --git a/trunk/modules/thai/thai-shaper.h b/trunk/modules/thai/thai-shaper.h
new file mode 100644
index 00000000..cb2f7edc
--- /dev/null
+++ b/trunk/modules/thai/thai-shaper.h
@@ -0,0 +1,80 @@
+/* Pango
+ * thai-shaper.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Author: Owen Taylor <otaylor@redhat.com>
+ *
+ * Copyright (C) 2004 Theppitak Karoonboonyanan
+ * Copyright (C) 2002 Software and Language Engineering Laboratory, NECTEC
+ * Author: Theppitak Karoonboonyanan <thep@linux.thai.net>
+ *
+ * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
+ * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __THAI_SHAPER_H__
+#define __THAI_SHAPER_H__
+
+typedef struct _ThaiFontInfo ThaiFontInfo;
+
+/* Font encodings we will use
+ */
+typedef enum {
+ THAI_FONT_NONE,
+ THAI_FONT_TIS,
+ THAI_FONT_TIS_MAC,
+ THAI_FONT_TIS_WIN
+} ThaiFontSet;
+
+typedef enum {
+ THAI_FONTINFO_X,
+ THAI_FONTINFO_XFT
+} ThaiFontInfoType;
+
+struct _ThaiFontInfo
+{
+ PangoFont *font;
+ ThaiFontSet font_set;
+};
+
+/*
+ * Abstract methods (implemented by each shaper module)
+ */
+PangoGlyph
+thai_get_glyph_tis (ThaiFontInfo *font_info, guchar c);
+
+PangoGlyph
+thai_make_glyph_tis (ThaiFontInfo *font_info, guchar c);
+
+PangoGlyph
+thai_get_glyph_uni (ThaiFontInfo *font_info, gunichar uc);
+
+PangoGlyph
+thai_make_glyph_uni (ThaiFontInfo *font_info, gunichar uc);
+
+PangoGlyph
+thai_make_unknown_glyph (ThaiFontInfo *font_info, gunichar uc);
+
+void
+thai_set_glyphs (ThaiFontInfo *font_info,
+ const char *text,
+ gint length,
+ PangoScript script,
+ PangoGlyphString *glyphs);
+
+#endif /* __THAI_SHAPER_H__ */
diff --git a/trunk/modules/tibetan/Makefile.am b/trunk/modules/tibetan/Makefile.am
new file mode 100644
index 00000000..3b7959dc
--- /dev/null
+++ b/trunk/modules/tibetan/Makefile.am
@@ -0,0 +1,20 @@
+include $(top_srcdir)/modules/Module.mk
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_TIBETAN_FC
+noinst_LTLIBRARIES += libpango-tibetan-fc.la
+else
+if DYNAMIC_TIBETAN_FC
+module_LTLIBRARIES += pango-tibetan-fc.la
+endif
+endif
+endif
+
+tibetan_fc_sources = $(common_sources) tibetan-fc.c
+
+pango_tibetan_fc_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
+pango_tibetan_fc_la_LIBADD = $(pangoft2libs)
+pango_tibetan_fc_la_SOURCES = $(tibetan_fc_sources)
+libpango_tibetan_fc_la_SOURCES = $(tibetan_fc_sources)
+libpango_tibetan_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_tibetan_fc
diff --git a/trunk/modules/tibetan/tibetan-fc.c b/trunk/modules/tibetan/tibetan-fc.c
new file mode 100644
index 00000000..ff65071c
--- /dev/null
+++ b/trunk/modules/tibetan/tibetan-fc.c
@@ -0,0 +1,573 @@
+/* Pango
+ * tibetan-fc.c: Shaper for Tibetan script
+ *
+ * Copyright (C) 2005 DIT, Government of Bhutan <http://www.dit.gov.bt>
+ * Contact person : Pema Geyleg <pema_geyleg@druknet.bt>
+ *
+ * Based on code from khmer shapers developed by Jens Herden
+ * <jens@tibetanos.inf > and Javier Sola <javier@tibetanos.info>
+ *
+ * Based on code from other shapers
+ * Copyright (C) 1999-2004 Red Hat Software
+ * Author: Owen Taylor <otaylor@redhat.com>
+
+ * Partially based on Indic shaper
+ * Copyright (C) 2001, 2002 IBM Corporation
+ * Author: Eric Mader <mader@jtcsv.com>
+ *
+ * The first module for Tibetan shaper was developed by Mr. Karunakar under
+ * PanLocalization project.
+ * Mr. Chris Fynn, Mr.Javier Sola, Mr. Namgay Thinley were involved
+ * while developing this shaper.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * The license on the original Indic shaper code is as follows:
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished
+ * to do so, provided that the above copyright notice(s) and this
+ * permission notice appear in all copies of the Software and that
+ * both the above copyright notice(s) and this permission notice
+ * appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR
+ * ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
+ * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written
+ * authorization of the copyright holder.
+ */
+#include <config.h>
+#include <string.h>
+
+#include "pango-engine.h"
+#include "pango-ot.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+
+
+#define SCRIPT_ENGINE_NAME "TibetanScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+
+typedef PangoEngineShape TibetanEngineFc;
+typedef PangoEngineShapeClass TibetanEngineFcClass ;
+
+
+static PangoEngineScriptInfo tibetan_scripts[] =
+{
+ { PANGO_SCRIPT_TIBETAN, "*" }
+};
+
+static PangoEngineInfo script_engines[] =
+{
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ tibetan_scripts, G_N_ELEMENTS (tibetan_scripts)
+ }
+};
+
+
+/*
+ * Vocabulary
+ * Base -> A consonant in its full (not subscript) form. It is the
+ * center of the syllable, it can be souranded by subjoined consonants, vowels,
+ * signs... but there is only one base in a stack, it has to be coded as
+ * the first character of the syllable.Included here are also groups of base + subjoined
+ * which are represented by one single code point in unicode (e.g. 0F43) Also other characters
+ * that might take subjoined consonants or other combining characters.
+ * Subjoined -> Subjoined consonants and groups of subjoined consonants which have a single code-point
+ * to repersent the group (even if each subjoined consonant is represented independently
+ * by anothe code-point
+ * Tsa Phru --> Tsa Phru character, Bhutanese people will always place it right after the base, but sometimes, due to
+ * "normalization" is placed after all the subjoined consonants, and it is also permitted there.
+ * A Chung Vowel lengthening mark --> . 0F71 It is placed after the base and any subjoined consonants but before any vowels
+ * Precomposed Sanskrit vowels --> The are combinations of subjoined consonants + vowels that have been assigned
+ * a given code-point (in spite of each single part of them having also a code-point
+ * They are avoided, and users are encouraged to use the combination of code-points that
+ * represents the same sound instead of using this combined characters. This is included here
+ * for compatibility with possible texts that use them (they are not in the Dzongkha keyboard).
+ * Halanta -> The Halanta or Virama character 0F84 indicates that a consonant should not use its inheernt vowel,
+ * in spite of not having other vowels present. It is usually placed immediatly after a base consonant,
+ * but in some special cases it can also be placed after a subjoined consonant, so this is also
+ * permitted in this algorithm. (Halanta is always displayed in Tibetan not used as a connecting char)
+ *
+ * Subjoined vowels -> Dependent vowels (matras) placed below the base and below all subjoined consonants. There
+ * might be as much as three subjoined vowels in a given stack (only one in general text, but up
+ * to three for abreviations, they have to be permitted).
+ * Superscript vowels -> There are three superscript vowels, and they can be repeated or combined (up to three
+ * times. They can combine with subjoined vowels, and are always coded after these.
+ * Anusvara --> Nasalisation sign. Traditioinally placed in absence of vowels, but also after vowels. In some
+ * special cases it can be placed before a vowel, so this is also permitted
+ * Candrabindu -> Forms of the Anusvara with different glyphs (and different in identity) which can be placed
+ * without vowel or after the vowel, but never before. Cannot combine with Anusvara.
+ * Stress marks -> Marks placed above or below a syllable, affecting the whole syllable. They are combining
+ * marks, so they have to be attached to a specific stack. The are using to emphasise a syllable.
+ *
+ * Digits -> Digits are not considered as non-combining characters because there are a few characters which
+ * combine with them, so they have to be considered independently.
+ * Digit combining marks -> dependent marks that combine with digits.
+ *
+ * TODO
+ * There are a number of characters in the CJK block that are used in Tibetan script, two of these are symbols
+ * are used as bases for combining glyphs, and have not been encoded in Tibetan. As these characters are outside
+ * of the tibetan block, they have not been treated in this program.
+*/
+
+
+enum TibetanCharClassValues
+{
+ CC_RESERVED = 0, /* Non Combining Characters*/
+ CC_BASE = 1, /* Base Consonants, Base Consonants with Subjoined attached in code point, Sanskrit base marks*/
+ CC_SUBJOINED = 2, /* Subjoined Consonats, combination of more than Subjoined Consonants in the code point*/
+ CC_TSA_PHRU = 3, /* Tsa-Phru character 0F39*/
+ CC_A_CHUNG = 4, /* Vowel Lenthening a-chung mark 0F71*/
+ CC_COMP_SANSKRIT = 5, /* Precomposed Sanskrit vowels including Subjoined characters and vowels*/
+ CC_HALANTA = 6, /* Halanta Character 0F84*/
+ CC_BELOW_VOWEL = 7, /* Subjoined vowels*/
+ CC_ABOVE_VOWEL = 8, /* Superscript vowels*/
+ CC_ANUSVARA = 9, /* Tibetan sign Rjes Su Nga Ro 0F7E*/
+ CC_CANDRABINDU = 10, /* Tibetan sign Sna Ldan and Nyi Zla Naa Da 0F82, 0F83*/
+ CC_VISARGA = 11, /* Tibetan sign Rnam Bcad (0F7F)*/
+ CC_ABOVE_S_MARK = 12, /* Stress Marks placed above the text*/
+ CC_BELOW_S_MARK = 13, /* Stress Marks placed below the text*/
+ CC_DIGIT = 14, /* Dzongkha Digits*/
+ CC_PRE_DIGIT_MARK = 15, /* Mark placed before the digit*/
+ CC_POST_BELOW_DIGIT_M = 16, /* Mark placed below or after the digit*/
+ CC_COUNT = 17 /* This is the number of character classes*/
+};
+
+
+enum TibetanCharClassFlags
+{
+ CF_CLASS_MASK = 0x0000FFFF,
+
+ CF_DOTTED_CIRCLE = 0x04000000, /* add a dotted circle if a character with this flag is the first in a syllable*/
+ CF_DIGIT = 0x01000000, /* flag to speed up comparaisson*/
+ CF_PREDIGIT = 0x02000000, /* flag to detect pre-digit marks for reordering*/
+
+ /* position flags*/
+ CF_POS_BEFORE = 0x00080000,
+ CF_POS_BELOW = 0x00040000,
+ CF_POS_ABOVE = 0x00020000,
+ CF_POS_AFTER = 0x00010000,
+ CF_POS_MASK = 0x000f0000
+};
+
+
+/* Characters that get refrered to by name */
+enum TibetanChar
+{
+ C_DOTTED_CIRCLE = 0x25CC,
+ C_PRE_NUMBER_MARK = 0x0F3F
+};
+
+
+enum
+{
+ /* simple classes, they are used in the statetable (in this file) to control the length of a syllable
+ * they are also used to know where a character should be placed (location in reference to the base character)
+ * and also to know if a character, when independtly displayed, should be displayed with a dotted-circle to
+ * indicate error in syllable construction
+ */
+ _xx = CC_RESERVED,
+ _ba = CC_BASE,
+ _sj = CC_SUBJOINED | CF_DOTTED_CIRCLE | CF_POS_BELOW,
+ _tp = CC_TSA_PHRU | CF_DOTTED_CIRCLE | CF_POS_ABOVE,
+ _ac = CC_A_CHUNG | CF_DOTTED_CIRCLE | CF_POS_BELOW,
+ _cs = CC_COMP_SANSKRIT | CF_DOTTED_CIRCLE | CF_POS_BELOW,
+ _ha = CC_HALANTA | CF_DOTTED_CIRCLE | CF_POS_BELOW,
+ _bv = CC_BELOW_VOWEL | CF_DOTTED_CIRCLE | CF_POS_BELOW,
+ _av = CC_ABOVE_VOWEL | CF_DOTTED_CIRCLE | CF_POS_ABOVE,
+ _an = CC_ANUSVARA | CF_DOTTED_CIRCLE | CF_POS_ABOVE,
+ _cb = CC_CANDRABINDU | CF_DOTTED_CIRCLE | CF_POS_ABOVE,
+ _vs = CC_VISARGA | CF_DOTTED_CIRCLE| CF_POS_AFTER,
+ _as = CC_ABOVE_S_MARK | CF_DOTTED_CIRCLE | CF_POS_ABOVE,
+ _bs = CC_BELOW_S_MARK | CF_DOTTED_CIRCLE | CF_POS_BELOW,
+ _di = CC_DIGIT | CF_DIGIT,
+ _pd = CC_PRE_DIGIT_MARK | CF_DOTTED_CIRCLE | CF_PREDIGIT | CF_POS_BEFORE ,
+ _bd = CC_POST_BELOW_DIGIT_M | CF_DOTTED_CIRCLE | CF_POS_AFTER
+};
+
+
+/* Character class: a character class value
+ * ORed with character class flags.
+ */
+typedef glong TibetanCharClass;
+/*_xx Non Combining characters*/
+/*_ba Base Consonants*/
+/*_sj Subjoined consonants*/
+/*_tp Tsa - phru*/
+/*_ac A-chung, Vowel Lengthening mark*/
+/*_cs Precomposed Sanskrit vowel + subjoined consonants*/
+/*_ha Halanta/Virama*/
+/*_bv Below vowel*/
+/*_av above vowel*/
+/*_an Anusvara*/
+/*_cb Candrabindu*/
+/*_vs Visaraga/Post mark*/
+/*_as Upper Stress marks*/
+/*_bs Lower Stress marks*/
+/*_di Digit*/
+/*_pd Number pre combining, Needs reordering*/
+/*_bd Other number combining marks*/
+
+
+static const TibetanCharClass tibetanCharClasses[] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f*/
+ _xx, _ba, _xx, _xx, _ba, _ba, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0F00 - 0F0F 0*/
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _bd, _bd, _xx, _xx, _xx, _xx, _xx, _xx, /* 0F10 - 0F1F 1*/
+ _di, _di, _di, _di, _di, _di, _di, _di, _di, _di, _xx, _xx, _xx, _xx, _xx, _xx, /* 0F20 - 0F2F 2*/
+ _xx, _xx, _xx, _xx, _xx, _bs, _xx, _bs, _xx, _tp, _xx, _xx, _xx, _xx, _bd, _pd, /* 0F30 - 0F3F 3*/
+ _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _xx, _ba, _ba, _ba, _ba, _ba, _ba, _ba, /* 0F40 - 0F4F 4*/
+ _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, /* 0F50 - 0F5F 5*/
+ _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _ba, _xx, _xx, _xx, _xx, _xx, /* 0F60 - 0F6F 6*/
+ _xx, _ac, _av, _cs, _bv, _bv, _cs, _cs, _cs, _cs, _av, _av, _av, _av, _an, _vs, /* 0F70 - 0F7F 7*/
+ _av, _cs, _cb, _cb, _ha, _xx, _as, _as, _ba, _ba, _ba, _ba, _xx, _xx, _xx, _xx, /* 0F80 - 0F8F 8*/
+ _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _xx, _sj, _sj, _sj, _sj, _sj, _sj, _sj, /* 0F90 - 0F9F 9*/
+ _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, /* 0FA0 - 0FAF a*/
+ _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _sj, _xx, _sj, _sj, /* 0FB0 - 0FBF b*/
+ _xx, _xx, _xx, _xx, _xx, _xx, _bs, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0FC0 - 0FCF c*/
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0FD0 - 0FDF d*/
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0FE0 - 0FEF e*/
+ _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, /* 0FF0 - 0FFF f*/
+};
+
+/* this define must reflect the range of tibetanCharClasses */
+/*First Tibetan Character*/
+#define firstChar 0x0F00
+/*Last Tibetan Character*/
+#define lastChar 0x0FFF
+
+/* The stateTable is used to calculate the end (the length) of a well
+ * formed Tibetan Stack
+ *
+ * Each horizontal line is ordered exactly the same way as the values in TibetanClassTable
+ * CharClassValues.This coincidence of values allows the follow up of the table.
+ *
+ * Each line corresponds to a state, which does not necessarily need to be a type
+ * of component... for example, state 2 is a base, with is always a first character
+ * in the Stack but the state could be produced a consonant of any type when
+ * it is the first character that is analysed (in ground state).
+ */
+
+static const gint8 tibetanStateTable[][CC_COUNT] =
+{
+ /*Dzongkha state table*/
+ /*xx ba sj tp ac cs ha bv av an cb vs as bs di pd bd*/
+ { 1, 2, 4, 3, 8, 7, 9, 10, 14, 13, 17, 18, 19, 19, 20, 21, 21,}, /* 0 - ground state*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,}, /* 1 - exit state (or sign to the right of the syllable)*/
+ {-1, -1, 4, 3, 8, 7, 9, 10, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 2 - Base consonant*/
+ {-1, -1, 5, -1, 8, 7, -1, 10, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 3 - Tsa phru after base*/
+ {-1, -1, 4, 6, 8, 7, 9, 10, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 4 - Subjoined consonant after base*/
+ {-1, -1, 5, -1, 8, 7, -1, 10, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 5 - Subjoined consonant after tsa phru*/
+ {-1, -1, -1, -1, 8, 7, -1, 10, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 6 - Tsa phru after subjoined consonant*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, 19, -1, -1, -1,}, /* 7 - Pre Composed Sanskrit*/
+ {-1, -1, -1, -1, -1, -1, -1, 10, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 8 - A-chung*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, 14, 13, 17, -1, 19, 19, -1, -1, -1,}, /* 9 - Halanta*/
+ {-1, -1, -1, -1, -1, -1, -1, 11, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 10 - below vowel 1*/
+ {-1, -1, -1, -1, -1, -1, -1, 12, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 11 - below vowel 2*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, 14, 13, 17, 18, 19, 19, -1, -1, -1,}, /* 12 - below vowel 3*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, 14, 17, 17, 18, 19, 19, -1, -1, -1,}, /* 13 - Anusvara before vowel*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, 15, 17, 17, 18, 19, 19, -1, -1, -1,}, /* 14 - above vowel 1*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, 16, 17, 17, 18, 19, 19, -1, -1, -1,}, /* 15 - above vowel 2*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 17, 18, 19, 19, -1, -1, -1,}, /* 16 - above vowel 3*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, 19, 19, -1, -1, -1,}, /* 17 - Anusvara or Candrabindu after vowel*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, 19, -1, -1, -1,}, /* 18 - Visarga*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,}, /* 19 - strss mark*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, 21,}, /* 20 - digit*/
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,}, /* 21 - digit mark*/
+};
+
+
+enum property_flags
+{
+ abvf = 0x0001,
+ pref = 0x0002,
+ pstf = 0x0004,
+ blwf = 0x0008,
+
+ pres = 0x0010,
+ blws = 0x0020,
+ abvs = 0x0040,
+ psts = 0x0080,
+ clig = 0x0100,
+
+ dist = 0x0200,
+ blwm = 0x0400,
+ abvm = 0x0800,
+};
+
+
+enum properties
+{
+ blwf_p = /*(blwf | blws | clig | dist | blwm)*/ (abvf | pref | pstf | pres | abvs | psts | abvm),
+ pstf_p = /*(blwf | blws | pref | pres | pstf | psts | clig | dist | blwm)*/ (abvf | abvs | abvm),
+ abvf_p = /*(abvf | abvs | clig | dist | abvm)*/ (pref | pstf | blwf | pres | blws | psts | blwm),
+ pref_p = /*(pref | pres | clig | dist)*/ (abvf | pstf | blwf | blws | abvs | psts | blwm | abvm),
+ default_p = /*(pres | blws | clig | dist | abvm | blwm)*/ (pref | blwf |abvf | pstf | abvs | psts)
+};
+
+
+/* Below we define how a character in the input string is either in the tibetanCharClasses table
+ * (in which case we get its type back), or an unknown object in which case we get _xx (CC_RESERVED) back
+ */
+static TibetanCharClass
+get_char_class (gunichar ch)
+{
+
+ if (ch < firstChar || ch > lastChar)
+ return CC_RESERVED;
+
+ return tibetanCharClasses[ch - firstChar];
+}
+
+
+/* Given an input string of characters and a location in which to start looking
+ * calculate, using the state table, which one is the last character of the syllable
+ * that starts in the starting position.
+ */
+static glong
+find_syllable (const gunichar *chars,
+ glong start,
+ glong char_count)
+{
+ glong cursor = start;
+ gint8 state = 0;
+ TibetanCharClass charClass;
+
+ while (cursor < char_count)
+ {
+ charClass = get_char_class (chars[cursor]) & CF_CLASS_MASK;
+ state = tibetanStateTable[state][charClass];
+
+ if (state < 0)
+ break;
+
+ cursor += 1;
+ }
+
+ return cursor;
+}
+
+static const PangoOTFeatureMap gsub_features[] =
+{
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"blws", blws},
+ {"abvs", abvs},
+ {"psts", psts},
+ {"clig", clig},
+ {"calt", PANGO_OT_ALL_GLYPHS}
+};
+
+static const PangoOTFeatureMap gpos_features[] =
+{
+ {"dist", dist},
+ {"blwm", blwm},
+ {"abvm", abvm},
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
+
+static PangoGlyph
+get_index (PangoFcFont *fc_font, gunichar wc)
+{
+ PangoGlyph index = pango_fc_font_get_glyph (fc_font, wc);
+ if (!index)
+ index = PANGO_GET_UNKNOWN_GLYPH ( wc);
+ return index;
+}
+
+
+static void
+tibetan_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ PangoFcFont *fc_font;
+ FT_Face face;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ glong n_chars;
+ gunichar *wcs;
+ const char *p;
+ int i;
+ glong syllable;
+ TibetanCharClass charClass;
+ glong cursor = 0;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return;
+
+ buffer = pango_ot_buffer_new (fc_font);
+
+ wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);
+
+ p = text;
+ /* This loop only exits when we reach the end of a run, which may contain
+ * several syllables.
+ */
+ while (cursor < n_chars)
+ {
+ syllable = find_syllable (wcs, cursor, n_chars);
+
+ /* shall we add a dotted circle?
+ * If in the position in which the base should be (first char in the string) there is
+ * a character that has the Dotted circle flag (a character that cannot be a base)
+ * then write a dotted circle
+ */
+ if (get_char_class (wcs[cursor]) & CF_DOTTED_CIRCLE)
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_DOTTED_CIRCLE), default_p, p - text);
+ }
+
+ /* If it encounters a digit followed by number pre combining mark, then reorder the two characters
+ * coeng Ro if they are present
+ */
+ for (i = cursor; i < syllable; i += 1)
+ {
+ charClass = get_char_class (wcs[i]);
+
+ if ((charClass & CF_DIGIT )
+ && ( get_char_class (wcs[i+1]) & CF_PREDIGIT))
+ {
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_PRE_NUMBER_MARK), pref_p, p - text);
+ p = g_utf8_next_char (p);
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pref_p, p - text);
+ i += 1;
+ } else {
+ switch (charClass & CF_POS_MASK)
+ {
+ case CF_POS_ABOVE :
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), abvf_p, p - text);
+ break;
+
+ case CF_POS_AFTER :
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text);
+ break;
+
+ case CF_POS_BELOW :
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
+ break;
+
+ default:
+ /* default - any other characters */
+ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), default_p, p - text);
+ break;
+ } /* switch */
+ }
+
+ p = g_utf8_next_char (p);
+ } /* for */
+
+ cursor = syllable; /* move the pointer to the start of next syllable */
+ } /* while */
+
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
+ desc.static_gsub_features = gsub_features;
+ desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
+ desc.static_gpos_features = gpos_features;
+
+ /* TODO populate other_features from analysis->extra_attrs */
+ desc.n_other_features = 0;
+ desc.other_features = NULL;
+
+ ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
+
+ pango_ot_ruleset_substitute (ruleset, buffer);
+ pango_ot_ruleset_position (ruleset, buffer);
+ pango_ot_buffer_output (buffer, glyphs);
+
+ g_free (wcs);
+ pango_ot_buffer_destroy (buffer);
+
+ pango_fc_font_unlock_face (fc_font);
+}
+
+
+static void
+tibetan_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = tibetan_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (TibetanEngineFc, tibetan_engine_fc,
+ tibetan_engine_fc_class_init, NULL)
+
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ tibetan_engine_fc_register_type (module);
+}
+
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (tibetan_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/trunk/pango-uninstalled.pc.in b/trunk/pango-uninstalled.pc.in
new file mode 100644
index 00000000..d25b888b
--- /dev/null
+++ b/trunk/pango-uninstalled.pc.in
@@ -0,0 +1,7 @@
+Name: Pango Uninstalled
+Description: Internationalized text handling, Not Installed
+Version: @VERSION@
+Requires: glib-2.0,gobject-2.0,gmodule-no-export-2.0
+Libs: ${pc_top_builddir}/${pcfiledir}/pango/libpango-@PANGO_API_VERSION@.la
+Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@
+
diff --git a/trunk/pango-view/GLASS.txt b/trunk/pango-view/GLASS.txt
new file mode 100644
index 00000000..610b595e
--- /dev/null
+++ b/trunk/pango-view/GLASS.txt
@@ -0,0 +1,170 @@
+I Can Eat Glass
+In various languages
+
+Adopted from http://www.columbia.edu/kermit/utf8.html#glass
+Do not edit. Submit additions to the URL above and resynch.
+
+Permission is granted by the Kermit project (http://www.columbia.edu/kermit/)
+to redistribute this file, with absolutely no warranty.
+
+
+
+Sanskrit: काचं शकà¥à¤¨à¥‹à¤®à¥à¤¯à¤¤à¥à¤¤à¥à¤®à¥ । नोपहिनसà¥à¤¤à¤¿ मामॠ॥
+Sanskrit (standard transcription): kÄcaṃ Å›aknomyattum; nopahinasti mÄm.
+Classical Greek: ὕαλον ϕαγεῖν δύναμαι· τοῦτο οὔ με βλάπτει.
+Greek: ΜποÏÏŽ να φάω σπασμένα γυαλιά χωÏίς να πάθω τίποτα.
+Etruscan: (NEEDED)
+Latin: Vitrum edere possum; mihi non nocet.
+Old French: Je puis mangier del voirre. Ne me nuit.
+French: Je peux manger du verre, ça ne me fait pas de mal.
+Provençal / Occitan: Pòdi manjar de veire, me nafrariá pas.
+Québécois: J'peux manger d'la vitre, ça m'fa pas mal.
+Walloon: Dji pou magnî do vêre, çoula m' freut nén må.
+Champenois: (NEEDED)
+Lorrain: (NEEDED)
+Picard: Ch'peux mingi du verre, cha m'foé mie n'ma.
+Corsican: (NEEDED)
+Kreyòl Ayisyen: Mwen kap manje vè, li pa blese'm.
+Basque: Kristala jan dezaket, ez dit minik ematen.
+Catalan: Puc menjar vidre que no em fa mal.
+Spanish: Puedo comer vidrio, no me hace daño.
+Aragones: Puedo minchar beire, no me'n fa mal .
+Galician: Eu podo xantar cristais e non cortarme.
+Portuguese: Posso comer vidro, não me faz mal.
+Brazilian Portuguese (7): Posso comer vidro, não me machuca.
+Caboverdiano: M' podê cumê vidru, ca ta maguâ-m'.
+Papiamentu: Ami por kome glas anto e no ta hasimi daño.
+Italian: Posso mangiare il vetro e non mi fa male.
+Milanese: Sôn bôn de magnà el véder, el me fa minga mal.
+Roman: Me posso magna' er vetro, e nun me fa male.
+Napoletano: M' pozz magna' o'vetr, e nun m' fa mal.
+Sicilian: Puotsu mangiari u vitru, nun mi fa mali.
+Venetian: Mi posso magnare el vetro, no'l me fa mae.
+Zeneise (Genovese): Pòsso mangiâ o veddro e o no me fà mâ.
+Rheto-Romance / Romansch: (NEEDED)
+Romany / Tsigane: (NEEDED)
+Romanian: Pot să mănânc sticlă și ea nu mă rănește.
+Esperanto: Mi povas manÄi vitron, Äi ne damaÄas min.
+Pictish: (NEEDED)
+Breton: (NEEDED)
+Cornish: Mý a yl dybry gwéder hag éf ny wra ow ankenya.
+Welsh: Dw i'n gallu bwyta gwydr, 'dyw e ddim yn gwneud dolur i mi.
+Manx Gaelic: Foddym gee glonney agh cha jean eh gortaghey mee.
+Old Irish (Ogham): ᚛᚛ᚉᚑᚅᚔᚉᚉᚔᚋ ᚔᚈᚔ ášáš‚ášáš…ᚑ ᚅᚔᚋᚌᚓᚅášášœ
+Old Irish (Latin): Con·iccim ithi nglano. Ním·géna.
+Irish: Is féidir liom gloinne a ithe. Ní dhéanann sí dochar ar bith dom.
+Scottish Gaelic: S urrainn dhomh gloinne ithe; cha ghoirtich i mi.
+Anglo-Saxon (Runes): á›áš³á›«á›—ᚨᚷ᛫ᚷᛚᚨᛋ᛫ᛖᚩá›ášªáš¾á›«áš©áš¾á›žá›«áš»á›á›á›«áš¾á›–᛫ᚻᛖᚪᚱᛗá›ášªáš§á›«á›—ᛖ᛬
+Anglo-Saxon (Latin): Ic mæg glæs eotan ond hit ne hearmiað me.
+Middle English: Ich canne glas eten and hit hirtiþ me nouÈt.
+English: I can eat glass and it doesn't hurt me.
+English (IPA): [aɪ kæn iËt glÉ‘Ës ænd ɪt dÉz nÉ’t hÉœËt miË] (Received Pronunciation)
+English (Braille): ⠊⠀⠉â â â €â ‘â â žâ €â ›â ‡â â Žâ Žâ €â â â ™â €â Šâ žâ €â ™â •â ‘â Žâ â žâ €â “⠥⠗⠞⠀â â ‘
+Lalland Scots / Doric: Ah can eat gless, it disnae hurt us.
+Glaswegian: (NEEDED)
+Gothic (4): ðŒ¼ðŒ°ðŒ² ðŒ²ðŒ»ðŒ´ðƒ ðŒ¹Ìˆð„ðŒ°ðŒ½, ðŒ½ðŒ¹ ðŒ¼ðŒ¹ðƒ ð…ðŒ¿ ðŒ½ðŒ³ðŒ°ðŒ½ ðŒ±ð‚ðŒ¹ðŒ²ðŒ²ðŒ¹ðŒ¸.
+Old Norse (Runes): á›–áš´ áš·á›–á› á›–á›á› ᚧ ᚷᛚᛖᚱ ᛘᚾ ᚦᛖᛋᛋ ᚨᚧ áš¡á›– ᚱᚧᚨ ᛋᚨᚱ
+Old Norse (Latin): Ek get etið gler án þess að verða sár.
+Norsk / Norwegian (Nynorsk): Eg kan eta glas utan å skada meg.
+Norsk / Norwegian (Bokmål): Jeg kan spise glass uten å skade meg.
+Føroyskt / Faroese: (NEEDED)
+Ãslenska / Icelandic: Ég get etið gler án þess að meiða mig.
+Svenska / Swedish: Jag kan äta glas utan att skada mig.
+Dansk / Danish: Jeg kan spise glas, det gør ikke ondt på mig.
+Soenderjysk: Æ ka æe glass uhen at det go mæ naue.
+Frysk / Frisian: Ik kin glês ite, it docht me net sear.
+Nederlands / Dutch: Ik kan glas eten, het doet mij geen kwaad.
+Kirchröadsj/Bôchesserplat: Iech ken glaas èèse, mer 't deet miech jing pieng.
+Afrikaans: Ek kan glas eet, maar dit doen my nie skade nie.
+Lëtzebuergescht / Luxemburgish: Ech kan Glas iessen, daat deet mir nët wei.
+Deutsch / German: Ich kann Glas essen, ohne mir weh zu tun.
+Ruhrdeutsch: Ich kann Glas verkasematuckeln, ohne dattet mich wat jucken tut.
+Lausitzer Mundart ("Lusatian"): Ich koann Gloos assn und doas dudd merr ni wii.
+Odenwälderisch: Iech konn glaasch voschbachteln ohne dass es mir ebbs daun doun dud.
+Sächsisch / Saxon: 'sch kann Glos essn, ohne dass'sch mer wehtue.
+Pfälzisch: Isch konn Glass fresse ohne dasses mer ebbes ausmache dud.
+Schwäbisch / Swabian: I kå Glas frässa, ond des macht mr nix!
+Bayrisch / Bavarian: I koh Glos esa, und es duard ma ned wei.
+Allemannisch: I kaun Gloos essen, es tuat ma ned weh.
+Schwyzerdütsch: Ich chan Glaas ässe, das tuet mir nöd weeh.
+Hungarian: Meg tudom enni az üveget, nem lesz tőle bajom.
+Suomi / Finnish: Voin syödä lasia, se ei vahingoita minua.
+Sami (Northern): Sáhtán borrat lása, dat ii leat bávÄÄas.
+Erzian: Мон ÑÑ€Ñан Ñуликадо, ды зыÑн ÑйÑÑ‚ÑÐ½Ð·Ñ Ð° ули.
+Karelian: (NEEDED)
+Vepsian: (NEEDED)
+Votian: (NEEDED)
+Livonian: (NEEDED)
+Estonian: Ma võin klaasi süüa, see ei tee mulle midagi.
+Latvian: Es varu ēst stiklu, tas man nekaitē.
+Lithuanian: Aš galiu valgyti stiklą ir jis manęs nežeidžia
+Old Prussian: (NEEDED)
+Sorbian (Wendish): (NEEDED)
+Czech: Mohu jíst sklo, neublíží mi.
+Slovak: Môžem jesť sklo. Nezraní ma.
+Polska / Polish: Mogę jeść szkło i mi nie szkodzi.
+Slovenian: Lahko jem steklo, ne da bi mi Å¡kodovalo.
+Croatian: Ja mogu jesti staklo i ne boli me.
+Serbian (Latin): Mogu jesti staklo a da mi ne Å¡kodi.
+Serbian (Cyrillic): Могу јеÑти Ñтакло а да ми не шкоди.
+Macedonian: Можам да јадам Ñтакло, а не ме штета.
+Russian: Я могу еÑÑ‚ÑŒ Ñтекло, оно мне не вредит.
+Belarusian (Cyrillic): Я магу еÑці шкло, Ñно мне не шкодзіць.
+Belarusian (Lacinka): Ja mahu jeści škło, jano mne ne škodzić.
+Ukrainian: Я можу Ñ—Ñти шкло, й воно мені не пошкодить.
+Bulgarian: Мога да Ñм Ñтъкло, то не ми вреди.
+Georgian: მინáƒáƒ¡ ვჭáƒáƒ› დრáƒáƒ áƒ მტკივáƒ.
+Armenian: Ô¿Ö€Õ¶Õ¡Õ´ Õ¡ÕºÕ¡Õ¯Õ« Õ¸Ö‚Õ¿Õ¥Õ¬ Ö‡ Õ«Õ¶Õ®Õ« Õ¡Õ¶Õ°Õ¡Õ¶Õ£Õ«Õ½Õ¿ Õ¹Õ¨Õ¶Õ¥Ö€Ö‰
+Albanian: Unë mund të ha qelq dhe nuk më gjen gjë.
+Turkish: Cam yiyebilirim, bana zararı dokunmaz.
+Turkish (Ottoman): جام ييه بلورم بڭا ضررى طوقونمز
+Bangla / Bengali: আমি কাà¦à¦š খেতে পারি, তাতে আমার কোনো কà§à¦·à¦¤à¦¿ হয় না।
+Marathi: मी काच खाऊ शकतो, मला ते दà¥à¤–त नाही.
+Hindi: मैं काà¤à¤š खा सकता हूà¤, मà¥à¤à¥‡ उस से कोई पीडा नहीं होती.
+Tamil: நான௠கணà¯à®£à®¾à®Ÿà®¿ சாபà¯à®ªà®¿à®Ÿà¯à®µà¯‡à®©à¯, அதனால௠எனகà¯à®•à¯ ஒர௠கேடà¯à®®à¯ வராதà¯.
+Urdu(2): میں کانچ کھا سکتا ÛÙˆÚº اور مجھے تکلی٠نÛیں Ûوتی Û”
+Pashto(2): زه شيشه Ø®ÙˆÚ“Ù„Û Ø´Ù…ØŒ هغه ما نه خوږوي
+Farsi / Persian: .من می توانم بدون٠احساس درد شيشه بخورم
+Arabic(2): أنا قادر على أكل الزجاج و هذا لا يؤلمني.
+Aramaic: (NEEDED)
+Hebrew(2): ×× ×™ יכול ל×כול זכוכית וזה ×œ× ×ž×–×™×§ לי.
+Yiddish(2): ×יך קען עסן גל×ָז ×ון עס טוט מיר נישט װײ.
+Judeo-Arabic: (NEEDED)
+Ladino: (NEEDED)
+GÇʼÇz: (NEEDED)
+Amharic: (NEEDED)
+Twi: Metumi awe tumpan, ɜnyɜ me hwee.
+Hausa (Latin): Inā iya taunar gilāshi kuma in gamā lāfiyā.
+Hausa (Ajami) (2): Ø¥Ùنا Ø¥ÙÙ‰ÙŽ تَونَر غÙلَاش٠كÙÙ…ÙŽ Ø¥ÙÙ† غَمَا لَاÙÙىَا
+Yoruba(3): Mo lè je̩ dígí, kò ní pa mí lára.
+(Ki)Swahili: Naweza kula bilauri na sikunyui.
+Malay: Saya boleh makan kaca dan ia tidak mencederakan saya.
+Tagalog: Kaya kong kumain nang bubog at hindi ako masaktan.
+Chamorro: Siña yo' chumocho krestat, ti ha na'lalamen yo'.
+Javanese: Aku isa mangan beling tanpa lara.
+Burmese: (NEEDED)
+Vietnamese (quốc ngữ): Tôi có thể ăn thủy tinh mà không hại gì.
+Vietnamese (nôm) (4): 些 𣎠世 咹 水 晶 𦓡 空 𣎠害 咦
+Khmer: (NEEDED)
+Lao: (NEEDED)
+Thai: ฉันà¸à¸´à¸™à¸à¸£à¸°à¸ˆà¸à¹„ด้ à¹à¸•à¹ˆà¸¡à¸±à¸™à¹„ม่ทำให้ฉันเจ็บ
+Mongolian (Cyrillic): Би шил идÑй чадна, надад хортой биш
+Mongolian (Classic) (5): ᠪᠢ ᠰᠢᠯᠢ ᠢᠳᠡᠶᠦ ᠴᠢᠳᠠᠨᠠ ᠂ ᠨᠠᠳᠤᠷ ᠬᠣᠤᠷᠠᠳᠠᠢ ᠪᠢᠰᠢ
+Dzongkha: (NEEDED)
+Nepali: (NEEDED)
+Tibetan: ཤེལ་སྒོ་ཟ་ནས་ང་ན་གི་མ་རེདà¼
+Chinese: 我能åžä¸‹çŽ»ç’ƒè€Œä¸ä¼¤èº«ä½“。
+Chinese (Traditional): 我能åžä¸‹çŽ»ç’ƒè€Œä¸å‚·èº«é«”。
+Taiwanese(6): Góa Ä“-tàng chiaÌh po-lê, mÄ bÄ“ tioÌh-siong.
+Japanese: ç§ã¯ã‚¬ãƒ©ã‚¹ã‚’食ã¹ã‚‰ã‚Œã¾ã™ã€‚ãã‚Œã¯ç§ã‚’å‚·ã¤ã‘ã¾ã›ã‚“。
+Korean: 나는 유리를 ë¨¹ì„ ìˆ˜ 있어요. ê·¸ëž˜ë„ ì•„í”„ì§€ ì•Šì•„ìš”
+Bislama: Mi save kakae glas, hemi no save katem mi.
+Hawaiian: Hiki iaÊ»u ke Ê»ai i ke aniani; Ê»aÊ»ole nÅ lÄ au e Ê»eha.
+Marquesan: E koÊ»ana e kai i te karahi, mea Ê»Ä, Ê»aÊ»e hauhau.
+Chinook Jargon: Naika məkmək kakshət labutay, pi weyk ukuk munk-sik nay.
+Navajo: Tsésǫʼ yishÄ…ÌÄ…go bííníshghah dóó doo shiÅ‚ neezgai da.
+Cherokee (and Cree, Ojibwa, Inuktitut, and other Native American languages): (NEEDED)
+Garifuna: (NEEDED)
+Gullah: (NEEDED)
+Lojban: mi kakne le nu citka le blaci .iku'i le se go'i na xrani mi
+Nórdicg: Ljœr ye caudran créneþ ý jor cẃran.
diff --git a/trunk/pango-view/HELLO.txt b/trunk/pango-view/HELLO.txt
new file mode 100644
index 00000000..21acb941
--- /dev/null
+++ b/trunk/pango-view/HELLO.txt
@@ -0,0 +1,54 @@
+This is Pango (Παν語)
+
+This is a list of ways to say hello in various languages.
+Its purpose is to illustrate a number of scripts.
+
+---------------------------------------------------------
+Arabic السَّلام عليكÙÙ…
+Bengali (বাঙà§à¦²à¦¾) ষাগতোম
+Burmese မ္ရန္မာ
+Cherokee (á£áŽ³áŽ©) Ꭳáá²
+Czech (Äesky) Dobrý den
+Danish (Dansk) Hej, Goddag
+English Hello
+Esperanto Saluton
+Estonian Tere, Tervist
+FORTRAN PROGRAM
+Finnish (Suomi) Hei
+French (Français) Bonjour, Salut
+German (Deutsch Nord) Guten Tag
+German (Deutsch Süd) Grüß Gott
+Georgian (ქáƒáƒ áƒ—ველი) გáƒáƒ›áƒáƒ áƒ¯áƒáƒ‘áƒ
+Gujarati ગà«àªœàª°àª¾àª¤àª¿
+Greek (Ελληνικά) Γειά σας
+Hebrew שלו×
+Hindi नमसà¥à¤¤à¥‡, नमसà¥à¤•à¤¾à¤°à¥¤
+Italiano Ciao, Buon giorno
+IPA English (ɪŋglɪʃ) hɛləʊ
+Lao ສບາàºàº”
+Maltese Ċaw, Saħħa
+Nederlands, Vlaams Hallo, Dag
+Norwegian (Norsk) Hei, God dag
+Punjabi ਪà©à¨‚ਜਾਬਿ
+Polish Dzień dobry, Hej
+Russian (РуÑÑкий) ЗдравÑтвуйте!
+Sinhala (සිංහල) ආයුබà·à·€à¶±à·Š
+Slovak Dobrý deň
+Spanish (Español) ¡Hola!
+Swedish (Svenska) Hej, Goddag
+Thai (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ
+Tamil (தமிழà¯) வணகà¯à®•à®®à¯
+Turkish (Türkçe) Merhaba
+Vietnamese (Tiếng Việt) Xin Chào
+Yiddish (ײַדישע)‎ ד×ָס הײַזעלע
+
+Japanese (日本語) ã“ã‚“ã«ã¡ã¯, コï¾ï¾†ï¾ï¾Š
+Chinese (中文,普通è¯,汉语) 你好
+Cantonese (粵語,廣æ±è©±) 早晨, 你好
+Korean (한글) 안녕하세요, 안녕하십니까
+
+Difference among chinese characters in GB, JIS, KSC, BIG5:
+ GB -- 元气 å¼€å‘
+ JIS -- 元気 開発
+ KSC -- 元氣 開發
+ BIG5 -- 元氣 開發
diff --git a/trunk/pango-view/Makefile.am b/trunk/pango-view/Makefile.am
new file mode 100644
index 00000000..9780c146
--- /dev/null
+++ b/trunk/pango-view/Makefile.am
@@ -0,0 +1,194 @@
+## Process this file with automake to create Makefile.in.
+
+TEST_TEXTS = \
+ test-arabic.txt \
+ test-chinese.txt \
+ test-devanagari.txt \
+ test-gurmukhi.txt \
+ test-hebrew.txt \
+ test-ipa.txt \
+ test-justify.txt \
+ test-lao.txt \
+ test-latin.txt \
+ test-long-paragraph.txt \
+ test-mixed.markup \
+ test-mixed.txt \
+ test-nko.txt \
+ test-opentype-language.markup \
+ test-syriac.txt \
+ test-tamil.txt \
+ test-thai.txt \
+ test-tibetan.txt \
+ HELLO.txt \
+ GLASS.txt
+
+EXTRA_DIST = \
+ viewer-win32.c \
+ $(TEST_TEXTS)
+
+CLEANFILES = pangorc
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(PANGO_DEBUG_FLAGS) \
+ $(GLIB_CFLAGS) \
+ $(XFT_CFLAGS) \
+ $(CAIRO_CFLAGS) \
+ $(FREETYPE_CFLAGS) \
+ $(X_CFLAGS)
+
+noinst_PROGRAMS =
+bin_PROGRAMS =
+
+#########################################################
+if HAVE_FREETYPE
+noinst_PROGRAMS += pangoft2-view
+
+pangoft2_view_SOURCES = \
+ viewer-render.h \
+ viewer-render.c \
+ viewer.h \
+ viewer-main.c \
+ viewer-pangoft2.c \
+ pangoft2-view.c
+
+pangoft2_view_LDADD = \
+ ../pango/libpango-$(PANGO_API_VERSION).la \
+ ../pango/libpangoft2-$(PANGO_API_VERSION).la \
+ $(GLIB_LIBS) \
+ $(FREETYPE_LIBS)
+endif
+#########################################################
+
+#########################################################
+if HAVE_X
+noinst_PROGRAMS += pangox-view
+
+pangox_view_SOURCES = \
+ viewer-render.h \
+ viewer-render.c \
+ viewer.h \
+ viewer-x.h \
+ viewer-x.c \
+ viewer-main.c \
+ viewer-pangox.c \
+ pangox-view.c
+
+pangox_view_LDADD = \
+ ../pango/libpango-$(PANGO_API_VERSION).la \
+ ../pango/libpangox-$(PANGO_API_VERSION).la \
+ $(GLIB_LIBS) \
+ $(X_LIBS)
+endif
+#########################################################
+
+#########################################################
+if HAVE_XFT
+noinst_PROGRAMS += pangoxft-view
+
+pangoxft_view_SOURCES = \
+ viewer-render.h \
+ viewer-render.c \
+ viewer.h \
+ viewer-x.h \
+ viewer-x.c \
+ viewer-main.c \
+ viewer-pangoxft.c \
+ pangoxft-view.c
+
+pangoxft_view_LDADD = \
+ ../pango/libpango-$(PANGO_API_VERSION).la \
+ ../pango/libpangoft2-$(PANGO_API_VERSION).la \
+ ../pango/libpangoxft-$(PANGO_API_VERSION).la \
+ $(GLIB_LIBS) \
+ $(XFT_LIBS) \
+ $(X_LIBS)
+endif
+#########################################################
+
+#########################################################
+if HAVE_CAIRO
+if HAVE_X
+if HAVE_CAIRO_XLIB
+noinst_PROGRAMS += pangocairo-view
+
+pangocairo_view_SOURCES = \
+ viewer-render.h \
+ viewer-render.c \
+ viewer.h \
+ viewer-cairo.h \
+ viewer-cairo.c \
+ viewer-x.h \
+ viewer-x.c \
+ viewer-main.c \
+ viewer-pangocairo.c \
+ pangocairo-view.c
+
+pangocairo_view_LDADD = \
+ ../pango/libpango-$(PANGO_API_VERSION).la \
+ ../pango/libpangoft2-$(PANGO_API_VERSION).la \
+ ../pango/libpangocairo-$(PANGO_API_VERSION).la \
+ $(GLIB_LIBS) \
+ $(CAIRO_LIBS) \
+ $(X_LIBS)
+endif
+endif
+endif
+#########################################################
+
+#########################################################
+if HAVE_X
+bin_PROGRAMS += pango-view
+pango_view_SOURCES = \
+ viewer-render.h \
+ viewer-render.c \
+ viewer.h \
+ viewer-x.h \
+ viewer-x.c \
+ viewer-main.c \
+ pango-view.c
+pango_view_LDADD = \
+ ../pango/libpango-$(PANGO_API_VERSION).la \
+ $(GLIB_LIBS)
+if HAVE_X
+pango_view_SOURCES += \
+ viewer-pangox.c
+pango_view_LDADD += \
+ ../pango/libpangox-$(PANGO_API_VERSION).la
+endif
+if HAVE_FREETYPE
+pango_view_SOURCES += \
+ viewer-pangoft2.c
+pango_view_LDADD += \
+ ../pango/libpangoft2-$(PANGO_API_VERSION).la \
+ $(FREETYPE_LIBS)
+endif
+if HAVE_XFT
+pango_view_SOURCES += \
+ viewer-pangoxft.c
+pango_view_LDADD += \
+ ../pango/libpangoft2-$(PANGO_API_VERSION).la \
+ ../pango/libpangoxft-$(PANGO_API_VERSION).la \
+ $(XFT_LIBS)
+endif
+if HAVE_CAIRO
+if HAVE_CAIRO_XLIB
+pango_view_SOURCES += \
+ viewer-cairo.h \
+ viewer-cairo.c \
+ viewer-pangocairo.c
+pango_view_LDADD += \
+ ../pango/libpangoft2-$(PANGO_API_VERSION).la \
+ ../pango/libpangocairo-$(PANGO_API_VERSION).la \
+ $(CAIRO_LIBS)
+endif
+endif
+pango_view_LDADD += \
+ $(X_LIBS)
+endif
+#########################################################
+
+BUILT_SOURCES = pangorc
+
+pangorc: $(srcdir)/../modules/pangorc
+ cp $(srcdir)/../modules/pangorc $@
diff --git a/trunk/pango-view/pango-view.c b/trunk/pango-view/pango-view.c
new file mode 100644
index 00000000..9771e8cc
--- /dev/null
+++ b/trunk/pango-view/pango-view.c
@@ -0,0 +1,23 @@
+#include <config.h>
+#include "viewer.h"
+
+extern const PangoViewer pangocairo_viewer;
+extern const PangoViewer pangoxft_viewer;
+extern const PangoViewer pangoft2_viewer;
+extern const PangoViewer pangox_viewer;
+
+const PangoViewer *viewers[] = {
+#ifdef HAVE_CAIRO_XLIB
+ &pangocairo_viewer,
+#endif
+#ifdef HAVE_XFT
+ &pangoxft_viewer,
+#endif
+#ifdef HAVE_FREETYPE
+ &pangoft2_viewer,
+#endif
+#ifdef HAVE_X
+ &pangox_viewer,
+#endif
+ NULL
+};
diff --git a/trunk/pango-view/pangocairo-view.c b/trunk/pango-view/pangocairo-view.c
new file mode 100644
index 00000000..c5ba8716
--- /dev/null
+++ b/trunk/pango-view/pangocairo-view.c
@@ -0,0 +1,8 @@
+#include "viewer.h"
+
+extern const PangoViewer pangocairo_viewer;
+
+const PangoViewer *viewers[] = {
+ &pangocairo_viewer,
+ NULL
+};
diff --git a/trunk/pango-view/pangoft2-view.c b/trunk/pango-view/pangoft2-view.c
new file mode 100644
index 00000000..d4ac695c
--- /dev/null
+++ b/trunk/pango-view/pangoft2-view.c
@@ -0,0 +1,8 @@
+#include "viewer.h"
+
+extern const PangoViewer pangoft2_viewer;
+
+const PangoViewer *viewers[] = {
+ &pangoft2_viewer,
+ NULL
+};
diff --git a/trunk/pango-view/pangox-view.c b/trunk/pango-view/pangox-view.c
new file mode 100644
index 00000000..72e97603
--- /dev/null
+++ b/trunk/pango-view/pangox-view.c
@@ -0,0 +1,8 @@
+#include "viewer.h"
+
+extern const PangoViewer pangox_viewer;
+
+const PangoViewer *viewers[] = {
+ &pangox_viewer,
+ NULL
+};
diff --git a/trunk/pango-view/pangoxft-view.c b/trunk/pango-view/pangoxft-view.c
new file mode 100644
index 00000000..bdf893f8
--- /dev/null
+++ b/trunk/pango-view/pangoxft-view.c
@@ -0,0 +1,8 @@
+#include "viewer.h"
+
+extern const PangoViewer pangoxft_viewer;
+
+const PangoViewer *viewers[] = {
+ &pangoxft_viewer,
+ NULL
+};
diff --git a/trunk/pango-view/test-arabic.txt b/trunk/pango-view/test-arabic.txt
new file mode 100644
index 00000000..58653a6f
--- /dev/null
+++ b/trunk/pango-view/test-arabic.txt
@@ -0,0 +1,7 @@
+بÙسْم٠ٱللّٰه٠ٱلرَّحْمٰن٠ٱلرَّحÙيمÙ
+اَلْحَمْد٠لÙلّٰه٠رَبّ٠الْعَالَمÙينَ
+اَلرَّحْمٰن٠الرَّحÙيمÙ
+مَالÙك٠يَوْم٠الدّÙينÙ
+اÙيَّاكَ نَعْبÙد٠وَ اÙيَّاكَ نَسْتَعÙينÙ
+اÙهْدÙنَا الصّÙرَاطَ الْمÙسْتَقÙيمَ
+صÙرَاطَ الَّذÙينَ اَنْعَمْتَ عَلَيهÙمْ غَيْر٠الْمَغْضÙوب٠عَلَيْهÙÙ… ÙˆÙŽ لَا الضَّٓالّÙينَ
diff --git a/trunk/pango-view/test-chinese.txt b/trunk/pango-view/test-chinese.txt
new file mode 100644
index 00000000..d4fb796a
--- /dev/null
+++ b/trunk/pango-view/test-chinese.txt
@@ -0,0 +1,7 @@
+你好,这是中文竖排测试。
+欢迎æ¥åˆ°ä¸­å›½åŒ—京。
+白日ä¾å±±å°½ï¼Œ
+黄河入海æµã€‚
+欲穷åƒé‡Œç›®ï¼Œ
+更上一层楼。
+谢谢ï¼
diff --git a/trunk/pango-view/test-devanagari.txt b/trunk/pango-view/test-devanagari.txt
new file mode 100644
index 00000000..9cfccc56
--- /dev/null
+++ b/trunk/pango-view/test-devanagari.txt
@@ -0,0 +1,9 @@
+कि KI
+किकि KIKI
+कà¥à¤•à¤¿ KKI
+कà¥à¤•à¥à¤•à¤¿ KKKI
+कà¥à¥à¤•à¤¿ KKI (sp)
+कà¥à¤¼à¤•à¤¿ KKI (sp)
+कà¥à¥à¤•à¥à¤•à¤¿ KKKI (sp)
+कà¥à¥à¤•à¥à¥à¤•à¤¿ KKKI (sp)
+कà¥à¤¼à¤•à¥à¤¼à¤•à¤¿ KKKI (sp)
diff --git a/trunk/pango-view/test-gurmukhi.txt b/trunk/pango-view/test-gurmukhi.txt
new file mode 100644
index 00000000..f3d05920
--- /dev/null
+++ b/trunk/pango-view/test-gurmukhi.txt
@@ -0,0 +1,26 @@
+ਹਰੀ ਸਿੰਘ ਨਲੂਆ
+
+ਹਰੀ ਸਿੰਘ ਨਲੂਆ (ਨਲਵਾ)
+
+
+ਸਿੱਖ ਕੌਮ ਦਾ ਅਣਖੀ ਅਤੇ ਬਹਾਦਰ ਜਰਨੈਲ, ਜਿਸ ਦੇ ਨਾਂ ਤੋਂ ਪਠਾਣੀਆਂ ਆਪਣੇ ਬੱਚਿਆਂ ਨੂੰ ਡਰਾਉਦੀਆਂ ਸਨ ਕਿ ਪà©à©±à¨¤ ਸੌਂ ਜਾ ਨਹੀਂ ਤਾਂ ਨਲੂਆ ਆ ਜਾਵੇਗਾ।
+
+
+ਵਿਸ਼ਾ-ਸੂਚੀ
+[ਛà©à¨ªà¨¾à¨“]
+
+ * ੧ ਜਨਮ ਅਤੇ ਸਿਖਲਾਈ
+ * ੨ ਨਲੂਆ
+ * ੩ ਖਾਲਸਾ ਫੌਜ
+ * ੪ ਕਸ਼ਮੀਰ
+ * ੫ ਜੰਗ ਜਮਰੌਦ
+ * ੬ ਜਾਗੀਰ ਵਾਪਸੀ
+
+ ਜਨਮ ਅਤੇ ਸਿਖਲਾਈ
+
+ਸਰਦਾਰ ਹਰੀ ਸਿੰਘ ਦਾ ਜਨਮ ਗà©à©±à¨œà¨°à¨¾à¨µà¨¾à¨²à©‡ ਵਿਖੇ ਹੋਇਆ। ਪਿਤਾ ਦੀ ਮੌਤ ਨਿੱਕੀ ਉਮਰ ਵਿੱਚ ਹੋਣ ਉਪਰੰਤ, ਉਹਨਾਂ ਦਾ ਪਾਲਣ ਪੋਸ਼ਣ ਉਹਨਾਂ ਦੇ ਨਾਨਕੇ ਪਰਿਵਾਰ ਵਿੱਚ ਹੋਇਆ।
+
+ਸਰਦਾਰ ਹਰੀ ਸਿੰਘ ਨਲੂਆ ਦੇ ਪਰਿਵਾਰ ਵਿੱਚ ਦੋ ਪਤਨੀਆਂ, ਜਿੰਨà©à¨¹à¨¾à¨‚ ਦਾ ਜ਼ੋਰਾਵਰ ਸਿੰਘ ਤੇ ਗà©à¨°à¨¦à¨¿à©±à¨¤ ਸਿੰਘ, ਅਤੇ ਅਰਜਨ ਸਿੰਘ ਤੇ ਪੰਜਾਬ ਸਿੰਘ ਨਾਂ ਦੇ ਚਾਰ ਪà©à©±à¨¤à¨° ਸਨ। ਚਾਰੇ ਪà©à©±à¨¤à¨° ਆਪਣੇ ਪਿਓ ਵਾਂਗ ਬਹਾਦਰ ਨਹੀਂ ਸਨ।
+ਇਹਨਾਂ ਕਰਕੇ ਮਹਾਰਾਜਾ ਰਣਜੀਤ ਸਿੰਘ ਨੇ ਅੰਤ ਵਿੱਚ ਸਰਦਾਰ ਹਰੀ ਸਿੰਘ ਦੀ ਸਾਰੀ ਜਾਗੀਰ ਨੂੰ ਵਾਪਸ ਲੈ ਲਈ ਆਪਣੇ ਸਰਦਾਰ ਵਿੱਚ ਵੰਡ ਦਿੱਤੀ।
+ਸਰਦਾਰ ਹਰੀ ਸਿੰਘ ਦੇ ਬਾਅਦ ਇਹਨਾਂ ਕੋਲ 40,000 ਹਜ਼ਾਰ ਦੀ ਸਲਾਨਾ ਜਾਗੀਰ ਅਤੇ 60 ਤੋਂ 70 ਸਵਾਰ ਰਹੇ।
+
diff --git a/trunk/pango-view/test-hebrew.txt b/trunk/pango-view/test-hebrew.txt
new file mode 100644
index 00000000..15467d87
--- /dev/null
+++ b/trunk/pango-view/test-hebrew.txt
@@ -0,0 +1,13 @@
+בְּרֵ×ש×ִ֖ית ×‘Ö¼Ö¸×¨Ö¸Ö£× ×Ö±×œÖ¹×”Ö´Ö‘×™× ×ֵ֥ת הַשּ×Ö¸×žÖ·Ö–×™Ö´× ×•Ö°×ֵ֥ת ×”Ö¸×ָֽרֶץ׃
+וְהָ×ָ֗רֶץ הָֽיְתָ֥ה תֹ֨הוּ֙ וָבֹ֔הוּ וְחֹ֖ש×ֶךְ עַל־פְּנֵ֣י ×ªÖ°×”Ö‘×•Ö¹× ×•Ö°×¨Ö£×•Ö¼×—Ö· ×Ö±×œÖ¹×”Ö´Ö”×™× ×žÖ°×¨Ö·×—Ö¶Ö–×¤Ö¶×ª עַל־פְּנֵ֥י הַמָּֽיִ×׃
+וַיֹּ֥×מֶר ×Ö±×œÖ¹×”Ö´Ö–×™× ×™Ö°×”Ö´Ö£×™ ×֑וֹר וַֽיְהִי־×ֽוֹר׃
+×•Ö·×™Ö¼Ö·Ö§×¨Ö°× ×Ö±×œÖ¹×”Ö´Ö›×™× ×ֶת־הָ×֖וֹר כִּי־ט֑וֹב וַיַּבְדֵּ֣ל ×Ö±×œÖ¹×”Ö´Ö”×™× ×‘Ö¼ÖµÖ¥×™×Ÿ ×”Ö¸×֖וֹר וּבֵ֥ין הַחֹֽש×ֶךְ׃
+×•Ö·×™Ö¼Ö´×§Ö°×¨Ö¸Ö¨× ×ֱלֹהִ֤י× ׀ לָ×וֹר֙ ×™Ö”×•Ö¹× ×•Ö°×œÖ·×—Ö¹Ö–×©×ֶךְ ×§Ö¸Ö£×¨Ö¸× ×œÖ¸Ö‘×™Ö°×œÖ¸×” וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר ×™Ö¥×•Ö¹× ×ֶחָֽד׃
+וַיֹּ֣×מֶר ×Ö±×œÖ¹×”Ö´Ö”×™× ×™Ö°×”Ö´Ö¥×™ רָקִ֖יעַ בְּת֣וֹךְ ×”Ö·×žÖ¼Ö¸Ö‘×™Ö´× ×•Ö´×™×”Ö´Ö£×™ מַבְדִּ֔יל בֵּ֥ין ×žÖ·Ö–×™Ö´× ×œÖ¸×žÖ¸Ö½×™Ö´×׃
+וַיַּ֣עַשׂ ×ֱלֹהִי×Ö® ×ֶת־הָֽרָקִיעַ֒ וַיַּבְדֵּ֗ל בֵּ֤ין הַמַּ֨יִ×Ö™ ×ֲש×ֶר֙ מִתַּ֣חַת לָֽרָקִ֔יעַ וּבֵ֣ין ×”Ö·×žÖ¼Ö·Ö”×™Ö´× ×ֲש×ֶ֖ר מֵעַ֣ל לָֽרָקִ֑יעַ וַֽיְהִי־כֵֽן׃
+×•Ö·×™Ö¼Ö´×§Ö°×¨Ö¸Ö§× ×Ö±×œÖ¹×”Ö´Ö›×™× ×œÖ¸Ö½×¨Ö¸×§Ö´Ö–×™×¢Ö· ש×Ö¸×žÖ¸Ö‘×™Ö´× ×•Ö·Ö½×™Ö°×”Ö´×™Ö¾×¢Ö¶Ö¥×¨Ö¶×‘ וַֽיְהִי־בֹ֖קֶר ×™Ö¥×•Ö¹× ×©×ֵנִֽי׃
+וַיֹּ֣×מֶר ×Ö±×œÖ¹×”Ö´Ö—×™× ×™Ö´×§Ö¼Ö¸×•Ö¨×•Ö¼ ×”Ö·×žÖ¼Ö·Öœ×™Ö´× ×žÖ´×ªÖ¼Ö·Ö¤×—Ö·×ª הַשּ×ָמַ֨יִ×Ö™ ×Ö¶×œÖ¾×žÖ¸×§Ö£×•Ö¹× ×ֶחָ֔ד וְתֵֽרָ×Ö¶Ö–×” הַיַּבָּש×Ö¸Ö‘×” וַֽיְהִי־כֵֽן׃
+×•Ö·×™Ö¼Ö´×§Ö°×¨Ö¸Ö¨× ×ֱלֹהִ֤י× ׀ לַיַּבָּש×ָה֙ ×ֶ֔רֶץ וּלְמִקְוֵ֥ה ×”Ö·×žÖ¼Ö·Ö–×™Ö´× ×§Ö¸×¨Ö¸Ö£× ×™Ö·×žÖ¼Ö´Ö‘×™× ×•Ö·×™Ö¼Ö·Ö¥×¨Ö°× ×Ö±×œÖ¹×”Ö´Ö–×™× ×›Ö¼Ö´×™Ö¾×˜Ö½×•Ö¹×‘×ƒ
+וַיֹּ֣×מֶר ×Ö±×œÖ¹×”Ö´Ö—×™× ×ªÖ¼Ö·Ö½×“Ö°×©×ÖµÖ¤× ×”Ö¸×ָ֨רֶץ֙ דֶּ֗ש×Ö¶× ×¢ÖµÖš×©×‚Ö¶×‘ מַזְרִ֣יעַ זֶ֔רַע ×¢ÖµÖ£×¥ פְּרִ֞י עֹ֤שֶׂה פְּרִי֙ לְמִינ֔וֹ ×ֲש×ֶ֥ר זַרְעוֹ־ב֖וֹ עַל־הָ×ָ֑רֶץ וַֽיְהִי־כֵֽן׃
+×•Ö·×ªÖ¼×•Ö¹×¦ÖµÖ¨× ×”Ö¸×ָ֜רֶץ דֶּ֠ש×Ö¶× ×¢ÖµÖ£×©×‚Ö¶×‘ מַזְרִ֤יעַ זֶ֨רַע֙ לְמִינֵ֔הוּ וְעֵ֧ץ עֹֽשֶׂה־פְּרִ֛י ×ֲש×ֶ֥ר זַרְעוֹ־ב֖וֹ לְמִינֵ֑הוּ ×•Ö·×™Ö¼Ö·Ö¥×¨Ö°× ×Ö±×œÖ¹×”Ö´Ö–×™× ×›Ö¼Ö´×™Ö¾×˜Ö½×•Ö¹×‘×ƒ
+וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר ×™Ö¥×•Ö¹× ×©×ְלִיש×ִֽי׃
diff --git a/trunk/pango-view/test-ipa.txt b/trunk/pango-view/test-ipa.txt
new file mode 100644
index 00000000..2fdd5e2c
--- /dev/null
+++ b/trunk/pango-view/test-ipa.txt
@@ -0,0 +1,8 @@
+n̩ a̩ m̩ w̩ i̩ l̩ j̩̩ ɳ̩ ŋ̩
+n̽ a̽ m̽ w̽ i̽ l̽ j̽ ɳ̽ ŋ̽
+ff fi fl e˥˩ i˦˨˥
+aÌˆÌƒÌ É›ÌƒÌˆÌ€ É©Ì‚Ì É”ÌƒÌ‚ ʉ̄̈ ɠ̪̥̈
+ŋ̥ n̥ n̪̰
+k͡p m͡i l͡w l͡i m͡w
+
+
diff --git a/trunk/pango-view/test-justify.txt b/trunk/pango-view/test-justify.txt
new file mode 100644
index 00000000..754ed28c
--- /dev/null
+++ b/trunk/pango-view/test-justify.txt
@@ -0,0 +1,5 @@
+<span letter_spacing="2048">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc sit amet nulla. Cras elit. Fusce nibh orci, vehicula ut, congue ut, auctor quis, turpis.</span>
+
+Fusce ullamcorper porttitor quam. Nullam at nulla sit amet neque rutrum porttitor. Quisque mattis blandit velit. Aenean nec risus sed libero rhoncus suscipit. Cras dapibus.
+
+قصابه با بابام رÙیقه. پشت خونمون یه دباغیه. اینقده بچه گوسÙند توشه! خونه‌مون ساس داره. ساس کوچیک Ùˆ سیاس. هر جا بزنه جاش باد می‌کنه. وقتی داره از دیوار اتاق می‌ره بالا، نمی‌تونه خودشو Ù†Ú¯Ù‡ داره، می‌اÙته رو تن ما، می‌گیره خونمونو می‌مکه. یه دÙعه همه اثاث مثاثامونو ریختیم بیرون، یه عالمه دوا خریدیم زدیم همه جا: به رختخوابا،‌ زیر زیلو، سوراخ سنبه‌ها. ولی ساسها بیشتر شدن، کمتر نشدن. بابام توی حموم کار می‌کنه.
diff --git a/trunk/pango-view/test-lao.txt b/trunk/pango-view/test-lao.txt
new file mode 100644
index 00000000..012025e4
--- /dev/null
+++ b/trunk/pango-view/test-lao.txt
@@ -0,0 +1,2 @@
+ເàºàº±àºšàºžàº²àºšàº‡àº²àº¡à»†àº¡àº²àºàº²àºà»ƒàº«à»‰à»àºŸàº™à»†à»„ດ້ເຫັນເຕັມໆຕາທີ່ມະຫາສານ.ຄອມ
+ ປະຈຸບັນ, ຕ້ອງàºàº­àº¡àº®àº±àºšàºàº±àº™àº§à»ˆàº² àºàº°à»àºªàº•àº­àºšàº®àº±àºšà»àº™àº§à»€àºžàº‡àºªàº°àº•àº´àº‡àºàº³àº¥àº±àº‡àº¡àº²à»àº®àº‡àº­àºµà»ˆàº«àº¥àºµ, ບາງບົດເພງນອàºàºˆàº²àºàºˆàº°à»€àº›àº±àº™àº—ີ່ນິàºàº»àº¡à»ƒàº™àºšà»‰àº²àº™à»€àº®àº»àº² ເມືອງເຮົາà»àº¥à»‰àº§ àºàº±àº‡àº‚້າມàºàº±à»ˆàº‡à»„ປດັງຢູ່ບ້ານເພີ່ນອີàº. ບà»à»ˆà»àº¡à»ˆàº™àº•àº±à»‰àº‡à»€àº§àº»à»‰àº² ເມື່ອàºà»ˆàº­àº™àº™àº±àºàº—່ອງທ່ຽວຊາວຕ່າງຊາດທີ່ເຂົ້າມາທ່ຽວບ້ານເຮົາເພິ່ນມັàºàº–າມວ່າ ເປັນຫàºàº±àº‡àº„ົນລາວຈຶ່ງບà»à»ˆàº¡àº±àºà»€àº›àº´àº”ເພງລາວໂດàºàºªàº°à»€àºžàº²àº°à»ƒàº™àº®à»‰àº²àº™àºàº´àº™àº”ື່ມ, ຮ້ານອາຫານ ຫລື à»àº¡à»ˆàº™à»àº•à»ˆàº•àº²àº¡àºšà»‰àº²àº™à»€àº®àº·àº­àº™ à»àº¥àº° ຕະຫລາດ, à»àº•à»ˆàº”ຽວນີ້ຂà»àº›àº°àº—ານໂທດ ເພິ່ນຫັນມາເປີດເພງລາວàºàº±àº™à»àº¥à»‰àº§ ເນື່ອງຈາàºàºªàº±àº‡àº„ົມàºà»à»ˆàºàº­àº¡àº®àº±àºš, ບົດເພງàºà»à»ˆàº¡à»ˆàº§àº™ ເນື້ອຫາàºà»à»ˆàº–ືàºà»ƒàºˆà»àº–ມàºàº±àº‡à»€àº›àº±àº™àºàº²àº™àºªàº»à»ˆàº‡à»€àºªàºµàº¡à»ƒàº«à»‰àºªàº´àº¥àº°àº›àº´àº™àº¥àº²àº§ à»àº¥àº° ຜູ້ຢູ່ເບື້ອງຫລັງມີàºàº³àº¥àº±àº‡à»ƒàºˆàºžàº±àº”ທະນາວຽຠà»àº¥àº° ຜົນງານຂອງຕົນອີàº... ອີàºàº”້ານໜື່ງນອàºàºˆàº²àº™àºªàº´àº¥àº°àº›àº´àº™àºˆàº°àº•à»‰àº­àº‡àºšàº¸àºàºšàº·àº™ ເພື່ອໃຫ້ຕົວເອງໄດ້ເຂົ້າມາຢູ່ໃນວົງàºàº²àº™à»àº¥à»‰àº§, àºà»ˆàº²àºà»€àºˆàº»à»‰àº²àº‚ອງຄ້າàºà»€àºžàº‡àºà»à»ˆàºžàº°àºàº²àºàº²àº¡à»€àºŸàº±à»‰àº™àº«àº²àº™àº±àºàº®à»‰àº­àº‡àºªàº½àº‡àº”ີ ມີà»àº§àº§àº”ັງເຂົ້າມາເປັນສະມາຊິàºàº‚ອງຄ້າàºà»€àºžàº‡àº•àº»àº™à»€àº­àº‡à»€àºŠàº±à»ˆàº™àºàº±àº™.
diff --git a/trunk/pango-view/test-latin.txt b/trunk/pango-view/test-latin.txt
new file mode 100644
index 00000000..31fe90bd
--- /dev/null
+++ b/trunk/pango-view/test-latin.txt
@@ -0,0 +1,9 @@
+'Twas brillig, and the slithy toves
+Did gyre and gimble in the wabe;
+All mimsy were the borogoves,
+And the mome raths outgrabe.
+
+'Beware the Jabberwock, my son!
+The jaws that bite, the claws that catch!
+Beware the Jubjub bird, and shun
+The frumious Bandersnatch!'
diff --git a/trunk/pango-view/test-long-paragraph.txt b/trunk/pango-view/test-long-paragraph.txt
new file mode 100644
index 00000000..95c795b5
--- /dev/null
+++ b/trunk/pango-view/test-long-paragraph.txt
@@ -0,0 +1,18 @@
+از طر٠من و بچه‌ها برای
+شادان حکمت
+
+آقا باور کن، آقا!
+
+-دل من و این تلخی بی‌نهایت
+ سر چشمه‌اش کجاست؟
+- آب دریاها
+ سخت تلخ است آقا!
+ Ùدریکو گارسیا لورکا
+
+
+
+
+
+
+
+من اسمم کاظمه. ما توی یه Ú©ÙˆÚ†Ù‡ بن بست خونه داریم. کوچه‌مون خاکیه. اونوقت خیلی پایئن تر از خونه ما - زیاد پایین نه - اینور می‌پیچی یه نونواس. از اونجا صا٠می‌ریم اینجا. یه خیابونه اینجا. اونوقت خیلی پایین‌ترش یه حمومه. بعداً یه بقالی هم دم خونمونه. یه خرده انور خرابه، یه قصابیه. قصابه با بابام رÙیقه. پشت خونمون یه دباغیه. اینقده بچه گوسÙند توشه! خونه‌مون ساس داره. ساس کوچیک Ùˆ سیاس. هر جا بزنه جاش باد می‌کنه. وقتی داره از دیوار اتاق می‌ره بالا، نمی‌تونه خودشو Ù†Ú¯Ù‡ داره، می‌اÙته رو تن ما، می‌گیره خونمونو می‌مکه. یه دÙعه همه اثاث مثاثامونو ریختیم بیرون، یه عالمه دوا خریدیم زدیم همه جا: به رختخوابا،‌ زیر زیلو، سوراخ سنبه‌ها. ولی ساسها بیشتر شدن، کمتر نشدن. بابام توی حموم کار می‌کنه. دوتا برادر داریم، یه خواهر: من Ùˆ مصطÙÛŒ Ùˆ زهرا کوچولو. بابا وقتی داره شب می‌شه برمی‌گرده خونه. همیشه استخوناش درد می‌کنه. سر هیچی به هیچی می‌گیره می‌زنه‌مون، بازهم طلبکاره. مثلاً وسط سال، صبح ساعت شیش می‌آد می‌گه، «پاشو برو سیگار بÙروش، پول دربیار لباس بخر!» من هم می‌گم: «لباس می‌خوام چی‌ کار؟» اون هم می‌گیره با کمربند حالمونو جا می‌آره. باز خوبه سه ماه تعطیلی خودمون می‌ریم کار می‌کنیم. یه کارخونه هست. می‌ریم اونجا قابلمه درست می‌کنیم، کاسه درست می‌کنیم، عصر Ú©Ù‡ شونصد تا کاسه درست کردیم، دستگارو تمیز می‌کنیم برمی‌گردیم خونه. پارسال Ù‡Ùته‌ای پنجاه تومن مزد می‌دادن. امسال دیگه خدا می‌دونه. با همه این حرÙا، بمیریم بهتره آقا! هر روز هر روز کتک. بابام دیشب بیخودی مصطÙÛŒ رو گرÙت زد. گرÙت زدش Ú¯Ùت: «چرا وقتی می‌ری دست به آب، سر پا می‌شاشی؟ بشی بشاش!» مصطÙی‌مون هیچی حالیش نمی‌شه. قد زهرامون بوده Ú©Ù‡ از بالا پشت بوم اÙتاده، رگ کله‌اش تکون خرده. حالا سیزده سالشه. نه چارده،‌ چارده سالشه. داداش بزرگ‌ مونه. الان مدرسه عقب اÙتاده‌ها درس می‌خونه. آب، بابا، بار میخونه یاد بگیره، بیاد جلو. دو سه کلمه بلده حر٠بزنه ولی چیزه... نمیتونه قشنگ حر٠بزنه. بابام می‌خواد از مدرسه ورش داره، بذاره یه جا Ú©Ù‡ کار یاد بگیره. بابا زهرا را از همه بیشتر می‌خواد. اون هم هر کاری دلش بخواد می‌کنه. هرچی می‌گیم گوش نمی‌کنه، می‌ره تو جوب محل کثاÙت‌کاری می‌کنه. اون روزی حواسم نبود، رÙت یه مشت دیگ مونده سر Ú©ÙˆÚ†Ù‡ بود ورداشت خورد. شب دلش درد گرÙت نزدیک بود بمیره. اونوقت بابام اومد گرÙت منو با شیلنگ کشت. آقا Ù…Ú¯Ù‡ شهر هرته؟ خر کتک می‌خوره. دیگه چرا ما رو می‌زنن؟ برن به خر بزنن! آخه من Ú©Ù‡ نمی‌تونم همه‌ش مواظب زهرا باشم. راستی یه صاحب حیاط داریم، خیلی بد اخلاقه آقا! اسمش عباس آقاس. صبح می‌ره ظهر می‌آد. سپور شهرداریه. بیست Ùˆ چار ساعت می‌آد بند میکنه به ما، میگه: «آب زیاد مصر٠نکنین، چاه پر میشه.» زهرامون Ú©Ù‡ گاهی گریه می‌کنه، دادش بلند می‌شه می‌گه: «صدای این تخم‌سگو Ø®ÙÙ‡ کنین!» اونوقت Ú©Ù‡ مادرمون زنده بود، یه دÙعه می‌خواست از دست عباس آقا Ù†Ùت بریزه سرش، خودشو آتیش بزنه. عباس آقا اصلاً رحم حالیش نمی‌شه؛ پسر سیزده ساله‌شو گرÙته از خونه انداخته بیرون. اون هم رÙته توی کوچه‌ پس ‌کوچه‌‌ها ول شده. حالا خدا می‌دونه کجاس، Ú†Ù‡ کار می‌کنه،‌ از کجا می‌آره می‌خوره. بچه‌ها می‌گن: «شب‌ها می‌ره توی پارک‌ها پیش سگها می‌خوابه.» Ú©Ù‡ رÙته دهات خونهٔ باباش، می‌گه دیگه نمی‌آم تهران. آقا، ما هم دلمون می‌خواد میرÙتیم دهمون با گوسÙندها بازی می‌کردیم؛ با بابا بزرگ‌مون می‌رÙتیم دشت بز می‌چروندیم،‌ بادوم پاک می‌کردیم، انگور می‌چیدیم. دهمون ولی خیلی دوره آخه! زن عباس آقا حق داره، آقا! محله‌مون خیلی بده. هر روز اونجا دعواس، دعوا، چاقو Ú©Ø´ÛŒ. توی خرابه هم پر معتاده، بگی دوهزار تا هم بیشتر. می‌رن اونجا قمار می‌کنن، شیره می‌کشن، آمپول می‌زنن تو رگشون. ماهم از ترس معتادها جرأت نمی‌کنیم از خونه بریم کوچه، یه ذره بازی کنیم. از کمیته‌م نمی‌ترسن، میگیرن بچه‌های مردمو می‌دزدن، میبرن توی کوره‌ها،‌ توی دلاشون چیز قایم می‌کنن؛ هروئین قایم میکنن. یه امیر ریزه هست تریاکیه، اون روزی اومد خرم کنه، Ú¯Ùت: «بیا سوار ماشین بشیم، بریم یه جائی.» من هم از ترسم خر نشدم. یه چیز خنده دار بگم بخندی، آقا: اینورمون یه همسایه داریم، اسمش ربابه. انوقت توپ،‌ لنگه Ú©ÙØ´ØŒ تنکه، هرچی بیÙته خونشون،‌ شوهرش ور می‌داره می‌اندازه توی آب انبارشون. هروقت هم Ú©ÙˆÚ†Ù‡ شلوغ بشه، شوهر رباب می‌آد بیرون می‌گه: «واق، عو!» اون هم مث مصطÙی‌ ما لقوه‌ایه‌؛ دستش می‌لزره، همه جاش می‌لرزه. اون روز اومد دم دکون، رÙت اونور جوب نشت. این یکی همسایه‌مون رÙت یه کتاب دربارهٔ خدا Ùˆ Ùرشته‌ها آورد براش خوند. رباب خانم خودش خونه یه اعیونه کار می‌کنه؛ چیزاشونو می‌شوره، باغ‌شونو آب می‌ده؛ Ú©Ù„Ùتی می‌کنه. بعد همه‌ش می‌آد پز اربابشو می‌ده. الان دیگه همه اهل محل می‌دونن باغ خونهٔ ارباب رباب خانوم اندازه پارک شهره. استخرش از مال پارک شهر هم گنده‌تره. هروقت هم Ú©Ù‡ ارباب می‌خواد‌ آبتنی کنه،‌ اول یه قطره دوای مخصوص هست، می‌ریزه توی استخر Ú©Ù‡ آب‌شو می‌کنه مث اشک چشم. بعد می‌ره زیر دوش، با عطر Ùˆ گلاب خودشو می‌شوره. بعد می‌پره توی استخر، می‌گیره شوخی شوخی آب می‌پاشه به رباب خانوم. زن اربابش هم خارجیه. مال همون کشوریه Ú©Ù‡ شیش ماه شبه، شیش ماه روز. رباب یه چاخان‌هایی می‌کنه Ú©Ù‡ کلهٔ آدم سوت می‌کشه! می‌گه ارباب یه سگ پشمالو داره،‌ اسمش مونیکاس. قسم می‌خوره می‌گه مونیکا غذاشو با کارد Ùˆ چنگال می‌خوره. اللَه اکبر به این دروغ. یه پیرزنه هم هست سر کوچمونه. با خودش تنهایی زندگی می‌کنه. اسمش ننه غلامه. هشتاد نود سالشه ولی خجالت نمی‌کشه،‌ از امریکا خوشش می‌آد. همه ازش می‌ترسن؛ هر ÙˆÙت بیاد بیرون، Ùحش می‌ده، جیغ Ùˆ ویغ می‌زنه. مثلا من اذیتش کردم، می‌آد سر Ùحش‌رو می‌کشه به تو. وقتی بچه‌ها بخوان لج‌شو در‌بیارن، می‌گن: «مرگ بر امریکا!» اونوقت اون هم حرصش می‌گیره، هزار تا Ùحش بی‌ناموسی Ùˆ خوار Ùˆ مادر می‌کشه به جون همه. ننه غلام دیونه‌س. بعضی وقتا هم با‌ آدم خوبه. یه روز من Ùˆ زهرا رو گرÙت به زور برد خونه‌ش، کله پاچه داد، Ú¯Ùت «بخورین!» ما هم خوردیم. ته کاسه یه لقمه موند Ú©Ù‡ روش یه عالمه مو بود. Ú¯Ùت: «اگه نخورین با همین چاقو سرتونو می‌برم.» ما هم از ترس جونمون خوردیم. ننه غلام وقتی سر حاله، چیز می‌آره می‌ده آدم. مثلا یکی زخمه،‌ دوا می‌آره بهش می‌ده. مثلا کسی چیزی نداره، چیز می‌آره بهش می‌ده، وسط کوچه‌مون یه خونه‌س Ú©Ù‡ دخترهاش خرابن، آقا. اونوقت شیره‌ای‌ها Ùˆ چاقوکش‌ها می‌رن خونه‌شون، کار بد می‌کنن. بعضی وقتا هم دختر‌هاش لباس سرخ Ùˆ زرد تن می‌کنن Ùˆ Ú©ÙØ´ پاشنه بلند تق‌تقی می‌پوشن، می‌رن واسه بالاشهری‌ها قر می‌دن. یه دÙعه هم داشتم می‌رÙتم پیش بچه‌ها «لیس پس لیس» بازی کنم Ú©Ù‡ دختر کوچیکه‌ش امیر ریزه رو صدا کرد Ùˆ بهش Ú¯Ùت: «تو چقدر پاهات لاغره!» بعد امیر ریزه هم نامردی نکرد. Ú¯Ùت:«خودت چرا لمبه‌هات چاقه؟» بعد دوتایی کرکر خندیدن. خودم با همین دو تا چشمام دیدم، آقا! اونوقت ما هم Ú©Ù‡ می‌بینیم محله‌مون پر از بی‌تربیتی‌یه، زدیم با Ù‡Ùت‌تا از بچه محلامون قهر کردیم. با اون Ù‡Ùت‌تا هم بمیرم آشتی نمی‌کنم، آقا. با یکی‌شون یه ساله قهریم، اسمش محمده. یه روز سر کوچه‌مون عروسی بود، ما هم داشتیم بازی می‌کردیم. من دراومدم به محمد Ú¯Ùتم: «محمد امشب Ú†Ù‡ خبره؟ آبجی‌ت می‌ره حجله؟» ناراحت شد، Ú¯Ùت: «باهات قهرم.» من هم Ú¯Ùتم: «چه بهتر! می‌رم درسامو می‌خونم.» به خدا ما Ú†Ù‡ می‌دونستیم، به خیالمون عروسی آبجیشه، آقا! Ùقط با دو Ù†Ùر دوستیم: مهدی ملخ Ùˆ حسن گامبو. مهدی از بس مردنیه، همه ملخ صداش می‌کنن. باباش قوری بست می‌زنه. وسط بازی یهو پیداش می‌شه، می‌آد می‌گه: «اگه منو بازی ندین، بازی‌تونو بهم می‌زنم.» اونوقت تا Ú©Ù‡ دس بهش می‌خوره، جیغش می‌ره هوا، میگه: «گه خوردم، Ú¯Ù‡ خوردم.» اونوقت می‌ره از حرصش با میخ یه شکل‌هایی می‌کشه روی دیوار، می‌گه: «این عکس کاظمه.» Ùسقلی Ùوتش کنی، قل می‌خوره، ها. آقا، ما دوچرخه خیلی دوست داریم، بعضی وقتا می‌ریم یه تومن می‌دیم چرخ کرایه می‌کنیم. حسن گامبو زورش می‌آد، با سنگ می‌زنه، می‌گه: «منو باید سوار Ú©Ù†ÛŒ.» من هم می‌بینم داره دلش می‌شکنه، می‌گم: «بیا تو هم سوار شو!» داداش حسن گامبو پنج ماهه رÙته لب مرز با خارجیا بجنگه. حسن می‌گه: «رÙته امریکا رو نابود کنه، برگرده.» بابای حسن آهنکاره؛ یعنی قالب می‌سازه، پشقاب می‌سازه، همه‌چی می‌سازه. نه Ú©Ù‡ حسن خیکیه، بچه‌ها صداش می‌کنن: «حسن گامبو، سرت تو شامپو!» می‌خواییم با این دو Ù†Ùر هم قهر کنیم بره. Ù‡ÛŒ می‌آن در خونمون داد می‌زنن: «کاظم، بیا بازی، بیا بازی!» بازی چیه، آقا؟ بده بچه بازی کنه. رÙوزه بشیم Ú†Ù‡ کار؟ دلم می‌خواد دکتر، مهندس، بازنشست، نیرو هوایی، هرچی شد بشیم، بریم Ù¾ÛŒ کارمون بره. ولی تو خونه ما نمی‌شه درس خوند. تا می‌آم بشینم، باید پاشم برم نون بخرم، جارو کنم، خشتک زهرامونو بشورم. پارسال Ú©Ù‡ رÙوزه شدم، همه‌ش نیم نمره می‌خواستم قبول بشم. مدرسه‌مونم خیلی هردمبیه، آقا! بچه‌هاش دزدن، می‌آن دÙترامونو می‌دزدن. سر کلاس یکی Ú¯Ú† پرت می‌کنه، یکی رو نیمکت ضرب می‌گیره، یکی پا می‌شه می‌رقصه. ما هم Ú©Ù‡ می‌بینیم خر تو خره، حوصله‌مون سر می‌ره، از مدرسه جیم می‌شیم، می‌ریم Ùروشگاه بزرگ. اونجا پله‌برقی داره. می‌ریم می‌ایستیم خودمونو می‌زینم به اون راه. الکی نگاه می‌کنیم به جنس منس‌ها؛ یعنی مثلا ما هم اومدیم چیز بخریم. بعد می‌ریم سوار پله‌برقی می‌شیم، می‌ریم سواری می‌خوریم، عشق می‌کنیم. آقا، اجازه؟ سه تا دایی هم دارم، آقا! یکی‌شون دایی ضامن، یکی‌شونم دایی مرتضی. اونی Ú©Ù‡ وضعش خوبه اسمش دایی رضوانه. یه وانت داره با یه اتوشویی. تا پامونو می‌ذاریم در دکونش، نامرد یه لگد می‌زنه در اونجامون، می‌گه: «بزن به چاک! باز اومدی از دخل ک٠ببری» به خدا تهمت می‌زنه، آقا! آقا، به خدا هیچکی به اندازه ما از دزدی بدش نمی‌آد. آقا، دایی مرتضی‌مون اولها کارگر بلورسازی بود، ولی وقتی من هنوز تو دل مادرم بودم، اÙتاد زندان. یه شب Ù‡Ùت Ù†Ùر ریختن سرش، اون هم چاقو کشید، زد یکی‌شونو کشت. بعد دادگاه هم اومد بیخودی تقصیر رو گذاشت گردن دایی ما. قبل انقلاب از زندان اومد بیرون، رÙت معتاد شد. حالا هم همیشه با زنش دعوا مراÙعه داره. گاهی می‌ذاره از خونه‌ش می‌ره، می‌ره می‌ره پیداش نمی‌شه. بعد Ú©Ù‡ برمی‌گرده، الکی به زنش می‌گه، رÙته بودم بیمارستان ترک کنم. دایی مرتضی یه بچه کوچولو داره، هروقت می‌آد خونمون، می‌خواد از پله‌هامون بره بالا، بیاد پایین. ما هم می‌ریم دنبالش Ú©Ù‡ Ù†ÛŒÙته سرش بشکنه. می‌ریم بغلش می‌کنیم. اونوقت می‌ترسه، سÙت آدمو می‌گیره. دایی ضامن‌مون توی دولت آباد Ù†Ùتیه، بعضی روزها Ú©Ù‡ می‌ره Ù†Ùت پخش کنه منو هم با خودش می‌بره. اون تا می‌ره Ù†Ùت بده به خونه‌ها، بچه‌ها می‌گیرن مسخره‌م می‌کنن، می‌گن: «ای عرب پا Ù†Ùتی، Ú©ÛŒ اومدی، Ú©ÛŒ رÙتی؟» سنگ می‌زنن تو کله‌ام. من هم Ú©Ù‡ زورم نمی‌رسه، گریه‌م می‌گیره. یه روز رÙتیم در یه خونه Ù†Ùت بدیم، اونوقت یه پسره بود - لال بود - دنبالمون کرد تا سر کوچه‌شون. Ùحش مادر داد، Ú¯Ùت: «دیگه در خونه ما نیا!» لال بود، آقا! نمی‌دونیم Ú†ÛŒ می‌گÙت... آقا، هر وقت از مادرمون حر٠می‌زنیم، بغض می‌آد گلومونو می‌گیره، ول‌مون نمی‌کنه... مادرمون سر بچه مرد، آقا! شب درد بچه گرÙتش. رÙتیم نبات خانومو آوردیم. نبات خانوم مامای محله‌س، شله، یه چشمش هم چپه. صبح Ú©Ù‡ بچه اومد دنیا، مادرمون گذاشت از دنیا رÙت. بچه‌ هم پشت سرش مرد، آقا!... مادرمون اون وقت Ú©Ù‡ زنده بود، توی کارخونهٔ استارلایت کار می‌کرد. جوراب شلواری می‌باÙت. وقتی شکمش اومد بالا، از اونجا بیرونش کردن. مادرمون اینقده سختی کشیده Ú©Ù‡ خدا بگه، بس! همیشه مریض بود، بعضی وقتا هم غش می‌کرد. پاهاش قد یه متکا باد کرده بود، آقا!... آقا، باور کن، آقا... وقتی مادرمون مرد ما صد برابر الان بغض کردیم. من Ùˆ زهرا Ùˆ مصطÙÛŒ شب تا صبح خوابمون نبرد. بابام اون شب هزار تا سیگار کشید،‌ ولی صبحش مادرمون مرد. وقتی رÙتیم خاکش کنیم، ننه غلام نمی‌خواست بذاره ما بریم تماشا، می‌گÙت، ما بچه‌ایم، گناه داریم. ولی من دزدکی توی مرده‌شور خونه هم رÙتم. بوی بدی می‌ده مرده‌شور خونه، بوی گربهٔ مرده. آدم می‌خواد دل Ùˆ روده‌شو بالا بیاره. وقتی مادرمونو اوردن گذاشتن توی سالن مرده‌شور خونه، Ù‡Ùت تا مرده زودتر مرده بودن. مادرمون Ù†Ùر هشتم بود. مرده‌ها منتظر بودن دوش خالی بشه، سر نوبت برن تو، غسل کنن. جنازه یه دختر مدرسه هم بود. نمی‌دونی ÙÚ© Ùˆ Ùامیل دختره چی‌کار می‌کردن؛ یکی سرشو می‌زد به دیوار، یکی Ú©Ùش‌شو دراورده بود می‌زد تو سر خودش. مادرمونو Ú©Ù‡ اوردن بذارن توی قبر، سروکله‌ٔ مصطÙÛŒ هم پیداش شد. مادرمون با مصطÙÛŒ خوب بود. خدا بیامرز Ú©Ù‡ رÙت توی قبر، نمی‌دونم از کجا یه مگس اومد نشست روی Ú©Ùنش. تا مصطÙÛŒ کیش‌اش کرد، مگسه گذاشت در رÙت. بعد شروع کردن با بیل خاک ریختن روی سر مادرمون. رباب خانم با ناخن صورتشو می‌کند. بابام داشت توی دل خودش گریه می‌کرد. اگه مصطÙÛŒ نمی‌زد زیر گریه Ùˆ توی خاک Ùˆ خل غلت نمی‌خورد، من هم گریه نمی‌کردم... مادرمونو Ú©Ù‡ خاک کردیم، دم قبرستان حلوای نذری پخش می‌کردن. واسه اینکه بوی گربهٔ مرده از دماغم بره، یه قاشق حلوا گذاشتم دهنم. ولی صاحب عذا Ú©Ù‡ روشو برگردوند، تÙØ´ کردم. آقا، هیچی نمی‌تونستیم بخوریم. آقا، ما دلمون خیلی تنگه، هیشکی نیست ما را زÙت کنه. دل‌مون می‌خواد از این دنیا می‌رÙتیم. آقا، باورتون نمی‌شه، توی محله ما ملت تند تند می‌میرن، آقا! زهرامون یه همبازی داره، همقد خودشه. اسمش الهامه، پنج سالشه. ده بیست روز پیش باباش از داربست اÙتاد زمین عکس برگردون شد، مرد. دیروز الهام اومده بود خونه‌مون، یه عکس از باباش هم اورده بود، می‌گÙت، هر شب خواب باباشو می‌بینه Ú©Ù‡ اون دنیا آتیش درست کرده، می‌خواد بیاد بگیره اونو کباب کنه بخوره. یه حرÙهایی می‌زد Ú©Ù‡ مو به تن آدم سیخ می‌شد. اونوقت شب Ú©Ù‡ خوابم برد، خوابیدم، خواب دیدم عزرائیل Ùˆ شمر با آتیش اومدن بالای سرم، Ù‡ÛŒ می‌چرخن Ùˆ چه‌چه می‌خندن. عزرائیل نصÙه‌س، آقا! یعنی پا نداره. من هم اومدم از دست‌شون در برم Ú©Ù‡ دیدم یه خرگوشه داره با مامانش قایم موشک بازی می‌کنه. رÙتم بگم، من هم بازی Ú©Ù‡ گذاشتن در رÙتن. من هم دنبالشون کردم. خسته Ú©Ù‡ شدم دیدم سوار یه قایقم، یه سگ هم داشتم. داشتم با سگ بازی می‌کردم Ú©Ù‡ یهو امیر ریزه پشت پا انداخت، اÙتادم توی آب. من هم رÙتم سوار دوچرخه شدم، زدم به چاک. سگ هم از توی قایق پرید، اومد دنبالم. بعدش دیدم یه هلی‌کوپتر بالای سرمه، می‌خواد باید بستنی لیوانی‌مو قاپ بزنه. من هم با سنگ زدم شیشه‌شو شکوندم. اون هم ترسید در رÙت، توی Ú©ÙˆÚ†Ù‡ دباغ‌ها غیب شد. بعدش دیدم عباس آقا گرگ شده، می‌خواد بیاد زهرامونو بگیره لقمه‌ٔ چپش کنه. از ترسم دویدم توی پارک Ùˆ رÙتم سوار تاب شدم. اینقده تاب بازی کردم تا حسابی سرم گیج رÙت. اومدم از تاب بپرم پایین، دیدیم زیر پام یه چاهه، یه چاه به این گندگی. داشتم ول می‌شدم ته چاه Ú©Ù‡ از خواب پریدم. نشستم گریه کردم. اونوقت بابام بیدار شد، پرسید: «باز Ú†ÛŒ شده؟ شاشیدی؟» Ú¯Ùتم: «می‌ترسم.» Ú¯Ùت: «بگیر بخواب بابا تو هم دلت خوشه!» من هم لحاÙÙˆ Ú©Ù‡ کشیدم روی سرم، همه‌ش خدا خدا می‌کردم ایم دÙعه Ú©Ù‡ خوابم برد، شانسم بگه، بزنه خواب خوشبختی ببینم، دلم خوش بشه. ولی اگه ما شانس داشتیم، آقا، اسم‌مونو می‌ذاشتن شانسعلی.
diff --git a/trunk/pango-view/test-mixed.markup b/trunk/pango-view/test-mixed.markup
new file mode 100644
index 00000000..daac071d
--- /dev/null
+++ b/trunk/pango-view/test-mixed.markup
@@ -0,0 +1,9 @@
+<span lang="zh-cn">你好,这是中文竖排测试。
+欢迎æ¥åˆ°ä¸­å›½åŒ—京。
+白日ä¾å±±å°½ï¼Œ</span>
+<span lang="en">Roses are Red,
+Grass is Green. 2006</span>
+<span lang="fa">Arabic is گل‌ها قرمزند،â€
+چمن سبز. ۲۰۰۶</span>
+<span lang="zh-cn">白日ä¾å±±å°½ï¼Œ 2006</span>
+<span lang="ja">「ノートを買ã£ãŸã€‚ã€</span>
diff --git a/trunk/pango-view/test-mixed.txt b/trunk/pango-view/test-mixed.txt
new file mode 100644
index 00000000..c04a91b5
--- /dev/null
+++ b/trunk/pango-view/test-mixed.txt
@@ -0,0 +1,9 @@
+你好,这是中文竖排测试。
+欢迎æ¥åˆ°ä¸­å›½åŒ—京。
+白日ä¾å±±å°½ï¼Œ
+Roses are Red,
+Grass is Green. 2006
+Arabic is گل‌ها قرمزند،â€
+چمن سبز. ۲۰۰۶
+白日ä¾å±±å°½ï¼Œ 2006
+「ノートを買ã£ãŸã€‚ã€
diff --git a/trunk/pango-view/test-nko.txt b/trunk/pango-view/test-nko.txt
new file mode 100644
index 00000000..65a4347e
--- /dev/null
+++ b/trunk/pango-view/test-nko.txt
@@ -0,0 +1,15 @@
+ßߘߊ߬ßߌ߲߬ߠߊ߫ ߟߊ߬ߘß߲߬ߞß߬ߦߊ߬ߟߌ ߜߙߋ߬ߡߊ߬ߕß߰ߟߌ
+ߞߖ߭ߊߓߎߟߊ߲ߞߊ ß“ß߲߬ߡߊ߬ߞߊ߲ ߠߎ߬ :
+
+ßߘߊ߬ßߌ߲߬ߠߊ߫ ߘߎ߰ߙߋ߲ ߠߎ߬ ߟߊ߫ ߢß߲߯ߓßß² ߟߊ߬ߘß߲߬ߞß߬ߦߊ߬ߟߌ ߞߊߡߊ߬ ߞߖ߭ߊߓߎߟߊߟߊ߲ߞߊ߫߸ ( ߞߊ߬ߓߌߛߊ߬ ) ߣߌ߫ ( ߓߌ߬ߛ߭ߊ߯ߙߊ ) ߘß߬ߘߊ ߟߎ߬ ߟߊ߫ ߓߊ߯ߙߊ߫
+ߘߊߞߎ߲ ߡߌ߬ߘߊ߬ ßžß£ß ßžßŠß²ß¬ß¸ (IDRC = ߞߣߊߘߊ߫ ßߘß߬ߓߊ߬ ߡߣߊ߬ߙß߲߬ߠߌ߲ ßߊ߲ߓߊ ßž.ß.ß¡.ß.) ߞߊ߬ ß¡ßß² ß–ßß°ß£ß ß“ßß« ߸ (MTDS =
+ߡߊ߬ߙßߞߎ߫ ß–ßŠß¬ß¥ß ßŸßŠß¬ß¥ß™ßŽß¬ßžßŒß¬ßŸßŒ ߗߋߢߊߟߌ ß¡.ß–.ߥߗ.) ßߊ߬ߙߊ ߘßß« ߊ߬ ߞߊ߲߬ ( ߞߖ߭ߊߓߎߟߊ߲ߞߊ߫ ߕߎߞߑߣßߔߊߞ ) ߘß߬ߞߙߎ ßߊ߲ߓߊ ßß߬.
+
+ߞߎ߲߬ߜߙߊ ߣߌ߲߬ ߞߊ߬ ߕߣß߬ߓߊ߫ ß›ß߬ߘß߲߬ ߡߊߙßߞߎ߬ ߖߡߊ߬ߣߊ ߡߊ߬ߞß߬ߙß߲߬ߞß߬ߙß߲߬ߠߌ ßžßߕߌ߮ ߣߴߊ߬ ߣß߬ßß߬ ߖߡߊ ߟߊ߫ ߸ ß߬ ߟߎ߬ ß¡ßß² ߠߎ߫ ߣߊ߬ ߘߊ߫
+ßžßߕߌ߯ ߟߎ߬ ߞߊ߲ߕߌ߮ ßžßߦߌ߬ߘߊ߬، ߞߊ߬ ß•ß߬ߣßß« ß›ß߬ߘß߲߬ ߞߣߊߘߊ߫ ߟߊ߬ߛߌ߰ߘߋ߲ ßߣߊ߫ ߟߊ߫ ߣߊ߬ߟߌ ߣߌ߫ ߜߙߋ߫ ßœß˜ß ß˜ßŽß°ß™ß‹ß²ß« ߣߊ߬ߓߊ߮ ߟߎ߬ ߟߊ߫.
+
+ߕߋ߬ߟߋ߫ ߛߓߊ߬ ߖߊ߬ߣß߲߬ ߓߊ߯ߙߊ ߘßߊߣßß² ßžßß« ߸ ߞߎ߲߬ߜߙߊ ߕߘß߬ߒ߬ߘßß¬ß“ßŠß°ß•ß ßŸßŽß« ß“ß߲߬ ߘߊ߫ ߞߊ߲߫ ß£ßŠß¬ß•ß ß¢ßŒß²ß¬ ߠߎ߫ ߡߊ߬ :
+
+• ߕߟߋ߬ߓߊ߮ ߛߋߒߞßߟߦߊ ߣߌ߫ ߟß߲ߕߊ ( ß•.ß›.ߟ. ICT ) ߘߊ߲߬ߠߊߕßß­ ߥߊߟߌ߫ ߞߊ߲߫ ߞߋߟߋ߲߫ ߡߊ߬ ߕߋ߲߬ ߸ ß߬ ߦߋ߫ ߡߌ߬ߙߌ߲߬ߘߌ ߟߎ߬ ߢß߲߯
+ß•ßß« ßžß£ß ßß߬ߣߊ߲ ߥߙߊ߬ ߟߊ߫ ߟߋ߬، ߞߊ߬ ߕߟߋ߬ߓߊ߮ ߟß߲ߠߌ߲ ߓߊߓߋ߭ ߥߎ߬ߛߎ ߖߊ߲߬ߧߊ߫ ߸ ߞߵߊ߬ ߞߊ߬ߙߊ߲ ߣߴߊ߬ ߘߊ ߜߟß߬ߦߊ߫، ߞߊ߬ߕߎ߯ ߸ ߊ߬
+ߘߌ߫ ß¦ß™ß ßŸß߲ߠߌ߲ߧߊ ßߣߊ߫ ß–ßß²ßß߲߫ ßžßߛߓßß«. \ No newline at end of file
diff --git a/trunk/pango-view/test-opentype-language.markup b/trunk/pango-view/test-opentype-language.markup
new file mode 100644
index 00000000..87b69576
--- /dev/null
+++ b/trunk/pango-view/test-opentype-language.markup
@@ -0,0 +1,5 @@
+Rendering U+0431 CYRILLIC SMALL LETTER BE
+using DejaVu Sans:
+
+<span font_desc="DejaVu Sans">Russian: <span lang="ru">б</span>
+Serbian: <span lang="sr">б</span></span>
diff --git a/trunk/pango-view/test-syriac.txt b/trunk/pango-view/test-syriac.txt
new file mode 100644
index 00000000..05fedc7b
--- /dev/null
+++ b/trunk/pango-view/test-syriac.txt
@@ -0,0 +1,18 @@
+ܠܫܢܢ
+Ü’ÜܕܦܪÜÜ•Ü Ü’Ü¢ÜÜ¡ÜÜ¢ ÜÜ•Ü¡
+
+ÜܬÜܡܘܢ ܥܠÜÜ¡Ü¢ ܘܥܠÜܡܬܢ
+ܠܫܢܢ ܡܪܢÜÜ
+ܦܪÜÜ£Ü Ü¡Ü•Ü˜ÜªÜ Ü©Ü•Ü¡ÜÜ
+
+ܠܫܢܢ ÜÜ Ü— ÜÜܬܘܬܢ
+ܘܬܘܕÜܬܢ ܘܣܦܪÜܘܬܢ
+Üܠܦܚܠܗ Ü’ÜŸÜ  ܫܘܒ݂ܗܪÜ
+
+Ü¡Ü’Ü˜Ü¥Ü Ü—Ü˜Ü Ü•ÜܘܠܦܢÜ
+ܚܠÜÜ Ü’ÜªÜ¬Ü¡Ü Ü˜Ü©ÜªÜÜ¢Ü
+Ü¬Ü“Ý‚Ü ÜÜ Ü— ܠܪܫܢ ܪܡÜ
+
+ܡܠܦܢܢ ÜÜ¢Ü Ü“Ü¢Ü’ÜªÜ
+ܡܫܘܬÜܣܠܗܘܢ ܡܕܪܫÜܬÜ
+ܡܫܘܬÜܣܠܗܘܢ ܓܘ ÜܡܘܬÜ
diff --git a/trunk/pango-view/test-tamil.txt b/trunk/pango-view/test-tamil.txt
new file mode 100644
index 00000000..ff080a24
--- /dev/null
+++ b/trunk/pango-view/test-tamil.txt
@@ -0,0 +1,13 @@
+à®®à¯à®°à¯à®•à®©à¯ அலà¯à®²à®¤à¯ அழகà¯
+திர௠வி.க.
+
+ கà¯à®®à®°à®•à¯à®°à¯à®ªà®°à®°à¯
+
+உலக௠கà¯à®³à®¿à®° எமத௠மதியில௠ஒழà¯à®•à¯ மமà¯à®¤ கிரணமே
+ உரà¯à®•à¯ மடிய ரிதய நெகிழ உணரà¯à®µà®¿ லெழà¯à®¨ லà¯à®¤à®¯à®®à¯‡
+கலைய௠நிறைவ௠மறிவ௠மà¯à®¤à®¿à®° à®®à¯à®¤à®¿à®°à¯ மதà¯à®° நறவமே
+ கழà¯à®µà¯ தà¯à®•à®³à®°à¯ à®®à¯à®´à¯à®• நெடிய கரà¯à®£à¯ˆ பெரà¯à®•à¯ சலதியே
+அலகில௠பà¯à®µà®© à®®à¯à®Ÿà®¿à®¯à¯à®®à¯ வெளியில௠அளிய௠மொளியி னிலயமே
+ அறிவ௠ளறிவை யறிவ௠மவரà¯à®®à¯ அறிய வரிய பிரமமே
+மலையின௠மகளà¯à®•à®£à¯ மணியை யனைய மதலை வரà¯à®• வரà¯à®•à®µà¯‡
+ வளமை தழà¯à®µà¯ பரிதி பà¯à®°à®¿à®¯à®¿à®©à¯ மரà¯à®µà¯ கà¯à®®à®°à®©à¯ வரà¯à®•à®µà¯‡
diff --git a/trunk/pango-view/test-thai.txt b/trunk/pango-view/test-thai.txt
new file mode 100644
index 00000000..4bb8d2e0
--- /dev/null
+++ b/trunk/pango-view/test-thai.txt
@@ -0,0 +1,11 @@
+ลำดับนั้น เทวดาà¸à¸¥à¹ˆà¸²à¸§à¸„าถาà¸à¸°à¸žà¸£à¸°à¸¡à¸«à¸²à¸ªà¸±à¸•à¸§à¹Œà¸§à¹ˆà¸²:
+
+“à¸à¸²à¸£à¸‡à¸²à¸™à¸­à¸±à¸™à¹ƒà¸” ยังไม่ถึงที่สุดด้วยความพยายาม à¸à¸²à¸£à¸‡à¸²à¸™à¸­à¸±à¸™à¸™à¸±à¹‰à¸™à¸à¹‡à¹„ร้ผล มีความลำบาà¸à¹€à¸à¸´à¸”ขึ้น à¸à¸²à¸£à¸—ำความพยายามในà¸à¸²à¸™à¸°à¸­à¸±à¸™à¹„ม่สมควรใด จนความตายปราà¸à¸à¸‚ึ้น ความพยายามในà¸à¸²à¸™à¸°à¸­à¸±à¸™à¹„ม่สมควรนั้น จะมีประโยชน์อะไรâ€
+
+เมื่อนางมณีเมขลาà¸à¸¥à¹ˆà¸²à¸§à¸­à¸¢à¹ˆà¸²à¸‡à¸™à¸µà¹‰à¹à¸¥à¹‰à¸§ พระมหาสัตว์เมื่อจะทำนางมณีเมขลาให้จำนนต่อถ้อยคำ จึงได้ตรัสคาถาต่อไปว่า:
+
+“ดูà¸à¹ˆà¸­à¸™à¹€à¸—วดา ผู้ใดรู้à¹à¸ˆà¹‰à¸‡à¸à¸²à¸£à¸‡à¸²à¸™à¸—ี่ทำจะไม่ลุล่วงไปได้จริง ๆ ชื่อว่าไม่รัà¸à¸©à¸²à¸Šà¸µà¸§à¸´à¸•à¸‚องตน ถ้าผู้นั้นละความเพียรในà¸à¸²à¸™à¸°à¹€à¸Šà¹ˆà¸™à¸™à¸±à¹‰à¸™à¹€à¸ªà¸µà¸¢ à¸à¹‡à¸ˆà¸°à¸žà¸¶à¸‡à¸£à¸¹à¹‰à¸œà¸¥à¹à¸«à¹ˆà¸‡à¸„วามเà¸à¸µà¸¢à¸ˆà¸„ร้าน ดูà¸à¹ˆà¸­à¸™à¹€à¸—วดา คนบางพวà¸à¹ƒà¸™à¹‚ลà¸à¸™à¸µà¹‰à¹€à¸«à¹‡à¸™à¸œà¸¥à¹à¸«à¹ˆà¸‡à¸„วามประสงค์ของตน จึงประà¸à¸­à¸šà¸à¸²à¸£à¸‡à¸²à¸™à¸—ั้งหลาย à¸à¸²à¸£à¸‡à¸²à¸™à¹€à¸«à¸¥à¹ˆà¸²à¸™à¸±à¹‰à¸™à¸ˆà¸°à¸ªà¸³à¹€à¸£à¹‡à¸ˆà¸«à¸£à¸·à¸­à¹„ม่à¸à¹‡à¸•à¸²à¸¡ ดูà¸à¹ˆà¸­à¸™à¹€à¸—วดา ท่านà¸à¹‡à¹€à¸«à¹‡à¸™à¸œà¸¥à¹à¸«à¹ˆà¸‡à¸à¸£à¸£à¸¡à¸›à¸£à¸°à¸ˆà¸±à¸à¸©à¹Œà¹à¸à¹ˆà¸•à¸™à¹à¸¥à¹‰à¸§à¸¡à¸´à¹ƒà¸Šà¹ˆà¸«à¸£à¸·à¸­ คนอื่น ๆ จมในมหาสมุทรหมด เราคนเดียวยังว่ายข้ามอยู่ à¹à¸¥à¸°à¹„ด้เห็น ท่าน มาสถิตอยู่ใà¸à¸¥à¹‰ ๆ เรา เรานั้นจัà¸à¸žà¸¢à¸²à¸¢à¸²à¸¡à¸•à¸²à¸¡à¸ªà¸•à¸´à¸à¸³à¸¥à¸±à¸‡ จัà¸à¸—ำความเพียรที่บุรุษควรทำ ไปให้ถึงà¸à¸±à¹ˆà¸‡à¹à¸«à¹ˆà¸‡à¸¡à¸«à¸²à¸ªà¸¡à¸¸à¸—รâ€
+
+--
+พระมหาชนà¸
+พระราชนิพนธ์ พระบาทสมเด็จพระเจ้าอยู่หัว ภูมิพลอดุลยเดชฯ
diff --git a/trunk/pango-view/test-tibetan.txt b/trunk/pango-view/test-tibetan.txt
new file mode 100644
index 00000000..83d44aab
--- /dev/null
+++ b/trunk/pango-view/test-tibetan.txt
@@ -0,0 +1,12 @@
+Regular letters འབྲུག་རྒྱལ་à½à½–་འདི་དགའ་à½à½¼à½‚་à½à½¼à¼‹à½¡à½¼à½‘à¼
+Reordering of Digits ༡༿༢༿༣༿ Illegal ཀ༿ སà¾à¼¿à¼¾
+Digits with other combining marks ༡༾༢༘༤༥༦ Illegal ཀ༘à½à¼™à½¦à¾à¼˜à¼™
+Tsa phru after base ཀ༹ Illegal ཀྱུ༹ ཀི༹
+Tsa phru after subjoined སà¾à¼¹ རྒྱ༹
+A-Chung ཀཱ ཀྲཱ གླཱ གྱཱ༹ Illegal ཀཱུ ཀཱི
+Halanta ཀ྄ ཀ྄ཱ སà¾à¾„ སà¾à¾±à¾„
+Vowels ཀྱུ སà¾à¾±à½´à½² ཀྀ ཀེ ཀོ ལà¾à½» ཀཽ
+Anusvara ཀུཾ ཀིཾ ཀཾི ཀིཾ ཀཾིཾ
+Visaraga ཀཿ Illegal ཀ༵ཿ
+Lower Stress Mark ཀ༷ ཀཱ༵
+Candrabindu ཀྃ ཀིྃ Illegal ཀིྃ
diff --git a/trunk/pango-view/viewer-cairo.c b/trunk/pango-view/viewer-cairo.c
new file mode 100644
index 00000000..baabe2dc
--- /dev/null
+++ b/trunk/pango-view/viewer-cairo.c
@@ -0,0 +1,53 @@
+/* viewer-cairo.c: Common code for Cairo-based viewers
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+
+#include "viewer-cairo.h"
+
+#ifdef HAVE_CAIRO_XLIB
+#include "viewer-x.h"
+#include <cairo-xlib.h>
+
+static cairo_surface_t *
+cairo_x_view_create_surface (gpointer instance,
+ gpointer surface,
+ int width,
+ int height)
+{
+ XViewer *x = (XViewer *)instance;
+ Drawable drawable = (Drawable) surface;
+
+ return cairo_xlib_surface_create (x->display, drawable,
+ DefaultVisual (x->display, x->screen),
+ width, height);
+}
+
+static CairoViewerIface cairo_x_viewer_iface = {
+ &x_viewer,
+ cairo_x_view_create_surface
+};
+
+const CairoViewerIface *
+get_default_cairo_viewer_iface (void)
+{
+ return &cairo_x_viewer_iface;
+}
+#endif /* HAVE_CAIRO_XLIB */
diff --git a/trunk/pango-view/viewer-cairo.h b/trunk/pango-view/viewer-cairo.h
new file mode 100644
index 00000000..ba5a5d7c
--- /dev/null
+++ b/trunk/pango-view/viewer-cairo.h
@@ -0,0 +1,42 @@
+/* viewer-cairo.h: Common headers for Cairo-based viewers
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef VIEWER_CAIRO_H
+#define VIEWER_CAIRO_H
+
+#include <cairo.h>
+
+#include "viewer.h"
+
+typedef struct _CairoViewerIface CairoViewerIface;
+
+struct _CairoViewerIface
+{
+ const PangoViewer *backend_class;
+
+ cairo_surface_t * (*create_surface) (gpointer instance,
+ gpointer surface,
+ int width,
+ int height);
+};
+
+const CairoViewerIface *get_default_cairo_viewer_iface (void);
+
+#endif /* VIEWER_CAIRO_H */
diff --git a/trunk/pango-view/viewer-main.c b/trunk/pango-view/viewer-main.c
new file mode 100644
index 00000000..f3d93df4
--- /dev/null
+++ b/trunk/pango-view/viewer-main.c
@@ -0,0 +1,162 @@
+/* viewer-main.c: Main routine for viewers
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ * Copyright (C) 2006 Behdad Esfahbod
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#ifdef G_OS_UNIX
+#include <sys/wait.h>
+#endif
+
+#include "viewer.h"
+#include "viewer-render.h"
+
+int
+main (int argc,
+ char **argv)
+{
+ const PangoViewer *view;
+ gpointer instance;
+ PangoContext *context;
+ int run;
+ int width, height;
+ gpointer surface;
+
+ g_type_init();
+ setlocale (LC_ALL, "");
+ parse_options (argc, argv);
+
+ view = opt_viewer;
+
+ g_assert (view->id);
+
+ instance = view->create (view);
+ context = view->get_context (instance);
+ do_output (context, NULL, NULL, NULL, NULL, &width, &height);
+ surface = view->create_surface (instance, width, height);
+ for (run = 0; run < MAX(1,opt_runs); run++)
+ view->render (instance, surface, context, width, height, NULL);
+
+ if (opt_output)
+ {
+ if (!view->write)
+ fail ("%s viewer backend does not support writing", view->name);
+ else
+ {
+ FILE *stream;
+
+ if (view->write_suffix && g_str_has_suffix (opt_output, view->write_suffix))
+ {
+ stream = g_fopen (opt_output, "wb");
+ if (!stream)
+ fail ("Cannot open output file %s: %s\n",
+ opt_output, g_strerror (errno));
+ }
+ else
+ {
+ int fd;
+ const gchar *convert_argv[4] = {"convert", "-", "%s"};
+ GError *error;
+
+ convert_argv[2] = opt_output;
+
+ if (!g_spawn_async_with_pipes (NULL, (gchar **)convert_argv, NULL,
+ G_SPAWN_SEARCH_PATH |
+ G_SPAWN_STDOUT_TO_DEV_NULL |
+ G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, NULL, &fd, NULL, NULL, &error))
+ fail ("When running ImageMagick 'convert' command: %s\n", error->message);
+ stream = fdopen (fd, "wb");
+ }
+ view->write (instance, surface, stream, width, height);
+ fclose (stream);
+ }
+ }
+
+ if (opt_display)
+ {
+ char *title;
+ title = get_options_string ();
+
+ if (view->display)
+ {
+ gpointer window = NULL;
+ gpointer state = NULL;
+
+ if (view->create_window)
+ window = view->create_window (instance, title, width, height);
+
+ while (1)
+ {
+ state = view->display (instance, surface, window, width, height, state);
+ if (!state)
+ break;
+
+ view->render (instance, surface, context, width, height, state);
+ }
+
+ if (view->destroy_window)
+ view->destroy_window (instance, window);
+ }
+ else
+ {
+ int fd;
+ FILE *stream;
+ const gchar *display_argv[5] = {"display", "-title", "%s", "-"};
+ GError *error = NULL;
+ GPid pid;
+
+ if (!view->write)
+ fail ("%s viewer backend does not support displaying or writing", view->name);
+ display_argv[2] = title;
+
+ if (!g_spawn_async_with_pipes (NULL, (gchar **)display_argv, NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD |
+ G_SPAWN_SEARCH_PATH |
+ G_SPAWN_STDOUT_TO_DEV_NULL |
+ G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, &pid, &fd, NULL, NULL, &error))
+ fail ("When running ImageMagick 'display' command: %s\n", error->message);
+ stream = fdopen (fd, "wb");
+ view->write (instance, surface, stream, width, height);
+ fclose (stream);
+#ifdef G_OS_UNIX
+ waitpid (pid, NULL, 0);
+#endif
+ g_spawn_close_pid (pid);
+ }
+
+ g_free (title);
+ }
+
+ view->destroy_surface (instance, surface);
+ g_object_unref (context);
+ view->destroy (instance);
+ finalize ();
+ return 0;
+}
diff --git a/trunk/pango-view/viewer-pangocairo.c b/trunk/pango-view/viewer-pangocairo.c
new file mode 100644
index 00000000..09f205c0
--- /dev/null
+++ b/trunk/pango-view/viewer-pangocairo.c
@@ -0,0 +1,427 @@
+/* viewer-pangocairo.c: PangoCairo viewer backend.
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "viewer-render.h"
+#include "viewer-cairo.h"
+
+#include <pango/pangocairo.h>
+
+typedef struct
+{
+ const CairoViewerIface *iface;
+
+ gpointer backend;
+
+ PangoFontMap *fontmap;
+ cairo_font_options_t *font_options;
+} CairoViewer;
+
+/* TODO: hinting */
+static gpointer
+pangocairo_view_create (const PangoViewer *klass)
+{
+ CairoViewer *instance;
+
+ instance = g_slice_new (CairoViewer);
+
+ instance->iface = get_default_cairo_viewer_iface ();
+ instance->backend = instance->iface->backend_class->create (instance->iface->backend_class);
+
+ instance->fontmap = pango_cairo_font_map_get_default ();
+ pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (instance->fontmap), opt_dpi);
+
+ instance->font_options = cairo_font_options_create ();
+ if (opt_hinting != HINT_DEFAULT)
+ {
+ cairo_font_options_set_hint_metrics (instance->font_options, CAIRO_HINT_METRICS_ON);
+
+ if (opt_hinting == HINT_NONE)
+ cairo_font_options_set_hint_style (instance->font_options, CAIRO_HINT_STYLE_NONE);
+ else if (opt_hinting == HINT_FULL)
+ cairo_font_options_set_hint_style (instance->font_options, CAIRO_HINT_STYLE_FULL);
+ }
+
+ return instance;
+}
+
+static void
+pangocairo_view_destroy (gpointer instance)
+{
+ CairoViewer *c = (CairoViewer *) instance;
+
+ cairo_font_options_destroy (c->font_options);
+
+ g_object_unref (c->fontmap);
+
+ c->iface->backend_class->destroy (c->backend);
+
+ g_slice_free (CairoViewer, c);
+}
+
+static PangoContext *
+pangocairo_view_get_context (gpointer instance)
+{
+ CairoViewer *c = (CairoViewer *) instance;
+ PangoContext *context;
+
+ context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (c->fontmap));
+ pango_cairo_context_set_font_options (context, c->font_options);
+
+ return context;
+}
+
+typedef struct
+{
+ gpointer backend;
+
+ cairo_surface_t *cairo;
+} CairoSurface;
+
+static gpointer
+pangocairo_view_create_surface (gpointer instance,
+ int width,
+ int height)
+{
+ CairoViewer *c = (CairoViewer *) instance;
+ CairoSurface *surface;
+
+ surface = g_slice_new (CairoSurface);
+
+ surface->backend = c->iface->backend_class->create_surface (c->backend,
+ width, height);
+
+ surface->cairo = c->iface->create_surface (c->backend,
+ surface->backend,
+ width, height);
+
+ return surface;
+}
+
+static void
+pangocairo_view_destroy_surface (gpointer instance,
+ gpointer surface)
+{
+ CairoViewer *c = (CairoViewer *) instance;
+ CairoSurface *c_surface = (CairoSurface *) surface;
+
+ c->iface->backend_class->destroy_surface (c->backend, c_surface->backend);
+ cairo_surface_destroy (c_surface->cairo);
+
+ g_slice_free (CairoSurface, surface);
+}
+
+static void
+render_callback (PangoLayout *layout,
+ int x,
+ int y,
+ gpointer context,
+ gpointer data)
+{
+ cairo_t *cr = (cairo_t *) context;
+ gboolean show_borders = GPOINTER_TO_UINT (data) == 0xdeadbeef;
+
+ cairo_save (cr);
+ cairo_translate (cr, x, y);
+
+ if (show_borders)
+ {
+ cairo_pattern_t *pattern;
+ PangoRectangle ink, logical;
+ double lw = cairo_get_line_width (cr);
+ PangoLayoutIter* iter;
+
+ pango_layout_get_extents (layout, &ink, &logical);
+
+ /* draw resolved gravity "roof" in blue */
+ cairo_save (cr);
+ cairo_translate (cr,
+ (double)logical.x / PANGO_SCALE,
+ (double)logical.y / PANGO_SCALE);
+ cairo_scale (cr,
+ (double)logical.width / PANGO_SCALE * 0.5,
+ (double)logical.height / PANGO_SCALE * 0.5);
+ cairo_translate (cr, 1.0, 1.0);
+ cairo_rotate (cr,
+ pango_gravity_to_rotation (
+ pango_context_get_base_gravity (
+ pango_layout_get_context (layout))));
+ cairo_move_to (cr, -1.0, -1.0);
+ cairo_rel_line_to (cr, +1.0, -0.2); /* / */
+ cairo_rel_line_to (cr, +1.0, +0.2); /* \ */
+ cairo_close_path (cr); /* - */
+ pattern = cairo_pattern_create_linear (0, -1.0, 0, -1.2);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.0, 0.0, 0.0, 1.0, 0.0);
+ cairo_pattern_add_color_stop_rgba (pattern, 1.0, 0.0, 0.0, 1.0, 0.15);
+ cairo_set_source (cr, pattern);
+ cairo_fill (cr);
+ /* once more, without close_path this time */
+ cairo_move_to (cr, -1.0, -1.0);
+ cairo_rel_line_to (cr, +1.0, -0.2); /* / */
+ cairo_rel_line_to (cr, +1.0, +0.2); /* \ */
+ /* silly line_width is not locked :(. get rid of scale. */
+ cairo_restore (cr);
+ cairo_save (cr);
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.7, 0.2);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+
+ /* draw block progression arrow in green */
+ cairo_save (cr);
+ cairo_translate (cr,
+ (double)logical.x / PANGO_SCALE,
+ (double)logical.y / PANGO_SCALE);
+ cairo_scale (cr,
+ (double)logical.width / PANGO_SCALE * 0.5,
+ (double)logical.height / PANGO_SCALE * 0.5);
+ cairo_translate (cr, 1.0, 1.0);
+ cairo_move_to (cr, -0.4, -0.7);
+ cairo_rel_line_to (cr, +0.8, 0.0); /* -- */
+ cairo_rel_line_to (cr, 0.0, +0.9); /* | */
+ cairo_rel_line_to (cr, +0.4, 0.0); /* - */
+ cairo_rel_line_to (cr, -0.8, +0.5); /* / */
+ cairo_rel_line_to (cr, -0.8, -0.5); /* \ */
+ cairo_rel_line_to (cr, +0.4, 0.0); /* - */
+ cairo_close_path (cr); /* | */
+ pattern = cairo_pattern_create_linear (0, -0.7, 0, 0.7);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.0, 0.0, 1.0, 0.0, 0.0);
+ cairo_pattern_add_color_stop_rgba (pattern, 1.0, 0.0, 1.0, 0.0, 0.15);
+ cairo_set_source (cr, pattern);
+ cairo_fill_preserve (cr);
+ /* silly line_width is not locked :(. get rid of scale. */
+ cairo_restore (cr);
+ cairo_save (cr);
+ cairo_set_source_rgba (cr, 0.0, 0.7, 0.0, 0.2);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ /* draw baselines with line direction arrow in orange */
+ cairo_save (cr);
+ cairo_set_source_rgba (cr, 1.0, 0.5, 0.0, 0.5);
+ iter = pango_layout_get_iter (layout);
+ do
+ {
+ PangoLayoutLine *line = pango_layout_iter_get_line (iter);
+ double width = (double)logical.width / PANGO_SCALE;
+
+ y = pango_layout_iter_get_baseline (iter);
+ cairo_save (cr);
+ cairo_translate (cr,
+ (double)logical.x / PANGO_SCALE + width * 0.5,
+ (double)y / PANGO_SCALE);
+ if (line->resolved_dir)
+ cairo_scale (cr, -1, 1);
+ cairo_move_to (cr, -width * .5, -lw*0.2);
+ cairo_rel_line_to (cr, +width * .9, -lw*0.3);
+ cairo_rel_line_to (cr, 0, -lw);
+ cairo_rel_line_to (cr, +width * .1, +lw*1.5);
+ cairo_rel_line_to (cr, -width * .1, +lw*1.5);
+ cairo_rel_line_to (cr, 0, -lw);
+ cairo_rel_line_to (cr, -width * .9, -lw*0.3);
+ cairo_close_path (cr);
+ cairo_fill (cr);
+ cairo_restore (cr);
+ }
+ while (pango_layout_iter_next_line (iter));
+ pango_layout_iter_free (iter);
+ cairo_restore (cr);
+
+ /* draw the logical rect in red */
+ cairo_save (cr);
+ cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
+ cairo_rectangle (cr,
+ (double)logical.x / PANGO_SCALE - lw / 2,
+ (double)logical.y / PANGO_SCALE - lw / 2,
+ (double)logical.width / PANGO_SCALE + lw,
+ (double)logical.height / PANGO_SCALE + lw);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ /* draw the ink rect in green */
+ cairo_save (cr);
+ cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 0.5);
+ cairo_rectangle (cr,
+ (double)ink.x / PANGO_SCALE - lw / 2,
+ (double)ink.y / PANGO_SCALE - lw / 2,
+ (double)ink.width / PANGO_SCALE + lw,
+ (double)ink.height / PANGO_SCALE + lw);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+ }
+
+ pango_cairo_show_layout (cr, layout);
+
+ cairo_restore (cr);
+}
+
+static void
+transform_callback (PangoContext *context,
+ PangoMatrix *matrix,
+ gpointer cr_context,
+ gpointer state)
+{
+ cairo_t *cr = (cairo_t *)cr_context;
+ cairo_matrix_t cairo_matrix;
+
+ if (matrix)
+ {
+ cairo_matrix.xx = matrix->xx;
+ cairo_matrix.yx = matrix->yx;
+ cairo_matrix.xy = matrix->xy;
+ cairo_matrix.yy = matrix->yy;
+ cairo_matrix.x0 = matrix->x0;
+ cairo_matrix.y0 = matrix->y0;
+ }
+ else
+ {
+ cairo_matrix_init_identity (&cairo_matrix);
+ }
+
+ cairo_set_matrix (cr, &cairo_matrix);
+
+ pango_cairo_update_context (cr, context);
+}
+
+static void
+pangocairo_view_render (gpointer instance,
+ gpointer surface,
+ PangoContext *context,
+ int width,
+ int height,
+ gpointer state)
+{
+ cairo_t *cr;
+ CairoSurface *c_surface = (CairoSurface *) surface;
+
+ if (!surface)
+ {
+ cairo_surface_t *cs;
+ /* This is annoying ... we have to create a temporary surface just to
+ * get the extents of the text.
+ */
+ /* image surface here is not good as it may have font options different
+ * from the target surface */
+ cs = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1);
+ cr = cairo_create (cs);
+ cairo_surface_destroy (cs);
+ }
+ else
+ cr = cairo_create (c_surface->cairo);
+
+ transform_callback (context, NULL, cr, state);
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_paint (cr);
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ do_output (context, render_callback, transform_callback, cr, state, NULL, NULL);
+
+ cairo_destroy (cr);
+}
+
+#ifdef HAVE_CAIRO_PNG
+static cairo_status_t
+write_func (void *closure,
+ const unsigned char *data,
+ unsigned int length)
+{
+ FILE *stream = (FILE *) closure;
+ unsigned int l;
+
+ l = fwrite (data, 1, length, stream);
+
+ return l == length ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR;
+}
+
+static void
+pangocairo_view_write (gpointer instance,
+ gpointer surface,
+ FILE *stream,
+ int width,
+ int height)
+{
+ CairoSurface *c_surface = (CairoSurface *) surface;
+
+ cairo_surface_write_to_png_stream (c_surface->cairo, write_func, stream);
+}
+#endif
+
+static gpointer
+pangocairo_view_create_window (gpointer instance,
+ const char *title,
+ int width,
+ int height)
+{
+ CairoViewer *c = (CairoViewer *) instance;
+
+ return c->iface->backend_class->create_window (c->backend,
+ title,
+ width, height);
+}
+
+static void
+pangocairo_view_destroy_window (gpointer instance,
+ gpointer window)
+{
+ CairoViewer *c = (CairoViewer *) instance;
+
+ c->iface->backend_class->destroy_window (c->backend,
+ window);
+}
+
+static gpointer
+pangocairo_view_display (gpointer instance,
+ gpointer surface,
+ gpointer window,
+ int width, int height,
+ gpointer state)
+{
+ CairoViewer *c = (CairoViewer *) instance;
+ CairoSurface *c_surface = (CairoSurface *) surface;
+
+ return c->iface->backend_class->display (c->backend,
+ c_surface->backend,
+ window,
+ width, height,
+ state);
+}
+
+const PangoViewer pangocairo_viewer = {
+ "PangoCairo",
+ "cairo",
+ NULL,
+ pangocairo_view_create,
+ pangocairo_view_destroy,
+ pangocairo_view_get_context,
+ pangocairo_view_create_surface,
+ pangocairo_view_destroy_surface,
+ pangocairo_view_render,
+#ifdef HAVE_CAIRO_PNG
+ pangocairo_view_write,
+#else
+ NULL,
+#endif
+ pangocairo_view_create_window,
+ pangocairo_view_destroy_window,
+ pangocairo_view_display
+};
diff --git a/trunk/pango-view/viewer-pangoft2.c b/trunk/pango-view/viewer-pangoft2.c
new file mode 100644
index 00000000..a3672399
--- /dev/null
+++ b/trunk/pango-view/viewer-pangoft2.c
@@ -0,0 +1,162 @@
+/* viewer-pangoft2.c: PangoFT2 viewer backend.
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "viewer-render.h"
+#include "viewer.h"
+
+#include <pango/pangoft2.h>
+
+static void
+substitute_func (FcPattern *pattern,
+ gpointer data)
+{
+ if (opt_hinting != HINT_DEFAULT)
+ {
+ FcPatternDel (pattern, FC_HINTING);
+ FcPatternAddBool (pattern, FC_HINTING, opt_hinting != HINT_NONE);
+
+ FcPatternDel (pattern, FC_AUTOHINT);
+ FcPatternAddBool (pattern, FC_AUTOHINT, opt_hinting == HINT_AUTO);
+ }
+}
+
+static gpointer
+pangoft2_view_create (const PangoViewer *klass)
+{
+ PangoFontMap *fontmap;
+ fontmap = pango_ft2_font_map_new ();
+
+ pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (fontmap), opt_dpi, opt_dpi);
+ pango_ft2_font_map_set_default_substitute (PANGO_FT2_FONT_MAP (fontmap), substitute_func, NULL, NULL);
+
+ return fontmap;
+}
+
+static void
+pangoft2_view_destroy (gpointer instance)
+{
+ g_object_unref (instance);
+}
+
+static PangoContext *
+pangoft2_view_get_context (gpointer instance)
+{
+ return pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (instance));
+}
+
+static gpointer
+pangoft2_view_create_surface (gpointer instance,
+ int width,
+ int height)
+{
+ FT_Bitmap *bitmap;
+
+ bitmap = g_slice_new (FT_Bitmap);
+ bitmap->width = width;
+ bitmap->pitch = (bitmap->width + 3) & ~3;
+ bitmap->rows = height;
+ bitmap->buffer = g_malloc (bitmap->pitch * bitmap->rows);
+ bitmap->num_grays = 256;
+ bitmap->pixel_mode = ft_pixel_mode_grays;
+ memset (bitmap->buffer, 0x00, bitmap->pitch * bitmap->rows);
+
+ return bitmap;
+}
+
+static void
+pangoft2_view_destroy_surface (gpointer instance,
+ gpointer surface)
+{
+ FT_Bitmap *bitmap = (FT_Bitmap *) surface;
+
+ g_free (bitmap->buffer);
+ g_slice_free (FT_Bitmap, bitmap);
+}
+
+static void
+render_callback (PangoLayout *layout,
+ int x,
+ int y,
+ gpointer context,
+ gpointer state)
+{
+ pango_ft2_render_layout ((FT_Bitmap *)context,
+ layout,
+ x, y);
+}
+
+static void
+pangoft2_view_render (gpointer instance,
+ gpointer surface,
+ PangoContext *context,
+ int width,
+ int height,
+ gpointer state)
+{
+ int pix_idx;
+ FT_Bitmap *bitmap = (FT_Bitmap *) surface;
+
+ do_output (context, render_callback, NULL, surface, state, NULL, NULL);
+
+ for (pix_idx=0; pix_idx<bitmap->pitch * bitmap->rows; pix_idx++)
+ bitmap->buffer[pix_idx] = 255 - bitmap->buffer[pix_idx];
+}
+
+static void
+pangoft2_view_write (gpointer instance,
+ gpointer surface,
+ FILE *stream,
+ int width,
+ int height)
+{
+ int row;
+ FT_Bitmap *bitmap = (FT_Bitmap *) surface;
+
+ /* Write it as pgm to output */
+ fprintf(stream,
+ "P5\n"
+ "%d %d\n"
+ "255\n", width, height);
+ for (row = 0; row < height; row++)
+ fwrite(bitmap->buffer + row * bitmap->pitch, 1, width, stream);
+}
+
+const PangoViewer pangoft2_viewer = {
+ "PangoFT2",
+ "ft2",
+ ".pgm",
+ pangoft2_view_create,
+ pangoft2_view_destroy,
+ pangoft2_view_get_context,
+ pangoft2_view_create_surface,
+ pangoft2_view_destroy_surface,
+ pangoft2_view_render,
+ pangoft2_view_write,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/trunk/pango-view/viewer-pangox.c b/trunk/pango-view/viewer-pangox.c
new file mode 100644
index 00000000..084747b3
--- /dev/null
+++ b/trunk/pango-view/viewer-pangox.c
@@ -0,0 +1,122 @@
+/* viewer-pangox.c: PangoX viewer backend.
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+
+#include "viewer-render.h"
+#include "viewer-x.h"
+
+#include <pango/pangox.h>
+
+static void
+pangox_view_destroy (gpointer instance)
+{
+ XViewer *x = (XViewer *)instance;
+
+ pango_x_shutdown_display (x->display);
+
+ x_view_destroy (instance);
+}
+
+static PangoContext *
+pangox_view_get_context (gpointer instance)
+{
+ XViewer *x = (XViewer *) instance;
+ PangoContext *context;
+ PangoMatrix matrix = {0., 0., 0., 0., 0., 0.};
+
+ context = pango_x_get_context (x->display);
+
+ /* We set an all-zero matrix on the context, to negotiate that
+ * this backend doesn't support transformations.
+ */
+ pango_context_set_matrix (context, &matrix);
+
+ return context;
+}
+
+typedef struct
+{
+ XViewer *x;
+ Drawable drawable;
+ GC gc;
+} MyXContext;
+
+static void
+render_callback (PangoLayout *layout,
+ int x,
+ int y,
+ gpointer context,
+ gpointer state)
+{
+ MyXContext *x_context = (MyXContext *) context;
+
+ pango_x_render_layout (x_context->x->display,
+ x_context->drawable,
+ x_context->gc,
+ layout,
+ x, y);
+}
+
+static void
+pangox_view_render (gpointer instance,
+ gpointer surface,
+ PangoContext *context,
+ int width,
+ int height,
+ gpointer state)
+{
+ XViewer *x = (XViewer *) instance;
+ Pixmap pixmap = (Pixmap) surface;
+ GC gc;
+ MyXContext x_context;
+
+ gc = XCreateGC (x->display, pixmap, 0, NULL);
+
+ XSetForeground(x->display, gc, WhitePixel(x->display, x->screen));
+ XFillRectangle (x->display, pixmap, gc, 0, 0, width, height);
+
+ x_context.x = x;
+ x_context.drawable = pixmap;
+ x_context.gc = gc;
+
+ XSetForeground(x->display, gc, BlackPixel(x->display, x->screen));
+ do_output (context, render_callback, NULL, &x_context, state, NULL, NULL);
+
+ XFlush(x->display);
+
+ XFreeGC (x->display, gc);
+}
+
+const PangoViewer pangox_viewer = {
+ "PangoX",
+ "x",
+ NULL,
+ x_view_create,
+ pangox_view_destroy,
+ pangox_view_get_context,
+ x_view_create_surface,
+ x_view_destroy_surface,
+ pangox_view_render,
+ NULL,
+ x_view_create_window,
+ x_view_destroy_window,
+ x_view_display
+};
diff --git a/trunk/pango-view/viewer-pangoxft.c b/trunk/pango-view/viewer-pangoxft.c
new file mode 100644
index 00000000..80863ca7
--- /dev/null
+++ b/trunk/pango-view/viewer-pangoxft.c
@@ -0,0 +1,151 @@
+/* viewer-pangoxft.c: PangoXft viewer backend.
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+
+#include "viewer-render.h"
+#include "viewer-x.h"
+
+#include <pango/pangoxft.h>
+
+static void
+default_substitute (FcPattern *pattern,
+ gpointer data)
+{
+ FcPatternDel (pattern, FC_DPI);
+ FcPatternAddInteger (pattern, FC_DPI, opt_dpi);
+
+ if (opt_hinting != HINT_DEFAULT)
+ {
+ FcPatternDel (pattern, FC_HINTING);
+ FcPatternAddBool (pattern, FC_HINTING, opt_hinting != HINT_NONE);
+
+ FcPatternDel (pattern, FC_AUTOHINT);
+ FcPatternAddBool (pattern, FC_AUTOHINT, opt_hinting == HINT_AUTO);
+ }
+}
+
+static gpointer
+pangoxft_view_create (const PangoViewer *klass)
+{
+ XViewer *instance;
+
+ instance = x_view_create (klass);
+
+ XftInit (NULL);
+
+ pango_xft_set_default_substitute (instance->display, instance->screen,
+ default_substitute, NULL, NULL);
+
+ return instance;
+}
+
+static void
+pangoxft_view_destroy (gpointer instance)
+{
+ XViewer *x = (XViewer *)instance;
+
+ pango_xft_shutdown_display (x->display, x->screen);
+
+ x_view_destroy (instance);
+}
+
+static PangoContext *
+pangoxft_view_get_context (gpointer instance)
+{
+ XViewer *x = (XViewer *) instance;
+
+ return pango_xft_get_context (x->display, x->screen);
+}
+
+typedef struct
+{
+ XftDraw *draw;
+ XftColor color;
+} MyXftContext;
+
+static void
+render_callback (PangoLayout *layout,
+ int x,
+ int y,
+ gpointer context,
+ gpointer state)
+{
+ MyXftContext *xft_context = (MyXftContext *) context;
+
+ pango_xft_render_layout (xft_context->draw,
+ &xft_context->color,
+ layout,
+ x * PANGO_SCALE, y * PANGO_SCALE);
+}
+
+static void
+pangoxft_view_render (gpointer instance,
+ gpointer surface,
+ PangoContext *context,
+ int width,
+ int height,
+ gpointer state)
+{
+ XViewer *x = (XViewer *) instance;
+ Pixmap pixmap = (Pixmap) surface;
+ MyXftContext xft_context;
+ XftDraw *draw;
+ XftColor color;
+
+ draw = XftDrawCreate (x->display, pixmap,
+ DefaultVisual (x->display, x->screen),
+ DefaultColormap (x->display, x->screen));
+
+ color.color.red = 0xffff;
+ color.color.blue = 0xffff;
+ color.color.green = 0xffff;
+ color.color.alpha = 0xffff;
+
+ XftDrawRect (draw, &color, 0, 0, width, height);
+
+ color.color.red = 0x0;
+ color.color.green = 0x0;
+ color.color.blue = 0x0;
+ color.color.alpha = 0xffff;
+
+ xft_context.draw = draw;
+ xft_context.color = color;
+
+ do_output (context, render_callback, NULL, &xft_context, state, NULL, NULL);
+
+ XftDrawDestroy (draw);
+}
+
+const PangoViewer pangoxft_viewer = {
+ "PangoXft",
+ "xft",
+ NULL,
+ pangoxft_view_create,
+ pangoxft_view_destroy,
+ pangoxft_view_get_context,
+ x_view_create_surface,
+ x_view_destroy_surface,
+ pangoxft_view_render,
+ NULL,
+ x_view_create_window,
+ x_view_destroy_window,
+ x_view_display
+};
diff --git a/trunk/pango-view/viewer-render.c b/trunk/pango-view/viewer-render.c
new file mode 100644
index 00000000..1c29c4e6
--- /dev/null
+++ b/trunk/pango-view/viewer-render.c
@@ -0,0 +1,711 @@
+/* viewer-render.c: Common code for rendering in viewers
+ *
+ * Copyright (C) 1999, 2004 Red Hat Software
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#include <errno.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <pango/pango.h>
+
+#include "viewer-render.h"
+
+#define DEFAULT_FONT_FAMILY "Sans"
+#define DEFAULT_FONT_SIZE 18
+
+#define _MAKE_FONT_NAME(family, size) family " " #size
+#define MAKE_FONT_NAME(family, size) _MAKE_FONT_NAME(family, size)
+
+const char *prog_name;
+
+gboolean opt_display = TRUE;
+int opt_dpi = 96;
+const char *opt_font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE);
+gboolean opt_header = FALSE;
+const char *opt_output = NULL;
+int opt_margin = 10;
+int opt_markup = FALSE;
+gboolean opt_rtl = FALSE;
+double opt_rotate = 0;
+gboolean opt_auto_dir = TRUE;
+const char *opt_text = NULL;
+gboolean opt_waterfall = FALSE;
+int opt_width = -1;
+int opt_indent = 0;
+gboolean opt_justify = 0;
+int opt_runs = 1;
+PangoAlignment opt_align = PANGO_ALIGN_LEFT;
+PangoEllipsizeMode opt_ellipsize = PANGO_ELLIPSIZE_NONE;
+PangoGravity opt_gravity = PANGO_GRAVITY_SOUTH;
+PangoGravityHint opt_gravity_hint = PANGO_GRAVITY_HINT_NATURAL;
+HintMode opt_hinting = HINT_DEFAULT;
+PangoWrapMode opt_wrap = PANGO_WRAP_WORD_CHAR;
+gboolean opt_wrap_set = FALSE;
+const char *opt_pangorc = NULL;
+const PangoViewer *opt_viewer = NULL;
+const char *opt_language = NULL;
+
+/* Text (or markup) to render */
+static char *text;
+
+void
+fail (const char *format, ...)
+{
+ const char *msg;
+
+ va_list vap;
+ va_start (vap, format);
+ msg = g_strdup_vprintf (format, vap);
+ g_printerr ("%s: %s\n", prog_name, msg);
+
+ exit (1);
+}
+
+static PangoFontDescription *
+get_font_description (void)
+{
+ PangoFontDescription *font_description = pango_font_description_from_string (opt_font);
+
+ if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_FAMILY) == 0)
+ pango_font_description_set_family (font_description, DEFAULT_FONT_FAMILY);
+
+ if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_SIZE) == 0)
+ pango_font_description_set_size (font_description, DEFAULT_FONT_SIZE * PANGO_SCALE);
+
+ return font_description;
+}
+
+static PangoLayout *
+make_layout(PangoContext *context,
+ const char *text,
+ double size)
+{
+ static PangoFontDescription *font_description;
+ PangoAlignment align;
+ PangoLayout *layout;
+
+ layout = pango_layout_new (context);
+ if (opt_markup)
+ pango_layout_set_markup (layout, text, -1);
+ else
+ pango_layout_set_text (layout, text, -1);
+
+ pango_layout_set_auto_dir (layout, opt_auto_dir);
+ pango_layout_set_ellipsize (layout, opt_ellipsize);
+ pango_layout_set_justify (layout, opt_justify);
+
+ font_description = get_font_description ();
+ if (size > 0)
+ pango_font_description_set_size (font_description, size * PANGO_SCALE);
+
+ if (opt_width > 0)
+ {
+ pango_layout_set_wrap (layout, opt_wrap);
+ pango_layout_set_width (layout, (opt_width * opt_dpi * PANGO_SCALE + 36) / 72);
+ }
+
+ if (opt_indent != 0)
+ pango_layout_set_indent (layout, (opt_indent * opt_dpi * PANGO_SCALE + 36) / 72);
+
+ align = opt_align;
+ if (align != PANGO_ALIGN_CENTER &&
+ pango_context_get_base_dir (context) != PANGO_DIRECTION_LTR) {
+ /* pango reverses left and right if base dir ir rtl. so we should
+ * reverse to cancel that. unfortunately it also does that for
+ * rtl paragraphs, so we cannot really get left/right. all we get
+ * is default/other-side. */
+ align = PANGO_ALIGN_LEFT + PANGO_ALIGN_RIGHT - align;
+ }
+ pango_layout_set_alignment (layout, align);
+
+ pango_layout_set_font_description (layout, font_description);
+
+ pango_font_description_free (font_description);
+
+ return layout;
+}
+
+gchar *
+get_options_string (void)
+{
+ PangoFontDescription *font_description = get_font_description ();
+ gchar *font_name;
+ gchar *result;
+
+ if (opt_waterfall)
+ pango_font_description_unset_fields (font_description, PANGO_FONT_MASK_SIZE);
+
+ font_name = pango_font_description_to_string (font_description);
+ result = g_strdup_printf ("%s: %s (%d dpi)", opt_viewer->name, font_name, opt_dpi);
+ pango_font_description_free (font_description);
+ g_free (font_name);
+
+ return result;
+}
+
+static void
+output_body (PangoLayout *layout,
+ RenderCallback render_cb,
+ gpointer cb_context,
+ gpointer cb_data,
+ int *width,
+ int *height,
+ gboolean supports_matrix)
+{
+ PangoRectangle logical_rect;
+ int size, start_size, end_size, increment;
+ int x = 0, y = 0;
+
+ if (!supports_matrix)
+ {
+ const PangoMatrix* matrix;
+ const PangoMatrix identity = PANGO_MATRIX_INIT;
+ PangoContext *context = pango_layout_get_context (layout);
+ matrix = pango_context_get_matrix (context);
+ if (matrix)
+ {
+ x += matrix->x0;
+ y += matrix->y0;
+ }
+ pango_context_set_matrix (context, &identity);
+ pango_layout_context_changed (layout);
+ }
+
+ if (opt_waterfall)
+ {
+ start_size = 8;
+ end_size = 48;
+ increment = 4;
+ }
+ else
+ {
+ start_size = end_size = -1;
+ increment = 1;
+ }
+
+ *width = 0;
+ *height = 0;
+
+ for (size = start_size; size <= end_size; size += increment)
+ {
+ if (size > 0)
+ {
+ PangoFontDescription *desc = pango_font_description_copy (pango_layout_get_font_description (layout));
+ pango_font_description_set_size (desc, size * PANGO_SCALE);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+ }
+
+ pango_layout_get_extents (layout, NULL, &logical_rect);
+
+ if (render_cb)
+ (*render_cb) (layout, x, y+*height, cb_context, cb_data);
+
+ *width = MAX (*width, PANGO_PIXELS (logical_rect.x + logical_rect.width));
+ *width = MAX (*width, PANGO_PIXELS (pango_layout_get_width (layout)));
+ *height += PANGO_PIXELS (logical_rect.height);
+ }
+}
+
+static void
+set_transform (PangoContext *context,
+ TransformCallback transform_cb,
+ gpointer cb_context,
+ gpointer cb_data,
+ PangoMatrix *matrix)
+{
+ pango_context_set_matrix (context, matrix);
+ if (transform_cb)
+ (*transform_cb) (context, matrix, cb_context, cb_data);
+}
+
+void
+do_output (PangoContext *context,
+ RenderCallback render_cb,
+ TransformCallback transform_cb,
+ gpointer cb_context,
+ gpointer cb_data,
+ int *width_out,
+ int *height_out)
+{
+ PangoLayout *layout;
+ PangoRectangle rect;
+ PangoMatrix matrix = PANGO_MATRIX_INIT;
+ PangoMatrix *orig_matrix;
+ gboolean supports_matrix;
+ int rotated_width, rotated_height;
+ int x = opt_margin;
+ int y = opt_margin;
+ int width, height;
+
+ width = 0;
+ height = 0;
+
+ orig_matrix = pango_matrix_copy (pango_context_get_matrix (context));
+ /* If the backend sets an all-zero matrix on the context,
+ * means that it doesn't support transformations.
+ */
+ supports_matrix = !orig_matrix ||
+ (orig_matrix->xx != 0. || orig_matrix->xy != 0. ||
+ orig_matrix->yx != 0. || orig_matrix->yy != 0. ||
+ orig_matrix->x0 != 0. || orig_matrix->y0 != 0.);
+
+ set_transform (context, transform_cb, cb_context, cb_data, NULL);
+
+ pango_context_set_language (context,
+ opt_language ? pango_language_from_string (opt_language)
+ : pango_language_get_default ());
+ pango_context_set_base_dir (context,
+ opt_rtl ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
+
+ if (opt_header)
+ {
+ char *options_string = get_options_string ();
+ pango_context_set_base_gravity (context, PANGO_GRAVITY_SOUTH);
+ layout = make_layout (context, options_string, 10);
+ pango_layout_get_extents (layout, NULL, &rect);
+
+ width = MAX (width, PANGO_PIXELS (rect.width));
+ height += PANGO_PIXELS (rect.height);
+
+ if (render_cb)
+ (*render_cb) (layout, x, y, cb_context, cb_data);
+
+ y += PANGO_PIXELS (rect.height);
+
+ g_object_unref (layout);
+ g_free (options_string);
+ }
+
+ if (opt_rotate != 0)
+ {
+ if (supports_matrix)
+ pango_matrix_rotate (&matrix, opt_rotate);
+ else
+ g_printerr ("The backend does not support rotated text\n");
+ }
+
+ pango_context_set_base_gravity (context, opt_gravity);
+ pango_context_set_gravity_hint (context, opt_gravity_hint);
+
+ layout = make_layout (context, text, -1);
+
+ set_transform (context, transform_cb, cb_context, cb_data, &matrix);
+
+ output_body (layout,
+ NULL, NULL, NULL,
+ &rotated_width, &rotated_height,
+ supports_matrix);
+
+ rect.x = rect.y = 0;
+ rect.width = rotated_width;
+ rect.height = rotated_height;
+
+ pango_matrix_transform_pixel_rectangle (&matrix, &rect);
+
+ matrix.x0 = x - rect.x;
+ matrix.y0 = y - rect.y;
+
+ set_transform (context, transform_cb, cb_context, cb_data, &matrix);
+
+ if (render_cb)
+ output_body (layout,
+ render_cb, cb_context, cb_data,
+ &rotated_width, &rotated_height,
+ supports_matrix);
+
+ width = MAX (width, rect.width);
+ height += rect.height;
+
+ width += 2 * opt_margin;
+ height += 2 * opt_margin;
+
+ if (width_out)
+ *width_out = width;
+ if (height_out)
+ *height_out = height;
+
+ pango_context_set_matrix (context, orig_matrix);
+ pango_matrix_free (orig_matrix);
+ g_object_unref (layout);
+}
+
+static gboolean
+parse_enum (GType type,
+ int *value,
+ const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ char *possible_values = NULL;
+ gboolean ret;
+
+ ret = pango_parse_enum (type,
+ arg,
+ value,
+ FALSE,
+ &possible_values);
+
+ if (!ret && error)
+ {
+ g_set_error(error,
+ G_OPTION_ERROR,
+ G_OPTION_ERROR_BAD_VALUE,
+ "Argument for %s must be one of %s",
+ name,
+ possible_values);
+ ret = FALSE;
+ }
+
+ g_free (possible_values);
+
+ return ret;
+}
+
+static gboolean
+parse_align (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ return parse_enum (PANGO_TYPE_ALIGNMENT, &opt_align,
+ name, arg, data, error);
+}
+
+static gboolean
+parse_ellipsis (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ return parse_enum (PANGO_TYPE_ELLIPSIZE_MODE, &opt_ellipsize,
+ name, arg, data, error);
+}
+
+static gboolean
+parse_gravity (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ return parse_enum (PANGO_TYPE_GRAVITY, &opt_gravity,
+ name, arg, data, error);
+}
+
+static gboolean
+parse_gravity_hint (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ return parse_enum (PANGO_TYPE_GRAVITY_HINT, &opt_gravity_hint,
+ name, arg, data, error);
+}
+
+static gboolean
+parse_hinting (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ gboolean ret = TRUE;
+
+ if (strcmp (arg, "none") == 0)
+ opt_hinting = HINT_NONE;
+ else if (strcmp (arg, "auto") == 0)
+ opt_hinting = HINT_AUTO;
+ else if (strcmp (arg, "full") == 0)
+ opt_hinting = HINT_FULL;
+ else
+ {
+ g_set_error(error,
+ G_OPTION_ERROR,
+ G_OPTION_ERROR_BAD_VALUE,
+ "Argument for --hinting must be one of none/auto/full");
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+static gboolean
+parse_wrap (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ gboolean ret;
+ if ((ret = parse_enum (PANGO_TYPE_WRAP_MODE, &opt_wrap,
+ name, arg, data, error)))
+ {
+ opt_wrap_set = TRUE;
+ }
+ return ret;
+}
+
+static gchar *
+backends_to_string (void)
+{
+ GString *backends = g_string_new (NULL);
+ const PangoViewer **viewer;
+
+ for (viewer = viewers; *viewer; viewer++)
+ if ((*viewer)->id)
+ {
+ g_string_append (backends, (*viewer)->id);
+ g_string_append_c (backends, '/');
+ }
+ g_string_truncate (backends, MAX (0, (gint)backends->len - 1));
+
+ return g_string_free(backends,FALSE);
+}
+
+static int
+backends_get_count (void)
+{
+ const PangoViewer **viewer;
+ int i = 0;
+
+ for (viewer = viewers; *viewer; viewer++)
+ if ((*viewer)->id)
+ i++;
+
+ return i;
+}
+
+
+static gchar *
+backend_description (void)
+{
+ GString *description = g_string_new("Pango backend to use for rendering ");
+ int backends_count = backends_get_count ();
+
+ if (backends_count > 1)
+ g_string_append_printf(description,"(default: %s)", (*viewers)->id);
+ else if (backends_count == 1)
+ g_string_append_printf(description,"(only available: %s)", (*viewers)->id);
+ else
+ g_string_append_printf(description,"(no backends found!)");
+
+ return g_string_free(description,FALSE);
+
+}
+
+
+static gboolean
+parse_backend (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ gboolean ret = TRUE;
+ const PangoViewer **viewer;
+
+ for (viewer = viewers; *viewer; viewer++)
+ if (!g_ascii_strcasecmp ((*viewer)->id, arg))
+ break;
+
+ if (*viewer)
+ opt_viewer = *viewer;
+ else
+ {
+ gchar *backends = backends_to_string ();
+
+ g_set_error(error,
+ G_OPTION_ERROR,
+ G_OPTION_ERROR_BAD_VALUE,
+ "Available --backend options are: %s",
+ backends);
+ g_free(backends);
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+
+static gboolean
+show_version(const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ g_printf("%s (%s) %s\n", prog_name, PACKAGE_NAME, PACKAGE_VERSION);
+ g_printf("module interface version: %s\n", MODULE_VERSION);
+
+ if (PANGO_VERSION != pango_version())
+ g_printf("\nLinked Pango library has a different version: %s\n", pango_version_string ());
+
+ exit(0);
+}
+
+void
+parse_options (int argc, char *argv[])
+{
+ gchar *backend_options = backends_to_string ();
+ GOptionFlags backend_flag = backends_get_count () > 1 ? 0 : G_OPTION_FLAG_HIDDEN;
+ gchar *backend_desc = backend_description ();
+ GOptionEntry entries[] =
+ {
+ {"no-auto-dir", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_auto_dir,
+ "No layout direction according to contents", NULL},
+ {"backend", 0, backend_flag, G_OPTION_ARG_CALLBACK, &parse_backend,
+ backend_desc, backend_options},
+ {"no-display", 'q', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_display,
+ "Do not display (just write to file or whatever)", NULL},
+ {"dpi", 0, 0, G_OPTION_ARG_INT, &opt_dpi,
+ "Set the resolution", "number"},
+ {"align", 0, 0, G_OPTION_ARG_CALLBACK, &parse_align,
+ "Text alignment", "left/center/right"},
+ {"ellipsize", 0, 0, G_OPTION_ARG_CALLBACK, &parse_ellipsis,
+ "Ellipsization mode", "start/middle/end"},
+ {"font", 0, 0, G_OPTION_ARG_STRING, &opt_font,
+ "Set the font description", "description"},
+ {"gravity", 0, 0, G_OPTION_ARG_CALLBACK, &parse_gravity,
+ "Base gravity: glyph rotation", "south/east/north/west/auto"},
+ {"gravity-hint", 0, 0, G_OPTION_ARG_CALLBACK, &parse_gravity_hint,
+ "Gravity hint", "natural/strong/line"},
+ {"header", 0, 0, G_OPTION_ARG_NONE, &opt_header,
+ "Display the options in the output", NULL},
+ {"hinting", 0, 0, G_OPTION_ARG_CALLBACK, &parse_hinting,
+ "Hinting style", "none/auto/full"},
+ {"indent", 0, 0, G_OPTION_ARG_INT, &opt_indent,
+ "Width in points to indent paragraphs", "points"},
+ {"justify", 0, 0, G_OPTION_ARG_NONE, &opt_justify,
+ "Align paragraph lines to be justified", NULL},
+ {"language", 0, 0, G_OPTION_ARG_STRING, &opt_language,
+ "Language to use for font selection", "en_US/etc"},
+ {"margin", 0, 0, G_OPTION_ARG_INT, &opt_margin,
+ "Set the margin on the output in pixels", "pixels"},
+ {"markup", 0, 0, G_OPTION_ARG_NONE, &opt_markup,
+ "Interpret text as Pango markup", NULL},
+ {"output", 'o', 0, G_OPTION_ARG_STRING, &opt_output,
+ "Save rendered image to output file", "file"},
+ {"pangorc", 0, 0, G_OPTION_ARG_STRING, &opt_pangorc,
+ "pangorc file to use (default is ./pangorc)", "file"},
+ {"rtl", 0, 0, G_OPTION_ARG_NONE, &opt_rtl,
+ "Set base direction to right-to-left", NULL},
+ {"rotate", 0, 0, G_OPTION_ARG_DOUBLE, &opt_rotate,
+ "Angle at which to rotate results", "degrees"},
+ {"runs", 'n', 0, G_OPTION_ARG_INT, &opt_runs,
+ "Run Pango layout engine this many times", "integer"},
+ {"text", 't', 0, G_OPTION_ARG_STRING, &opt_text,
+ "Text to display (instead of a file)", "string"},
+ {"version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &show_version,
+ "Show version numbers", NULL},
+ {"waterfall", 0, 0, G_OPTION_ARG_NONE, &opt_waterfall,
+ "Create a waterfall display", NULL},
+ {"width", 'w', 0, G_OPTION_ARG_INT, &opt_width,
+ "Width in points to which to wrap output", "points"},
+ {"wrap", 0, 0, G_OPTION_ARG_CALLBACK, &parse_wrap,
+ "Text wrapping mode (needs a width to be set)", "word/char/word-char"},
+ {NULL}
+ };
+ GError *error = NULL;
+ GError *parse_error = NULL;
+ GOptionContext *context;
+ size_t len;
+
+ prog_name = g_path_get_basename (argv[0]);
+ context = g_option_context_new ("- FILE");
+ g_option_context_add_main_entries (context, entries, NULL);
+ if (!g_option_context_parse (context, &argc, &argv, &parse_error))
+ {
+ if (parse_error != NULL)
+ fail("%s", parse_error->message);
+ else
+ fail("Option parse error");
+ exit(1);
+ }
+ g_option_context_free(context);
+ g_free(backend_options);
+ g_free(backend_desc);
+
+ if ((opt_text && argc != 1) || (!opt_text && argc != 2))
+ {
+ if (opt_text && argc != 1)
+ fail ("When specifying --text, no file should be given");
+
+ g_printerr ("Usage: %s [OPTION...] FILE\n", prog_name);
+ exit (1);
+ }
+
+ /* set up the backend */
+ if (!opt_viewer)
+ {
+ opt_viewer = *viewers;
+ if (!opt_viewer)
+ fail ("No viewer backend found");
+ }
+
+ /* if wrap mode is set then width must be set */
+ if (opt_width < 0 && opt_wrap_set)
+ {
+ g_printerr ("The wrap mode only has effect if a width is set\n");
+ }
+
+ /* Get the text
+ */
+ if (opt_text)
+ {
+ text = g_strdup (opt_text);
+ len = strlen (text);
+ }
+ else
+ {
+ if (!g_file_get_contents (argv[1], &text, &len, &error))
+ fail ("%s\n", error->message);
+ }
+
+ /* Strip one trailing newline
+ */
+ if (len > 0 && text[len - 1] == '\n')
+ len--;
+ if (len > 0 && text[len - 1] == '\r')
+ len--;
+ text[len] = '\0';
+
+ /* Make sure we have valid markup
+ */
+ if (opt_markup &&
+ !pango_parse_markup (text, -1, 0, NULL, NULL, NULL, &error))
+ fail ("Cannot parse input as markup: %s", error->message);
+
+ /* Setup PANGO_RC_FILE
+ */
+ if (!opt_pangorc)
+ if (g_file_test ("./pangorc", G_FILE_TEST_IS_REGULAR))
+ opt_pangorc = "./pangorc";
+ if (opt_pangorc)
+ g_setenv ("PANGO_RC_FILE", opt_pangorc, TRUE);
+}
+
+
+void
+finalize (void)
+{
+ g_free (text);
+}
diff --git a/trunk/pango-view/viewer-render.h b/trunk/pango-view/viewer-render.h
new file mode 100644
index 00000000..10fb1a13
--- /dev/null
+++ b/trunk/pango-view/viewer-render.h
@@ -0,0 +1,86 @@
+/* viewer-render.c: Common code for rendering in viewers
+ *
+ * Copyright (C) 1999, 2004 Red Hat Software
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef VIEWER_RENDER_H
+#define VIEWER_RENDER_H
+
+#include <pango/pango-layout.h>
+
+#include "viewer.h"
+
+typedef enum {
+ HINT_DEFAULT,
+ HINT_NONE,
+ HINT_AUTO,
+ HINT_FULL
+} HintMode;
+
+typedef void (*RenderCallback) (PangoLayout *layout,
+ int x,
+ int y,
+ gpointer cb_context,
+ gpointer cb_data);
+typedef void (*TransformCallback) (PangoContext *context,
+ PangoMatrix *transform,
+ gpointer cb_context,
+ gpointer cb_data);
+
+void fail (const char *format, ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN;
+
+void parse_options (int argc,
+ char *argv[]);
+void do_output (PangoContext *context,
+ RenderCallback render_cb,
+ TransformCallback transform_cb,
+ gpointer cb_context,
+ gpointer cb_data,
+ int *width,
+ int *height);
+void finalize (void);
+gchar *get_options_string (void);
+
+extern const char *prog_name;
+
+/* handled by viewer-render.c */
+extern const char *opt_font;
+extern gboolean opt_header;
+extern int opt_margin;
+extern int opt_markup;
+extern gboolean opt_rtl;
+extern double opt_rotate;
+extern gboolean opt_auto_dir;
+extern const char *opt_text;
+extern gboolean opt_waterfall;
+extern int opt_width;
+extern int opt_indent;
+extern PangoEllipsizeMode opt_ellipsize;
+extern const char *opt_pangorc;
+
+/* handled by view.c */
+extern gboolean opt_display;
+extern const char *opt_output;
+extern int opt_runs;
+extern const PangoViewer *opt_viewer;
+
+/* handled by backend-specific code */
+extern int opt_dpi;
+extern HintMode opt_hinting;
+
+#endif /* VIEWER_RENDER_H */
diff --git a/trunk/pango-view/viewer-win32.c b/trunk/pango-view/viewer-win32.c
new file mode 100644
index 00000000..23a7dac5
--- /dev/null
+++ b/trunk/pango-view/viewer-win32.c
@@ -0,0 +1,748 @@
+/* Pango
+ * viewer-win32.c: Example program to view a UTF-8 encoding file
+ * using Pango to render result.
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#include <gtk/gtk.h>
+#include <gdk/win32/gdkwin32.h>
+
+#include <pango/pango.h>
+#include <pango/pangowin32.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define BUFSIZE 1024
+
+typedef struct _Paragraph Paragraph;
+
+/* Structure representing a paragraph
+ */
+struct _Paragraph {
+ char *text;
+ int length;
+ int height; /* Height, in pixels */
+ PangoLayout *layout;
+};
+
+GList *paragraphs;
+
+static PangoFontDescription *font_description;
+static Paragraph *highlight_para;
+static int highlight_offset;
+
+GtkWidget *styles_combo;
+
+static GtkWidget *message_label;
+GtkWidget *layout;
+
+PangoContext *context;
+
+static void fill_styles_combo (GtkWidget *combo);
+
+/* Read an entire file into a string
+ */
+static char *
+read_file(char *name)
+{
+ GString *inbuf;
+ FILE *file;
+ char *text;
+ char buffer[BUFSIZE];
+
+ file = fopen (name, "r");
+ if (!file)
+ {
+ fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname (), name);
+ return NULL;
+ }
+
+ inbuf = g_string_new (NULL);
+ while (1)
+ {
+ char *bp = fgets (buffer, BUFSIZE-1, file);
+ if (ferror (file))
+ {
+ fprintf (stderr, "%s: Error reading %s\n", g_get_prgname (), name);
+ g_string_free (inbuf, TRUE);
+ return NULL;
+ }
+ else if (bp == NULL)
+ break;
+
+ g_string_append (inbuf, buffer);
+ }
+
+ fclose (file);
+
+ text = inbuf->str;
+ g_string_free (inbuf, FALSE);
+
+ return text;
+}
+
+/* Take a UTF8 string and break it into paragraphs on \n characters
+ */
+static GList *
+split_paragraphs (char *text)
+{
+ char *p = text;
+ char *next;
+ gunichar wc;
+ GList *result = NULL;
+ char *last_para = text;
+
+ while (*p)
+ {
+ wc = g_utf8_get_char (p);
+ next = g_utf8_next_char (p);
+ if (wc == (gunichar)-1)
+ {
+ fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ());
+ g_list_foreach (result, (GFunc)g_free, NULL);
+ return NULL;
+ }
+ if (!*p || !wc || wc == '\n')
+ {
+ Paragraph *para = g_new (Paragraph, 1);
+ para->text = last_para;
+ para->length = p - last_para;
+ para->layout = pango_layout_new (context);
+ pango_layout_set_text (para->layout, para->text, para->length);
+ para->height = 0;
+
+ last_para = next;
+
+ result = g_list_prepend (result, para);
+ }
+ if (!wc) /* incomplete character at end */
+ break;
+ p = next;
+ }
+
+ return g_list_reverse (result);
+}
+
+/* Given an x-y position, return the paragraph and offset
+ * within the paragraph of the click.
+ */
+gboolean
+xy_to_cp (int width, int x, int y, Paragraph **para_return, int *index)
+{
+ GList *para_list;
+ int height = 0;
+
+ *para_return = NULL;
+
+ para_list = paragraphs;
+ while (para_list && height < y)
+ {
+ Paragraph *para = para_list->data;
+
+ if (height + para->height >= y)
+ {
+ gboolean result = pango_layout_xy_to_index (para->layout,
+ x * PANGO_SCALE,
+ (y - height) * PANGO_SCALE,
+ index, NULL);
+ if (result && para_return)
+ *para_return = para;
+
+ return result;
+ }
+
+ height += para->height;
+ para_list = para_list->next;
+ }
+
+ return FALSE;
+}
+
+/* Given a paragraph and offset in that paragraph, find the
+ * bounding rectangle for the character at the offset.
+ */
+void
+char_bounds (Paragraph *para, int index, int width, PangoRectangle *rect)
+{
+ GList *para_list;
+
+ int height = 0;
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *cur_para = para_list->data;
+
+ if (cur_para == para)
+ {
+ PangoRectangle pos;
+
+ pango_layout_index_to_pos (cur_para->layout, index, &pos);
+
+ rect->x = PANGO_PIXELS (MIN (pos.x, pos.x + pos.width));
+ rect->width = PANGO_PIXELS (ABS (pos.width));
+ rect->y = height + PANGO_PIXELS (pos.y);
+ rect->height = PANGO_PIXELS (pos.height);
+ }
+
+ height += cur_para->height;
+ para_list = para_list->next;
+ }
+}
+
+/* XOR a rectangle over a given character
+ */
+void
+xor_char (GtkWidget *layout, GdkRectangle *clip_rect,
+ Paragraph *para, int offset)
+{
+ static GdkGC *gc;
+ PangoRectangle rect; /* GdkRectangle in 1.2 is too limited
+ */
+ if (!gc)
+ {
+ GdkGCValues values;
+ values.foreground = layout->style->white.pixel ?
+ layout->style->white : layout->style->black;
+ values.function = GDK_XOR;
+ gc = gdk_gc_new_with_values (GTK_LAYOUT (layout)->bin_window,
+ &values,
+ GDK_GC_FOREGROUND | GDK_GC_FUNCTION);
+ }
+
+ gdk_gc_set_clip_rectangle (gc, clip_rect);
+
+ char_bounds (para, offset, layout->allocation.width, &rect);
+
+ rect.y -= GTK_LAYOUT (layout)->yoffset;
+
+ if ((rect.y + rect.height >= 0) && (rect.y < layout->allocation.height))
+ gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, gc, TRUE,
+ rect.x, rect.y, rect.width, rect.height);
+}
+
+/* Handle a size allocation by re-laying-out each paragraph to
+ * the new width, setting the new size for the layout and
+ * then queing a redraw
+ */
+void
+size_allocate (GtkWidget *layout, GtkAllocation *allocation)
+{
+ GList *tmp_list;
+ guint height = 0;
+ PangoDirection base_dir = pango_context_get_base_dir (context);
+
+ tmp_list = paragraphs;
+ while (tmp_list)
+ {
+ Paragraph *para = tmp_list->data;
+ PangoRectangle logical_rect;
+
+ tmp_list = tmp_list->next;
+
+ pango_layout_set_alignment (para->layout,
+ base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT);
+ pango_layout_set_width (para->layout, layout->allocation.width * PANGO_SCALE);
+
+ pango_layout_get_extents (para->layout, NULL, &logical_rect);
+ para->height = PANGO_PIXELS (logical_rect.height);
+
+ height += para->height;
+ }
+
+ gtk_layout_set_size (GTK_LAYOUT (layout), allocation->width, height);
+
+ if (GTK_LAYOUT (layout)->yoffset + allocation->height > height)
+ gtk_adjustment_set_value (GTK_LAYOUT (layout)->vadjustment, (float)(height - allocation->height));
+}
+
+/* Handle a draw/expose by finding the paragraphs that intersect
+ * the region and reexposing them.
+ */
+void
+draw (GtkWidget *layout, GdkRectangle *area)
+{
+ GList *tmp_list;
+ guint height = 0;
+ HDC hdc;
+ const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND|GDK_GC_FONT;
+
+ gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window,
+ layout->style->base_gc[layout->state],
+ TRUE,
+ area->x, area->y,
+ area->width, area->height);
+
+ gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], area);
+
+ hdc = gdk_win32_hdc_get (GTK_LAYOUT (layout)->bin_window,
+ layout->style->text_gc[GTK_STATE_NORMAL],
+ mask);
+ tmp_list = paragraphs;
+ while (tmp_list &&
+ height < area->y + area->height + GTK_LAYOUT (layout)->yoffset)
+ {
+ Paragraph *para = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (height + para->height >= GTK_LAYOUT (layout)->yoffset + area->y)
+ pango_win32_render_layout (hdc, para->layout,
+ 0, height - GTK_LAYOUT (layout)->yoffset);
+ height += para->height;
+ }
+
+ gdk_win32_hdc_release (GTK_LAYOUT (layout)->bin_window,
+ layout->style->text_gc[GTK_STATE_NORMAL],
+ mask);
+ gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], NULL);
+
+ if (highlight_para)
+ xor_char (layout, area, highlight_para, highlight_offset);
+}
+
+gboolean
+expose (GtkWidget *layout, GdkEventExpose *event)
+{
+ if (event->window == GTK_LAYOUT (layout)->bin_window)
+ draw (layout, &event->area);
+
+ return TRUE;
+}
+
+void
+button_press (GtkWidget *layout, GdkEventButton *event)
+{
+ Paragraph *para = NULL;
+ int offset;
+ gchar *message;
+
+ xy_to_cp (layout->allocation.width,
+ event->x, event->y + GTK_LAYOUT (layout)->yoffset,
+ &para, &offset);
+
+ if (highlight_para)
+ xor_char (layout, NULL, highlight_para, highlight_offset);
+
+ highlight_para = para;
+ highlight_offset = offset;
+
+ if (para)
+ {
+ gunichar wc;
+
+ wc = g_utf8_get_char (para->text + offset);
+ message = g_strdup_printf ("Current char: U%04x", wc);
+
+ xor_char (layout, NULL, highlight_para, highlight_offset);
+ }
+ else
+ message = g_strdup_printf ("Current char:");
+
+ gtk_label_set_text (GTK_LABEL (message_label), message);
+ g_free (message);
+}
+
+static void
+checkbutton_toggled (GtkWidget *widget, gpointer data)
+{
+ GList *para_list;
+
+ pango_context_set_base_dir (context, GTK_TOGGLE_BUTTON (widget)->active ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *para = para_list->data;
+
+ pango_layout_context_changed (para->layout);
+ para_list = para_list->next;
+ }
+
+ gtk_widget_queue_resize (layout);
+}
+
+static void
+reload_font ()
+{
+ GList *para_list;
+
+ pango_context_set_font_description (context, font_description);
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *para = para_list->data;
+
+ pango_layout_context_changed (para->layout);
+ para_list = para_list->next;
+ }
+
+ if (layout)
+ gtk_widget_queue_resize (layout);
+}
+
+void
+set_family (GtkWidget *entry, gpointer data)
+{
+ gchar *family_name = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+ if (!family_name || family_name[0] == '\0')
+ return;
+ pango_font_description_set_family(font_description, family_name);
+ fill_styles_combo (styles_combo);
+}
+
+void
+set_style (GtkWidget *entry, gpointer data)
+{
+ char *str = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+ PangoFontDescription *tmp_desc;
+
+ tmp_desc = pango_font_description_from_string (str);
+
+ pango_font_description_set_style(font_description, pango_font_description_get_style(tmp_desc));
+ pango_font_description_set_variant(font_description, pango_font_description_get_variant(tmp_desc));
+ pango_font_description_set_weight(font_description, pango_font_description_get_weight(tmp_desc));
+ pango_font_description_set_stretch(font_description, pango_font_description_get_stretch(tmp_desc));
+
+ pango_font_description_free (tmp_desc);
+ g_free (str);
+
+ reload_font ();
+}
+
+void
+font_size_changed (GtkAdjustment *adj)
+{
+ pango_font_description_set_size(font_description, (int)(adj->value * PANGO_SCALE + 0.5));
+ reload_font();
+}
+
+static int
+compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
+{
+ int val = strcmp (pango_font_description_get_family(a), pango_font_description_get_family(b));
+ if (val != 0)
+ return val;
+
+ if (pango_font_description_get_weight(a) != pango_font_description_get_weight(b))
+ return pango_font_description_get_weight(a) - pango_font_description_get_weight(b);
+
+ if (pango_font_description_get_style(a) != pango_font_description_get_style(b))
+ return pango_font_description_get_style(a) - pango_font_description_get_style(b);
+
+ if (pango_font_description_get_stretch(a) != pango_font_description_get_stretch(b))
+ return pango_font_description_get_stretch(a) - pango_font_description_get_stretch(b);
+
+ if (pango_font_description_get_stretch(a) != pango_font_description_get_stretch(b))
+ return pango_font_description_get_stretch(a) - pango_font_description_get_stretch(b);
+
+ return 0;
+}
+
+static int
+font_description_sort_func (const void *a, const void *b)
+{
+ return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b);
+}
+
+typedef struct
+{
+ PangoFontDescription **descs;
+ int n_descs;
+} FontDescInfo;
+
+static void
+free_info (FontDescInfo *info)
+{
+ pango_font_descriptions_free (info->descs, info->n_descs);
+}
+
+static void
+fill_styles_combo (GtkWidget *combo)
+{
+ int i;
+ GList *style_list = NULL;
+ PangoFontFace **faces;
+ PangoFontFamily *family, **families;
+ FontDescInfo *info;
+ int n_families;
+ const char *family_name = pango_font_description_get_family(font_description);
+
+ /*
+ * Now map back the given family name to the family. There are more efficient
+ * ways to handle this but it should not matter much ...
+ */
+ pango_context_list_families (context, &families, &n_families);
+ g_assert(n_families > 0);
+ family = families[0]; /* just in case */
+ for (i = 0; i < n_families; i++)
+ {
+ if (0 == g_strcasecmp(pango_font_family_get_name(families[i]), family_name))
+ {
+ family = families[i];
+ break;
+ }
+ }
+ g_free (families);
+
+ info = g_new (FontDescInfo, 1);
+ pango_font_family_list_faces (family, &faces, &info->n_descs);
+
+ info->descs = g_new0 (PangoFontDescription*, info->n_descs);
+ for (i = 0; i < info->n_descs; i++)
+ {
+ info->descs[i] = pango_font_face_describe(faces[i]);
+ }
+ g_free (faces);
+
+ gtk_object_set_data_full (GTK_OBJECT (combo), "descs", info, (GtkDestroyNotify)free_info);
+
+ qsort (info->descs, info->n_descs, sizeof(PangoFontDescription *), font_description_sort_func);
+
+ for (i=0; i<info->n_descs; i++)
+ {
+ char *str;
+
+ PangoFontDescription *tmp_desc;
+
+ tmp_desc = info->descs[i];
+ pango_font_description_set_family(tmp_desc, NULL);
+ pango_font_description_unset_fields(tmp_desc, PANGO_FONT_MASK_SIZE);
+
+ str = pango_font_description_to_string (tmp_desc);
+ style_list = g_list_prepend (style_list, str);
+ }
+
+ style_list = g_list_reverse (style_list);
+
+ gtk_combo_set_popdown_strings (GTK_COMBO (combo), style_list);
+ g_list_foreach (style_list, (GFunc)g_free, NULL);
+}
+
+static GtkWidget *
+make_styles_combo ()
+{
+ GtkWidget *combo;
+
+ combo = gtk_combo_new ();
+ gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE);
+ gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed",
+ GTK_SIGNAL_FUNC (set_style), NULL);
+
+ styles_combo = combo;
+ fill_styles_combo (combo);
+
+ return combo;
+}
+
+static int
+cmp_families (const PangoFontFamily** a, const PangoFontFamily** b)
+{
+ return strcmp (pango_font_family_get_name (*a), pango_font_family_get_name (*b));
+}
+
+GtkWidget *
+make_families_menu ()
+{
+ GtkWidget *combo;
+ int n_families;
+ PangoFontFamily **families;
+ GList *family_list = NULL;
+ int i;
+
+ pango_context_list_families (context, &families, &n_families);
+ qsort (families, n_families, sizeof(char *), cmp_families);
+
+ for (i=0; i<n_families; i++)
+ family_list = g_list_prepend (family_list, pango_font_family_get_name (families[i]));
+
+ family_list = g_list_reverse (family_list);
+
+ combo = gtk_combo_new ();
+ gtk_combo_set_popdown_strings (GTK_COMBO (combo), family_list);
+ gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE);
+ gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE);
+
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), pango_font_description_get_family(font_description));
+
+ gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed",
+ GTK_SIGNAL_FUNC (set_family), NULL);
+
+ g_list_free (family_list);
+
+ return combo;
+}
+
+
+GtkWidget *
+make_font_selector (void)
+{
+ GtkWidget *hbox;
+ GtkWidget *util_hbox;
+ GtkWidget *label;
+ GtkWidget *option_menu;
+ GtkWidget *spin_button;
+ GtkAdjustment *adj;
+
+ hbox = gtk_hbox_new (FALSE, 4);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Family:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ option_menu = make_families_menu ();
+ gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Style:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ option_menu = make_styles_combo ();
+ gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Size:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ spin_button = gtk_spin_button_new (NULL, 1., 0);
+ gtk_box_pack_start (GTK_BOX (util_hbox), spin_button, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin_button));
+ adj->value = PANGO_PIXELS (pango_font_description_get_size(font_description));
+ adj->lower = 0;
+ adj->upper = 1024;
+ adj->step_increment = 1;
+ adj->page_size = 10;
+ gtk_adjustment_changed (adj);
+ gtk_adjustment_value_changed (adj);
+
+ gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
+ GTK_SIGNAL_FUNC (font_size_changed), NULL);
+
+ return hbox;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *text;
+ GtkWidget *window;
+ GtkWidget *scrollwin;
+ GtkWidget *vbox, *hbox;
+ GtkWidget *frame;
+ GtkWidget *checkbutton;
+
+ gtk_init (&argc, &argv);
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage: %s FILE\n", g_get_prgname ());
+ exit(1);
+ }
+
+ /* Create the list of paragraphs from the supplied file
+ */
+ text = read_file (argv[1]);
+ if (!text)
+ exit(1);
+
+ context = pango_win32_get_context ();
+
+ paragraphs = split_paragraphs (text);
+
+ pango_context_set_language (context, pango_language_from_string ("en_US"));
+ pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
+
+ font_description = pango_font_description_new ();
+ pango_font_description_set_family(font_description, "sans");
+ pango_font_description_set_size(font_description, 16 * PANGO_SCALE);
+#if 0 /* default init ok? */
+ font_description.style = PANGO_STYLE_NORMAL;
+ font_description.variant = PANGO_VARIANT_NORMAL;
+ font_description.weight = 500;
+ font_description.stretch = PANGO_STRETCH_NORMAL;
+#endif
+
+ pango_context_set_font_description (context, font_description);
+
+ /* Create the user interface
+ */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+
+ vbox = gtk_vbox_new (FALSE, 4);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ hbox = make_font_selector ();
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+ scrollwin = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ gtk_box_pack_start (GTK_BOX (vbox), scrollwin, TRUE, TRUE, 0);
+
+ layout = gtk_layout_new (NULL, NULL);
+ gtk_widget_set_events (layout, GDK_BUTTON_PRESS_MASK);
+ gtk_widget_set_app_paintable (layout, TRUE);
+
+ gtk_signal_connect (GTK_OBJECT (layout), "size_allocate",
+ GTK_SIGNAL_FUNC (size_allocate), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "expose_event",
+ GTK_SIGNAL_FUNC (expose), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "draw",
+ GTK_SIGNAL_FUNC (draw), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "button_press_event",
+ GTK_SIGNAL_FUNC (button_press), paragraphs);
+#if GTK_CHECK_VERSION (1,3,2)
+ gtk_widget_set_double_buffered (layout, FALSE);
+#endif
+ gtk_container_add (GTK_CONTAINER (scrollwin), layout);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+
+ message_label = gtk_label_new ("Current char:");
+ gtk_misc_set_padding (GTK_MISC (message_label), 1, 1);
+ gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5);
+ gtk_container_add (GTK_CONTAINER (frame), message_label);
+
+ checkbutton = gtk_check_button_new_with_label ("Use RTL global direction");
+ gtk_signal_connect (GTK_OBJECT (checkbutton), "toggled",
+ GTK_SIGNAL_FUNC (checkbutton_toggled), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), checkbutton, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/trunk/pango-view/viewer-x.c b/trunk/pango-view/viewer-x.c
new file mode 100644
index 00000000..95724d86
--- /dev/null
+++ b/trunk/pango-view/viewer-x.c
@@ -0,0 +1,241 @@
+/* viewer-x.c: Common code for X-based viewers
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#include <string.h>
+
+#include "viewer-render.h"
+#include "viewer-x.h"
+
+void
+x_view_init (gpointer instance,
+ const PangoViewer *klass)
+{
+ XViewer *x = (XViewer *)instance;
+
+ x->display = XOpenDisplay (NULL);
+ if (!x->display)
+ fail ("Cannot open display %s\n", XDisplayName (NULL));
+
+ x->screen = DefaultScreen (x->display);
+}
+
+gpointer
+x_view_create (const PangoViewer *klass)
+{
+ XViewer *instance;
+
+ instance = g_slice_new (XViewer);
+
+ x_view_init (instance, klass);
+
+ return instance;
+}
+
+void
+x_view_destroy (gpointer instance)
+{
+ XViewer *x = (XViewer *)instance;
+
+ XCloseDisplay (x->display);
+
+ g_slice_free (XViewer, instance);
+}
+
+gpointer
+x_view_create_surface (gpointer instance,
+ int width,
+ int height)
+{
+ XViewer *x = (XViewer *) instance;
+ Pixmap pixmap;
+
+ pixmap = XCreatePixmap (x->display, DefaultRootWindow (x->display), width, height,
+ DefaultDepth (x->display, x->screen));
+
+ return (gpointer) pixmap;
+}
+
+void
+x_view_destroy_surface (gpointer instance,
+ gpointer surface)
+{
+ XViewer *x = (XViewer *) instance;
+ Pixmap pixmap = (Pixmap) surface;
+
+ XFreePixmap (x->display, pixmap);
+}
+
+static void
+update (Display *display,
+ Pixmap pixmap,
+ Window window,
+ Region *update_region)
+{
+ GC gc;
+ XRectangle extents;
+
+ XClipBox (*update_region, &extents);
+
+ gc = XCreateGC (display, pixmap, 0, NULL);
+
+ XCopyArea (display, pixmap, window, gc,
+ extents.x, extents.y,
+ extents.width, extents.height,
+ extents.x, extents.y);
+
+ XFreeGC (display, gc);
+
+ XDestroyRegion (*update_region);
+ *update_region = NULL;
+}
+
+static void
+expose (XExposeEvent *xev,
+ Region *update_region)
+{
+ XRectangle r;
+
+ if (!*update_region)
+ *update_region = XCreateRegion ();
+
+ r.x = xev->x;
+ r.y = xev->y;
+ r.width = xev->width;
+ r.height = xev->height;
+
+ XUnionRectWithRegion (&r, *update_region, *update_region);
+}
+
+gpointer
+x_view_create_window (gpointer instance,
+ const char *title,
+ int width,
+ int height)
+{
+ XViewer *x = (XViewer *) instance;
+ unsigned long bg;
+ Window window;
+ XSizeHints size_hints;
+
+ bg = WhitePixel (x->display, x->screen);
+ window = XCreateSimpleWindow (x->display, DefaultRootWindow (x->display),
+ 0, 0, width, height, 0,
+ bg, bg);
+
+ XSelectInput (x->display, window, ExposureMask | KeyPressMask);
+
+ XMapWindow (x->display, window);
+ XmbSetWMProperties (x->display, window,
+ title,
+ NULL, NULL, 0, NULL, NULL, NULL);
+
+ memset ((char *)&size_hints, 0, sizeof (XSizeHints));
+ size_hints.flags = PSize | PMaxSize;
+ size_hints.width = width; size_hints.height = height; /* for compat only */
+ size_hints.max_width = width; size_hints.max_height = height;
+
+ XSetWMNormalHints (x->display, window, &size_hints);
+
+ return (gpointer) window;
+}
+
+void
+x_view_destroy_window (gpointer instance,
+ gpointer window)
+{
+ XViewer *x = (XViewer *) instance;
+ Window win = (Window) window;
+
+ XDestroyWindow (x->display, win);
+}
+
+gpointer
+x_view_display (gpointer instance,
+ gpointer surface,
+ gpointer win,
+ int width,
+ int height,
+ gpointer state)
+{
+ XViewer *x = (XViewer *) instance;
+ Pixmap pixmap = (Pixmap) surface;
+ Window window = (Window) win;
+ XEvent xev;
+ XRectangle r;
+ Region update_region;
+ unsigned int quit_keycode;
+ unsigned int borders_keycode;
+ gboolean show_borders = FALSE;
+
+ if (state)
+ show_borders = GPOINTER_TO_UINT (state) == 0xdeadbeef;
+
+ /* force a full redraw */
+ update_region = XCreateRegion ();
+ r.x = 0;
+ r.y = 0;
+ r.width = width;
+ r.height = height;
+ XUnionRectWithRegion (&r, update_region, update_region);
+
+ borders_keycode = XKeysymToKeycode(x->display, 'B');
+ quit_keycode = XKeysymToKeycode(x->display, 'Q');
+
+ while (1)
+ {
+ if (!XPending (x->display) && update_region)
+ update (x->display, pixmap, window, &update_region);
+
+ XNextEvent (x->display, &xev);
+ switch (xev.xany.type) {
+ case KeyPress:
+ if (xev.xkey.keycode == quit_keycode)
+ return NULL;
+ else if (xev.xkey.keycode == borders_keycode)
+ {
+ show_borders = !show_borders;
+ return GUINT_TO_POINTER (show_borders ? 0xdeadbeef : 0xbe);
+ }
+ break;
+ case Expose:
+ expose (&xev.xexpose, &update_region);
+ break;
+ }
+ }
+}
+
+const PangoViewer x_viewer = {
+ "X",
+ NULL,
+ NULL,
+ x_view_create,
+ x_view_destroy,
+ NULL,
+ x_view_create_surface,
+ x_view_destroy_surface,
+ NULL,
+ NULL,
+ x_view_create_window,
+ x_view_destroy_window,
+ x_view_display
+};
+
+const PangoViewer *fallback_viewer = &x_viewer;
diff --git a/trunk/pango-view/viewer-x.h b/trunk/pango-view/viewer-x.h
new file mode 100644
index 00000000..28f61f6b
--- /dev/null
+++ b/trunk/pango-view/viewer-x.h
@@ -0,0 +1,70 @@
+/* viewer-x.h: Common headers for X-based viewers
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef VIEWER_X_H
+#define VIEWER_X_H
+
+#include <pango/pango.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "viewer.h"
+
+
+typedef struct
+{
+ Display *display;
+ int screen;
+} XViewer;
+
+
+extern const PangoViewer x_viewer;
+
+void x_view_init (gpointer instance,
+ const PangoViewer *klass);
+
+gpointer x_view_create (const PangoViewer *klass);
+
+void x_view_destroy (gpointer instance);
+
+gpointer x_view_create_surface (gpointer instance,
+ int width,
+ int height);
+
+void x_view_destroy_surface (gpointer instance,
+ gpointer surface);
+
+gpointer x_view_create_window (gpointer instance,
+ const char *title,
+ int width,
+ int height);
+
+void x_view_destroy_window (gpointer instance,
+ gpointer window);
+
+gpointer x_view_display (gpointer instance,
+ gpointer surface,
+ gpointer window,
+ int width,
+ int height,
+ gpointer state);
+
+#endif /* VIEWER_X_H */
diff --git a/trunk/pango-view/viewer.h b/trunk/pango-view/viewer.h
new file mode 100644
index 00000000..4d1d836a
--- /dev/null
+++ b/trunk/pango-view/viewer.h
@@ -0,0 +1,99 @@
+/* viewer.h: PangoViewer class
+ *
+ * Copyright (C) 1999,2004,2005 Red Hat, Inc.
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef VIEWER_H
+#define VIEWER_H
+
+#include <stdio.h>
+#include <pango/pango.h>
+
+typedef struct _PangoViewer PangoViewer;
+
+struct _PangoViewer {
+
+ const char *name;
+
+ const char *id;
+
+ const char *write_suffix;
+
+ gpointer (*create) (const PangoViewer *klass);
+
+ void (*destroy) (gpointer instance);
+
+ PangoContext * (*get_context) (gpointer instance);
+
+ gpointer (*create_surface) (gpointer instance,
+ int width,
+ int height);
+
+ void (*destroy_surface) (gpointer instance,
+ gpointer surface);
+
+ void (*render) (gpointer instance,
+ gpointer surface,
+ PangoContext *context,
+ int width,
+ int height,
+ gpointer state);
+
+ /* The following can be NULL */
+
+ void (*write) (gpointer instance,
+ gpointer surface,
+ FILE *stream,
+ int width,
+ int height);
+
+ gpointer (*create_window) (gpointer instance,
+ const char *title,
+ int width,
+ int height);
+
+ void (*destroy_window) (gpointer instance,
+ gpointer window);
+
+ gpointer (*display) (gpointer instance,
+ gpointer surface,
+ gpointer window,
+ int width,
+ int height,
+ gpointer state);
+
+ void (*load) (gpointer instance,
+ gpointer surface,
+ guchar *buffer,
+ int width,
+ int height,
+ int stride);
+
+ void (*save) (gpointer instance,
+ gpointer surface,
+ guchar *buffer,
+ int width,
+ int height,
+ int stride);
+
+};
+
+extern const PangoViewer *fallback_viewer;
+extern const PangoViewer *viewers[];
+
+#endif /* VIEWER_H */
diff --git a/trunk/pango-zip.sh.in b/trunk/pango-zip.sh.in
new file mode 100755
index 00000000..504d6a38
--- /dev/null
+++ b/trunk/pango-zip.sh.in
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+# Build zipfiles for Pango on Win32: separate runtime and developer packages
+
+ZIP=/tmp/pango-@PANGO_VERSION@.zip
+DEVZIP=/tmp/pango-dev-@PANGO_VERSION@.zip
+cd @prefix@
+
+mkdir -p share/doc/pango-@PANGO_VERSION@
+cp -p @abs_srcdir@/COPYING share/doc/pango-@PANGO_VERSION@
+
+mkdir -p share/doc/pango-dev-@PANGO_VERSION@
+cp -p @abs_srcdir@/COPYING share/doc/pango-dev-@PANGO_VERSION@
+
+rm $ZIP
+zip $ZIP -@ <<EOF
+bin/pango-querymodules.exe
+etc/pango/pango.aliases
+etc/pango/pango.modules
+bin/libpango-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@.dll
+bin/libpangoft2-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@.dll
+bin/libpangowin32-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@.dll
+bin/libpangocairo-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@.dll
+EOF
+
+zip $ZIP lib/pango/@PANGO_MODULE_VERSION@/modules/*.dll
+
+zip -r $ZIP share/doc/pango-@PANGO_VERSION@
+
+rm $DEVZIP
+zip -r $DEVZIP -@ <<EOF
+include/pango-1.0
+lib/libpango-@PANGO_API_VERSION@.dll.a
+lib/pango-@PANGO_API_VERSION@.lib
+lib/pango-@PANGO_API_VERSION@.def
+lib/libpangoft2-@PANGO_API_VERSION@.dll.a
+lib/pangoft2-@PANGO_API_VERSION@.lib
+lib/pangoft2-@PANGO_API_VERSION@.def
+lib/libpangowin32-@PANGO_API_VERSION@.dll.a
+lib/pangowin32-@PANGO_API_VERSION@.lib
+lib/pangowin32-@PANGO_API_VERSION@.def
+lib/libpangocairo-@PANGO_API_VERSION@.dll.a
+lib/pangocairo-@PANGO_API_VERSION@.lib
+lib/pangocairo-@PANGO_API_VERSION@.def
+lib/pkgconfig/pango.pc
+lib/pkgconfig/pangoft2.pc
+lib/pkgconfig/pangowin32.pc
+lib/pkgconfig/pangocairo.pc
+share/gtk-doc/html/pango
+EOF
+
+zip -r $DEVZIP share/doc/pango-dev-@PANGO_VERSION@
diff --git a/trunk/pango.pc.in b/trunk/pango.pc.in
new file mode 100644
index 00000000..64d77aa8
--- /dev/null
+++ b/trunk/pango.pc.in
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+pango_module_version=@PANGO_MODULE_VERSION@
+
+Name: Pango
+Description: Internationalized text handling
+Version: @VERSION@
+Requires: glib-2.0,gobject-2.0,gmodule-no-export-2.0
+Libs: -L${libdir} -lpango-@PANGO_API_VERSION@ @PKGCONFIG_MATH_LIBS@
+Cflags: -I${includedir}/pango-1.0
+
diff --git a/trunk/pango/Makefile.am b/trunk/pango/Makefile.am
new file mode 100644
index 00000000..8f73ebd7
--- /dev/null
+++ b/trunk/pango/Makefile.am
@@ -0,0 +1,501 @@
+## Process this file with automake to create Makefile.in.
+
+# We set GPATH here; this gives us semantics for GNU make
+# which are more like other make's VPATH.
+GPATH = $(srcdir)
+
+if HAVE_FREETYPE
+OPENTYPE_SUBDIR=opentype
+endif
+
+FRIBIDI_SUBDIR=mini-fribidi
+
+SUBDIRS = $(OPENTYPE_SUBDIR) $(FRIBIDI_SUBDIR)
+
+DIST_SUBDIRS = mini-fribidi opentype
+
+INCLUDES = \
+ -DG_LOG_DOMAIN=\"Pango\" \
+ -DPANGO_ENABLE_BACKEND \
+ -DPANGO_ENABLE_ENGINE \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBDIR=\"$(libdir)\" \
+ -I$(top_srcdir) \
+ $(PANGO_DEBUG_FLAGS) \
+ $(GLIB_CFLAGS) \
+ $(XFT_CFLAGS) \
+ $(CAIRO_CFLAGS) \
+ $(FREETYPE_CFLAGS) \
+ $(X_CFLAGS)
+
+BUILT_SOURCES = pango-enum-types.h pango-enum-types.c pango-features.h
+
+pangoincludedir=$(includedir)/pango-1.0/pango
+
+if OS_WIN32
+else
+libm = -lm
+endif
+
+# ------------------- libpango -------------------
+
+lib_LTLIBRARIES = libpango-1.0.la
+
+libpango_1_0_la_LDFLAGS = $(LIBRARY_LIBTOOL_OPTIONS)
+libpango_1_0_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(libm) \
+ $(INCLUDED_LANG_MODULES)
+libpango_1_0_la_DEPENDENCIES = \
+ $(INCLUDED_LANG_MODULES)
+
+libpango_1_0_la_LIBADD += mini-fribidi/libmini-fribidi.la
+libpango_1_0_la_DEPENDENCIES += mini-fribidi/libmini-fribidi.la
+
+if OS_WIN32
+libpango_1_0_la_LDFLAGS += -export-symbols $(srcdir)/pango.def -Wl,pango-win32-res.o
+libpango_1_0_la_DEPENDENCIES += pango-win32-res.o pango.def
+endif
+pango-win32-res.o: pango.rc
+ $(WINDRES) $< $@
+
+libpango_1_0_la_SOURCES = \
+ break.c \
+ ellipsize.c \
+ fonts.c \
+ glyphstring.c \
+ mapping.c \
+ modules.c \
+ pango-attributes.c \
+ pango-color.c \
+ pango-color-table.h \
+ pango-context.c \
+ pango-coverage.c \
+ pango-engine.c \
+ pango-engine-private.h \
+ pango-fontmap.c \
+ pango-fontset.c \
+ pango-glyph-item.c \
+ pango-glyph-item-private.h \
+ pango-gravity.c \
+ pango-impl-utils.h \
+ pango-item.c \
+ pango-language.c \
+ pango-layout.c \
+ pango-layout-private.h \
+ pango-markup.c \
+ pango-matrix.c \
+ pango-renderer.c \
+ pango-script.c \
+ pango-script-lang-table.h \
+ pango-script-table.h \
+ pango-tabs.c \
+ pango-utils.c \
+ reorder-items.c \
+ shape.c \
+ pango-enum-types.c \
+ module-defs-lang.c
+
+pango_headers = \
+ pango.h \
+ pango-attributes.h \
+ pango-break.h \
+ pango-context.h \
+ pango-coverage.h \
+ pango-engine.h \
+ pango-font.h \
+ pango-fontmap.h \
+ pango-fontset.h \
+ pango-glyph.h \
+ pango-glyph-item.h \
+ pango-gravity.h \
+ pango-item.h \
+ pango-language.h \
+ pango-layout.h \
+ pango-matrix.h \
+ pango-modules.h \
+ pango-renderer.h \
+ pango-script.h \
+ pango-tabs.h \
+ pango-types.h \
+ pango-utils.h
+
+pangoinclude_HEADERS = \
+ $(pango_headers) \
+ pango-features.h \
+ pango-enum-types.h
+
+pango-enum-types.h: s-enum-types-h
+ @true
+s-enum-types-h: @REBUILD@ $(pango_headers) Makefile
+ ( cd $(srcdir) && glib-mkenums \
+ --fhead "#ifndef __PANGO_ENUM_TYPES_H__\n#define __PANGO_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@filename@\" */\n" \
+ --vhead "GType @enum_name@_get_type (void);\n#define PANGO_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
+ --ftail "G_END_DECLS\n\n#endif /* __PANGO_ENUM_TYPES_H__ */" \
+ $(pango_headers) ) > tmp-pango-enum-types.h \
+ && (cmp -s tmp-pango-enum-types.h pango-enum-types.h || cp tmp-pango-enum-types.h pango-enum-types.h ) \
+ && rm -f tmp-pango-enum-types.h \
+ && echo timestamp > $(@F)
+
+pango-enum-types.c: s-enum-types-c
+ @true
+s-enum-types-c: @REBUILD@ $(pango_headers) Makefile
+ ( cd $(srcdir) && glib-mkenums \
+ --fhead "#include <pango.h>" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (g_intern_static_string (\"@EnumName@\"), values);\n }\n return etype;\n}\n" \
+ $(pango_headers) ) > tmp-pango-enum-types.c \
+ && (cmp -s tmp-pango-enum-types.c pango-enum-types.c || cp tmp-pango-enum-types.c pango-enum-types.c ) \
+ && rm -f tmp-pango-enum-types.c \
+ && echo timestamp > $(@F)
+
+pango-features.h:
+ cd $(top_builddir) && ./config.status pango/pango-features.h
+
+# ------------------- libpangox -------------------
+
+if HAVE_X
+pangoinclude_HEADERS += pangox.h
+lib_LTLIBRARIES += libpangox-1.0.la
+aliasdir = $(sysconfdir)/pango
+alias_DATA = pangox.aliases
+endif
+
+libpangox_1_0_la_LDFLAGS = $(LIBRARY_LIBTOOL_OPTIONS)
+libpangox_1_0_la_LIBADD = \
+ libpango-$(PANGO_API_VERSION).la \
+ $(INCLUDED_X_MODULES) \
+ $(GLIB_LIBS) \
+ $(X_LIBS) \
+ $(X_EXTRA_LIBS)
+libpangox_1_0_la_DEPENDENCIES = \
+ libpango-$(PANGO_API_VERSION).la \
+ $(INCLUDED_X_MODULES)
+libpangox_1_0_la_SOURCES = \
+ modules.h \
+ module-defs-x.c \
+ pangox.c \
+ pangox-private.h \
+ pangox-fontcache.c \
+ pangox-fontmap.c
+
+
+# ------------------- libpangoft2 -------------------
+
+if HAVE_FREETYPE
+pangoinclude_HEADERS += pangofc-font.h pangofc-fontmap.h
+pangoinclude_HEADERS += pangoft2.h pango-ot.h pangofc-decoder.h
+lib_LTLIBRARIES += libpangoft2-1.0.la
+endif
+
+libpangoft2_1_0_la_LDFLAGS = $(LIBRARY_LIBTOOL_OPTIONS)
+libpangoft2_1_0_la_LIBADD = \
+ opentype/libharfbuzz-1.la \
+ libpango-$(PANGO_API_VERSION).la \
+ $(INCLUDED_FC_MODULES) \
+ $(GLIB_LIBS) \
+ $(FREETYPE_LIBS) \
+ $(libm)
+libpangoft2_1_0_la_DEPENDENCIES = \
+ opentype/libharfbuzz-1.la \
+ libpango-$(PANGO_API_VERSION).la \
+ $(INCLUDED_FC_MODULES)
+libpangoft2_1_0_la_SOURCES = \
+ modules.h \
+ module-defs-fc.c \
+ pangofc-font.c \
+ pangofc-fontmap.c \
+ pangofc-decoder.c \
+ pangofc-private.h \
+ pangoft2.h \
+ pangoft2.c \
+ pangoft2-private.h \
+ pangoft2-fontmap.c \
+ pangoft2-render.c \
+ pango-ot-private.h \
+ pango-ot-buffer.c \
+ pango-ot-info.c \
+ pango-ot-ruleset.c \
+ pango-ot-tag.c
+
+
+if OS_WIN32
+libpangoft2_1_0_la_LDFLAGS += -export-symbols $(srcdir)/pangoft2.def -Wl,pangoft2-win32-res.o
+libpangoft2_1_0_la_DEPENDENCIES += pangoft2-win32-res.o pangoft2.def
+endif
+pangoft2-win32-res.o: pangoft2.rc
+ $(WINDRES) $< $@
+
+
+# ------------------- libpangoxft -------------------
+
+if HAVE_XFT
+pangoinclude_HEADERS += pangoxft.h pangoxft-render.h pango-ot.h
+lib_LTLIBRARIES += libpangoxft-1.0.la
+endif
+
+libpangoxft_1_0_la_LDFLAGS = $(LIBRARY_LIBTOOL_OPTIONS)
+libpangoxft_1_0_la_LIBADD = \
+ libpangoft2-$(PANGO_API_VERSION).la \
+ libpango-$(PANGO_API_VERSION).la \
+ $(GLIB_LIBS) \
+ $(X_LIBS) \
+ $(XFT_LIBS) \
+ $(libm)
+libpangoxft_1_0_la_DEPENDENCIES = \
+ libpangoft2-$(PANGO_API_VERSION).la \
+ libpango-$(PANGO_API_VERSION).la
+libpangoxft_1_0_la_SOURCES = \
+ pangoxft-font.c \
+ pangoxft-fontmap.c \
+ pangoxft-private.h \
+ pangoxft-render.c
+
+
+# ------------------- libpangocairo -------------------
+
+if HAVE_CAIRO
+pangoinclude_HEADERS += pangocairo.h
+lib_LTLIBRARIES += libpangocairo-1.0.la
+endif
+
+libpangocairo_1_0_la_LDFLAGS = $(LIBRARY_LIBTOOL_OPTIONS)
+libpangocairo_1_0_la_LIBADD = \
+ libpango-$(PANGO_API_VERSION).la \
+ $(GLIB_LIBS) \
+ $(CAIRO_LIBS) \
+ $(libm)
+libpangocairo_1_0_la_DEPENDENCIES = \
+ libpango-$(PANGO_API_VERSION).la
+libpangocairo_1_0_la_SOURCES = \
+ pangocairo-context.c \
+ pangocairo-font.c \
+ pangocairo-fontmap.c \
+ pangocairo-render.c \
+ pangocairo-private.h
+
+if HAVE_CAIRO_WIN32
+if OS_WIN32
+libpangocairo_1_0_la_LDFLAGS += -export-symbols $(srcdir)/pangocairo.def
+libpangocairo_1_0_la_DEPENDENCIES += pangocairo.def
+endif
+
+libpangocairo_1_0_la_LIBADD += libpangowin32-$(PANGO_API_VERSION).la $(WIN32_LIBS)
+libpangocairo_1_0_la_DEPENDENCIES += libpangowin32-$(PANGO_API_VERSION).la
+
+libpangocairo_1_0_la_SOURCES += pangocairo-win32font.c pangocairo-win32fontmap.c pangocairo-win32.h
+endif
+
+if HAVE_CAIRO_FREETYPE
+libpangocairo_1_0_la_LIBADD += libpangoft2-$(PANGO_API_VERSION).la $(FREETYPE_LIBS)
+libpangocairo_1_0_la_DEPENDENCIES += libpangoft2-$(PANGO_API_VERSION).la
+
+libpangocairo_1_0_la_SOURCES += \
+ pangocairo-fcfont.c \
+ pangocairo-fcfontmap.c \
+ pangocairo-fc.h
+endif
+
+if HAVE_CAIRO_ATSUI
+libpangocairo_1_0_la_SOURCES += \
+ modules.h \
+ module-defs-atsui.c \
+ pangoatsui.h \
+ pangoatsui.c \
+ pangoatsui-private.h \
+ pangoatsui-fontmap.c \
+ pangocairo-atsui.h \
+ pangocairo-atsuifont.c \
+ pangocairo-atsuifont.h \
+ pangocairo-atsuifontmap.c
+pangoinclude_HEADERS += pangoatsui.h
+
+libpangocairo_1_0_la_CFLAGS = -xobjective-c
+libpangocairo_1_0_la_LDFLAGS += -framework CoreFoundation -framework Carbon -framework Cocoa
+endif
+
+# ------------------- libpangowin32 -------------------
+
+if HAVE_WIN32
+pangoinclude_HEADERS += pangowin32.h
+lib_LTLIBRARIES += libpangowin32-1.0.la
+endif
+
+libpangowin32_1_0_la_LDFLAGS = $(LIBRARY_LIBTOOL_OPTIONS)
+libpangowin32_1_0_la_LIBADD = \
+ libpango-$(PANGO_API_VERSION).la \
+ $(INCLUDED_WIN32_MODULES) \
+ $(GLIB_LIBS) \
+ $(WIN32_LIBS)
+libpangowin32_1_0_la_DEPENDENCIES = \
+ libpango-$(PANGO_API_VERSION).la \
+ $(INCLUDED_WIN32_MODULES)
+libpangowin32_1_0_la_SOURCES = \
+ modules.h \
+ module-defs-win32.c \
+ pangowin32.h \
+ pangowin32.c \
+ pangowin32-private.h \
+ pangowin32-fontcache.c \
+ pangowin32-fontmap.c
+
+if OS_WIN32
+libpangowin32_1_0_la_LDFLAGS += -export-symbols $(srcdir)/pangowin32.def -Wl,pangowin32-win32-res.o
+libpangowin32_1_0_la_DEPENDENCIES += pangowin32-win32-res.o pangowin32.def
+endif
+pangowin32-win32-res.o: pangowin32.rc
+ $(WINDRES) $< $@
+
+
+# ------------------- win32 build stuff -------------------
+
+if OS_WIN32
+install-def-files:
+ $(INSTALL) $(srcdir)/pango.def $(DESTDIR)$(libdir)/pango-$(PANGO_API_VERSION).def
+if HAVE_FREETYPE
+ $(INSTALL) $(srcdir)/pangoft2.def $(DESTDIR)$(libdir)/pangoft2-$(PANGO_API_VERSION).def
+endif
+ $(INSTALL) $(srcdir)/pangowin32.def $(DESTDIR)$(libdir)/pangowin32-$(PANGO_API_VERSION).def
+ $(INSTALL) $(srcdir)/pangocairo.def $(DESTDIR)$(libdir)/pangocairo-$(PANGO_API_VERSION).def
+uninstall-def-files:
+ -rm $(DESTDIR)$(libdir)/pango$(PANGO_API_VERSION).def
+if HAVE_FREETYPE
+ -rm $(DESTDIR)$(libdir)/pangoft2-$(PANGO_API_VERSION).def
+endif
+ -rm $(DESTDIR)$(libdir)/pangowin32-$(PANGO_API_VERSION).def
+ -rm $(DESTDIR)$(libdir)/pangocairo-$(PANGO_API_VERSION).def
+else
+install-def-files:
+uninstall-def-files:
+
+endif
+
+if MS_LIB_AVAILABLE
+noinst_DATA = pango-$(PANGO_API_VERSION).lib pangoft2-$(PANGO_API_VERSION).lib pangowin32-$(PANGO_API_VERSION).lib pangocairo-$(PANGO_API_VERSION).lib
+
+install-ms-lib: pango-$(PANGO_API_VERSION).lib pangoft2-$(PANGO_API_VERSION).lib pangowin32-$(PANGO_API_VERSION).lib pangocairo-$(PANGO_API_VERSION).lib
+ $(INSTALL) pango-$(PANGO_API_VERSION).lib $(DESTDIR)$(libdir)
+if HAVE_FREETYPE
+ $(INSTALL) pangoft2-$(PANGO_API_VERSION).lib $(DESTDIR)$(libdir)
+endif
+ $(INSTALL) pangowin32-$(PANGO_API_VERSION).lib $(DESTDIR)$(libdir)
+ $(INSTALL) pangocairo-$(PANGO_API_VERSION).lib $(DESTDIR)$(libdir)
+
+uninstall-ms-lib:
+ -rm $(DESTDIR)$(libdir)/pango-$(PANGO_API_VERSION).lib
+ -rm $(DESTDIR)$(libdir)/pangoft2-$(PANGO_API_VERSION).lib
+ -rm $(DESTDIR)$(libdir)/pangowin32-$(PANGO_API_VERSION).lib
+ -rm $(DESTDIR)$(libdir)/pangocairo-$(PANGO_API_VERSION).lib
+else
+install-ms-lib:
+uninstall-ms-lib:
+endif
+
+pango-$(PANGO_API_VERSION).lib: libpango-$(PANGO_API_VERSION).la $(srcdir)/pango.def
+ lib -name:libpango-$(PANGO_API_VERSION)-$(PANGO_CURRENT_MINUS_AGE).dll -def:$(srcdir)/pango.def -out:$@
+
+pangoft2-$(PANGO_API_VERSION).lib: libpangoft2-$(PANGO_API_VERSION).la $(srcdir)/pangoft2.def
+ lib -name:libpangoft2-$(PANGO_API_VERSION)-$(PANGO_CURRENT_MINUS_AGE).dll -def:$(srcdir)/pangoft2.def -out:$@
+
+pangowin32-$(PANGO_API_VERSION).lib: libpangowin32-$(PANGO_API_VERSION).la $(srcdir)/pangowin32.def
+ lib -name:libpangowin32-$(PANGO_API_VERSION)-$(PANGO_CURRENT_MINUS_AGE).dll -def:$(srcdir)/pangowin32.def -out:$@
+
+pangocairo-$(PANGO_API_VERSION).lib: libpangocairo-$(PANGO_API_VERSION).la $(srcdir)/pangocairo.def
+ lib -name:libpangocairo-$(PANGO_API_VERSION)-$(PANGO_CURRENT_MINUS_AGE).dll -def:$(srcdir)/pangocairo.def -out:$@
+
+
+# ------------------- pango-querymodules -------------------
+
+bin_PROGRAMS = pango-querymodules
+
+#
+# As a temporary hack, we pull in libpangox here so that we can link
+#
+pango_querymodules_SOURCES = \
+ querymodules.c
+
+pango_querymodules_LDADD =
+if HAVE_X
+pango_querymodules_LDADD += libpangox-$(PANGO_API_VERSION).la
+endif
+if HAVE_XFT
+pango_querymodules_LDADD += libpangoxft-$(PANGO_API_VERSION).la
+endif
+if HAVE_FREETYPE
+pango_querymodules_LDADD += libpangoft2-$(PANGO_API_VERSION).la
+endif
+if HAVE_WIN32
+pango_querymodules_LDADD += libpangowin32-$(PANGO_API_VERSION).la
+endif
+pango_querymodules_LDADD += libpango-$(PANGO_API_VERSION).la $(GLIB_LIBS)
+
+EXTRA_DIST = \
+ pango-enum-types.h \
+ module-defs.h \
+ module-defs-fc.c.win32 \
+ module-defs-win32.c.win32 \
+ pango.def \
+ pangocairo.def \
+ pangowin32.def \
+ pangoft2.def \
+ makefile.msc \
+ pango.rc \
+ pango.rc.in \
+ pangox.aliases \
+ pangoft2.rc \
+ pangoft2.rc.in \
+ pangowin32.rc \
+ pangowin32.rc.in \
+ check.defs
+
+
+if HAVE_INCLUDED_MODULES
+included-modules:
+ @cd $(top_builddir)/modules && $(MAKE) $(AM_MAKEFLAGS) included-modules
+
+$(INCLUDED_LANG_MODULES) $(INCLUDED_X_MODULES) $(INCLUDED_FC_MODULES) $(INCLUDED_WIN32_MODULES) $(INCLUDED_ATSUI_MODULES): included-modules
+ @true
+
+.PHONY: included-modules
+endif
+
+MODULE_DEF_FILES = \
+ module-defs.h \
+ module-defs-lang.c \
+ module-defs-x.c \
+ module-defs-fc.c \
+ module-defs-win32.c \
+ module-defs-atsui.c
+
+$(MODULE_DEF_FILES): $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status pango/$@
+
+CLEANFILES = \
+ pango-enum-types.h \
+ s-enum-types-h \
+ pango-enum-types.c \
+ s-enum-types-c
+
+MOSTLYCLEANFILES = \
+ *.def.list \
+ *.def.expected
+
+DISTCLEANFILES = \
+ pango-features.h \
+ $(MODULE_DEF_FILES)
+
+install-data-local: install-ms-lib install-def-files
+
+install-exec-hook:
+if DISABLE_EXPLICIT_DEPS
+ -for i in libpangoft2-$(PANGO_API_VERSION).la libpangoxft-$(PANGO_API_VERSION).la libpangox-$(PANGO_API_VERSION).la libpangowin32-$(PANGO_API_VERSION).la; do \
+ test -f $(DESTDIR)$(libdir)/$$i && $(SHELL) $(top_srcdir)/sanitize-la.sh $(DESTDIR)$(libdir)/$$i ; \
+ done
+endif
+
+uninstall-local: uninstall-ms-lib uninstall-def-files
+
+TESTS = check.defs
diff --git a/trunk/pango/break.c b/trunk/pango/break.c
new file mode 100644
index 00000000..091d2541
--- /dev/null
+++ b/trunk/pango/break.c
@@ -0,0 +1,1738 @@
+/* Pango
+ * break.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-break.h"
+#include "pango-modules.h"
+#include <string.h>
+
+#define PARAGRAPH_SEPARATOR 0x2029
+#define PARAGRAPH_SEPARATOR_STRING "\xE2\x80\xA9"
+
+/* See http://www.unicode.org/unicode/reports/tr14/ if you hope
+ * to understand the line breaking code.
+ */
+
+typedef enum
+{
+ BREAK_ALREADY_HANDLED, /* didn't use the table */
+ BREAK_PROHIBITED, /* no break, even if spaces intervene */
+ BREAK_IF_SPACES, /* "indirect break" (only if there are spaces) */
+ BREAK_ALLOWED /* "direct break" (can always break here) */
+ /* TR 14 has one more break-opportunity class,
+ * "indirect break opportunity for combining marks following a space"
+ * but we handle that inline in the code.
+ */
+} BreakOpportunity;
+
+
+enum
+{
+ INDEX_OPEN_PUNCTUATION,
+ INDEX_CLOSE_PUNCTUATION,
+ INDEX_QUOTATION,
+ INDEX_NON_BREAKING_GLUE,
+ INDEX_NON_STARTER,
+ INDEX_EXCLAMATION,
+ INDEX_SYMBOL,
+ INDEX_INFIX_SEPARATOR,
+ INDEX_PREFIX,
+ INDEX_POSTFIX,
+ INDEX_NUMERIC,
+ INDEX_ALPHABETIC,
+ INDEX_IDEOGRAPHIC,
+ INDEX_INSEPARABLE,
+ INDEX_HYPHEN,
+ INDEX_AFTER,
+ INDEX_BEFORE,
+ INDEX_BEFORE_AND_AFTER,
+ INDEX_ZERO_WIDTH_SPACE,
+ INDEX_COMBINING_MARK,
+ INDEX_WORD_JOINER,
+
+ /* End of the table */
+
+ INDEX_END_OF_TABLE,
+
+ /* The following are not in the tables */
+ INDEX_MANDATORY,
+ INDEX_CARRIAGE_RETURN,
+ INDEX_LINE_FEED,
+ INDEX_SURROGATE,
+ INDEX_CONTINGENT,
+ INDEX_SPACE,
+ INDEX_COMPLEX_CONTEXT,
+ INDEX_AMBIGUOUS,
+ INDEX_UNKNOWN,
+ INDEX_NEXT_LINE,
+ INDEX_HANGUL_L_JAMO,
+ INDEX_HANGUL_V_JAMO,
+ INDEX_HANGUL_T_JAMO,
+ INDEX_HANGUL_LV_SYLLABLE,
+ INDEX_HANGUL_LVT_SYLLABLE,
+};
+
+static const BreakOpportunity row_OPEN_PUNCTUATION[INDEX_END_OF_TABLE] = {
+ BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_CLOSE_PUNCTUATION[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_QUOTATION[INDEX_END_OF_TABLE] = {
+ BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_NON_BREAKING_GLUE[INDEX_END_OF_TABLE] = {
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_NON_STARTER[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_EXCLAMATION[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_SYMBOL[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_INFIX_SEPARATOR[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_PREFIX[INDEX_END_OF_TABLE] = {
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_POSTFIX[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_NUMERIC[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_ALPHABETIC[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_IDEOGRAPHIC[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_INSEPARABLE[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_HYPHEN[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_AFTER[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_BEFORE[INDEX_END_OF_TABLE] = {
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_BEFORE_AND_AFTER[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_ZERO_WIDTH_SPACE[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED, BREAK_ALLOWED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED
+};
+
+static const BreakOpportunity row_COMBINING_MARK[INDEX_END_OF_TABLE] = {
+ BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_ALLOWED, BREAK_ALLOWED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity row_WORD_JOINER[INDEX_END_OF_TABLE] = {
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_IF_SPACES,
+ BREAK_IF_SPACES, BREAK_IF_SPACES, BREAK_PROHIBITED, BREAK_PROHIBITED,
+ BREAK_PROHIBITED
+};
+
+static const BreakOpportunity *const line_break_rows[INDEX_END_OF_TABLE] = {
+ row_OPEN_PUNCTUATION, /* INDEX_OPEN_PUNCTUATION */
+ row_CLOSE_PUNCTUATION, /* INDEX_CLOSE_PUNCTUATION */
+ row_QUOTATION, /* INDEX_QUOTATION */
+ row_NON_BREAKING_GLUE, /* INDEX_NON_BREAKING_GLUE */
+ row_NON_STARTER, /* INDEX_NON_STARTER */
+ row_EXCLAMATION, /* INDEX_EXCLAMATION */
+ row_SYMBOL, /* INDEX_SYMBOL */
+ row_INFIX_SEPARATOR, /* INDEX_INFIX_SEPARATOR */
+ row_PREFIX, /* INDEX_PREFIX */
+ row_POSTFIX, /* INDEX_POSTFIX */
+ row_NUMERIC, /* INDEX_NUMERIC */
+ row_ALPHABETIC, /* INDEX_ALPHABETIC */
+ row_IDEOGRAPHIC, /* INDEX_IDEOGRAPHIC */
+ row_INSEPARABLE, /* INDEX_INSEPARABLE */
+ row_HYPHEN, /* INDEX_HYPHEN */
+ row_AFTER, /* INDEX_AFTER */
+ row_BEFORE, /* INDEX_BEFORE */
+ row_BEFORE_AND_AFTER, /* INDEX_BEFORE_AND_AFTER */
+ row_ZERO_WIDTH_SPACE, /* INDEX_ZERO_WIDTH_SPACE */
+ row_COMBINING_MARK, /* INDEX_COMBINING_MARK */
+ row_WORD_JOINER /* INDEX_WORD_JOINER */
+};
+
+/* Map GUnicodeBreakType to table indexes */
+static const int line_break_indexes[] = {
+ INDEX_MANDATORY,
+ INDEX_CARRIAGE_RETURN,
+ INDEX_LINE_FEED,
+ INDEX_COMBINING_MARK,
+ INDEX_SURROGATE,
+ INDEX_ZERO_WIDTH_SPACE,
+ INDEX_INSEPARABLE,
+ INDEX_NON_BREAKING_GLUE,
+ INDEX_CONTINGENT,
+ INDEX_SPACE,
+ INDEX_AFTER,
+ INDEX_BEFORE,
+ INDEX_BEFORE_AND_AFTER,
+ INDEX_HYPHEN,
+ INDEX_NON_STARTER,
+ INDEX_OPEN_PUNCTUATION,
+ INDEX_CLOSE_PUNCTUATION,
+ INDEX_QUOTATION,
+ INDEX_EXCLAMATION,
+ INDEX_IDEOGRAPHIC,
+ INDEX_NUMERIC,
+ INDEX_INFIX_SEPARATOR,
+ INDEX_SYMBOL,
+ INDEX_ALPHABETIC,
+ INDEX_PREFIX,
+ INDEX_POSTFIX,
+ INDEX_COMPLEX_CONTEXT,
+ INDEX_AMBIGUOUS,
+ INDEX_UNKNOWN,
+ INDEX_NEXT_LINE,
+ INDEX_WORD_JOINER,
+ INDEX_HANGUL_L_JAMO,
+ INDEX_HANGUL_V_JAMO,
+ INDEX_HANGUL_T_JAMO,
+ INDEX_HANGUL_LV_SYLLABLE,
+ INDEX_HANGUL_LVT_SYLLABLE
+};
+
+#define BREAK_TYPE_SAFE(btype) \
+ (btype < G_N_ELEMENTS(line_break_indexes) ? btype : G_UNICODE_BREAK_UNKNOWN)
+#define BREAK_INDEX(btype) \
+ (line_break_indexes[(btype)])
+#define BREAK_ROW(before_type) \
+ (line_break_rows[BREAK_INDEX (before_type)])
+#define BREAK_OP(before_type, after_type) \
+ (BREAK_ROW (before_type)[BREAK_INDEX (after_type)])
+#define IN_BREAK_TABLE(btype) \
+ (btype < G_N_ELEMENTS(line_break_indexes) && BREAK_INDEX(btype) < INDEX_END_OF_TABLE)
+
+
+
+/*
+ * Hangul Conjoining Jamo handling.
+ *
+ * The way we implement it is just a bit different from TR14,
+ * but produces the same results.
+ * The same algorithm is also used in TR29 for cluster boundaries.
+ *
+ */
+
+
+/* An enum that works as the states of the Hangul syllables system.
+ **/
+typedef enum
+{
+ JAMO_L, /* G_UNICODE_BREAK_HANGUL_L_JAMO */
+ JAMO_V, /* G_UNICODE_BREAK_HANGUL_V_JAMO */
+ JAMO_T, /* G_UNICODE_BREAK_HANGUL_T_JAMO */
+ JAMO_LV, /* G_UNICODE_BREAK_HANGUL_LV_SYLLABLE */
+ JAMO_LVT, /* G_UNICODE_BREAK_HANGUL_LVT_SYLLABLE */
+ NO_JAMO /* Other */
+} JamoType;
+
+/* There are Hangul syllables encoded as characters, that act like a
+ * sequence of Jamos. For each character we define a JamoType
+ * that the character starts with, and one that it ends with. This
+ * decomposes JAMO_LV and JAMO_LVT to simple other JAMOs. So for
+ * example, a character with LineBreak type
+ * G_UNICODE_BREAK_HANGUL_LV_SYLLABLE has start=JAMO_L and end=JAMO_V.
+ */
+typedef struct _CharJamoProps
+{
+ JamoType start, end;
+} CharJamoProps;
+
+/* Map from JamoType to CharJamoProps that hold only simple
+ * JamoTypes (no LV or LVT) or none.
+ */
+static const CharJamoProps HangulJamoProps[] = {
+ {JAMO_L, JAMO_L}, /* JAMO_L */
+ {JAMO_V, JAMO_V}, /* JAMO_V */
+ {JAMO_T, JAMO_T}, /* JAMO_T */
+ {JAMO_L, JAMO_V}, /* JAMO_LV */
+ {JAMO_L, JAMO_T}, /* JAMO_LVT */
+ {NO_JAMO, NO_JAMO} /* NO_JAMO */
+};
+
+/* A character forms a syllable with the previous character if and only if:
+ * JamoType(this) is not NO_JAMO and:
+ *
+ * HangulJamoProps[JamoType(prev)].end and
+ * HangulJamoProps[JamoType(this)].start are equal,
+ * or the former is one less than the latter.
+ */
+
+#define IS_JAMO(btype) \
+ ((btype >= G_UNICODE_BREAK_HANGUL_L_JAMO) && \
+ (btype <= G_UNICODE_BREAK_HANGUL_LVT_SYLLABLE))
+#define JAMO_TYPE(btype) \
+ (IS_JAMO(btype) ? (btype - G_UNICODE_BREAK_HANGUL_L_JAMO) : NO_JAMO)
+
+
+
+
+/* "virama script" is just an optimization; it includes a bunch of
+ * scripts without viramas in them
+ */
+#define VIRAMA_SCRIPT(wc) ((wc) >= 0x0901 && (wc) <= 0x17FF)
+#define VIRAMA(wc) ((wc) == 0x094D || \
+ (wc) == 0x09CD || \
+ (wc) == 0x0A4D || \
+ (wc) == 0x0ACD || \
+ (wc) == 0x0B4D || \
+ (wc) == 0x0BCD || \
+ (wc) == 0x0C4D || \
+ (wc) == 0x0CCD || \
+ (wc) == 0x0D4D || \
+ (wc) == 0x0DCA || \
+ (wc) == 0x0E3A || \
+ (wc) == 0x0F84 || \
+ (wc) == 0x1039 || \
+ (wc) == 0x17D2)
+/* Types of Japanese characters */
+#define JAPANESE(wc) ((wc) >= 0x2F00 && (wc) <= 0x30FF)
+#define KANJI(wc) ((wc) >= 0x2F00 && (wc) <= 0x2FDF)
+#define HIRAGANA(wc) ((wc) >= 0x3040 && (wc) <= 0x309F)
+#define KATAKANA(wc) ((wc) >= 0x30A0 && (wc) <= 0x30FF)
+
+#define LATIN(wc) (((wc) >= 0x0020 && (wc) <= 0x02AF) || ((wc) >= 0x1E00 && (wc) <= 0x1EFF))
+#define CYRILLIC(wc) (((wc) >= 0x0400 && (wc) <= 0x052F))
+#define GREEK(wc) (((wc) >= 0x0370 && (wc) <= 0x3FF) || ((wc) >= 0x1F00 && (wc) <= 0x1FFF))
+#define KANA(wc) ((wc) >= 0x3040 && (wc) <= 0x30FF)
+#define HANGUL(wc) ((wc) >= 0xAC00 && (wc) <= 0xD7A3)
+#define BACKSPACE_DELETES_CHARACTER(wc) (!LATIN (wc) && !CYRILLIC (wc) && !GREEK (wc) && !KANA(wc) && !HANGUL(wc))
+
+
+/* p. 132-133 of Unicode spec table 5-6 will help understand this */
+typedef enum
+{
+ STATE_SENTENCE_OUTSIDE,
+ STATE_SENTENCE_BODY,
+ STATE_SENTENCE_TERM,
+ STATE_SENTENCE_POST_TERM_CLOSE,
+ STATE_SENTENCE_POST_TERM_SPACE,
+ STATE_SENTENCE_POST_TERM_SEP,
+ STATE_SENTENCE_DOT,
+ STATE_SENTENCE_POST_DOT_CLOSE,
+ STATE_SENTENCE_POST_DOT_SPACE,
+ STATE_SENTENCE_POST_DOT_OPEN,
+ /* never include line/para separators in a sentence for now */
+ /* This isn't in the spec, but I can't figure out why they'd include
+ * one line/para separator in lines ending with Term but not with
+ * period-terminated lines, so I'm doing it for the dot lines also
+ */
+ STATE_SENTENCE_POST_DOT_SEP
+} SentenceState;
+
+/* We call "123" and "foobar" words, but "123foo" is two words;
+ * the Unicode spec just calls "123" a non-word
+ */
+typedef enum
+{
+ WordNone,
+ WordLetters,
+ WordNumbers
+} WordType;
+
+
+/**
+ * pango_default_break:
+ * @text: text to break
+ * @length: length of text in bytes (may be -1 if @text is nul-terminated)
+ * @analysis: a #PangoAnalysis for the @text
+ * @attrs: logical attributes to fill in
+ * @attrs_len: size of the array passed as @attrs
+ *
+ * This is the default break algorithm, used if no language
+ * engine overrides it. Normally you should use pango_break()
+ * instead. Unlike pango_break(),
+ * @analysis can be %NULL, but only do that if you know what
+ * you're doing. If you need an analysis to pass to pango_break(),
+ * you need to pango_itemize(). In most cases however you should
+ * simply use pango_get_log_attrs().
+ **/
+void
+pango_default_break (const gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len)
+{
+ /* The rationale for all this is in section 5.15 of the Unicode 3.0 book,
+ * the line breaking stuff is also in TR14 on unicode.org
+ */
+
+ /* This is a default break implementation that should work for nearly all
+ * languages. Language engines can override it optionally.
+ */
+
+ /* FIXME one cheesy optimization here would be to memset attrs to 0
+ * before we start, and then never assign %FALSE to anything
+ */
+
+ const gchar *next;
+ gint i;
+
+ gunichar prev_wc;
+ gunichar next_wc;
+
+ JamoType prev_jamo;
+
+ GUnicodeBreakType next_break_type;
+ GUnicodeType prev_type;
+ GUnicodeBreakType prev_break_type; /* skips spaces */
+ gboolean prev_was_break_space;
+
+ WordType current_word_type = WordNone;
+ gunichar last_word_letter = 0;
+ gunichar base_character = 0;
+
+ SentenceState sentence_state = STATE_SENTENCE_OUTSIDE;
+ /* Tracks what will be the end of the sentence if a period is
+ * determined to actually be a sentence-ending period.
+ */
+ gint possible_sentence_end = -1;
+ /* possible sentence break before Open* after a period-ended sentence */
+ gint possible_sentence_boundary = -1;
+ gboolean almost_done = FALSE;
+ gboolean done = FALSE;
+
+ g_return_if_fail (length == 0 || text != NULL);
+ g_return_if_fail (attrs != NULL);
+
+ next = text;
+
+ prev_type = (GUnicodeType) -1;
+ prev_break_type = G_UNICODE_BREAK_UNKNOWN;
+ prev_was_break_space = FALSE;
+ prev_wc = 0;
+ prev_jamo = NO_JAMO;
+
+ if (length == 0 || *text == '\0')
+ next_wc = PARAGRAPH_SEPARATOR;
+ else
+ next_wc = g_utf8_get_char (next);
+
+ next_break_type = g_unichar_break_type (next_wc);
+ next_break_type = BREAK_TYPE_SAFE (next_break_type);
+
+ for (i = 0; !done ; i++)
+ {
+ GUnicodeType type;
+ gunichar wc;
+ GUnicodeBreakType break_type;
+ BreakOpportunity break_op;
+ JamoType jamo;
+ gboolean makes_hangul_syllable;
+
+ wc = next_wc;
+ break_type = next_break_type;
+
+ if (almost_done)
+ {
+ /*
+ * If we have already reached the end of @text g_utf8_next_char()
+ * may not increment next
+ */
+ next_wc = 0;
+ next_break_type = G_UNICODE_BREAK_UNKNOWN;
+ done = TRUE;
+ }
+ else
+ {
+ next = g_utf8_next_char (next);
+
+ if ((length >= 0 && next >= text + length) || *next == '\0')
+ {
+ /* This is how we fill in the last element (end position) of the
+ * attr array - assume there's a paragraph separators off the end
+ * of @text.
+ */
+ next_wc = PARAGRAPH_SEPARATOR;
+ almost_done = TRUE;
+ }
+ else
+ next_wc = g_utf8_get_char (next);
+
+ next_break_type = g_unichar_break_type (next_wc);
+ next_break_type = BREAK_TYPE_SAFE (next_break_type);
+ }
+
+ type = g_unichar_type (wc);
+ jamo = JAMO_TYPE (break_type);
+
+ /* Determine wheter this forms a Hangul syllable with prev. */
+ if (jamo == NO_JAMO)
+ makes_hangul_syllable = FALSE;
+ else
+ {
+ JamoType prev_end = HangulJamoProps[prev_jamo].end ;
+ JamoType this_start = HangulJamoProps[ jamo].start;
+
+ /* See comments before IS_JAMO */
+ makes_hangul_syllable = (prev_end == this_start) || (prev_end + 1 == this_start);
+ }
+
+ /* Can't just use the type here since isspace() doesn't
+ * correspond to a Unicode character type
+ */
+ attrs[i].is_white = g_unichar_isspace (wc);
+
+ /* Just few spaces have variable width. So explicitly mark them.
+ */
+ attrs[i].is_expandable_space = (0x0020 == wc || 0x00A0 == wc);
+
+ /* ---- Cursor position breaks (Grapheme breaks) ---- */
+
+ if (wc == '\n')
+ {
+ /* Break before line feed unless prev char is a CR */
+
+ if (prev_wc != '\r')
+ attrs[i].is_cursor_position = TRUE;
+ else
+ attrs[i].is_cursor_position = FALSE;
+ }
+ else if (i == 0 ||
+ prev_type == G_UNICODE_CONTROL ||
+ prev_type == G_UNICODE_FORMAT)
+ {
+ /* Break at first position (must be special cased, or if the
+ * first char is say a combining mark there won't be a
+ * cursor position at the start, which seems wrong to me
+ * ???? - maybe it makes sense though, who knows)
+ */
+ /* break after all format or control characters */
+ attrs[i].is_cursor_position = TRUE;
+ }
+ else
+ {
+ switch (type)
+ {
+ case G_UNICODE_CONTROL:
+ case G_UNICODE_FORMAT:
+ /* Break before all format or control characters */
+ attrs[i].is_cursor_position = TRUE;
+ break;
+
+ case G_UNICODE_COMBINING_MARK:
+ case G_UNICODE_ENCLOSING_MARK:
+ case G_UNICODE_NON_SPACING_MARK:
+ /* Unicode spec includes "Combining marks plus Tibetan
+ * subjoined characters" as joining chars, but lists the
+ * Tibetan subjoined characters as combining marks, and
+ * g_unichar_type() returns NON_SPACING_MARK for the Tibetan
+ * subjoined characters. So who knows, beats me.
+ */
+
+ /* It's a joining character, break only if preceded by
+ * control or format; we already handled the case where
+ * it was preceded earlier, so here we know it wasn't,
+ * don't break
+ */
+ attrs[i].is_cursor_position = FALSE;
+ break;
+
+ case G_UNICODE_LOWERCASE_LETTER:
+ case G_UNICODE_MODIFIER_LETTER:
+ case G_UNICODE_OTHER_LETTER:
+ case G_UNICODE_TITLECASE_LETTER:
+ case G_UNICODE_UPPERCASE_LETTER:
+
+ if (makes_hangul_syllable)
+ attrs[i].is_cursor_position = FALSE;
+ else
+ {
+ /* Handle non-Hangul-syllable non-combining chars */
+
+ /* Break before Jamo if they are in a broken sequence or
+ * next to non-Jamo; break if preceded by Jamo; don't
+ * break if a letter is preceded by a virama; break in
+ * all other cases. No need to check whether we are or are
+ * preceded by Jamo explicitly, since a Jamo is not
+ * a virama, we just break in all cases where we
+ * aren't a or preceded by a virama. Don't fool with
+ * viramas if we aren't part of a script that uses them.
+ */
+
+ if (VIRAMA_SCRIPT (wc))
+ {
+ /* Check whether we're preceded by a virama; this
+ * could use some optimization.
+ */
+ if (VIRAMA (prev_wc))
+ attrs[i].is_cursor_position = FALSE;
+ else
+ attrs[i].is_cursor_position = TRUE;
+ }
+ else
+ {
+ attrs[i].is_cursor_position = TRUE;
+ }
+ }
+ break;
+
+ default:
+ /* Some weirdo char, just break here, why not */
+ attrs[i].is_cursor_position = TRUE;
+ break;
+ }
+ }
+
+ /* If this is a grapheme boundary, we have to decide if backspace
+ * deletes a character or the whole grapheme cluster */
+ if (attrs[i].is_cursor_position)
+ attrs[i].backspace_deletes_character = BACKSPACE_DELETES_CHARACTER (base_character);
+ else
+ attrs[i].backspace_deletes_character = FALSE;
+
+ /* ---- Line breaking ---- */
+
+ break_op = BREAK_ALREADY_HANDLED;
+
+ g_assert (prev_break_type != G_UNICODE_BREAK_SPACE);
+
+ attrs[i].is_line_break = FALSE;
+ attrs[i].is_mandatory_break = FALSE;
+
+ if (attrs[i].is_cursor_position) /* If it's not a grapheme boundary,
+ * it's not a line break either
+ */
+ {
+ /* space followed by a combining mark is handled
+ * specially; (rule 7a from TR 14)
+ */
+ if (break_type == G_UNICODE_BREAK_SPACE &&
+ next_break_type == G_UNICODE_BREAK_COMBINING_MARK)
+ break_type = G_UNICODE_BREAK_IDEOGRAPHIC;
+
+ /* Unicode doesn't specify char wrap; we wrap around all chars
+ * except where a line break is prohibited, which means we
+ * effectively break everywhere except inside runs of spaces.
+ */
+ attrs[i].is_char_break = TRUE;
+
+ /* Make any necessary replacements first */
+ switch (prev_break_type)
+ {
+ case G_UNICODE_BREAK_HANGUL_L_JAMO:
+ case G_UNICODE_BREAK_HANGUL_V_JAMO:
+ case G_UNICODE_BREAK_HANGUL_T_JAMO:
+ case G_UNICODE_BREAK_HANGUL_LV_SYLLABLE:
+ case G_UNICODE_BREAK_HANGUL_LVT_SYLLABLE:
+ /* treat Jamo as IDEOGRAPHIC from now
+ */
+ prev_break_type = G_UNICODE_BREAK_IDEOGRAPHIC;
+ break;
+
+ case G_UNICODE_BREAK_AMBIGUOUS:
+ /* FIXME
+ * we need to resolve the East Asian width
+ * to decide what to do here
+ */
+ case G_UNICODE_BREAK_COMPLEX_CONTEXT:
+ /* FIXME
+ * language engines should handle this case...
+ */
+ case G_UNICODE_BREAK_UNKNOWN:
+ /* convert unknown, complex, ambiguous to ALPHABETIC
+ */
+ prev_break_type = G_UNICODE_BREAK_ALPHABETIC;
+ break;
+
+ default:
+ ;
+ }
+
+ switch (prev_break_type)
+ {
+ case G_UNICODE_BREAK_MANDATORY:
+ case G_UNICODE_BREAK_LINE_FEED:
+ case G_UNICODE_BREAK_NEXT_LINE:
+ attrs[i].is_line_break = TRUE;
+ attrs[i].is_mandatory_break = TRUE;
+ break;
+
+ case G_UNICODE_BREAK_CARRIAGE_RETURN:
+ if (wc != '\n')
+ {
+ attrs[i].is_line_break = TRUE;
+ attrs[i].is_mandatory_break = TRUE;
+ }
+ break;
+
+ case G_UNICODE_BREAK_CONTINGENT:
+ /* can break after 0xFFFC by default, though we might want
+ * to eventually have a PangoLayout setting or
+ * PangoAttribute that disables this, if for some
+ * application breaking after objects is not desired.
+ */
+ break_op = BREAK_ALLOWED;
+ break;
+
+ case G_UNICODE_BREAK_SURROGATE:
+ g_assert_not_reached ();
+ break;
+
+ default:
+ g_assert (IN_BREAK_TABLE (prev_break_type));
+
+ /* Note that our table assumes that combining marks
+ * are only applied to alphabetic characters;
+ * tech report 14 explains how to remove this assumption
+ * from the code, if anyone ever cares, but it shouldn't
+ * be a problem. Also this issue sort of goes
+ * away since we only look for breaks on grapheme
+ * boundaries.
+ */
+
+ switch (break_type)
+ {
+ case G_UNICODE_BREAK_MANDATORY:
+ case G_UNICODE_BREAK_LINE_FEED:
+ case G_UNICODE_BREAK_CARRIAGE_RETURN:
+ case G_UNICODE_BREAK_NEXT_LINE:
+ case G_UNICODE_BREAK_SPACE:
+ /* These types all "pile up" at the end of lines and
+ * get elided.
+ */
+ break_op = BREAK_PROHIBITED;
+ break;
+
+ case G_UNICODE_BREAK_CONTINGENT:
+ /* break before 0xFFFC by default, eventually
+ * make this configurable?
+ */
+ break_op = BREAK_ALLOWED;
+ break;
+
+ case G_UNICODE_BREAK_SURROGATE:
+ g_assert_not_reached ();
+ break;
+
+ /* Hangul additions are from Unicode 4.1 UAX#14 */
+ case G_UNICODE_BREAK_HANGUL_L_JAMO:
+ case G_UNICODE_BREAK_HANGUL_V_JAMO:
+ case G_UNICODE_BREAK_HANGUL_T_JAMO:
+ case G_UNICODE_BREAK_HANGUL_LV_SYLLABLE:
+ case G_UNICODE_BREAK_HANGUL_LVT_SYLLABLE:
+ /* treat Jamo as IDEOGRAPHIC from now
+ */
+ break_type = G_UNICODE_BREAK_IDEOGRAPHIC;
+
+ if (makes_hangul_syllable)
+ break_op = BREAK_IF_SPACES;
+ else
+ break_op = BREAK_ALLOWED;
+ break;
+
+ case G_UNICODE_BREAK_AMBIGUOUS:
+ /* FIXME:
+ * we need to resolve the East Asian width
+ * to decide what to do here
+ */
+ case G_UNICODE_BREAK_COMPLEX_CONTEXT:
+ /* FIXME:
+ * language engines should handle this case...
+ */
+ case G_UNICODE_BREAK_UNKNOWN:
+ /* treat unknown, complex, and ambiguous like ALPHABETIC
+ * for now
+ */
+ break_op = BREAK_OP (prev_break_type, G_UNICODE_BREAK_ALPHABETIC);
+ break;
+
+ default:
+
+ g_assert (IN_BREAK_TABLE (break_type));
+ break_op = BREAK_OP (prev_break_type, break_type);
+ break;
+ }
+ break;
+ }
+
+ if (break_op != BREAK_ALREADY_HANDLED)
+ {
+ switch (break_op)
+ {
+ case BREAK_PROHIBITED:
+ /* can't break here */
+ attrs[i].is_char_break = FALSE;
+ break;
+
+ case BREAK_IF_SPACES:
+ /* break if prev char was space */
+ if (prev_was_break_space)
+ attrs[i].is_line_break = TRUE;
+ break;
+
+ case BREAK_ALLOWED:
+ attrs[i].is_line_break = TRUE;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+ }
+
+ if (break_type != G_UNICODE_BREAK_SPACE)
+ {
+ prev_break_type = break_type;
+ prev_was_break_space = FALSE;
+ prev_jamo = jamo;
+ }
+ else
+ prev_was_break_space = TRUE;
+
+ /* ---- Word breaks ---- */
+
+ /* default to not a word start/end */
+ attrs[i].is_word_start = FALSE;
+ attrs[i].is_word_end = FALSE;
+
+ if (current_word_type != WordNone)
+ {
+ /* Check for a word end */
+ switch (type)
+ {
+ case G_UNICODE_COMBINING_MARK:
+ case G_UNICODE_ENCLOSING_MARK:
+ case G_UNICODE_NON_SPACING_MARK:
+ case G_UNICODE_FORMAT:
+ /* nothing, we just eat these up as part of the word */
+ break;
+
+ case G_UNICODE_LOWERCASE_LETTER:
+ case G_UNICODE_MODIFIER_LETTER:
+ case G_UNICODE_OTHER_LETTER:
+ case G_UNICODE_TITLECASE_LETTER:
+ case G_UNICODE_UPPERCASE_LETTER:
+ if (current_word_type == WordLetters)
+ {
+ /* Japanese special cases for ending the word */
+ if (JAPANESE (last_word_letter) ||
+ JAPANESE (wc))
+ {
+ if ((HIRAGANA (last_word_letter) &&
+ !HIRAGANA (wc)) ||
+ (KATAKANA (last_word_letter) &&
+ !(KATAKANA (wc) || HIRAGANA (wc))) ||
+ (KANJI (last_word_letter) &&
+ !(HIRAGANA (wc) || KANJI (wc))) ||
+ (JAPANESE (last_word_letter) &&
+ !JAPANESE (wc)) ||
+ (!JAPANESE (last_word_letter) &&
+ JAPANESE (wc)))
+ attrs[i].is_word_end = TRUE;
+ }
+ }
+ else
+ {
+ /* end the number word, start the letter word */
+ attrs[i].is_word_end = TRUE;
+ attrs[i].is_word_start = TRUE;
+ current_word_type = WordLetters;
+ }
+
+ last_word_letter = wc;
+ break;
+
+ case G_UNICODE_DECIMAL_NUMBER:
+ case G_UNICODE_LETTER_NUMBER:
+ case G_UNICODE_OTHER_NUMBER:
+ if (current_word_type != WordNumbers)
+ {
+ attrs[i].is_word_end = TRUE;
+ attrs[i].is_word_start = TRUE;
+ current_word_type = WordNumbers;
+ }
+
+ last_word_letter = wc;
+ break;
+
+ default:
+ /* Punctuation, control/format chars, etc. all end a word. */
+ attrs[i].is_word_end = TRUE;
+ current_word_type = WordNone;
+ break;
+ }
+ }
+ else
+ {
+ /* Check for a word start */
+ switch (type)
+ {
+ case G_UNICODE_LOWERCASE_LETTER:
+ case G_UNICODE_MODIFIER_LETTER:
+ case G_UNICODE_OTHER_LETTER:
+ case G_UNICODE_TITLECASE_LETTER:
+ case G_UNICODE_UPPERCASE_LETTER:
+ current_word_type = WordLetters;
+ last_word_letter = wc;
+ attrs[i].is_word_start = TRUE;
+ break;
+
+ case G_UNICODE_DECIMAL_NUMBER:
+ case G_UNICODE_LETTER_NUMBER:
+ case G_UNICODE_OTHER_NUMBER:
+ current_word_type = WordNumbers;
+ last_word_letter = wc;
+ attrs[i].is_word_start = TRUE;
+ break;
+
+ default:
+ /* No word here */
+ break;
+ }
+ }
+
+ /* ---- Sentence breaks ---- */
+
+ /* The Unicode spec specifies sentence breakpoints, so that a piece of
+ * text would be partitioned into sentences, and all characters would
+ * be inside some sentence. This code implements that for is_sentence_boundary,
+ * but tries to keep leading/trailing whitespace out of sentences for
+ * the start/end flags
+ */
+
+ /* The Unicode spec seems to say that one trailing line/para
+ * separator can be tacked on to a sentence ending in ! or ?,
+ * but not a sentence ending in period; I think they're on crack
+ * so am allowing one to be tacked onto a sentence ending in period.
+ */
+
+#define MAYBE_START_NEW_SENTENCE \
+ switch (type) \
+ { \
+ case G_UNICODE_LINE_SEPARATOR: \
+ case G_UNICODE_PARAGRAPH_SEPARATOR: \
+ case G_UNICODE_CONTROL: \
+ case G_UNICODE_FORMAT: \
+ case G_UNICODE_SPACE_SEPARATOR: \
+ sentence_state = STATE_SENTENCE_OUTSIDE; \
+ break; \
+ \
+ default: \
+ sentence_state = STATE_SENTENCE_BODY; \
+ attrs[i].is_sentence_start = TRUE; \
+ break; \
+ }
+
+ /* No sentence break at the start of the text */
+
+ /* default to not a sentence breakpoint */
+ attrs[i].is_sentence_boundary = FALSE;
+ attrs[i].is_sentence_start = FALSE;
+ attrs[i].is_sentence_end = FALSE;
+
+ /* FIXME the Unicode spec lumps control/format chars with
+ * line/para separators in descriptive text, but not in the
+ * character class specs, in table 5-6, so who knows whether you
+ * are actually supposed to break on control/format
+ * characters. Seems semi-broken to break on tabs...
+ */
+
+ /* Break after line/para separators except carriage return
+ * followed by newline
+ */
+ switch (prev_type)
+ {
+ case G_UNICODE_LINE_SEPARATOR:
+ case G_UNICODE_PARAGRAPH_SEPARATOR:
+ case G_UNICODE_CONTROL:
+ case G_UNICODE_FORMAT:
+ if (wc == '\r')
+ {
+ if (next_wc != '\n')
+ attrs[i].is_sentence_boundary = TRUE;
+ }
+ else
+ attrs[i].is_sentence_boundary = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ /* break before para/line separators except newline following
+ * carriage return
+ */
+ switch (type)
+ {
+ case G_UNICODE_LINE_SEPARATOR:
+ case G_UNICODE_PARAGRAPH_SEPARATOR:
+ case G_UNICODE_CONTROL:
+ case G_UNICODE_FORMAT:
+ if (wc == '\n')
+ {
+ if (prev_wc != '\r')
+ attrs[i].is_sentence_boundary = TRUE;
+ }
+ else
+ attrs[i].is_sentence_boundary = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (sentence_state)
+ {
+ case STATE_SENTENCE_OUTSIDE:
+ /* Start sentence if we have non-whitespace/format/control */
+ switch (type)
+ {
+ case G_UNICODE_LINE_SEPARATOR:
+ case G_UNICODE_PARAGRAPH_SEPARATOR:
+ case G_UNICODE_CONTROL:
+ case G_UNICODE_FORMAT:
+ case G_UNICODE_SPACE_SEPARATOR:
+ break;
+
+ default:
+ attrs[i].is_sentence_start = TRUE;
+ sentence_state = STATE_SENTENCE_BODY;
+ break;
+ }
+ break;
+
+ case STATE_SENTENCE_BODY:
+ /* If we already broke here due to separators, end the sentence. */
+ if (attrs[i].is_sentence_boundary)
+ {
+ attrs[i].is_sentence_end = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+ }
+ else
+ {
+ if (wc == '.')
+ sentence_state = STATE_SENTENCE_DOT;
+ else if (wc == '?' || wc == '!')
+ sentence_state = STATE_SENTENCE_TERM;
+ }
+ break;
+
+ case STATE_SENTENCE_TERM:
+ /* End sentence on anything but close punctuation and some
+ * loosely-specified OTHER_PUNCTUATION such as period,
+ * comma, etc.; follow Unicode rules for breaks
+ */
+ switch (type)
+ {
+ case G_UNICODE_OTHER_PUNCTUATION:
+ case G_UNICODE_CLOSE_PUNCTUATION:
+ if (type == G_UNICODE_CLOSE_PUNCTUATION ||
+ wc == '.' ||
+ wc == ',' ||
+ wc == '?' ||
+ wc == '!')
+ sentence_state = STATE_SENTENCE_POST_TERM_CLOSE;
+ else
+ {
+ attrs[i].is_sentence_end = TRUE;
+ attrs[i].is_sentence_boundary = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+ }
+ break;
+
+ case G_UNICODE_SPACE_SEPARATOR:
+ attrs[i].is_sentence_end = TRUE;
+ sentence_state = STATE_SENTENCE_POST_TERM_SPACE;
+ break;
+
+ case G_UNICODE_LINE_SEPARATOR:
+ case G_UNICODE_PARAGRAPH_SEPARATOR:
+ attrs[i].is_sentence_end = TRUE;
+ sentence_state = STATE_SENTENCE_POST_TERM_SEP;
+ break;
+
+ default:
+ attrs[i].is_sentence_end = TRUE;
+ attrs[i].is_sentence_boundary = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+
+ break;
+ }
+ break;
+
+ case STATE_SENTENCE_POST_TERM_CLOSE:
+ /* End sentence on anything besides more punctuation; follow
+ * rules for breaks
+ */
+ switch (type)
+ {
+ case G_UNICODE_OTHER_PUNCTUATION:
+ case G_UNICODE_CLOSE_PUNCTUATION:
+ if (type == G_UNICODE_CLOSE_PUNCTUATION ||
+ wc == '.' ||
+ wc == ',' ||
+ wc == '?' ||
+ wc == '!')
+ /* continue in this state */
+ ;
+ else
+ {
+ attrs[i].is_sentence_end = TRUE;
+ attrs[i].is_sentence_boundary = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+ }
+ break;
+
+ case G_UNICODE_SPACE_SEPARATOR:
+ attrs[i].is_sentence_end = TRUE;
+ sentence_state = STATE_SENTENCE_POST_TERM_SPACE;
+ break;
+
+ case G_UNICODE_LINE_SEPARATOR:
+ case G_UNICODE_PARAGRAPH_SEPARATOR:
+ attrs[i].is_sentence_end = TRUE;
+ /* undo the unconditional break-at-all-line/para-separators
+ * from above; I'm not sure this is what the Unicode spec
+ * intends, but it seems right - we get to include
+ * a single line/para separator in the sentence according
+ * to their rules
+ */
+ attrs[i].is_sentence_boundary = FALSE;
+ sentence_state = STATE_SENTENCE_POST_TERM_SEP;
+ break;
+
+ default:
+ attrs[i].is_sentence_end = TRUE;
+ attrs[i].is_sentence_boundary = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+
+ break;
+ }
+ break;
+
+ case STATE_SENTENCE_POST_TERM_SPACE:
+
+ /* Sentence is definitely already ended; to enter this state
+ * we had to see a space, which ends the sentence.
+ */
+
+ switch (type)
+ {
+ case G_UNICODE_SPACE_SEPARATOR:
+ /* continue in this state */
+ break;
+
+ case G_UNICODE_LINE_SEPARATOR:
+ case G_UNICODE_PARAGRAPH_SEPARATOR:
+ /* undo the unconditional break-at-all-line/para-separators
+ * from above; I'm not sure this is what the Unicode spec
+ * intends, but it seems right
+ */
+ attrs[i].is_sentence_boundary = FALSE;
+ sentence_state = STATE_SENTENCE_POST_TERM_SEP;
+ break;
+
+ default:
+ attrs[i].is_sentence_boundary = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+
+ break;
+ }
+ break;
+
+ case STATE_SENTENCE_POST_TERM_SEP:
+ /* Break is forced at this point, unless we're a newline
+ * after a CR, then we will break after the newline on the
+ * next iteration. Only a single Sep can be in the
+ * sentence.
+ */
+ if (!(prev_wc == '\r' && wc == '\n'))
+ attrs[i].is_sentence_boundary = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+
+ break;
+
+ case STATE_SENTENCE_DOT:
+ switch (type)
+ {
+ case G_UNICODE_CLOSE_PUNCTUATION:
+ sentence_state = STATE_SENTENCE_POST_DOT_CLOSE;
+ break;
+
+ case G_UNICODE_SPACE_SEPARATOR:
+ possible_sentence_end = i;
+ sentence_state = STATE_SENTENCE_POST_DOT_SPACE;
+ break;
+
+ default:
+ /* If we broke on a control/format char, end the
+ * sentence; else this was not a sentence end, since
+ * we didn't enter the POST_DOT_SPACE state.
+ */
+ if (attrs[i].is_sentence_boundary)
+ {
+ attrs[i].is_sentence_end = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+ }
+ else
+ sentence_state = STATE_SENTENCE_BODY;
+ break;
+ }
+ break;
+
+ case STATE_SENTENCE_POST_DOT_CLOSE:
+ switch (type)
+ {
+ case G_UNICODE_SPACE_SEPARATOR:
+ possible_sentence_end = i;
+ sentence_state = STATE_SENTENCE_POST_DOT_SPACE;
+ break;
+
+ default:
+ /* If we broke on a control/format char, end the
+ * sentence; else this was not a sentence end, since
+ * we didn't enter the POST_DOT_SPACE state.
+ */
+ if (attrs[i].is_sentence_boundary)
+ {
+ attrs[i].is_sentence_end = TRUE;
+
+ MAYBE_START_NEW_SENTENCE;
+ }
+ else
+ sentence_state = STATE_SENTENCE_BODY;
+ break;
+ }
+ break;
+
+ case STATE_SENTENCE_POST_DOT_SPACE:
+
+ possible_sentence_boundary = i;
+
+ switch (type)
+ {
+ case G_UNICODE_SPACE_SEPARATOR:
+ /* remain in current state */
+ break;
+
+ case G_UNICODE_OPEN_PUNCTUATION:
+ sentence_state = STATE_SENTENCE_POST_DOT_OPEN;
+ break;
+
+ case G_UNICODE_LOWERCASE_LETTER:
+ /* wasn't a sentence-ending period; so re-enter the sentence
+ * body
+ */
+ sentence_state = STATE_SENTENCE_BODY;
+ break;
+
+ default:
+ /* End the sentence, break, maybe start a new one */
+
+ g_assert (possible_sentence_end >= 0);
+ g_assert (possible_sentence_boundary >= 0);
+
+ attrs[possible_sentence_boundary].is_sentence_boundary = TRUE;
+ attrs[possible_sentence_end].is_sentence_end = TRUE;
+
+ possible_sentence_end = -1;
+ possible_sentence_boundary = -1;
+
+ MAYBE_START_NEW_SENTENCE;
+
+ break;
+ }
+ break;
+
+ case STATE_SENTENCE_POST_DOT_OPEN:
+ switch (type)
+ {
+ case G_UNICODE_OPEN_PUNCTUATION:
+ /* continue in current state */
+ break;
+
+ case G_UNICODE_LOWERCASE_LETTER:
+ /* wasn't a sentence-ending period; so re-enter the sentence
+ * body
+ */
+ sentence_state = STATE_SENTENCE_BODY;
+ break;
+
+ default:
+ /* End the sentence, break, maybe start a new one */
+
+ g_assert (possible_sentence_end >= 0);
+ g_assert (possible_sentence_boundary >= 0);
+
+ attrs[possible_sentence_boundary].is_sentence_boundary = TRUE;
+ attrs[possible_sentence_end].is_sentence_end = TRUE;
+
+ possible_sentence_end = -1;
+ possible_sentence_boundary = -1;
+
+ MAYBE_START_NEW_SENTENCE;
+
+ break;
+ }
+ break;
+
+ case STATE_SENTENCE_POST_DOT_SEP:
+ /* Break is forced at this point, unless we're a newline
+ * after a CR, then we will break after the newline on the
+ * next iteration. Only a single Sep can be in the
+ * sentence.
+ */
+ if (!(prev_wc == '\r' && wc == '\n'))
+ attrs[i].is_sentence_boundary = TRUE;
+
+ g_assert (possible_sentence_end >= 0);
+ g_assert (possible_sentence_boundary >= 0);
+
+ attrs[possible_sentence_end].is_sentence_end = TRUE;
+
+ possible_sentence_end = -1;
+ possible_sentence_boundary = -1;
+
+ MAYBE_START_NEW_SENTENCE;
+
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ prev_type = type;
+ prev_wc = wc;
+
+ /* wc might not be a valid Unicode base character, but really all we
+ * need to know is the last non-combining character */
+ if (type != G_UNICODE_COMBINING_MARK &&
+ type != G_UNICODE_ENCLOSING_MARK &&
+ type != G_UNICODE_NON_SPACING_MARK)
+ base_character = wc;
+ }
+}
+
+static gboolean
+tailor_break (const gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len)
+{
+ if (analysis->lang_engine && PANGO_ENGINE_LANG_GET_CLASS (analysis->lang_engine)->script_break)
+ {
+ if (length < 0)
+ length = strlen (text);
+ else if (text == NULL)
+ text = "";
+
+ PANGO_ENGINE_LANG_GET_CLASS (analysis->lang_engine)->script_break (analysis->lang_engine, text, length, analysis, attrs, attrs_len);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * pango_break:
+ * @text: the text to process
+ * @length: length of @text in bytes (may be -1 if @text is nul-terminated)
+ * @analysis: #PangoAnalysis structure from pango_itemize()
+ * @attrs: an array to store character information in
+ * @attrs_len: size of the array passed as @attrs
+ *
+ * Determines possible line, word, and character breaks
+ * for a string of Unicode text with a single analysis. For most
+ * purposes you may want to use pango_get_log_attrs().
+ */
+void
+pango_break (const gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len)
+{
+ g_return_if_fail (analysis != NULL);
+ g_return_if_fail (attrs != NULL);
+
+ pango_default_break (text, length, analysis, attrs, attrs_len);
+ tailor_break (text, length, analysis, attrs, attrs_len);
+}
+
+/**
+ * pango_find_paragraph_boundary:
+ * @text: UTF-8 text
+ * @length: length of @text in bytes, or -1 if nul-terminated
+ * @paragraph_delimiter_index: return location for index of delimiter
+ * @next_paragraph_start: return location for start of next paragraph
+ *
+ * Locates a paragraph boundary in @text. A boundary is caused by
+ * delimiter characters, such as a newline, carriage return, carriage
+ * return-newline pair, or Unicode paragraph separator character. The
+ * index of the run of delimiters is returned in
+ * @paragraph_delimiter_index. The index of the start of the paragraph
+ * (index after all delimiters) is stored in @next_paragraph_start.
+ *
+ * If no delimiters are found, both @paragraph_delimiter_index and
+ * @next_paragraph_start are filled with the length of @text (an index one
+ * off the end).
+ **/
+void
+pango_find_paragraph_boundary (const gchar *text,
+ gint length,
+ gint *paragraph_delimiter_index,
+ gint *next_paragraph_start)
+{
+ const gchar *p = text;
+ const gchar *end;
+ const gchar *start = NULL;
+ const gchar *delimiter = NULL;
+
+ /* Only one character has type G_UNICODE_PARAGRAPH_SEPARATOR in
+ * Unicode 5.0; update the following code if that changes.
+ */
+
+ /* prev_sep is the first byte of the previous separator. Since
+ * the valid separators are \r, \n, and PARAGRAPH_SEPARATOR, the
+ * first byte is enough to identify it.
+ */
+ gchar prev_sep;
+
+
+ if (length < 0)
+ length = strlen (text);
+
+ end = text + length;
+
+ if (paragraph_delimiter_index)
+ *paragraph_delimiter_index = length;
+
+ if (next_paragraph_start)
+ *next_paragraph_start = length;
+
+ if (length == 0)
+ return;
+
+ prev_sep = 0;
+
+ while (p != end)
+ {
+ if (prev_sep == '\n' ||
+ prev_sep == PARAGRAPH_SEPARATOR_STRING[0])
+ {
+ g_assert (delimiter);
+ start = p;
+ break;
+ }
+ else if (prev_sep == '\r')
+ {
+ /* don't break between \r and \n */
+ if (*p != '\n')
+ {
+ g_assert (delimiter);
+ start = p;
+ break;
+ }
+ }
+
+ if (*p == '\n' ||
+ *p == '\r' ||
+ !strncmp(p, PARAGRAPH_SEPARATOR_STRING,
+ strlen(PARAGRAPH_SEPARATOR_STRING)))
+ {
+ if (delimiter == NULL)
+ delimiter = p;
+ prev_sep = *p;
+ }
+ else
+ prev_sep = 0;
+
+ p = g_utf8_next_char (p);
+ }
+
+ if (delimiter && paragraph_delimiter_index)
+ *paragraph_delimiter_index = delimiter - text;
+
+ if (start && next_paragraph_start)
+ *next_paragraph_start = start - text;
+}
+
+static int
+tailor_segment (const char *range_start,
+ const char *range_end,
+ PangoEngineLang *range_engine,
+ int chars_broken,
+ PangoAnalysis *analysis,
+ PangoLogAttr *log_attrs)
+{
+ int chars_in_range;
+ PangoLogAttr attr_before = log_attrs[0];
+
+ analysis->lang_engine = range_engine;
+ chars_in_range = g_utf8_strlen (range_start, range_end - range_start);
+
+
+ if (tailor_break (range_start,
+ range_end - range_start,
+ analysis,
+ log_attrs + chars_broken,
+ chars_in_range + 1))
+ {
+ /* if tailored, we enforce some of the attrs from before tailoring at
+ * the boundary
+ */
+
+ log_attrs[0].backspace_deletes_character = attr_before.backspace_deletes_character;
+
+ log_attrs[0].is_line_break |= attr_before.is_line_break;
+ log_attrs[0].is_mandatory_break |= attr_before.is_mandatory_break;
+ log_attrs[0].is_cursor_position |= attr_before.is_cursor_position;
+ }
+
+ return chars_in_range;
+}
+
+/**
+ * pango_get_log_attrs:
+ * @text: text to process
+ * @length: length in bytes of @text
+ * @level: embedding level, or -1 if unknown
+ * @language: language tag
+ * @log_attrs: array with one #PangoLogAttr per character in @text, plus one extra, to be filled in
+ * @attrs_len: length of @log_attrs array
+ *
+ * Computes a #PangoLogAttr for each character in @text. The @log_attrs
+ * array must have one #PangoLogAttr for each position in @text; if
+ * @text contains N characters, it has N+1 positions, including the
+ * last position at the end of the text. @text should be an entire
+ * paragraph; logical attributes can't be computed without context
+ * (for example you need to see spaces on either side of a word to know
+ * the word is a word).
+ */
+void
+pango_get_log_attrs (const char *text,
+ int length,
+ int level,
+ PangoLanguage *language,
+ PangoLogAttr *log_attrs,
+ int attrs_len)
+{
+ PangoMap *lang_map;
+ int chars_broken;
+ const char *range_start, *range_end;
+ PangoScript script;
+ PangoEngineLang *range_engine;
+ static guint engine_type_id = 0;
+ static guint render_type_id = 0;
+ PangoAnalysis analysis = { 0 };
+ PangoScriptIter *iter;
+
+ g_return_if_fail (length == 0 || text != NULL);
+ g_return_if_fail (log_attrs != NULL);
+
+ analysis.level = level;
+
+ pango_default_break (text, length, &analysis, log_attrs, attrs_len);
+
+ if (engine_type_id == 0)
+ {
+ engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_LANG);
+ render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_NONE);
+ }
+
+ lang_map = pango_find_map (language, engine_type_id, render_type_id);
+
+ chars_broken = 0;
+
+ iter = pango_script_iter_new (text, length);
+ pango_script_iter_get_range (iter, &range_start, &range_end, &script);
+ range_engine = (PangoEngineLang*) pango_map_get_engine (lang_map, script);
+ g_assert (range_start == text);
+
+ while (pango_script_iter_next (iter))
+ {
+ const char *run_start, *run_end;
+ PangoEngineLang* run_engine;
+
+ pango_script_iter_get_range (iter, &run_start, &run_end, &script);
+ run_engine = (PangoEngineLang*) pango_map_get_engine (lang_map, script);
+ g_assert (range_end == run_start);
+
+ if (range_engine != run_engine)
+ {
+ /* Engine has changed; do the tailoring for the current range,
+ * then start a new range.
+ */
+ chars_broken += tailor_segment (range_start, range_end, range_engine, chars_broken, &analysis, log_attrs);
+
+ range_start = run_start;
+ range_engine = run_engine;
+ }
+ range_end = run_end;
+ }
+ pango_script_iter_free (iter);
+
+ g_assert (length < 0 || range_end == text + length);
+
+ chars_broken += tailor_segment (range_start, range_end, range_engine, chars_broken, &analysis, log_attrs);
+
+ if (chars_broken + 1 < attrs_len)
+ g_warning ("pango_get_log_attrs: attrs_len should have been at least %d, but was %d. Expect corrupted memory.",
+ chars_broken + 1,
+ attrs_len);
+}
diff --git a/trunk/pango/check.defs b/trunk/pango/check.defs
new file mode 100755
index 00000000..0c26c636
--- /dev/null
+++ b/trunk/pango/check.defs
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+LANG=C
+
+test -z "$srcdir" && srcdir=.
+status=0
+
+get_pango_syms='nm "$so" | grep " T " | cut -d" " -f3'
+if [ "`uname -s`" = "Linux" ]; then
+ get_pango_syms='objdump -t "$so" | sed -n "/.*g *F *\.\(opd\|text\).* \(.*pango_.*\)$/s//\2/p"'
+fi
+
+for def in $srcdir/*.def; do
+ lib=${def%.def}
+ lib=${lib##*/}
+ so=.libs/lib${lib}-1.0.so
+
+ test -f "$so" || continue
+ echo Checking $def
+
+ expected=$lib.expected
+ list=$lib.list
+ eval $get_pango_syms | sort -u > "$expected"
+ cut -f 2 "$def" | grep -v EXPORTS | sort -u > "$list"
+
+ diff "$list" "$expected" && rm -f "$list" "$expected" || status=1
+done
+
+exit $status
diff --git a/trunk/pango/ellipsize.c b/trunk/pango/ellipsize.c
new file mode 100644
index 00000000..fb2bce60
--- /dev/null
+++ b/trunk/pango/ellipsize.c
@@ -0,0 +1,767 @@
+/* Pango
+ * ellipsize.c: Routine to ellipsize layout lines
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "pango-glyph-item-private.h"
+#include "pango-layout-private.h"
+#include "pango-engine-private.h"
+
+typedef struct _EllipsizeState EllipsizeState;
+typedef struct _RunInfo RunInfo;
+typedef struct _LineIter LineIter;
+
+
+/* Overall, the way we ellipsize is we grow a "gap" out from an original
+ * gap center position until:
+ *
+ * line_width - gap_width + ellipsize_width <= goal_width
+ *
+ * Line: [-------------------------------------------]
+ * Runs: [------)[---------------)[------------------]
+ * Gap center: *
+ * Gap: [----------------------]
+ *
+ * The gap center may be at the start or end in which case the gap grows
+ * in only one direction.
+ *
+ * Note the line and last run are logically closed at the end; this allows
+ * us to use a gap position at x=line_width and still have it be part of
+ * of a run.
+ *
+ * We grow the gap out one "span" at a time, where a span is simply a
+ * consecutive run of clusters that we can't interrupt with an ellipsis.
+ *
+ * When choosing whether to grow the gap at the start or the end, we
+ * calculate the next span to remove in both directions and see which
+ * causes the smaller increase in:
+ *
+ * MAX (gap_end - gap_center, gap_start - gap_center)
+ *
+ * All computations are done using logical order; the ellipsization
+ * process occurs before the runs are ordered into visual order.
+ */
+
+/* Keeps information about a single run */
+struct _RunInfo
+{
+ PangoGlyphItem *run;
+ int start_offset; /* Character offset of run start */
+ int width; /* Width of run in Pango units */
+};
+
+/* Iterator to a position within the ellipsized line */
+struct _LineIter
+{
+ PangoGlyphItemIter run_iter;
+ int run_index;
+};
+
+/* State of ellipsization process */
+struct _EllipsizeState
+{
+ PangoLayout *layout; /* Layout being ellipsized */
+ PangoAttrList *attrs; /* Attributes used for itemization/shaping */
+
+ RunInfo *run_info; /* Array of information about each run */
+ int n_runs;
+
+ int total_width; /* Original width of line in Pango units */
+ int gap_center; /* Goal for center of gap */
+
+ PangoGlyphItem *ellipsis_run; /* Run created to hold ellipsis */
+ int ellipsis_width; /* Width of ellipsis, in Pango units */
+ int ellipsis_is_cjk; /* Whether the first character in the ellipsized
+ * is wide; this triggers us to try to use a
+ * mid-line ellipsis instead of a baseline
+ */
+
+ PangoAttrIterator *line_start_attr; /* Cached PangoAttrIterator for the start of the run */
+
+ LineIter gap_start_iter; /* Iteratator pointig to the first cluster in gap */
+ int gap_start_x; /* x position of start of gap, in Pango units */
+ PangoAttrIterator *gap_start_attr; /* Attribute iterator pointing to a range containing
+ * the first character in gap */
+
+ LineIter gap_end_iter; /* Iterator pointing to last cluster in gap */
+ int gap_end_x; /* x position of end of gap, in Pango units */
+};
+
+/* Compute global information needed for the itemization process
+ */
+static void
+init_state (EllipsizeState *state,
+ PangoLayoutLine *line,
+ PangoAttrList *attrs)
+{
+ GSList *l;
+ int i, j;
+ int start_offset;
+
+ state->layout = line->layout;
+ state->attrs = attrs;
+
+ state->n_runs = g_slist_length (line->runs);
+ state->run_info = g_new (RunInfo, state->n_runs);
+
+ start_offset = g_utf8_strlen (line->layout->text,
+ line->start_index);
+
+ state->total_width = 0;
+ for (l = line->runs, i = 0; l; l = l->next, i++)
+ {
+ PangoGlyphItem *run = l->data;
+ int width = 0;
+
+ for (j = 0; j < run->glyphs->num_glyphs; j++)
+ width += run->glyphs->glyphs[j].geometry.width;
+
+ state->run_info[i].run = run;
+ state->run_info[i].width = width;
+ state->run_info[i].start_offset = start_offset;
+ state->total_width += width;
+
+ start_offset += run->item->num_chars;
+ }
+
+ state->ellipsis_run = NULL;
+ state->ellipsis_is_cjk = FALSE;
+ state->line_start_attr = NULL;
+ state->gap_start_attr = NULL;
+}
+
+/* Cleanup memory allocation
+ */
+static void
+free_state (EllipsizeState *state)
+{
+ if (state->line_start_attr)
+ pango_attr_iterator_destroy (state->line_start_attr);
+ if (state->gap_start_attr)
+ pango_attr_iterator_destroy (state->gap_start_attr);
+ g_free (state->run_info);
+}
+
+/* Computes the width of a single cluster
+ */
+static int
+get_cluster_width (LineIter *iter)
+{
+ PangoGlyphItemIter *run_iter = &iter->run_iter;
+ PangoGlyphString *glyphs = run_iter->glyph_item->glyphs;
+ int width = 0;
+ int i;
+
+ if (run_iter->start_glyph < run_iter->end_glyph) /* LTR */
+ {
+ for (i = run_iter->start_glyph; i < run_iter->end_glyph; i++)
+ width += glyphs->glyphs[i].geometry.width;
+ }
+ else /* RTL */
+ {
+ for (i = run_iter->start_glyph; i > run_iter->end_glyph; i--)
+ width += glyphs->glyphs[i].geometry.width;
+ }
+
+ return width;
+}
+
+/* Move forward one cluster. Returns %FALSE if we were already at the end
+ */
+static gboolean
+line_iter_next_cluster (EllipsizeState *state,
+ LineIter *iter)
+{
+ if (!_pango_glyph_item_iter_next_cluster (&iter->run_iter))
+ {
+ if (iter->run_index == state->n_runs - 1)
+ return FALSE;
+ else
+ {
+ iter->run_index++;
+ _pango_glyph_item_iter_init_start (&iter->run_iter,
+ state->run_info[iter->run_index].run,
+ state->layout->text);
+ }
+ }
+
+ return TRUE;
+}
+
+/* Move backward one cluster. Returns %FALSE if we were already at the end
+ */
+static gboolean
+line_iter_prev_cluster (EllipsizeState *state,
+ LineIter *iter)
+{
+ if (!_pango_glyph_item_iter_prev_cluster (&iter->run_iter))
+ {
+ if (iter->run_index == 0)
+ return FALSE;
+ else
+ {
+ iter->run_index--;
+ _pango_glyph_item_iter_init_end (&iter->run_iter,
+ state->run_info[iter->run_index].run,
+ state->layout->text);
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * An ellipsization boundary is defined by two things
+ *
+ * - Starts a cluster - forced by structure of code
+ * - Starts a grapheme - checked here
+ *
+ * In the future we'd also like to add a check for cursive connectivity here.
+ * This should be an addition to #PangoGlyphVisAttr
+ *
+ */
+
+/* Checks if there is a ellipsization boundary before the cluster @iter points to
+ */
+static gboolean
+starts_at_ellipsization_boundary (EllipsizeState *state,
+ LineIter *iter)
+{
+ RunInfo *run_info = &state->run_info[iter->run_index];
+
+ if (iter->run_iter.start_char == 0 && iter->run_index == 0)
+ return TRUE;
+
+ return state->layout->log_attrs[run_info->start_offset + iter->run_iter.start_char].is_cursor_position;
+}
+
+/* Checks if there is a ellipsization boundary after the cluster @iter points to
+ */
+static gboolean
+ends_at_ellipsization_boundary (EllipsizeState *state,
+ LineIter *iter)
+{
+ RunInfo *run_info = &state->run_info[iter->run_index];
+
+ if (iter->run_iter.end_char == run_info->run->item->num_chars && iter->run_index == state->n_runs - 1)
+ return TRUE;
+
+ return state->layout->log_attrs[run_info->start_offset + iter->run_iter.end_char + 1].is_cursor_position;
+}
+
+/* Helper function to re-itemize a string of text
+ */
+static PangoItem *
+itemize_text (EllipsizeState *state,
+ const char *text,
+ PangoAttrList *attrs)
+{
+ GList *items;
+ PangoItem *item;
+
+ items = pango_itemize (state->layout->context, text, 0, strlen (text), attrs, NULL);
+ g_assert (g_list_length (items) == 1);
+
+ item = items->data;
+ g_list_free (items);
+
+ return item;
+}
+
+/* Shapes the ellipsis using the font and is_cjk information computed by
+ * update_ellipsis_shape() from the first character in the gap.
+ */
+static void
+shape_ellipsis (EllipsizeState *state)
+{
+ PangoAttrList *attrs = pango_attr_list_new ();
+ GSList *run_attrs;
+ PangoItem *item;
+ PangoGlyphString *glyphs;
+ GSList *l;
+ PangoAttribute *fallback;
+ const char *ellipsis_text;
+ int i;
+
+ /* Create/reset state->ellipsis_run
+ */
+ if (!state->ellipsis_run)
+ {
+ state->ellipsis_run = g_slice_new (PangoGlyphItem);
+ state->ellipsis_run->glyphs = pango_glyph_string_new ();
+ state->ellipsis_run->item = NULL;
+ }
+
+ if (state->ellipsis_run->item)
+ {
+ pango_item_free (state->ellipsis_run->item);
+ state->ellipsis_run->item = NULL;
+ }
+
+ /* Create an attribute list
+ */
+ run_attrs = pango_attr_iterator_get_attrs (state->gap_start_attr);
+ for (l = run_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+ attr->start_index = 0;
+ attr->end_index = G_MAXINT;
+
+ pango_attr_list_insert (attrs, attr);
+ }
+
+ g_slist_free (run_attrs);
+
+ fallback = pango_attr_fallback_new (FALSE);
+ fallback->start_index = 0;
+ fallback->end_index = G_MAXINT;
+ pango_attr_list_insert (attrs, fallback);
+
+ /* First try using a specific ellipsis character in the best matching font
+ */
+ if (state->ellipsis_is_cjk)
+ ellipsis_text = "\342\213\257"; /* U+22EF: MIDLINE HORIZONTAL ELLIPSIS, used for CJK */
+ else
+ ellipsis_text = "\342\200\246"; /* U+2026: HORIZONTAL ELLIPSIS */
+
+ item = itemize_text (state, ellipsis_text, attrs);
+
+ /* If that fails we use "..." in the first matching font
+ */
+ if (!item->analysis.font ||
+ !_pango_engine_shape_covers (item->analysis.shape_engine, item->analysis.font,
+ item->analysis.language, g_utf8_get_char (ellipsis_text)))
+ {
+ pango_item_free (item);
+
+ /* Modify the fallback iter while it is inside the PangoAttrList; Don't try this at home
+ */
+ ((PangoAttrInt *)fallback)->value = TRUE;
+
+ ellipsis_text = "...";
+ item = itemize_text (state, ellipsis_text, attrs);
+ }
+
+ pango_attr_list_unref (attrs);
+
+ state->ellipsis_run->item = item;
+
+ /* Now shape
+ */
+ glyphs = state->ellipsis_run->glyphs;
+
+ pango_shape (ellipsis_text, strlen (ellipsis_text),
+ &item->analysis, glyphs);
+
+ state->ellipsis_width = 0;
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ state->ellipsis_width += glyphs->glyphs[i].geometry.width;
+}
+
+/* Helper function to advance a PangoAttrIterator to a particular
+ * byte index.
+ */
+static void
+advance_iterator_to (PangoAttrIterator *iter,
+ int new_index)
+{
+ int start, end;
+
+ do
+ {
+ pango_attr_iterator_range (iter, &start, &end);
+ if (end > new_index)
+ break;
+ }
+ while (pango_attr_iterator_next (iter));
+}
+
+/* Updates the shaping of the ellipsis if necessary when we move the
+ * position of the start of the gap.
+ *
+ * The shaping of the ellipsis is determined by two things:
+ *
+ * - The font attributes applied to the first character in the gap
+ * - Whether the first character in the gap is wide or not. If the
+ * first character is wide, then we assume that we are ellipsizing
+ * East-Asian text, so prefer a mid-line ellipsizes to a baseline
+ * ellipsis, since that's typical practice for Chinese/Japanese/Korean.
+ */
+static void
+update_ellipsis_shape (EllipsizeState *state)
+{
+ gboolean recompute = FALSE;
+ gunichar start_wc;
+ gboolean is_cjk;
+
+ /* Unfortunately, we can only advance PangoAttrIterator forward; so each
+ * time we back up we need to go forward to find the new position. To make
+ * this not utterly slow, we cache an iterator at the start of the line
+ */
+ if (!state->line_start_attr)
+ {
+ state->line_start_attr = pango_attr_list_get_iterator (state->attrs);
+ advance_iterator_to (state->line_start_attr, state->run_info[0].run->item->offset);
+ }
+
+ if (state->gap_start_attr)
+ {
+ /* See if the current attribute range contains the new start position
+ */
+ int start, end;
+
+ pango_attr_iterator_range (state->gap_start_attr, &start, &end);
+
+ if (state->gap_start_iter.run_iter.start_index < start)
+ {
+ pango_attr_iterator_destroy (state->gap_start_attr);
+ state->gap_start_attr = NULL;
+ }
+ }
+
+ /* Check whether we need to recompute the ellipsis because of new font attributes
+ */
+ if (!state->gap_start_attr)
+ {
+ state->gap_start_attr = pango_attr_iterator_copy (state->line_start_attr);
+ advance_iterator_to (state->gap_start_attr,
+ state->run_info[state->gap_start_iter.run_index].run->item->offset);
+
+ recompute = TRUE;
+ }
+
+ /* Check whether we need to recompute the ellipsis because we switch from CJK to not
+ * or vice-versa
+ */
+ start_wc = g_utf8_get_char (state->layout->text + state->gap_start_iter.run_iter.start_index);
+ is_cjk = g_unichar_iswide (start_wc);
+
+ if (is_cjk != state->ellipsis_is_cjk)
+ {
+ state->ellipsis_is_cjk = is_cjk;
+ recompute = TRUE;
+ }
+
+ if (recompute)
+ shape_ellipsis (state);
+}
+
+/* Computes the position of the gap center and finds the smallest span containing it
+ */
+static void
+find_initial_span (EllipsizeState *state)
+{
+ PangoGlyphItem *glyph_item;
+ PangoGlyphItemIter *run_iter;
+ gboolean have_cluster;
+ int i;
+ int x;
+ int cluster_width;
+
+ switch (state->layout->ellipsize)
+ {
+ case PANGO_ELLIPSIZE_NONE:
+ default:
+ g_assert_not_reached ();
+ case PANGO_ELLIPSIZE_START:
+ state->gap_center = 0;
+ break;
+ case PANGO_ELLIPSIZE_MIDDLE:
+ state->gap_center = state->total_width / 2;
+ break;
+ case PANGO_ELLIPSIZE_END:
+ state->gap_center = state->total_width;
+ break;
+ }
+
+ /* Find the run containing the gap center
+ */
+ x = 0;
+ for (i = 0; i < state->n_runs; i++)
+ {
+ if (x + state->run_info[i].width > state->gap_center)
+ break;
+
+ x += state->run_info[i].width;
+ }
+
+ if (i == state->n_runs) /* Last run is a closed interval, so back off one run */
+ {
+ i--;
+ x -= state->run_info[i].width;
+ }
+
+ /* Find the cluster containing the gap center
+ */
+ state->gap_start_iter.run_index = i;
+ run_iter = &state->gap_start_iter.run_iter;
+ glyph_item = state->run_info[i].run;
+
+ cluster_width = 0; /* Quiet GCC, the line must have at least one cluster */
+ for (have_cluster = _pango_glyph_item_iter_init_start (run_iter, glyph_item, state->layout->text);
+ have_cluster;
+ have_cluster = _pango_glyph_item_iter_next_cluster (run_iter))
+ {
+ cluster_width = get_cluster_width (&state->gap_start_iter);
+
+ if (x + cluster_width > state->gap_center)
+ break;
+
+ x += cluster_width;
+ }
+
+ if (!have_cluster) /* Last cluster is a closed interval, so back off one cluster */
+ x -= cluster_width;
+
+ state->gap_end_iter = state->gap_start_iter;
+
+ state->gap_start_x = x;
+ state->gap_end_x = x + cluster_width;
+
+ /* Expand the gap to a full span
+ */
+ while (!starts_at_ellipsization_boundary (state, &state->gap_start_iter))
+ {
+ line_iter_prev_cluster (state, &state->gap_start_iter);
+ state->gap_start_x -= get_cluster_width (&state->gap_start_iter);
+ }
+
+ while (!ends_at_ellipsization_boundary (state, &state->gap_end_iter))
+ {
+ line_iter_next_cluster (state, &state->gap_end_iter);
+ state->gap_end_x += get_cluster_width (&state->gap_end_iter);
+ }
+
+ update_ellipsis_shape (state);
+}
+
+/* Removes one run from the start or end of the gap. Returns FALSE
+ * if there's nothing left to remove in either direction.
+ */
+static gboolean
+remove_one_span (EllipsizeState *state)
+{
+ LineIter new_gap_start_iter;
+ LineIter new_gap_end_iter;
+ int new_gap_start_x;
+ int new_gap_end_x;
+ int width;
+
+ /* Find one span backwards and forward from the gap
+ */
+ new_gap_start_iter = state->gap_start_iter;
+ new_gap_start_x = state->gap_start_x;
+ do
+ {
+ if (!line_iter_prev_cluster (state, &new_gap_start_iter))
+ break;
+ width = get_cluster_width (&new_gap_start_iter);
+ new_gap_start_x -= width;
+ }
+ while (!starts_at_ellipsization_boundary (state, &new_gap_start_iter) ||
+ width == 0);
+
+ new_gap_end_iter = state->gap_end_iter;
+ new_gap_end_x = state->gap_end_x;
+ do
+ {
+ if (!line_iter_next_cluster (state, &new_gap_end_iter))
+ break;
+ width = get_cluster_width (&new_gap_end_iter);
+ new_gap_end_x += width;
+ }
+ while (!ends_at_ellipsization_boundary (state, &new_gap_end_iter) ||
+ width == 0);
+
+ if (state->gap_end_x == new_gap_end_x && state->gap_start_x == new_gap_start_x)
+ return FALSE;
+
+ /* In the case where we could remove a span from either end of the
+ * gap, we look at which causes the smaller increase in the
+ * MAX (gap_end - gap_center, gap_start - gap_center)
+ */
+ if (state->gap_end_x == new_gap_end_x ||
+ (state->gap_start_x != new_gap_start_x &&
+ state->gap_center - new_gap_start_x < new_gap_end_x - state->gap_center))
+ {
+ state->gap_start_iter = new_gap_start_iter;
+ state->gap_start_x = new_gap_start_x;
+
+ update_ellipsis_shape (state);
+ }
+ else
+ {
+ state->gap_end_iter = new_gap_end_iter;
+ state->gap_end_x = new_gap_end_x;
+ }
+
+ return TRUE;
+}
+
+/* Fixes up the properties of the ellipsis run once we've determined the final extents
+ * of the gap
+ */
+static void
+fixup_ellipsis_run (EllipsizeState *state)
+{
+ PangoGlyphString *glyphs = state->ellipsis_run->glyphs;
+ PangoItem *item = state->ellipsis_run->item;
+ int level;
+ int i;
+
+ /* Make the entire glyphstring into a single logical cluster */
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ glyphs->log_clusters[i] = 0;
+ glyphs->glyphs[i].attr.is_cluster_start = FALSE;
+ }
+
+ glyphs->glyphs[0].attr.is_cluster_start = TRUE;
+
+ /* Fix up the item to point to the entire elided text */
+ item->offset = state->gap_start_iter.run_iter.start_index;
+ item->length = state->gap_end_iter.run_iter.end_index - item->offset;
+ item->num_chars = g_utf8_strlen (state->layout->text + item->offset, item->length);
+
+ /* The level for the item is the minimum level of the elided text */
+ level = G_MAXINT;
+ for (i = state->gap_start_iter.run_index; i <= state->gap_end_iter.run_index; i++)
+ level = MIN (level, state->run_info[i].run->item->analysis.level);
+
+ item->analysis.level = level;
+}
+
+/* Computes the new list of runs for the line
+ */
+static GSList *
+get_run_list (EllipsizeState *state)
+{
+ PangoGlyphItem *partial_start_run = NULL;
+ PangoGlyphItem *partial_end_run = NULL;
+ GSList *result = NULL;
+ RunInfo *run_info;
+ PangoGlyphItemIter *run_iter;
+ int i;
+
+ /* We first cut out the pieces of the starting and ending runs we want to
+ * preserve; we do the end first in case the end and the start are
+ * the same. Doing the start first would disturb the indices for the end.
+ */
+ run_info = &state->run_info[state->gap_end_iter.run_index];
+ run_iter = &state->gap_end_iter.run_iter;
+ if (run_iter->end_char != run_info->run->item->num_chars)
+ {
+ partial_end_run = run_info->run;
+ run_info->run = pango_glyph_item_split (run_info->run, state->layout->text,
+ run_iter->end_index - run_info->run->item->offset);
+ }
+
+ run_info = &state->run_info[state->gap_start_iter.run_index];
+ run_iter = &state->gap_start_iter.run_iter;
+ if (run_iter->start_char != 0)
+ {
+ partial_start_run = pango_glyph_item_split (run_info->run, state->layout->text,
+ run_iter->start_index - run_info->run->item->offset);
+ }
+
+ /* Now assemble the new list of runs
+ */
+ for (i = 0; i < state->gap_start_iter.run_index; i++)
+ result = g_slist_prepend (result, state->run_info[i].run);
+
+ if (partial_start_run)
+ result = g_slist_prepend (result, partial_start_run);
+
+ result = g_slist_prepend (result, state->ellipsis_run);
+
+ if (partial_end_run)
+ result = g_slist_prepend (result, partial_end_run);
+
+ for (i = state->gap_end_iter.run_index + 1; i < state->n_runs; i++)
+ result = g_slist_prepend (result, state->run_info[i].run);
+
+ /* And free the ones we didn't use
+ */
+ for (i = state->gap_start_iter.run_index; i <= state->gap_end_iter.run_index; i++)
+ pango_glyph_item_free (state->run_info[i].run);
+
+ return g_slist_reverse (result);
+}
+
+/* Computes the width of the line as currently ellipsized
+ */
+static int
+current_width (EllipsizeState *state)
+{
+ return state->total_width - (state->gap_end_x - state->gap_start_x) + state->ellipsis_width;
+}
+
+/**
+ * _pango_layout_line_ellipsize:
+ * @line: a #PangoLayoutLine
+ * @attrs: Attributes being used for itemization/shaping
+ *
+ * Given a #PangoLayoutLine with the runs still in logical order, ellipsize
+ * it according the layout's policy to fit within the set width of the layout.
+ *
+ * Return value: whether the line had to be ellipsized
+ **/
+gboolean
+_pango_layout_line_ellipsize (PangoLayoutLine *line,
+ PangoAttrList *attrs)
+{
+ EllipsizeState state;
+ int goal_width;
+ gboolean is_ellipsized = FALSE;
+
+ if (line->layout->ellipsize == PANGO_ELLIPSIZE_NONE ||
+ line->layout->width < 0)
+ goto ret;
+
+ init_state (&state, line, attrs);
+
+ goal_width = state.layout->width;
+ if (state.layout->indent > 0 && state.layout->alignment != PANGO_ALIGN_CENTER)
+ goal_width -= state.layout->indent;
+
+ if (state.total_width <= goal_width)
+ goto out;
+
+ find_initial_span (&state);
+
+ while (current_width (&state) > goal_width)
+ {
+ if (!remove_one_span (&state))
+ break;
+ }
+
+ fixup_ellipsis_run (&state);
+
+ g_slist_free (line->runs);
+ line->runs = get_run_list (&state);
+ is_ellipsized = TRUE;
+
+ out:
+ free_state (&state);
+ ret:
+ return is_ellipsized;
+}
diff --git a/trunk/pango/fonts.c b/trunk/pango/fonts.c
new file mode 100644
index 00000000..0979ba1a
--- /dev/null
+++ b/trunk/pango/fonts.c
@@ -0,0 +1,1855 @@
+/* Pango
+ * fonts.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "pango-types.h"
+#include "pango-font.h"
+#include "pango-fontmap.h"
+#include "pango-impl-utils.h"
+
+static const char bad_font_warning[] = "%s called with null font argument, expect ugly output";
+
+struct _PangoFontDescription
+{
+ char *family_name;
+
+ PangoStyle style;
+ PangoVariant variant;
+ PangoWeight weight;
+ PangoStretch stretch;
+ PangoGravity gravity;
+
+ guint16 mask;
+ guint static_family : 1;
+ guint size_is_absolute : 1;
+
+ int size;
+};
+
+GType
+pango_font_description_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoFontDescription"),
+ (GBoxedCopyFunc)pango_font_description_copy,
+ (GBoxedFreeFunc)pango_font_description_free);
+
+ return our_type;
+}
+
+
+static const PangoFontDescription pfd_defaults = {
+ NULL, /* family_name */
+
+ PANGO_STYLE_NORMAL, /* style */
+ PANGO_VARIANT_NORMAL, /* variant */
+ PANGO_WEIGHT_NORMAL, /* weight */
+ PANGO_STRETCH_NORMAL, /* stretch */
+ PANGO_GRAVITY_SOUTH, /* gravity */
+
+ 0, /* mask */
+ 0, /* static_family */
+ FALSE, /* size_is_absolute */
+
+ 0, /* size */
+};
+
+/**
+ * pango_font_description_new:
+ *
+ * Creates a new font description structure with all fields unset.
+ *
+ * Return value: the newly allocated #PangoFontDescription, which
+ * should be freed using pango_font_description_free().
+ **/
+PangoFontDescription *
+pango_font_description_new (void)
+{
+ PangoFontDescription *desc = g_slice_new (PangoFontDescription);
+
+ *desc = pfd_defaults;
+
+ return desc;
+}
+
+/**
+ * pango_font_description_set_family:
+ * @desc: a #PangoFontDescription.
+ * @family: a string representing the family name.
+ *
+ * Sets the family name field of a font description. The family
+ * name represents a family of related font styles, and will
+ * resolve to a particular #PangoFontFamily. In some uses of
+ * #PangoFontDescription, it is also possible to use a comma
+ * separated list of family names for this field.
+ **/
+void
+pango_font_description_set_family (PangoFontDescription *desc,
+ const char *family)
+{
+ g_return_if_fail (desc != NULL);
+
+ pango_font_description_set_family_static (desc, family ? g_strdup (family) : NULL);
+ if (family)
+ desc->static_family = FALSE;
+}
+
+/**
+ * pango_font_description_set_family_static:
+ * @desc: a #PangoFontDescription
+ * @family: a string representing the family name.
+ *
+ * Like pango_font_description_set_family(), except that no
+ * copy of @family is made. The caller must make sure that the
+ * string passed in stays around until @desc has been freed
+ * or the name is set again. This function can be used if
+ * @family is a static string such as a C string literal, or
+ * if @desc is only needed temporarily.
+ **/
+void
+pango_font_description_set_family_static (PangoFontDescription *desc,
+ const char *family)
+{
+ g_return_if_fail (desc != NULL);
+
+ if (desc->family_name == family)
+ return;
+
+ if (desc->family_name && !desc->static_family)
+ g_free (desc->family_name);
+
+ if (family)
+ {
+ desc->family_name = (char *)family;
+ desc->static_family = TRUE;
+ desc->mask |= PANGO_FONT_MASK_FAMILY;
+ }
+ else
+ {
+ desc->family_name = pfd_defaults.family_name;
+ desc->static_family = pfd_defaults.static_family;
+ desc->mask &= ~PANGO_FONT_MASK_FAMILY;
+ }
+}
+
+/**
+ * pango_font_description_get_family:
+ * @desc: a #PangoFontDescription.
+ *
+ * Gets the family name field of a font description. See
+ * pango_font_description_set_family().
+ *
+ * Return value: the family name field for the font description, or
+ * %NULL if not previously set. This has the same life-time
+ * as the font description itself and should not be freed.
+ **/
+G_CONST_RETURN char *
+pango_font_description_get_family (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ return desc->family_name;
+}
+
+/**
+ * pango_font_description_set_style:
+ * @desc: a #PangoFontDescription
+ * @style: the style for the font description
+ *
+ * Sets the style field of a #PangoFontDescription. The
+ * #PangoStyle enumeration describes whether the font is slanted and
+ * the manner in which it is slanted; it can be either
+ * #PANGO_STYLE_NORMAL, #PANGO_STYLE_ITALIC, or #PANGO_STYLE_OBLIQUE.
+ * Most fonts will either have a italic style or an oblique
+ * style, but not both, and font matching in Pango will
+ * match italic specifications with oblique fonts and vice-versa
+ * if an exact match is not found.
+ **/
+void
+pango_font_description_set_style (PangoFontDescription *desc,
+ PangoStyle style)
+{
+ g_return_if_fail (desc != NULL);
+
+ desc->style = style;
+ desc->mask |= PANGO_FONT_MASK_STYLE;
+}
+
+/**
+ * pango_font_description_get_style:
+ * @desc: a #PangoFontDescription
+ *
+ * Gets the style field of a #PangoFontDescription. See
+ * pango_font_description_set_style().
+ *
+ * Return value: the style field for the font description.
+ * Use pango_font_description_get_set_fields() to find out if
+ * the field was explicitly set or not.
+ **/
+PangoStyle
+pango_font_description_get_style (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, pfd_defaults.style);
+
+ return desc->style;
+}
+
+/**
+ * pango_font_description_set_variant:
+ * @desc: a #PangoFontDescription
+ * @variant: the variant type for the font description.
+ *
+ * Sets the variant field of a font description. The #PangoVariant
+ * can either be %PANGO_VARIANT_NORMAL or %PANGO_VARIANT_SMALL_CAPS.
+ **/
+void
+pango_font_description_set_variant (PangoFontDescription *desc,
+ PangoVariant variant)
+{
+ g_return_if_fail (desc != NULL);
+
+ desc->variant = variant;
+ desc->mask |= PANGO_FONT_MASK_VARIANT;
+}
+
+/**
+ * pango_font_description_get_variant:
+ * @desc: a #PangoFontDescription.
+ *
+ * Gets the variant field of a #PangoFontDescription. See
+ * pango_font_description_set_variant().
+ *
+ * Return value: the variant field for the font description. Use
+ * pango_font_description_get_set_fields() to find out if
+ * the field was explicitly set or not.
+ **/
+PangoVariant
+pango_font_description_get_variant (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, pfd_defaults.variant);
+
+ return desc->variant;
+}
+
+/**
+ * pango_font_description_set_weight:
+ * @desc: a #PangoFontDescription
+ * @weight: the weight for the font description.
+ *
+ * Sets the weight field of a font description. The weight field
+ * specifies how bold or light the font should be. In addition
+ * to the values of the #PangoWeight enumeration, other intermediate
+ * numeric values are possible.
+ **/
+void
+pango_font_description_set_weight (PangoFontDescription *desc,
+ PangoWeight weight)
+{
+ g_return_if_fail (desc != NULL);
+
+ desc->weight = weight;
+ desc->mask |= PANGO_FONT_MASK_WEIGHT;
+}
+
+/**
+ * pango_font_description_get_weight:
+ * @desc: a #PangoFontDescription
+ *
+ * Gets the weight field of a font description. See
+ * pango_font_description_set_weight().
+ *
+ * Return value: the weight field for the font description. Use
+ * pango_font_description_get_set_fields() to find out if
+ * the field was explicitly set or not.
+ **/
+PangoWeight
+pango_font_description_get_weight (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, pfd_defaults.weight);
+
+ return desc->weight;
+}
+
+/**
+ * pango_font_description_set_stretch:
+ * @desc: a #PangoFontDescription
+ * @stretch: the stretch for the font description
+ *
+ * Sets the stretch field of a font description. The stretch field
+ * specifies how narrow or wide the font should be.
+ **/
+void
+pango_font_description_set_stretch (PangoFontDescription *desc,
+ PangoStretch stretch)
+{
+ g_return_if_fail (desc != NULL);
+
+ desc->stretch = stretch;
+ desc->mask |= PANGO_FONT_MASK_STRETCH;
+}
+
+/**
+ * pango_font_description_get_stretch:
+ * @desc: a #PangoFontDescription.
+ *
+ * Gets the stretch field of a font description.
+ * See pango_font_description_set_stretch().
+ *
+ * Return value: the stretch field for the font description. Use
+ * pango_font_description_get_set_fields() to find out if
+ * the field was explicitly set or not.
+ **/
+PangoStretch
+pango_font_description_get_stretch (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, pfd_defaults.stretch);
+
+ return desc->stretch;
+}
+
+/**
+ * pango_font_description_set_size:
+ * @desc: a #PangoFontDescription
+ * @size: the size of the font in points, scaled by PANGO_SCALE. (That is,
+ * a @size value of 10 * PANGO_SCALE is a 10 point font. The conversion
+ * factor between points and device units depends on system configuration
+ * and the output device. For screen display, a logical DPI of 96 is
+ * common, in which case a 10 point font corresponds to a 10 * (96 / 72) = 13.3
+ * pixel font. Use pango_font_description_set_absolute_size() if you need
+ * a particular size in device units.
+ *
+ * Sets the size field of a font description in fractional points. This is mutually
+ * exclusive with pango_font_description_set_absolute_size().
+ **/
+void
+pango_font_description_set_size (PangoFontDescription *desc,
+ gint size)
+{
+ g_return_if_fail (desc != NULL);
+ g_return_if_fail (size >= 0);
+
+ desc->size = size;
+ desc->size_is_absolute = FALSE;
+ desc->mask |= PANGO_FONT_MASK_SIZE;
+}
+
+/**
+ * pango_font_description_get_size:
+ * @desc: a #PangoFontDescription
+ *
+ * Gets the size field of a font description.
+ * See pango_font_description_set_size().
+ *
+ * Return value: the size field for the font description in points or device units.
+ * You must call pango_font_description_get_size_is_absolute()
+ * to find out which is the case. Returns 0 if the size field has not
+ * previously been set or it has been set to 0 explicitly.
+ * Use pango_font_description_get_set_fields() to
+ * find out if the field was explicitly set or not.
+ **/
+gint
+pango_font_description_get_size (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, pfd_defaults.size);
+
+ return desc->size;
+}
+
+/**
+ * pango_font_description_set_absolute_size:
+ * @desc: a #PangoFontDescription
+ * @size: the new size, in Pango units. There are %PANGO_SCALE Pango units in one
+ * device unit. For an output backend where a device unit is a pixel, a @size
+ * value of 10 * PANGO_SCALE gives a 10 pixel font.
+ *
+ * Sets the size field of a font description, in device units. This is mutually
+ * exclusive with pango_font_description_set_size() which sets the font size
+ * in points.
+ *
+ * Since: 1.8
+ **/
+void
+pango_font_description_set_absolute_size (PangoFontDescription *desc,
+ double size)
+{
+ g_return_if_fail (desc != NULL);
+ g_return_if_fail (size >= 0);
+
+ desc->size = size;
+ desc->size_is_absolute = TRUE;
+ desc->mask |= PANGO_FONT_MASK_SIZE;
+}
+
+/**
+ * pango_font_description_get_size_is_absolute:
+ * @desc: a #PangoFontDescription
+ *
+ * Determines whether the size of the font is in points (not absolute) or device units (absolute).
+ * See pango_font_description_set_size() and pango_font_description_set_absolute_size().
+ *
+ * Return value: whether the size for the font description is in
+ * points or device units. Use pango_font_description_get_set_fields() to
+ * find out if the size field of the font description was explicitly set or not.
+ *
+ * Since: 1.8
+ **/
+gboolean
+pango_font_description_get_size_is_absolute (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, pfd_defaults.size_is_absolute);
+
+ return desc->size_is_absolute;
+}
+
+/**
+ * pango_font_description_set_gravity:
+ * @desc: a #PangoFontDescription
+ * @gravity: the gravity for the font description.
+ *
+ * Sets the gravity field of a font description. The gravity field
+ * specifies how the glyphs should be rotated. If @gravity is
+ * %PANGO_GRAVITY_AUTO, this actually unsets the gravity mask on
+ * the font description.
+ *
+ * This function is seldom useful to the user. Gravity should normally
+ * be set on a #PangoContext.
+ *
+ * Since: 1.16
+ **/
+void
+pango_font_description_set_gravity (PangoFontDescription *desc,
+ PangoGravity gravity)
+{
+ g_return_if_fail (desc != NULL);
+
+ if (gravity == PANGO_GRAVITY_AUTO)
+ {
+ pango_font_description_unset_fields (desc, PANGO_FONT_MASK_GRAVITY);
+ return;
+ }
+
+ desc->gravity = gravity;
+ desc->mask |= PANGO_FONT_MASK_GRAVITY;
+}
+
+/**
+ * pango_font_description_get_gravity:
+ * @desc: a #PangoFontDescription
+ *
+ * Gets the gravity field of a font description. See
+ * pango_font_description_set_gravity().
+ *
+ * Return value: the gravity field for the font description. Use
+ * pango_font_description_get_set_fields() to find out if
+ * the field was explicitly set or not.
+ *
+ * Since: 1.16
+ **/
+PangoGravity
+pango_font_description_get_gravity (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, pfd_defaults.gravity);
+
+ return desc->gravity;
+}
+
+/**
+ * pango_font_description_get_set_fields:
+ * @desc: a #PangoFontDescription
+ *
+ * Determines which fields in a font description have been set.
+ *
+ * Return value: a bitmask with bits set corresponding to the
+ * fields in @desc that have been set.
+ **/
+PangoFontMask
+pango_font_description_get_set_fields (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, pfd_defaults.mask);
+
+ return desc->mask;
+}
+
+/**
+ * pango_font_description_unset_fields:
+ * @desc: a #PangoFontDescription
+ * @to_unset: bitmask of fields in the @desc to unset.
+ *
+ * Unsets some of the fields in a #PangoFontDescription. The unset
+ * fields will get back to their default values.
+ **/
+void
+pango_font_description_unset_fields (PangoFontDescription *desc,
+ PangoFontMask to_unset)
+{
+ PangoFontDescription unset_desc;
+
+ g_return_if_fail (desc != NULL);
+
+ unset_desc = pfd_defaults;
+ unset_desc.mask = to_unset;
+
+ pango_font_description_merge_static (desc, &unset_desc, TRUE);
+
+ desc->mask &= ~to_unset;
+}
+
+/**
+ * pango_font_description_merge:
+ * @desc: a #PangoFontDescription
+ * @desc_to_merge: the #PangoFontDescription to merge from
+ * @replace_existing: if %TRUE, replace fields in @desc with the
+ * corresponding values from @desc_to_merge, even if they
+ * are already exist.
+ *
+ * Merges the fields that are set in @desc_to_merge into the fields in
+ * @desc. If @replace_existing is %FALSE, only fields in @desc that
+ * are not already set are affected. If %TRUE, then fields that are
+ * already set will be replaced as well.
+ **/
+void
+pango_font_description_merge (PangoFontDescription *desc,
+ const PangoFontDescription *desc_to_merge,
+ gboolean replace_existing)
+{
+ gboolean family_merged;
+
+ g_return_if_fail (desc != NULL);
+ g_return_if_fail (desc_to_merge != NULL);
+
+ family_merged = desc_to_merge->family_name && (replace_existing || !desc->family_name);
+
+ pango_font_description_merge_static (desc, desc_to_merge, replace_existing);
+
+ if (family_merged)
+ {
+ desc->family_name = g_strdup (desc->family_name);
+ desc->static_family = FALSE;
+ }
+}
+
+/**
+ * pango_font_description_merge_static:
+ * @desc: a #PangoFontDescription
+ * @desc_to_merge: the #PangoFontDescription to merge from
+ * @replace_existing: if %TRUE, replace fields in @desc with the
+ * corresponding values from @desc_to_merge, even if they
+ * are already exist.
+ *
+ * Like pango_font_description_merge(), but only a shallow copy is made
+ * of the family name and other allocated fields. @desc can only be
+ * used until @desc_to_merge is modified or freed. This is meant
+ * to be used when the merged font description is only needed temporarily.
+ **/
+void
+pango_font_description_merge_static (PangoFontDescription *desc,
+ const PangoFontDescription *desc_to_merge,
+ gboolean replace_existing)
+{
+ PangoFontMask new_mask;
+
+ g_return_if_fail (desc != NULL);
+ g_return_if_fail (desc_to_merge != NULL);
+
+ if (replace_existing)
+ new_mask = desc_to_merge->mask;
+ else
+ new_mask = desc_to_merge->mask & ~desc->mask;
+
+ if (new_mask & PANGO_FONT_MASK_FAMILY)
+ pango_font_description_set_family_static (desc, desc_to_merge->family_name);
+ if (new_mask & PANGO_FONT_MASK_STYLE)
+ desc->style = desc_to_merge->style;
+ if (new_mask & PANGO_FONT_MASK_VARIANT)
+ desc->variant = desc_to_merge->variant;
+ if (new_mask & PANGO_FONT_MASK_WEIGHT)
+ desc->weight = desc_to_merge->weight;
+ if (new_mask & PANGO_FONT_MASK_STRETCH)
+ desc->stretch = desc_to_merge->stretch;
+ if (new_mask & PANGO_FONT_MASK_SIZE)
+ {
+ desc->size = desc_to_merge->size;
+ desc->size_is_absolute = desc_to_merge->size_is_absolute;
+ }
+ if (new_mask & PANGO_FONT_MASK_GRAVITY)
+ desc->gravity = desc_to_merge->gravity;
+
+ desc->mask |= new_mask;
+}
+
+static gint
+compute_distance (const PangoFontDescription *a,
+ const PangoFontDescription *b)
+{
+ if (a->style == b->style)
+ {
+ return abs(a->weight - b->weight);
+ }
+ else if (a->style != PANGO_STYLE_NORMAL &&
+ b->style != PANGO_STYLE_NORMAL)
+ {
+ /* Equate oblique and italic, but with a big penalty
+ */
+ return 1000000 + abs (a->weight - b->weight);
+ }
+ else
+ return G_MAXINT;
+}
+
+/**
+ * pango_font_description_better_match:
+ * @desc: a #PangoFontDescription
+ * @old_match: a #PangoFontDescription, or %NULL
+ * @new_match: a #PangoFontDescription
+ *
+ * Determines if the style attributes of @new_match are a closer match
+ * for @desc than @old_match, or if @old_match is %NULL, determines if
+ * @new_match is a match at all. Approximate matching is done for
+ * weight and style; other attributes must match exactly.
+ *
+ * Return value: %TRUE if @new_match is a better match
+ **/
+gboolean
+pango_font_description_better_match (const PangoFontDescription *desc,
+ const PangoFontDescription *old_match,
+ const PangoFontDescription *new_match)
+{
+ g_return_val_if_fail (desc != NULL, G_MAXINT);
+ g_return_val_if_fail (new_match != NULL, G_MAXINT);
+
+ if (new_match->variant == desc->variant &&
+ new_match->stretch == desc->stretch &&
+ new_match->gravity == desc->gravity)
+ {
+ int old_distance = old_match ? compute_distance (desc, old_match) : G_MAXINT;
+ int new_distance = compute_distance (desc, new_match);
+
+ if (new_distance < old_distance)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * pango_font_description_copy:
+ * @desc: a #PangoFontDescription
+ *
+ * Make a copy of a #PangoFontDescription.
+ *
+ * Return value: the newly allocated #PangoFontDescription, which should
+ * be freed with pango_font_description_free().
+ **/
+PangoFontDescription *
+pango_font_description_copy (const PangoFontDescription *desc)
+{
+ PangoFontDescription *result;
+
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ result = g_slice_new (PangoFontDescription);
+
+ *result = *desc;
+
+ if (result->family_name)
+ {
+ result->family_name = g_strdup (result->family_name);
+ result->static_family = FALSE;
+ }
+
+ return result;
+}
+
+/**
+ * pango_font_description_copy_static:
+ * @desc: a #PangoFontDescription
+ *
+ * Like pango_font_description_copy(), but only a shallow copy is made
+ * of the family name and other allocated fields. The result can only
+ * be used until @desc is modified or freed. This is meant to be used
+ * when the copy is only needed temporarily.
+ *
+ * Return value: the newly allocated #PangoFontDescription, which should
+ * be freed with pango_font_description_free().
+ **/
+PangoFontDescription *
+pango_font_description_copy_static (const PangoFontDescription *desc)
+{
+ PangoFontDescription *result;
+
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ result = g_slice_new (PangoFontDescription);
+
+ *result = *desc;
+ if (result->family_name)
+ result->static_family = TRUE;
+
+ return result;
+}
+
+/**
+ * pango_font_description_equal:
+ * @desc1: a #PangoFontDescription
+ * @desc2: another #PangoFontDescription
+ *
+ * Compares two font descriptions for equality. Two font descriptions
+ * are considered equal if the fonts they describe are provably identical.
+ * This means that their masks do not have to match, as long as other fields
+ * are all the same. (Two font descriptions may result in identical fonts
+ * being loaded, but still compare %FALSE.)
+ *
+ * Return value: %TRUE if the two font descriptions are identical,
+ * %FALSE otherwise.
+ **/
+gboolean
+pango_font_description_equal (const PangoFontDescription *desc1,
+ const PangoFontDescription *desc2)
+{
+ g_return_val_if_fail (desc1 != NULL, FALSE);
+ g_return_val_if_fail (desc2 != NULL, FALSE);
+
+ return desc1->style == desc2->style &&
+ desc1->variant == desc2->variant &&
+ desc1->weight == desc2->weight &&
+ desc1->stretch == desc2->stretch &&
+ desc1->size == desc2->size &&
+ desc1->size_is_absolute == desc2->size_is_absolute &&
+ desc1->gravity == desc2->gravity &&
+ (desc1->family_name == desc2->family_name ||
+ (desc1->family_name && desc2->family_name && g_ascii_strcasecmp (desc1->family_name, desc2->family_name) == 0));
+}
+
+#define TOLOWER(c) \
+ (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
+static guint
+case_insensitive_hash (const char *key)
+{
+ const char *p = key;
+ guint h = TOLOWER (*p);
+
+ if (h)
+ {
+ for (p += 1; *p != '\0'; p++)
+ h = (h << 5) - h + TOLOWER (*p);
+ }
+
+ return h;
+}
+
+/**
+ * pango_font_description_hash:
+ * @desc: a #PangoFontDescription
+ *
+ * Computes a hash of a #PangoFontDescription structure suitable
+ * to be used, for example, as an argument to g_hash_table_new().
+ * The hash value is independent of @desc->mask.
+ *
+ * Return value: the hash value.
+ **/
+guint
+pango_font_description_hash (const PangoFontDescription *desc)
+{
+ guint hash = 0;
+
+ g_return_val_if_fail (desc != NULL, 0);
+
+ if (desc->family_name)
+ hash = case_insensitive_hash (desc->family_name);
+ hash ^= desc->size;
+ hash ^= desc->size_is_absolute ? 0xc33ca55a : 0;
+ hash ^= desc->style << 16;
+ hash ^= desc->variant << 18;
+ hash ^= desc->weight << 16;
+ hash ^= desc->stretch << 26;
+ hash ^= desc->gravity << 28;
+
+ return hash;
+}
+
+/**
+ * pango_font_description_free:
+ * @desc: a #PangoFontDescription, or %NULL
+ *
+ * Frees a font description.
+ **/
+void
+pango_font_description_free (PangoFontDescription *desc)
+{
+ if (desc)
+ {
+ if (desc->family_name && !desc->static_family)
+ g_free (desc->family_name);
+
+ g_slice_free (PangoFontDescription, desc);
+ }
+}
+
+/**
+ * pango_font_descriptions_free:
+ * @descs: a pointer to an array of #PangoFontDescription, or %NULL
+ * @n_descs: number of font descriptions in @descs
+ *
+ * Frees a list of font descriptions from pango_font_map_list_fonts()
+ **/
+void
+pango_font_descriptions_free (PangoFontDescription **descs,
+ int n_descs)
+{
+ int i;
+
+ if (descs)
+ {
+ for (i = 0; i<n_descs; i++)
+ pango_font_description_free (descs[i]);
+ g_free (descs);
+ }
+}
+
+typedef struct
+{
+ int value;
+ const char str[16];
+} FieldMap;
+
+static const FieldMap style_map[] = {
+ { PANGO_STYLE_NORMAL, "" },
+ { PANGO_STYLE_OBLIQUE, "Oblique" },
+ { PANGO_STYLE_ITALIC, "Italic" }
+};
+
+static const FieldMap variant_map[] = {
+ { PANGO_VARIANT_NORMAL, "" },
+ { PANGO_VARIANT_SMALL_CAPS, "Small-Caps" }
+};
+
+static const FieldMap weight_map[] = {
+ { PANGO_WEIGHT_ULTRALIGHT, "Ultra-Light" },
+ { PANGO_WEIGHT_LIGHT, "Light" },
+ { PANGO_WEIGHT_NORMAL, "" },
+ { 500, "Medium" },
+ { PANGO_WEIGHT_SEMIBOLD, "Semi-Bold" },
+ { PANGO_WEIGHT_BOLD, "Bold" },
+ { PANGO_WEIGHT_ULTRABOLD, "Ultra-Bold" },
+ { PANGO_WEIGHT_HEAVY, "Heavy" }
+};
+
+static const FieldMap stretch_map[] = {
+ { PANGO_STRETCH_ULTRA_CONDENSED, "Ultra-Condensed" },
+ { PANGO_STRETCH_EXTRA_CONDENSED, "Extra-Condensed" },
+ { PANGO_STRETCH_CONDENSED, "Condensed" },
+ { PANGO_STRETCH_SEMI_CONDENSED, "Semi-Condensed" },
+ { PANGO_STRETCH_NORMAL, "" },
+ { PANGO_STRETCH_SEMI_EXPANDED, "Semi-Expanded" },
+ { PANGO_STRETCH_EXPANDED, "Expanded" },
+ { PANGO_STRETCH_EXTRA_EXPANDED, "Extra-Expanded" },
+ { PANGO_STRETCH_ULTRA_EXPANDED, "Ultra-Expanded" }
+};
+
+static const FieldMap gravity_map[] = {
+ { PANGO_GRAVITY_SOUTH, "Not-Rotated" },
+ { PANGO_GRAVITY_SOUTH, "South" },
+ { PANGO_GRAVITY_SOUTH, "Upside-Down" },
+ { PANGO_GRAVITY_NORTH, "North" },
+ { PANGO_GRAVITY_EAST, "Rotated-Left" },
+ { PANGO_GRAVITY_EAST, "East" },
+ { PANGO_GRAVITY_WEST, "Rotated-Right" },
+ { PANGO_GRAVITY_WEST, "West" }
+};
+
+static gboolean
+find_field (const FieldMap *map, int n_elements, const char *str, int len, int *val)
+{
+ int i;
+
+ for (i=0; i<n_elements; i++)
+ {
+ if (map[i].str[0] && g_ascii_strncasecmp (map[i].str, str, len) == 0 &&
+ map[i].str[len] == '\0')
+ {
+ if (val)
+ *val = map[i].value;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+find_field_any (const char *str, int len, PangoFontDescription *desc)
+{
+ gboolean found = FALSE;
+
+ if (g_ascii_strcasecmp (str, "Normal") == 0)
+ return TRUE;
+
+#define FIELD(NAME, MASK) \
+ G_STMT_START { \
+ if (find_field (NAME##_map, G_N_ELEMENTS (NAME##_map), str, len, \
+ desc ? (int *)&desc->NAME : NULL)) \
+ { \
+ found = TRUE; \
+ if (desc) \
+ desc->mask |= MASK; \
+ } \
+ } G_STMT_END
+
+ FIELD (style, PANGO_FONT_MASK_STYLE);
+ FIELD (variant, PANGO_FONT_MASK_VARIANT);
+ FIELD (weight, PANGO_FONT_MASK_WEIGHT);
+ FIELD (stretch, PANGO_FONT_MASK_STRETCH);
+ FIELD (gravity, PANGO_FONT_MASK_GRAVITY);
+
+#undef FIELD
+
+ return found;
+}
+
+static const char *
+getword (const char *str, const char *last, size_t *wordlen)
+{
+ const char *result;
+
+ while (last > str && g_ascii_isspace (*(last - 1)))
+ last--;
+
+ result = last;
+ while (result > str && !g_ascii_isspace (*(result - 1)))
+ result--;
+
+ *wordlen = last - result;
+
+ return result;
+}
+
+static gboolean
+parse_size (const char *word,
+ size_t wordlen,
+ int *pango_size,
+ gboolean *size_is_absolute)
+{
+ char *end;
+ double size = g_ascii_strtod (word, &end);
+
+ if (end != word &&
+ (end == word + wordlen ||
+ (end + 2 == word + wordlen && !strncmp (end, "px", 2))
+ ) && size >= 0 && size <= 1000000) /* word is a valid float */
+ {
+ if (pango_size)
+ *pango_size = (int)(size * PANGO_SCALE + 0.5);
+
+ if (size_is_absolute)
+ *size_is_absolute = end < word + wordlen;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * pango_font_description_from_string:
+ * @str: string representation of a font description.
+ *
+ * Creates a new font description from a string representation in the
+ * form "[FAMILY-LIST] [STYLE-OPTIONS] [SIZE]", where FAMILY-LIST is a
+ * comma separated list of families optionally terminated by a comma,
+ * STYLE_OPTIONS is a whitespace separated list of words where each WORD
+ * describes one of style, variant, weight, stretch, or gravity, and SIZE
+ * is a decimal number (size in points) or optionally followed by the
+ * unit modifier "px" for absolute size. Any one of the options may
+ * be absent. If FAMILY-LIST is absent, then the family_name field of
+ * the resulting font description will be initialized to %NULL. If
+ * STYLE-OPTIONS is missing, then all style options will be set to the
+ * default values. If SIZE is missing, the size in the resulting font
+ * description will be set to 0.
+ *
+ * Return value: a new #PangoFontDescription.
+ **/
+PangoFontDescription *
+pango_font_description_from_string (const char *str)
+{
+ PangoFontDescription *desc;
+ const char *p, *last;
+ size_t len, wordlen;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ desc = pango_font_description_new ();
+
+ desc->mask = PANGO_FONT_MASK_STYLE |
+ PANGO_FONT_MASK_WEIGHT |
+ PANGO_FONT_MASK_VARIANT |
+ PANGO_FONT_MASK_STRETCH;
+
+ len = strlen (str);
+ last = str + len;
+ p = getword (str, last, &wordlen);
+
+ /* Look for a size at the end of the string
+ */
+ if (wordlen != 0)
+ {
+ gboolean size_is_absolute;
+ if (parse_size (p, wordlen, &desc->size, &size_is_absolute))
+ {
+ desc->size_is_absolute = size_is_absolute;
+ desc->mask |= PANGO_FONT_MASK_SIZE;
+ last = p;
+ }
+ }
+
+ /* Now parse style words
+ */
+ p = getword (str, last, &wordlen);
+ while (wordlen != 0)
+ {
+ if (!find_field_any (p, wordlen, desc))
+ break;
+ else
+ {
+ last = p;
+ p = getword (str, last, &wordlen);
+ }
+ }
+
+ /* Remainder (str => p) is family list. Trim off trailing commas and leading and trailing white space
+ */
+
+ while (last > str && g_ascii_isspace (*(last - 1)))
+ last--;
+
+ if (last > str && *(last - 1) == ',')
+ last--;
+
+ while (last > str && g_ascii_isspace (*(last - 1)))
+ last--;
+
+ while (last > str && g_ascii_isspace (*str))
+ str++;
+
+ if (str != last)
+ {
+ desc->family_name = g_strndup (str, last - str);
+ desc->mask |= PANGO_FONT_MASK_FAMILY;
+ }
+
+ return desc;
+}
+
+static void
+append_field (GString *str, const FieldMap *map, int n_elements, int val)
+{
+ int i;
+ for (i=0; i<n_elements; i++)
+ {
+ if (map[i].value == val)
+ {
+ if (map[i].str && map[i].str[0])
+ {
+ if (str->len > 0 && str->str[str->len -1] != ' ')
+ g_string_append_c (str, ' ');
+ g_string_append (str, map[i].str);
+ }
+ return;
+ }
+ }
+
+ if (str->len > 0 || str->str[str->len -1] != ' ')
+ g_string_append_c (str, ' ');
+ g_string_append_printf (str, "%d", val);
+}
+
+/**
+ * pango_font_description_to_string:
+ * @desc: a #PangoFontDescription
+ *
+ * Creates a string representation of a font description. See
+ * pango_font_description_from_string() for a description of the
+ * format of the string representation. The family list in the
+ * string description will only have a terminating comma if the
+ * last word of the list is a valid style option.
+ *
+ * Return value: a new string that must be freed with g_free().
+ **/
+char *
+pango_font_description_to_string (const PangoFontDescription *desc)
+{
+ GString *result;
+
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ result = g_string_new (NULL);
+
+ if (desc->family_name && desc->mask & PANGO_FONT_MASK_FAMILY)
+ {
+ const char *p;
+ size_t wordlen;
+
+ g_string_append (result, desc->family_name);
+
+ /* We need to add a trailing comma if the family name ends
+ * in a keyword like "Bold", or if the family name ends in
+ * a number and no keywords will be added.
+ */
+ p = getword (desc->family_name, desc->family_name + strlen(desc->family_name), &wordlen);
+ if (wordlen != 0 &&
+ (find_field_any (p, wordlen, NULL) ||
+ (parse_size (p, wordlen, NULL, NULL) &&
+ desc->weight == PANGO_WEIGHT_NORMAL &&
+ desc->style == PANGO_STYLE_NORMAL &&
+ desc->stretch == PANGO_STRETCH_NORMAL &&
+ desc->variant == PANGO_VARIANT_NORMAL &&
+ (desc->mask & (PANGO_FONT_MASK_GRAVITY | PANGO_FONT_MASK_SIZE)) == 0)))
+ g_string_append_c (result, ',');
+ }
+
+ append_field (result, weight_map, G_N_ELEMENTS (weight_map), desc->weight);
+ append_field (result, style_map, G_N_ELEMENTS (style_map), desc->style);
+ append_field (result, stretch_map, G_N_ELEMENTS (stretch_map), desc->stretch);
+ append_field (result, variant_map, G_N_ELEMENTS (variant_map), desc->variant);
+ if (desc->mask & PANGO_FONT_MASK_GRAVITY)
+ append_field (result, gravity_map, G_N_ELEMENTS (gravity_map), desc->gravity);
+
+ if (result->len == 0)
+ g_string_append (result, "Normal");
+
+ if (desc->mask & PANGO_FONT_MASK_SIZE)
+ {
+ char buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+ if (result->len > 0 || result->str[result->len -1] != ' ')
+ g_string_append_c (result, ' ');
+
+ g_ascii_dtostr (buf, sizeof (buf), (double)desc->size / PANGO_SCALE);
+ g_string_append (result, buf);
+
+ if (desc->size_is_absolute)
+ g_string_append (result, "px");
+ }
+
+ return g_string_free (result, FALSE);
+}
+
+/**
+ * pango_font_description_to_filename:
+ * @desc: a #PangoFontDescription
+ *
+ * Creates a filename representation of a font description. The
+ * filename is identical to the result from calling
+ * pango_font_description_to_string(), but with underscores instead of
+ * characters that are untypical in filenames, and in lower case only.
+ *
+ * Return value: a new string that must be freed with g_free().
+ **/
+char *
+pango_font_description_to_filename (const PangoFontDescription *desc)
+{
+ char *result;
+ char *p;
+
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ result = pango_font_description_to_string (desc);
+
+ /* XXX This should be rewritten to read char-by-char instead
+ * of byte-by-byte, to be Unicode safe.
+ */
+ p = result;
+ while (*p)
+ {
+ if (strchr ("-+_.", *p) == NULL && !g_ascii_isalnum (*p))
+ *p = '_';
+ else
+ *p = g_ascii_tolower (*p);
+ p++;
+ }
+
+ return result;
+}
+
+G_DEFINE_TYPE (PangoFont, pango_font, G_TYPE_OBJECT)
+
+static void
+pango_font_class_init (PangoFontClass *class)
+{
+}
+
+static void
+pango_font_init (PangoFont *font)
+{
+}
+
+/**
+ * pango_font_describe:
+ * @font: a #PangoFont
+ *
+ * Returns a description of the font, with font size set in points.
+ * Use pango_font_describe_with_absolute_size() if you want the font
+ * size in device units.
+ *
+ * Return value: a newly-allocated #PangoFontDescription object.
+ **/
+PangoFontDescription *
+pango_font_describe (PangoFont *font)
+{
+ g_return_val_if_fail (font != NULL, NULL);
+
+ return PANGO_FONT_GET_CLASS (font)->describe (font);
+}
+
+/**
+ * pango_font_describe_with_absolute_size:
+ * @font: a #PangoFont
+ *
+ * Returns a description of the font, with absolute font size set
+ * (in device units). Use pango_font_describe() if you want the font
+ * size in points.
+ *
+ * Return value: a newly-allocated #PangoFontDescription object.
+ *
+ * Since: 1.14
+ **/
+PangoFontDescription *
+pango_font_describe_with_absolute_size (PangoFont *font)
+{
+ g_return_val_if_fail (font != NULL, NULL);
+
+ if (G_UNLIKELY (!PANGO_FONT_GET_CLASS (font)->describe_absolute))
+ {
+ g_warning ("describe_absolute not implemented for this font class, report this as a bug");
+ return pango_font_describe (font);
+ }
+
+ return PANGO_FONT_GET_CLASS (font)->describe_absolute (font);
+}
+
+/**
+ * pango_font_get_coverage:
+ * @font: a #PangoFont
+ * @language: the language tag
+ *
+ * Computes the coverage map for a given font and language tag.
+ *
+ * Return value: a newly-allocated #PangoCoverage object.
+ **/
+PangoCoverage *
+pango_font_get_coverage (PangoFont *font,
+ PangoLanguage *language)
+{
+ g_return_val_if_fail (font != NULL, NULL);
+
+ return PANGO_FONT_GET_CLASS (font)->get_coverage (font, language);
+}
+
+/**
+ * pango_font_find_shaper:
+ * @font: a #PangoFont
+ * @language: the language tag
+ * @ch: a Unicode character.
+ *
+ * Finds the best matching shaper for a font for a particular
+ * language tag and character point.
+ *
+ * Return value: the best matching shaper.
+ **/
+PangoEngineShape *
+pango_font_find_shaper (PangoFont *font,
+ PangoLanguage *language,
+ guint32 ch)
+{
+ PangoEngineShape* shaper;
+
+ g_return_val_if_fail (font != NULL, NULL);
+
+ shaper = PANGO_FONT_GET_CLASS (font)->find_shaper (font, language, ch);
+
+ return shaper;
+}
+
+/**
+ * pango_font_get_glyph_extents:
+ * @font: a #PangoFont
+ * @glyph: the glyph index
+ * @ink_rect: rectangle used to store the extents of the glyph as drawn
+ * or %NULL to indicate that the result is not needed.
+ * @logical_rect: rectangle used to store the logical extents of the glyph
+ * or %NULL to indicate that the result is not needed.
+ *
+ * Gets the logical and ink extents of a glyph within a font. The
+ * coordinate system for each rectangle has its origin at the
+ * base line and horizontal origin of the character with increasing
+ * coordinates extending to the right and down. The macros PANGO_ASCENT(),
+ * PANGO_DESCENT(), PANGO_LBEARING(), and PANGO_RBEARING() can be used to convert
+ * from the extents rectangle to more traditional font metrics. The units
+ * of the rectangles are in 1/PANGO_SCALE of a device unit.
+ **/
+void
+pango_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ if (G_UNLIKELY (!font))
+ {
+
+ if (!_pango_warning_history.get_glyph_extents)
+ {
+ _pango_warning_history.get_glyph_extents = TRUE;
+ g_warning (bad_font_warning, "pango_font_get_glyph_extents");
+ }
+ if (ink_rect)
+ {
+ ink_rect->x = PANGO_SCALE;
+ ink_rect->y = - (PANGO_UNKNOWN_GLYPH_HEIGHT - 1) * PANGO_SCALE;
+ ink_rect->height = (PANGO_UNKNOWN_GLYPH_HEIGHT - 2) * PANGO_SCALE;
+ ink_rect->width = (PANGO_UNKNOWN_GLYPH_WIDTH - 2) * PANGO_SCALE;
+ }
+ if (logical_rect)
+ {
+ logical_rect->x = logical_rect->y = 0;
+ logical_rect->y = - PANGO_UNKNOWN_GLYPH_HEIGHT * PANGO_SCALE;
+ logical_rect->height = PANGO_UNKNOWN_GLYPH_HEIGHT * PANGO_SCALE;
+ logical_rect->width = PANGO_UNKNOWN_GLYPH_WIDTH * PANGO_SCALE;
+ }
+ return;
+ }
+
+ PANGO_FONT_GET_CLASS (font)->get_glyph_extents (font, glyph, ink_rect, logical_rect);
+}
+
+/**
+ * pango_font_get_metrics:
+ * @font: a #PangoFont
+ * @language: language tag used to determine which script to get the metrics
+ * for, or %NULL to indicate to get the metrics for the entire
+ * font.
+ *
+ * Gets overall metric information for a font. Since the metrics may be
+ * substantially different for different scripts, a language tag can
+ * be provided to indicate that the metrics should be retrieved that
+ * correspond to the script(s) used by that language.
+ *
+ * Return value: a #PangoFontMetrics object. The caller must call pango_font_metrics_unref()
+ * when finished using the object.
+ **/
+PangoFontMetrics *
+pango_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ if (G_UNLIKELY (!font))
+ {
+ PangoFontMetrics *metrics;
+
+ if (!_pango_warning_history.get_metrics)
+ {
+ _pango_warning_history.get_metrics = TRUE;
+ g_warning (bad_font_warning, "pango_font_get_metrics");
+ }
+ metrics = pango_font_metrics_new ();
+
+ metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT;
+ metrics->descent = 0;
+ metrics->approximate_char_width = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_WIDTH;
+ metrics->approximate_digit_width = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_WIDTH;
+ metrics->underline_position = -PANGO_SCALE;
+ metrics->underline_thickness = PANGO_SCALE;
+ metrics->strikethrough_position = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT / 2;
+ metrics->strikethrough_thickness = PANGO_SCALE;
+
+ return metrics;
+ }
+
+ return PANGO_FONT_GET_CLASS (font)->get_metrics (font, language);
+}
+
+/**
+ * pango_font_get_font_map:
+ * @font: a #PangoFont
+ *
+ * Gets the font map for which the font was created.
+ *
+ * Return value: the #PangoFontMap for the font
+ *
+ * Since: 1.10
+ **/
+PangoFontMap *
+pango_font_get_font_map (PangoFont *font)
+{
+ if (G_UNLIKELY (!font))
+ {
+
+ if (!_pango_warning_history.get_font_map)
+ {
+ _pango_warning_history.get_font_map = TRUE;
+ g_warning (bad_font_warning, "pango_font_get_font_map");
+ }
+ return NULL;
+ }
+
+ if (PANGO_FONT_GET_CLASS (font)->get_font_map)
+ return PANGO_FONT_GET_CLASS (font)->get_font_map (font);
+ else
+ return NULL;
+}
+
+GType
+pango_font_metrics_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoFontMetrics"),
+ (GBoxedCopyFunc)pango_font_metrics_ref,
+ (GBoxedFreeFunc)pango_font_metrics_unref);
+
+ return our_type;
+}
+
+
+/**
+ * pango_font_metrics_new:
+ *
+ * Creates a new #PangoFontMetrics structure. This is only for
+ * internal use by Pango backends and there is no public way
+ * to set the fields of the structure.
+ *
+ * Return value: a newly-created #PangoFontMetrics structure
+ * with a reference count of 1.
+ **/
+PangoFontMetrics *
+pango_font_metrics_new (void)
+{
+ PangoFontMetrics *metrics = g_slice_new0 (PangoFontMetrics);
+ metrics->ref_count = 1;
+
+ return metrics;
+}
+
+/**
+ * pango_font_metrics_ref:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Increase the reference count of a font metrics structure by one.
+ *
+ * Return value: @metrics
+ **/
+PangoFontMetrics *
+pango_font_metrics_ref (PangoFontMetrics *metrics)
+{
+ if (!metrics)
+ return NULL;
+
+ metrics->ref_count++;
+
+ return metrics;
+}
+
+/**
+ * pango_font_metrics_unref:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Decrease the reference count of a font metrics structure by one. If
+ * the result is zero, frees the structure and any associated
+ * memory.
+ **/
+void
+pango_font_metrics_unref (PangoFontMetrics *metrics)
+{
+ if (!metrics)
+ return;
+ g_return_if_fail (metrics->ref_count > 0 );
+
+ metrics->ref_count--;
+
+ if (metrics->ref_count == 0)
+ g_slice_free (PangoFontMetrics, metrics);
+}
+
+/**
+ * pango_font_metrics_get_ascent:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Gets the ascent from a font metrics structure. The ascent is
+ * the distance from the baseline to the logical top of a line
+ * of text. (The logical top may be above or below the top of the
+ * actual drawn ink. It is necessary to lay out the text to figure
+ * where the ink will be.)
+ *
+ * Return value: the ascent, in Pango units. (1 point == %PANGO_SCALE Pango units.)
+ **/
+int
+pango_font_metrics_get_ascent (PangoFontMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->ascent;
+}
+
+/**
+ * pango_font_metrics_get_descent:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Gets the descent from a font metrics structure. The descent is
+ * the distance from the baseline to the logical bottom of a line
+ * of text. (The logical bottom may be above or below the bottom of the
+ * actual drawn ink. It is necessary to lay out the text to figure
+ * where the ink will be.)
+ *
+ * Return value: the descent, in Pango units. (1 point == %PANGO_SCALE Pango units.)
+ **/
+int
+pango_font_metrics_get_descent (PangoFontMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->descent;
+}
+
+/**
+ * pango_font_metrics_get_approximate_char_width:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Gets the approximate character width for a font metrics structure.
+ * This is merely a representative value useful, for example, for
+ * determining the initial size for a window. Actual characters in
+ * text will be wider and narrower than this.
+ *
+ * Return value: the character width, in Pango units. (1 point == %PANGO_SCALE Pango units.)
+ **/
+int
+pango_font_metrics_get_approximate_char_width (PangoFontMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->approximate_char_width;
+}
+
+/**
+ * pango_font_metrics_get_approximate_digit_width:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Gets the approximate digit width for a font metrics structure.
+ * This is merely a representative value useful, for example, for
+ * determining the initial size for a window. Actual digits in
+ * text can be wider or narrower than this, though this value
+ * is generally somewhat more accurate than the result of
+ * pango_font_metrics_get_approximate_char_width() for digits.
+ *
+ * Return value: the digit width, in Pango units. (1 point == %PANGO_SCALE Pango units.)
+ **/
+int
+pango_font_metrics_get_approximate_digit_width (PangoFontMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->approximate_digit_width;
+}
+
+/**
+ * pango_font_metrics_get_underline_position:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Gets the suggested position to draw the underline.
+ * The value returned is the distance <emphasis>above</emphasis> the
+ * baseline of the top of the underline. Since most fonts have
+ * underline positions beneath the baseline, this value is typically
+ * negative.
+ *
+ * Return value: the suggested underline position, in Pango units.
+ *
+ * Since: 1.6
+ **/
+int
+pango_font_metrics_get_underline_position (PangoFontMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->underline_position;
+}
+
+/**
+ * pango_font_metrics_get_underline_thickness:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Gets the suggested thickness to draw for the underline.
+ *
+ * Return value: the suggested underline thickness, in Pango units.
+ *
+ * Since: 1.6
+ **/
+int
+pango_font_metrics_get_underline_thickness (PangoFontMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->underline_thickness;
+}
+
+/**
+ * pango_font_metrics_get_strikethrough_position:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Gets the suggested position to draw the strikethrough.
+ * The value returned is the distance <emphasis>above</emphasis> the
+ * baseline of the top of the strikethrough.
+ *
+ * Return value: the suggested strikethrough position, in Pango units.
+ *
+ * Since: 1.6
+ **/
+int
+pango_font_metrics_get_strikethrough_position (PangoFontMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->strikethrough_position;
+}
+
+/**
+ * pango_font_metrics_get_strikethrough_thickness:
+ * @metrics: a #PangoFontMetrics structure
+ *
+ * Gets the suggested thickness to draw for the strikethrough.
+ *
+ * Return value: the suggested strikethrough thickness, in Pango units.
+ *
+ * Since: 1.6
+ **/
+int
+pango_font_metrics_get_strikethrough_thickness (PangoFontMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->strikethrough_thickness;
+}
+
+/*
+ * PangoFontFamily
+ */
+
+G_DEFINE_TYPE (PangoFontFamily, pango_font_family, G_TYPE_OBJECT)
+
+static void
+pango_font_family_class_init (PangoFontFamilyClass *class)
+{
+}
+
+static void
+pango_font_family_init (PangoFontFamily *family)
+{
+}
+
+/**
+ * pango_font_family_get_name:
+ * @family: a #PangoFontFamily
+ *
+ * Gets the name of the family. The name is unique among all
+ * fonts for the font backend and can be used in a #PangoFontDescription
+ * to specify that a face from this family is desired.
+ *
+ * Return value: the name of the family. This string is owned
+ * by the family object and must not be modified or freed.
+ **/
+G_CONST_RETURN char *
+pango_font_family_get_name (PangoFontFamily *family)
+{
+ g_return_val_if_fail (PANGO_IS_FONT_FAMILY (family), NULL);
+
+ return PANGO_FONT_FAMILY_GET_CLASS (family)->get_name (family);
+}
+
+/**
+ * pango_font_family_list_faces:
+ * @family: a #PangoFontFamily
+ * @faces: location to store an array of pointers to #PangoFontFace
+ * objects, or %NULL. This array should be freed with g_free()
+ * when it is no longer needed.
+ * @n_faces: location to store number of elements in @faces.
+ *
+ * Lists the different font faces that make up @family. The faces
+ * in a family share a common design, but differ in slant, weight,
+ * width and other aspects.
+ **/
+void
+pango_font_family_list_faces (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces)
+{
+ g_return_if_fail (PANGO_IS_FONT_FAMILY (family));
+
+ PANGO_FONT_FAMILY_GET_CLASS (family)->list_faces (family, faces, n_faces);
+}
+
+/**
+ * pango_font_family_is_monospace:
+ * @family: a #PangoFontFamily
+ *
+ * A monospace font is a font designed for text display where the the
+ * characters form a regular grid. For Western languages this would
+ * mean that the advance width of all characters are the same, but
+ * this categorization also includes Asian fonts which include
+ * double-width characters: characters that occupy two grid cells.
+ * g_unichar_iswide() returns a result that indicates whether a
+ * character is typically double-width in a monospace font.
+ *
+ * The best way to find out the grid-cell size is to call
+ * pango_font_metrics_get_approximate_digit_width(), since the results
+ * of pango_font_metrics_get_approximate_char_width() may be affected
+ * by double-width characters.
+ *
+ * Return value: %TRUE if the family is monospace.
+ *
+ * Since: 1.4
+ **/
+gboolean
+pango_font_family_is_monospace (PangoFontFamily *family)
+{
+ g_return_val_if_fail (PANGO_IS_FONT_FAMILY (family), FALSE);
+
+ if (PANGO_FONT_FAMILY_GET_CLASS (family)->is_monospace)
+ return PANGO_FONT_FAMILY_GET_CLASS (family)->is_monospace (family);
+ else
+ return FALSE;
+}
+
+/*
+ * PangoFontFace
+ */
+
+G_DEFINE_TYPE (PangoFontFace, pango_font_face, G_TYPE_OBJECT)
+
+static void
+pango_font_face_class_init (PangoFontFaceClass *class)
+{
+}
+
+static void
+pango_font_face_init (PangoFontFace *face)
+{
+}
+
+/**
+ * pango_font_face_describe:
+ * @face: a #PangoFontFace
+ *
+ * Returns the family, style, variant, weight and stretch of
+ * a #PangoFontFace. The size field of the resulting font description
+ * will be unset.
+ *
+ * Return value: a newly-created #PangoFontDescription structure
+ * holding the description of the face. Use pango_font_description_free()
+ * to free the result.
+ **/
+PangoFontDescription *
+pango_font_face_describe (PangoFontFace *face)
+{
+ g_return_val_if_fail (PANGO_IS_FONT_FACE (face), NULL);
+
+ return PANGO_FONT_FACE_GET_CLASS (face)->describe (face);
+}
+
+/**
+ * pango_font_face_is_synthesized:
+ * @face: a #PangoFontFace
+ *
+ * Returns whether a #PangoFontFace is synthesized by the underlying
+ * font rendering engine from another face, perhaps by shearing, emboldening,
+ * or lightening it.
+ *
+ * Return value: whether @face is synthesized.
+ *
+ * Since: 1.18
+ **/
+gboolean
+pango_font_face_is_synthesized (PangoFontFace *face)
+{
+ g_return_val_if_fail (PANGO_IS_FONT_FACE (face), FALSE);
+
+ if (PANGO_FONT_FACE_GET_CLASS (face)->is_synthesized != NULL)
+ return PANGO_FONT_FACE_GET_CLASS (face)->is_synthesized (face);
+ else
+ return FALSE;
+}
+
+/**
+ * pango_font_face_get_face_name:
+ * @face: a #PangoFontFace.
+ *
+ * Gets a name representing the style of this face among the
+ * different faces in the #PangoFontFamily for the face. This
+ * name is unique among all faces in the family and is suitable
+ * for displaying to users.
+ *
+ * Return value: the face name for the face. This string is
+ * owned by the face object and must not be modified or freed.
+ **/
+G_CONST_RETURN char *
+pango_font_face_get_face_name (PangoFontFace *face)
+{
+ g_return_val_if_fail (PANGO_IS_FONT_FACE (face), NULL);
+
+ return PANGO_FONT_FACE_GET_CLASS (face)->get_face_name (face);
+}
+
+/**
+ * pango_font_face_list_sizes:
+ * @face: a #PangoFontFace.
+ * @sizes: location to store a pointer to an array of int. This array
+ * should be freed with g_free().
+ * @n_sizes: location to store the number of elements in @sizes
+ *
+ * List the available sizes for a font. This is only applicable to bitmap
+ * fonts. For scalable fonts, stores %NULL at the location pointed to by
+ * @sizes and 0 at the location pointed to by @n_sizes. The sizes returned
+ * are in Pango units and are sorted in ascending order.
+ *
+ * Since: 1.4
+ **/
+void
+pango_font_face_list_sizes (PangoFontFace *face,
+ int **sizes,
+ int *n_sizes)
+{
+ g_return_if_fail (PANGO_IS_FONT_FACE (face));
+ g_return_if_fail (sizes == NULL || n_sizes != NULL);
+
+ if (n_sizes == NULL)
+ return;
+
+ if (PANGO_FONT_FACE_GET_CLASS (face)->list_sizes != NULL)
+ PANGO_FONT_FACE_GET_CLASS (face)->list_sizes (face, sizes, n_sizes);
+ else
+ {
+ if (sizes != NULL)
+ *sizes = NULL;
+ *n_sizes = 0;
+ }
+}
diff --git a/trunk/pango/glyphstring.c b/trunk/pango/glyphstring.c
new file mode 100644
index 00000000..0fcbb229
--- /dev/null
+++ b/trunk/pango/glyphstring.c
@@ -0,0 +1,360 @@
+/* Pango
+ * glyphstring.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include "pango-glyph.h"
+#include "pango-font.h"
+#include "pango-impl-utils.h"
+
+/**
+ * pango_glyph_string_new:
+ *
+ * Create a new #PangoGlyphString.
+ *
+ * Return value: the newly allocated #PangoGlyphString, which
+ * should be freed with pango_glyph_string_free().
+ */
+PangoGlyphString *
+pango_glyph_string_new (void)
+{
+ PangoGlyphString *string = g_slice_new (PangoGlyphString);
+
+ string->num_glyphs = 0;
+ string->space = 0;
+ string->glyphs = NULL;
+ string->log_clusters = NULL;
+
+ return string;
+}
+
+/**
+ * pango_glyph_string_set_size:
+ * @string: a #PangoGlyphString.
+ * @new_len: the new length of the string.
+ *
+ * Resize a glyph string to the given length.
+ */
+void
+pango_glyph_string_set_size (PangoGlyphString *string, gint new_len)
+{
+ g_return_if_fail (new_len >= 0);
+
+ while (new_len > string->space)
+ {
+ if (string->space == 0)
+ string->space = 1;
+ else
+ string->space *= 2;
+
+ if (string->space < 0)
+ {
+ g_warning ("glyph string length overflows maximum integer size, truncated");
+ new_len = string->space = G_MAXINT - 8;
+ }
+ }
+
+ string->glyphs = g_realloc (string->glyphs, string->space * sizeof (PangoGlyphInfo));
+ string->log_clusters = g_realloc (string->log_clusters, string->space * sizeof (gint));
+ string->num_glyphs = new_len;
+}
+
+GType
+pango_glyph_string_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoGlyphString"),
+ (GBoxedCopyFunc)pango_glyph_string_copy,
+ (GBoxedFreeFunc)pango_glyph_string_free);
+
+ return our_type;
+}
+
+/**
+ * pango_glyph_string_copy:
+ * @string: a #PangoGlyphString.
+ *
+ * Copy a glyph string and associated storage.
+ *
+ * Return value: the newly allocated #PangoGlyphString, which
+ * should be freed with pango_glyph_string_free().
+ */
+PangoGlyphString *
+pango_glyph_string_copy (PangoGlyphString *string)
+{
+ PangoGlyphString *new_string = g_slice_new (PangoGlyphString);
+
+ *new_string = *string;
+
+ new_string->glyphs = g_memdup (string->glyphs,
+ string->space * sizeof (PangoGlyphInfo));
+ new_string->log_clusters = g_memdup (string->log_clusters,
+ string->space * sizeof (gint));
+
+ return new_string;
+}
+
+/**
+ * pango_glyph_string_free:
+ * @string: a #PangoGlyphString.
+ *
+ * Free a glyph string and associated storage.
+ */
+void
+pango_glyph_string_free (PangoGlyphString *string)
+{
+ g_free (string->glyphs);
+ g_free (string->log_clusters);
+ g_slice_free (PangoGlyphString, string);
+}
+
+/**
+ * pango_glyph_string_extents_range:
+ * @glyphs: a #PangoGlyphString
+ * @start: start index
+ * @end: end index (the range is the set of bytes with
+ indices such that start <= index < end)
+ * @font: a #PangoFont
+ * @ink_rect: rectangle used to store the extents of the glyph string range as drawn
+ * or %NULL to indicate that the result is not needed.
+ * @logical_rect: rectangle used to store the logical extents of the glyph string range
+ * or %NULL to indicate that the result is not needed.
+ *
+ * Computes the extents of a sub-portion of a glyph string. The extents are
+ * relative to the start of the glyph string range (the origin of their
+ * coordinate system is at the start of the range, not at the start of the entire
+ * glyph string).
+ **/
+void
+pango_glyph_string_extents_range (PangoGlyphString *glyphs,
+ int start,
+ int end,
+ PangoFont *font,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ int x_pos = 0;
+ int i;
+
+ /* Note that the handling of empty rectangles for ink
+ * and logical rectangles is different. A zero-height ink
+ * rectangle makes no contribution to the overall ink rect,
+ * while a zero-height logical rect still reserves horizontal
+ * width. Also, we may return zero-width, positive height
+ * logical rectangles, while we'll never do that for the
+ * ink rect.
+ */
+ g_return_if_fail (start <= end);
+
+ if (G_UNLIKELY (!ink_rect && !logical_rect))
+ return;
+
+ if (ink_rect)
+ {
+ ink_rect->x = 0;
+ ink_rect->y = 0;
+ ink_rect->width = 0;
+ ink_rect->height = 0;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = 0;
+ logical_rect->width = 0;
+ logical_rect->height = 0;
+ }
+
+ for (i = start; i < end; i++)
+ {
+ PangoRectangle glyph_ink;
+ PangoRectangle glyph_logical;
+
+ PangoGlyphGeometry *geometry = &glyphs->glyphs[i].geometry;
+
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph,
+ ink_rect ? &glyph_ink : NULL,
+ logical_rect ? &glyph_logical : NULL);
+
+ if (ink_rect && glyph_ink.width != 0 && glyph_ink.height != 0)
+ {
+ if (ink_rect->width == 0 || ink_rect->height == 0)
+ {
+ ink_rect->x = x_pos + glyph_ink.x + geometry->x_offset;
+ ink_rect->width = glyph_ink.width;
+ ink_rect->y = glyph_ink.y + geometry->y_offset;
+ ink_rect->height = glyph_ink.height;
+ }
+ else
+ {
+ int new_x, new_y;
+
+ new_x = MIN (ink_rect->x, x_pos + glyph_ink.x + geometry->x_offset);
+ ink_rect->width = MAX (ink_rect->x + ink_rect->width,
+ x_pos + glyph_ink.x + glyph_ink.width + geometry->x_offset) - new_x;
+ ink_rect->x = new_x;
+
+ new_y = MIN (ink_rect->y, glyph_ink.y + geometry->y_offset);
+ ink_rect->height = MAX (ink_rect->y + ink_rect->height,
+ glyph_ink.y + glyph_ink.height + geometry->y_offset) - new_y;
+ ink_rect->y = new_y;
+ }
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->width += geometry->width;
+
+ if (i == start)
+ {
+ logical_rect->y = glyph_logical.y;
+ logical_rect->height = glyph_logical.height;
+ }
+ else
+ {
+ int new_y = MIN (logical_rect->y, glyph_logical.y);
+ logical_rect->height = MAX (logical_rect->y + logical_rect->height,
+ glyph_logical.y + glyph_logical.height) - new_y;
+ logical_rect->y = new_y;
+ }
+ }
+
+ x_pos += geometry->width;
+ }
+}
+
+/**
+ * pango_glyph_string_extents:
+ * @glyphs: a #PangoGlyphString
+ * @font: a #PangoFont
+ * @ink_rect: rectangle used to store the extents of the glyph string as drawn
+ * or %NULL to indicate that the result is not needed.
+ * @logical_rect: rectangle used to store the logical extents of the glyph string
+ * or %NULL to indicate that the result is not needed.
+ *
+ * Compute the logical and ink extents of a glyph string. See the documentation
+ * for pango_font_get_glyph_extents() for details about the interpretation
+ * of the rectangles.
+ */
+void
+pango_glyph_string_extents (PangoGlyphString *glyphs,
+ PangoFont *font,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ pango_glyph_string_extents_range (glyphs, 0, glyphs->num_glyphs,
+ font, ink_rect, logical_rect);
+}
+
+/**
+ * pango_glyph_string_get_width:
+ * @glyphs: a #PangoGlyphString
+ *
+ * Computes the logical width of the glyph string as can also be computed
+ * using pango_glyph_string_extents(). However, since this only computes the
+ * width, it's much faster. This is in fact only a convenience function that
+ * computes the sum of geometry.width for each glyph in the @glyphs.
+ *
+ * Return value: the logical width of the glyph string.
+ *
+ * Since: 1.14
+ */
+int
+pango_glyph_string_get_width (PangoGlyphString *glyphs)
+{
+ int i;
+ int width = 0;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ width += glyphs->glyphs[i].geometry.width;
+
+ return width;
+}
+
+/**
+ * pango_glyph_string_get_logical_widths:
+ * @glyphs: a #PangoGlyphString
+ * @text: the text corresponding to the glyphs
+ * @length: the length of @text, in bytes
+ * @embedding_level: the embedding level of the string
+ * @logical_widths: an array whose length is g_utf8_strlen (text, length)
+ * to be filled in with the resulting character widths.
+ *
+ * Given a #PangoGlyphString resulting from pango_shape() and the corresponding
+ * text, determine the screen width corresponding to each character. When
+ * multiple characters compose a single cluster, the width of the entire
+ * cluster is divided equally among the characters.
+ **/
+void
+pango_glyph_string_get_logical_widths (PangoGlyphString *glyphs,
+ const char *text,
+ int length,
+ int embedding_level,
+ int *logical_widths)
+{
+ int i, j;
+ int last_cluster = 0;
+ int width = 0;
+ int last_cluster_width = 0;
+ const char *p = text; /* Points to start of current cluster */
+
+ for (i=0; i<=glyphs->num_glyphs; i++)
+ {
+ int glyph_index = (embedding_level % 2 == 0) ? i : glyphs->num_glyphs - i - 1;
+
+ /* If this glyph belongs to a new cluster, or we're at the end, find
+ * the start of the next cluster, and assign the widths for this cluster.
+ */
+ if (i == glyphs->num_glyphs || p != text + glyphs->log_clusters[glyph_index])
+ {
+ int next_cluster = last_cluster;
+
+ if (i < glyphs->num_glyphs)
+ {
+ while (p < text + glyphs->log_clusters[glyph_index])
+ {
+ next_cluster++;
+ p = g_utf8_next_char (p);
+ }
+ }
+ else
+ {
+ while (p < text + length)
+ {
+ next_cluster++;
+ p = g_utf8_next_char (p);
+ }
+ }
+
+ for (j = last_cluster; j < next_cluster; j++)
+ logical_widths[j] = (width - last_cluster_width) / (next_cluster - last_cluster);
+
+ last_cluster = next_cluster;
+ last_cluster_width = width;
+ }
+
+ if (i < glyphs->num_glyphs)
+ width += glyphs->glyphs[glyph_index].geometry.width;
+ }
+}
+
diff --git a/trunk/pango/makefile.msc b/trunk/pango/makefile.msc
new file mode 100644
index 00000000..76e37294
--- /dev/null
+++ b/trunk/pango/makefile.msc
@@ -0,0 +1,290 @@
+TOP = ../..
+!INCLUDE $(TOP)/glib/build/win32/make.msc
+
+!IFNDEF PERL
+PERL = perl
+!ENDIF
+
+# Possibly override Pango version from build/win32/module.defs
+PANGO_VER = 1.0
+PANGO_MODULE_VERSION = 1.6.0
+
+# INCLUDES = -I .. -I .
+# -DHAVE_USP10_H
+# DEFINES = -DPACKAGE=\"Pango\" -DVERSION=\"$(PANGO_VER)\"
+# DEPCFLAGS = $(GLIB_CFLAGS) $(LIBICONV_CFLAGS) $(FREETYPE2_CFLAGS)
+
+!IFNDEF PACKAGE
+
+DLLS = pango pangowin32 pangoft2 pangocairo # pangox
+EXES = querymodules testfonts
+#? test1 test2 test3 test4 test5
+
+# The main target
+all : \
+ sub-all
+
+sub-all:
+ for %d in ($(DLLS)) do nmake -nologo -f makefile.msc sub-one-dll THIS=%d
+ for %d in ($(DLLS)) do nmake -nologo -f makefile.msc sub-one-lib THIS=%d
+ for %d in ($(EXES)) do nmake -nologo -f makefile.msc sub-one-exe THIS=%d
+
+sub-one-lib:
+ nmake -nologo -f makefile.msc $(THIS)-$(PANGO_VER)s.lib PACKAGE=$(THIS) OBJS_$(THIS)=1
+
+sub-one-dll:
+ nmake -nologo -f makefile.msc lib$(THIS)-$(PANGO_VER)-0.dll PACKAGE=$(THIS) OBJS_$(THIS)=1
+
+sub-one-exe:
+ nmake -nologo -f makefile.msc $(THIS).exe PACKAGE=$(THIS) OBJS_$(THIS)=1
+
+!ELSE
+
+PRJ_TOP = ..
+PKG_VER = $(PANGO_VER)
+PKG_DEF = $(PACKAGE).def
+
+PKG_CFLAGS = -FImsvc_recommended_pragmas.h -I.. -I. -I$(PRJ_TOP) \
+ -DPACKAGE=\"Pango\" -DVERSION=\"$(PANGO_VER)\" \
+ -DPANGO_ENABLE_BACKEND -DPANGO_ENABLE_ENGINE \
+ -DMODULE_VERSION=\"$(PANGO_MODULE_VERSION)\" \
+ $(GLIB_CFLAGS) $(LIBICONV_CFLAGS) \
+ $(X11_CFLAGS) -DSYSCONFDIR=\"/etc\" \
+ -DPANGO_BINARY_AGE=0
+
+#-DHAVE_USP10_H
+
+
+!IFDEF OBJS_pango
+# don't link with itself
+PKG_LINK = $(GLIB_LIBS) $(FONTCONFIG_LIBS)
+!ENDIF
+
+!IFDEF OBJS_pangowin32
+PKG_LINK = $(GLIB_LIBS) $(LIBICONV_LIBS) \
+ pango-$(PANGO_VER).lib
+!ENDIF
+
+!IFDEF OBJS_pangoft2
+PKG_CFLAGS = $(PKG_CFLAGS) $(FREETYPE2_CFLAGS) $(FONTCONFIG_CFLAGS) \
+ -DPANGO_MODULE_PREFIX=_pango_basic_ft2
+
+PKG_LINK = $(GLIB_LIBS) $(LIBICONV_LIBS) $(FREETYPE2_LIBS) $(FONTCONFIG_LIBS) \
+ pango-$(PANGO_VER).lib opentype\pango-ot.lib
+!ENDIF
+
+!IFDEF OBJS_pangox
+PKG_LINK = $(GLIB_LIBS) $(LIBICONV_LIBS) \
+ pango-$(PANGO_VER).lib $(X11_LIBS)
+!ENDIF
+
+!IFDEF OBJS_pangocairo
+PKG_LINK = $(GLIB_LIBS) $(LIBICONV_LIBS) \
+ pango-$(PANGO_VER).lib $(CAIRO_LIBS) \
+ pangowin32-$(PANGO_VER).lib $(FONTCONFIG_LIBS)
+!ENDIF
+
+!IF DEFINED (OBJS_querymodules) || DEFINED (OBJS_testfonts)
+PKG_LINK = $(GLIB_LIBS) $(LIBICONV_LIBS) \
+ pango-$(PANGO_VER).lib pangowin32-$(PANGO_VER).lib
+!ENDIF
+
+!IFDEF OBJS_pango
+OBJECTS = \
+ pango-enum-types.obj \
+ \
+ module-defs-lang.obj \
+ \
+ break.obj \
+ ellipsize.obj \
+ fonts.obj \
+ glyphstring.obj \
+ mapping.obj \
+ modules.obj \
+ pango-attributes.obj \
+ pango-engine.obj \
+ pango-color.obj \
+ pango-context.obj \
+ pango-coverage.obj \
+ pango-fontset.obj \
+ pango-fontmap.obj \
+ pango-glyph-item.obj \
+ pango-gravity.obj \
+ pango-item.obj \
+ pango-markup.obj \
+ pango-matrix.obj \
+ pango-language.obj \
+ pango-layout.obj \
+ pango-renderer.obj \
+ pango-script.obj \
+ pango-tabs.obj \
+ pango-utils.obj \
+ reorder-items.obj \
+ shape.obj \
+ \
+ fribidi.obj \
+ fribidi_types.obj \
+ fribidi_char_type.obj
+!ENDIF
+
+basic-win32.obj : ..\modules\basic\basic-win32.c
+ $(CC) $(PKG_CFLAGS) -GD -DPANGO_MODULE_PREFIX=_pango_basic_win32 -c ..\modules\basic\basic-win32.c
+
+basic-fc.obj : ..\modules\basic\basic-fc.c
+ $(CC) $(PKG_CFLAGS) -GD -DPANGO_MODULE_PREFIX=_pango_basic_ft2 -c ..\modules\basic\basic-fc.c
+
+basic-x.obj : ..\modules\basic\basic-x.c
+ $(CC) $(PKG_CFLAGS) -GD -DPANGO_MODULE_PREFIX=_pango_basic_xs -c ..\modules\basic\basic-x.c
+
+
+fribidi.obj : mini-fribidi\fribidi.c
+ $(CC) $(PKG_CFLAGS) -GD -c mini-fribidi\fribidi.c
+fribidi_types.obj : mini-fribidi\fribidi_types.c
+ $(CC) $(PKG_CFLAGS) -GD -c mini-fribidi\fribidi_types.c
+fribidi_char_type.obj : mini-fribidi\fribidi_char_type.c
+ $(CC) $(PKG_CFLAGS) -GD -c mini-fribidi\fribidi_char_type.c
+
+testfonts.obj : ..\examples\pangowin32tobmp.c
+ $(CC) $(PKG_CFLAGS) -GD -Fotestfonts.obj -c ..\examples\pangowin32tobmp.c
+
+!IFDEF OBJS_pangowin32
+PKG_CFLAGS = $(PKG_CFLAGS) -DPANGO_MODULE_PREFIX=_pango_basic_win32
+OBJECTS = \
+ module-defs-win32.obj \
+ pangowin32.obj \
+ pangowin32-fontcache.obj \
+ pangowin32-fontmap.obj \
+# pangowin32-render.obj \
+ basic-win32.obj
+!ENDIF
+
+!IFDEF OBJS_pangoft2
+OBJECTS = \
+ module-defs-fc.obj \
+ pangofc-decoder.obj \
+ pangofc-font.obj \
+ pangofc-fontmap.obj \
+ pangoft2.obj \
+ pangoft2-fontmap.obj \
+ pangoft2-render.obj \
+ \
+ pango-ot-buffer.obj \
+ pango-ot-info.obj \
+ pango-ot-tag.obj \
+ pango-ot-ruleset.obj \
+ \
+ basic-fc.obj
+
+PKG_CFLAGS = $(PKG_CFLAGS) $(FONTCONFIG_CFLAGS) $(FREETYPE2_CFLAGS)
+!ENDIF
+
+!IFDEF OBJS_pangox
+OBJECTS = \
+ module-defs-x.obj \
+ pangox.obj \
+ pangox-fontcache.obj \
+ pangox-fontmap.obj \
+ pango-indic.obj \
+ basic-x.obj
+!ENDIF
+
+# -DHAVE_CAIRO_FREETYPE
+!IFDEF OBJS_pangocairo
+PKG_CFLAGS = \
+ $(PKG_CFLAGS) $(FONTCONFIG_CFLAGS) $(FREETYPE2_CFLAGS) \
+ -DHAVE_CAIRO_WIN32 $(CAIRO_CFLAGS)
+OBJECTS = \
+ pangocairo-context.obj \
+ pangocairo-font.obj \
+ pangocairo-fontmap.obj \
+ pangocairo-render.obj \
+ pangocairo-win32font.obj \
+ pangocairo-win32fontmap.obj \
+# pangocairo-fcfont.obj \
+# pangocairo-fcfontmap.obj \
+!ENDIF
+
+!IFDEF OBJS_querymodules
+PKG_CFLAGS = $(PKG_CFLAGS) \
+ -DPACKAGE_NAME=\"Pango\" -DPACKAGE_VERSION=\"$(PANGO_VER)\"
+OBJECTS = \
+ querymodules.obj
+!ENDIF
+
+!IFNDEF OBJECTS
+OBJECTS = $(PACKAGE).obj
+!ENDIF
+
+module-defs-win32.c : module-defs-win32.c.win32
+ copy module-defs-win32.c.win32 module-defs-win32.c
+
+module-defs-fc.c : module-defs-fc.c.win32
+ copy module-defs-fc.c.win32 module-defs-fc.c
+
+module-defs-lang.c : module-defs-lang.c.win32
+ copy module-defs-lang.c.win32 module-defs-lang.c
+
+pango_headers= \
+ pango.h \
+ pango-attributes.h \
+ pango-break.h \
+ pango-context.h \
+ pango-coverage.h \
+ pango-engine.h \
+ pango-font.h \
+ pango-fontmap.h \
+ pango-fontset.h \
+ pango-glyph.h \
+ pango-glyph-item.h \
+ pango-gravity.h \
+ pango-item.h \
+ pango-layout.h \
+ pango-modules.h \
+ pango-renderer.h \
+ pango-script.h \
+ pango-tabs.h \
+ pango-types.h \
+ pango-utils.h \
+ pangofc-font.h \
+ pangofc-fontmap.h
+
+pango-enum-types.h: $(pango_headers) makefile.msc
+ $(PERL) $(GLIB)\gobject\glib-mkenums \
+ --fhead "#ifndef __PANGO_ENUM_TYPES_H__\n#define __PANGO_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@filename@\" */\n" \
+ --vhead "GType @enum_name@_get_type (void);\n#define PANGO_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
+ --ftail "G_END_DECLS\n#endif /* __PANGO_ENUM_TYPES_H__ */" \
+ $(pango_headers) > pango-enum-types.h
+
+pango-enum-types.c: $(pango_headers) pango-enum-types.h makefile.msc
+ $(PERL) $(GLIB)\gobject\glib-mkenums \
+ --fhead "#include <pango.h>" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
+ $(pango_headers) > pango-enum-types.c
+
+$(PACKAGE)-$(PKG_VER)s.lib : $(OBJECTS) $(PRJ_TOP)\config.h
+ lib /out:$(PACKAGE)-$(PKG_VER)s.lib $(OBJECTS)
+
+lib$(PACKAGE)-$(PKG_VER)-0.dll : $(OBJECTS) $(PKG_DEF) $(PRJ_TOP)\config.h
+ $(CC) $(CFLAGS) -LD -Fe$@ $(OBJECTS) $(PKG_LINK) \
+ user32.lib gdi32.lib advapi32.lib $(LDFLAGS) /implib:$(PACKAGE)-$(PKG_VER).lib /def:$(PKG_DEF)
+
+$(PACKAGE).exe : $(PKG_LINK) $(OBJECTS)
+ $(CC) $(CFLAGS) -Fe$(PACKAGE).exe $(OBJECTS) $(PKG_LINK) gdi32.lib user32.lib
+
+$(PRJ_TOP)\config.h.win32 : makefile.msc
+ echo /*almostempty*/ > $(PRJ_TOP)\config.h.win32
+ echo #define PANGO_BINARY_AGE 0 >> $(PRJ_TOP)\config.h.win32
+ echo #define DHAVE_USP10_H 1 >> $(PRJ_TOP)\config.h.win32
+
+$(PRJ_TOP)\config.h: $(PRJ_TOP)\config.h.win32
+ copy $(PRJ_TOP)\config.h.win32 $(PRJ_TOP)\config.h
+
+
+.c.obj :
+ $(CC) $(CFLAGS) -GD -c $(PKG_CFLAGS) $<
+
+!ENDIF #PACKAGE
diff --git a/trunk/pango/mapping.c b/trunk/pango/mapping.c
new file mode 100644
index 00000000..7000b69c
--- /dev/null
+++ b/trunk/pango/mapping.c
@@ -0,0 +1,328 @@
+/* Pango
+ * mapping.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+/* The initial implementation here is script independent,
+ * but it might actually need to be virtualized into the
+ * rendering modules. Otherwise, we probably will end up
+ * enforcing unnatural cursor behavior for some languages.
+ *
+ * The only distinction that Uniscript makes is whether
+ * cursor positioning is allowed within clusters or not.
+ */
+
+#include "pango-glyph.h"
+
+/**
+ * pango_glyph_string_index_to_x:
+ * @glyphs: the glyphs return from pango_shape()
+ * @text: the text for the run
+ * @length: the number of bytes (not characters) in @text.
+ * @analysis: the analysis information return from pango_itemize()
+ * @index_: the byte index within @text
+ * @trailing: whether we should compute the result for the beginning
+ * or end of the character.
+ * @x_pos: location to store result
+ *
+ * Converts from character position to x position. (X position
+ * is measured from the left edge of the run). Character positions
+ * are computed by dividing up each cluster into equal portions.
+ */
+
+void
+pango_glyph_string_index_to_x (PangoGlyphString *glyphs,
+ char *text,
+ int length,
+ PangoAnalysis *analysis,
+ int index,
+ gboolean trailing,
+ int *x_pos)
+{
+ int i;
+ int start_xpos = 0;
+ int end_xpos = 0;
+ int width = 0;
+
+ int start_index = -1;
+ int end_index = -1;
+
+ int cluster_chars = 0;
+ int cluster_offset = 0;
+
+ char *p;
+
+ g_return_if_fail (glyphs != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (length == 0 || text != NULL);
+
+ if (!x_pos) /* Allow the user to do the useless */
+ return;
+
+ if (glyphs->num_glyphs == 0)
+ {
+ *x_pos = 0;
+ return;
+ }
+
+ /* Calculate the starting and ending character positions
+ * and x positions for the cluster
+ */
+ if (analysis->level % 2) /* Right to left */
+ {
+ for (i = glyphs->num_glyphs - 1; i >= 0; i--)
+ width += glyphs->glyphs[i].geometry.width;
+
+ for (i = glyphs->num_glyphs - 1; i >= 0; i--)
+ {
+ if (glyphs->log_clusters[i] > index)
+ {
+ end_index = glyphs->log_clusters[i];
+ end_xpos = width;
+ break;
+ }
+
+ if (glyphs->log_clusters[i] != start_index)
+ {
+ start_index = glyphs->log_clusters[i];
+ start_xpos = width;
+ }
+
+ width -= glyphs->glyphs[i].geometry.width;
+ }
+ }
+ else /* Left to right */
+ {
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ if (glyphs->log_clusters[i] > index)
+ {
+ end_index = glyphs->log_clusters[i];
+ end_xpos = width;
+ break;
+ }
+
+ if (glyphs->log_clusters[i] != start_index)
+ {
+ start_index = glyphs->log_clusters[i];
+ start_xpos = width;
+ }
+
+ width += glyphs->glyphs[i].geometry.width;
+ }
+ }
+
+ if (end_index == -1)
+ {
+ end_index = length;
+ end_xpos = (analysis->level % 2) ? 0 : width;
+ }
+
+ /* Calculate offset of character within cluster */
+
+ p = text + start_index;
+ while (p < text + end_index)
+ {
+ if (p < text + index)
+ cluster_offset++;
+ cluster_chars++;
+ p = g_utf8_next_char (p);
+ }
+
+ if (trailing)
+ cluster_offset += 1;
+
+ *x_pos = ((cluster_chars - cluster_offset) * start_xpos +
+ cluster_offset * end_xpos) / cluster_chars;
+}
+
+/**
+ * pango_glyph_string_x_to_index:
+ * @glyphs: the glyphs return from pango_shape()
+ * @text: the text for the run
+ * @length: the number of bytes (not characters) in text.
+ * @analysis: the analysis information return from pango_itemize()
+ * @x_pos: the x offset (in #PangoGlyphUnit)
+ * @index_: location to store calculated byte index within @text
+ * @trailing: location to store a integer indicating where
+ * whether the user clicked on the leading or trailing
+ * edge of the character.
+ *
+ * Convert from x offset to character position. Character positions
+ * are computed by dividing up each cluster into equal portions.
+ * In scripts where positioning within a cluster is not allowed
+ * (such as Thai), the returned value may not be a valid cursor
+ * position; the caller must combine the result with the logical
+ * attributes for the text to compute the valid cursor position.
+ */
+void
+pango_glyph_string_x_to_index (PangoGlyphString *glyphs,
+ char *text,
+ int length,
+ PangoAnalysis *analysis,
+ int x_pos,
+ int *index,
+ gboolean *trailing)
+{
+ int i;
+ int start_xpos = 0;
+ int end_xpos = 0;
+ int width = 0;
+
+ int start_index = -1;
+ int end_index = -1;
+
+ int cluster_chars = 0;
+ char *p;
+
+ gboolean found = FALSE;
+
+ /* Find the cluster containing the position */
+
+ width = 0;
+
+ if (analysis->level % 2) /* Right to left */
+ {
+ for (i = glyphs->num_glyphs - 1; i >= 0; i--)
+ width += glyphs->glyphs[i].geometry.width;
+
+ for (i = glyphs->num_glyphs - 1; i >= 0; i--)
+ {
+ if (glyphs->log_clusters[i] != start_index)
+ {
+ if (found)
+ {
+ end_index = glyphs->log_clusters[i];
+ end_xpos = width;
+ break;
+ }
+ else
+ {
+ start_index = glyphs->log_clusters[i];
+ start_xpos = width;
+ }
+ }
+
+ width -= glyphs->glyphs[i].geometry.width;
+
+ if (width <= x_pos && x_pos < width + glyphs->glyphs[i].geometry.width)
+ found = TRUE;
+ }
+ }
+ else /* Left to right */
+ {
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ if (glyphs->log_clusters[i] != start_index)
+ {
+ if (found)
+ {
+ end_index = glyphs->log_clusters[i];
+ end_xpos = width;
+ break;
+ }
+ else
+ {
+ start_index = glyphs->log_clusters[i];
+ start_xpos = width;
+ }
+ }
+
+ if (width <= x_pos && x_pos < width + glyphs->glyphs[i].geometry.width)
+ found = TRUE;
+
+ width += glyphs->glyphs[i].geometry.width;
+ }
+ }
+
+ if (end_index == -1)
+ {
+ end_index = length;
+ end_xpos = (analysis->level % 2) ? 0 : width;
+ }
+
+ /* Calculate number of chars within cluster */
+ p = text + start_index;
+ while (p < text + end_index)
+ {
+ p = g_utf8_next_char (p);
+ cluster_chars++;
+ }
+
+ if (start_xpos == end_xpos)
+ {
+ if (index)
+ *index = start_index;
+ if (trailing)
+ *trailing = 0;
+ }
+ else
+ {
+ double cp = ((double)(x_pos - start_xpos) * cluster_chars) / (end_xpos - start_xpos);
+
+ /* LTR and right-to-left have to be handled separately
+ * here because of the edge condition when we are exactly
+ * at a pixel boundary; end_xpos goes with the next
+ * character for LTR, with the previous character for RTL.
+ */
+ if (start_xpos < end_xpos) /* Left-to-right */
+ {
+ if (index)
+ {
+ char *p = text + start_index;
+ int i = 0;
+
+ while (i + 1 <= cp)
+ {
+ p = g_utf8_next_char (p);
+ i++;
+ }
+
+ *index = (p - text);
+ }
+
+ if (trailing)
+ *trailing = (cp - (int)cp >= 0.5) ? 1 : 0;
+ }
+ else /* Right-to-left */
+ {
+ if (index)
+ {
+ char *p = text + start_index;
+ int i = 0;
+
+ while (i + 1 < cp)
+ {
+ p = g_utf8_next_char (p);
+ i++;
+ }
+
+ *index = (p - text);
+ }
+
+ if (trailing)
+ {
+ double cp_flip = cluster_chars - cp;
+ *trailing = (cp_flip - (int)cp_flip >= 0.5) ? 0 : 1;
+ }
+ }
+ }
+}
diff --git a/trunk/pango/mini-fribidi/Makefile.am b/trunk/pango/mini-fribidi/Makefile.am
new file mode 100644
index 00000000..44919522
--- /dev/null
+++ b/trunk/pango/mini-fribidi/Makefile.am
@@ -0,0 +1,31 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBDIR=\"$(libdir)\" \
+ $(PANGO_DEBUG_FLAGS) \
+ -I$(top_srcdir) \
+ $(GLIB_CFLAGS)
+
+LDADDS = @STRIP_BEGIN@ \
+ @x_ldflags@ \
+ @x_libs@ \
+ @GLIB_LIBS@ \
+ -lm \
+ @STRIP_END@
+
+noinst_LTLIBRARIES = libmini-fribidi.la
+
+libmini_fribidi_la_SOURCES = \
+ fribidi.c \
+ fribidi_char_type.c \
+ fribidi_config.h \
+ fribidi.h \
+ fribidi_types.c \
+ fribidi_types.h
+
+EXTRA_DIST = \
+ README \
+ fribidi_tab_char_type_2.i \
+ fribidi_types.i
+
diff --git a/trunk/pango/mini-fribidi/README b/trunk/pango/mini-fribidi/README
new file mode 100644
index 00000000..36874942
--- /dev/null
+++ b/trunk/pango/mini-fribidi/README
@@ -0,0 +1,23 @@
+This directory holds a stripped down version of GNU FriBidi library. The
+fribidi version that fribidi.patch is against is 0.10.7 release. The files
+fribidi_config.h and Makefile.am are specifically written for Pango integration.
+
+Like Pango, FriBidi is licensed under the terms of the GNU Lesser General
+Public License - see the file COPYING in the toplevel directory of the Pango
+distribution.
+
+The fribidi_tab_char_type_2.i table has been updated to correspond to
+Unicode 5.0.0.
+
+Please try not to make any changes to files duplicated in this directory.
+The aim has been to only remove lines from those files, not add new ones.
+Most of desired features can be implemented by preprocessor tricks in
+fribidi_config.h.
+
+This version of FriBidi is modified to support UTF-8 directly. Search for
+utf8 in the code to see where changes have gone. It also has been modified to
+short-circuit on unidirectional text. Search for unidirectional to find that
+part.
+
+November 09, 2005
+Behdad Esfahbod
diff --git a/trunk/pango/mini-fribidi/fribidi.c b/trunk/pango/mini-fribidi/fribidi.c
new file mode 100644
index 00000000..04fbc50a
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi.c
@@ -0,0 +1,957 @@
+/* FriBidi - Library of BiDi algorithm
+ * Copyright (C) 1999,2000 Dov Grobgeld, and
+ * Copyright (C) 2001,2002 Behdad Esfahbod.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library, in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ * For licensing issues, contact <dov@imagic.weizmann.ac.il> and
+ * <fwpg@sharif.edu>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fribidi.h"
+
+/* Redefine FRIBIDI_CHUNK_SIZE in config.h to override this. */
+#ifndef FRIBIDI_CHUNK_SIZE
+#ifdef MEM_OPTIMIZED
+#define FRIBIDI_CHUNK_SIZE 16
+#else
+#define FRIBIDI_CHUNK_SIZE 128
+#endif
+#endif
+
+#define DBG(s)
+#define DBG2(s, t)
+
+/*======================================================================
+ * Typedef for the run-length list.
+ *----------------------------------------------------------------------*/
+typedef struct _TypeLink TypeLink;
+
+struct _TypeLink
+{
+ TypeLink *prev;
+ TypeLink *next;
+
+ FriBidiCharType type;
+ FriBidiStrIndex pos, len;
+ FriBidiLevel level;
+};
+
+#define FRIBIDI_LEVEL_START -1
+#define FRIBIDI_LEVEL_END -1
+#define FRIBIDI_LEVEL_REMOVED -2
+
+typedef struct
+{
+ FriBidiCharType override; /* only L, R and N are valid */
+ FriBidiLevel level;
+}
+LevelInfo;
+
+static TypeLink *
+new_type_link (void)
+{
+ TypeLink *link;
+
+ link = g_slice_new0 (TypeLink);
+
+ return link;
+}
+
+static void
+free_type_link (TypeLink *link)
+{
+ g_slice_free (TypeLink, link);
+}
+
+#define FRIBIDI_ADD_TYPE_LINK(p,q) \
+ do { \
+ (p)->len = (q)->pos - (p)->pos; \
+ (p)->next = (q); \
+ (q)->prev = (p); \
+ (p) = (q); \
+ } while (0)
+
+static TypeLink *
+run_length_encode_types_utf8 (const char *s,
+ int bytelen,
+ FriBidiStrIndex *len,
+ FriBidiCharType *pored_types,
+ FriBidiCharType *panded_strongs)
+{
+ TypeLink *list, *last, *link;
+ FriBidiCharType char_type;
+ FriBidiCharType ored_types = 0;
+ FriBidiCharType anded_strongs = FRIBIDI_TYPE_RLE;
+ FriBidiStrIndex i;
+ const char *p;
+
+ /* Add the starting link */
+ list = new_type_link ();
+ list->type = FRIBIDI_TYPE_SOT;
+ list->level = FRIBIDI_LEVEL_START;
+ last = list;
+
+ /* Sweep over the string s */
+ i = 0;
+ for (p = s; p < s + bytelen; p = g_utf8_next_char(p)) {
+ char_type = fribidi_get_type (g_utf8_get_char (p));
+ ored_types |= char_type;
+ if (FRIBIDI_IS_STRONG (char_type))
+ anded_strongs &= char_type;
+ if (char_type != last->type)
+ {
+ link = new_type_link ();
+ link->type = char_type;
+ link->pos = i;
+ FRIBIDI_ADD_TYPE_LINK (last, link);
+ }
+ i++;
+ }
+
+ /* Add the ending link */
+ link = new_type_link ();
+ link->type = FRIBIDI_TYPE_EOT;
+ link->level = FRIBIDI_LEVEL_END;
+ link->pos = i;
+ FRIBIDI_ADD_TYPE_LINK (last, link);
+
+ if (len)
+ *len = i;
+
+ if (pored_types)
+ *pored_types = ored_types;
+ if (panded_strongs)
+ *panded_strongs = anded_strongs;
+
+ return list;
+}
+
+/* explicits_list is a list like type_rl_list, that holds the explicit
+ codes that are removed from rl_list, to reinsert them later by calling
+ the override_list.
+*/
+static void
+init_list (TypeLink **start,
+ TypeLink **end)
+{
+ TypeLink *list;
+ TypeLink *link;
+
+ /* Add the starting link */
+ list = new_type_link ();
+ list->type = FRIBIDI_TYPE_SOT;
+ list->level = FRIBIDI_LEVEL_START;
+ list->len = 0;
+ list->pos = 0;
+
+ /* Add the ending link */
+ link = new_type_link ();
+ link->type = FRIBIDI_TYPE_EOT;
+ link->level = FRIBIDI_LEVEL_END;
+ link->len = 0;
+ link->pos = 0;
+ list->next = link;
+ link->prev = list;
+
+ *start = list;
+ *end = link;
+}
+
+/* move an element before another element in a list, the list must have a
+ previous element, used to update explicits_list.
+ assuming that p have both prev and next or none of them, also update
+ the list that p is currently in, if any.
+*/
+static void
+move_element_before (TypeLink *p,
+ TypeLink *list)
+{
+ if (p->prev)
+ {
+ p->prev->next = p->next;
+ p->next->prev = p->prev;
+ }
+ p->prev = list->prev;
+ list->prev->next = p;
+ p->next = list;
+ list->prev = p;
+}
+
+/* override the rl_list 'base', with the elements in the list 'over', to
+ reinsert the previously-removed explicit codes (at X9) from
+ 'explicits_list' back into 'type_rl_list'. This is used at the end of I2
+ to restore the explicit marks, and also to reset the character types of
+ characters at L1.
+
+ it is assumed that the 'pos' of the first element in 'base' list is not
+ more than the 'pos' of the first element of the 'over' list, and the
+ 'pos' of the last element of the 'base' list is not less than the 'pos'
+ of the last element of the 'over' list. these two conditions are always
+ satisfied for the two usages mentioned above.
+
+ TBD: use some explanatory names instead of p, q, ...
+*/
+static void
+override_list (TypeLink *base,
+ TypeLink *over)
+{
+ TypeLink *p = base, *q, *r, *s, *t;
+ FriBidiStrIndex pos = 0, pos2;
+
+ if (!over)
+ return;
+ q = over;
+ while (q)
+ {
+ if (!q->len || q->pos < pos)
+ {
+ t = q;
+ q = q->next;
+ free_type_link (t);
+ continue;
+ }
+ pos = q->pos;
+ while (p->next && p->next->pos <= pos)
+ p = p->next;
+ /* now p is the element that q must be inserted 'in'. */
+ pos2 = pos + q->len;
+ r = p;
+ while (r->next && r->next->pos < pos2)
+ r = r->next;
+ /* now r is the last element that q affects. */
+ if (p == r)
+ {
+ /* split p into at most 3 interval, and insert q in the place of
+ the second interval, set r to be the third part. */
+ /* third part needed? */
+ if (p->next && p->next->pos == pos2)
+ r = r->next;
+ else
+ {
+ r = new_type_link ();
+ *r = *p;
+ if (r->next)
+ {
+ r->next->prev = r;
+ r->len = r->next->pos - pos2;
+ }
+ else
+ r->len -= pos - p->pos;
+ r->pos = pos2;
+ }
+ /* first part needed? */
+ if (p->prev && p->pos == pos)
+ {
+ t = p;
+ p = p->prev;
+ free_type_link (t);
+ }
+ else
+ p->len = pos - p->pos;
+ }
+ else
+ {
+ /* cut the end of p. */
+ p->len = pos - p->pos;
+ /* if all of p is cut, remove it. */
+ if (!p->len && p->prev)
+ p = p->prev;
+
+ /* cut the begining of r. */
+ r->pos = pos2;
+ if (r->next)
+ r->len = r->next->pos - pos2;
+ /* if all of r is cut, remove it. */
+ if (!r->len && r->next)
+ r = r->next;
+
+ /* remove the elements between p and r. */
+ for (s = p->next; s != r;)
+ {
+ t = s;
+ s = s->next;
+ free_type_link (t);
+ }
+ }
+ /* before updating the next and prev links to point to the inserted q,
+ we must remember the next element of q in the 'over' list.
+ */
+ t = q;
+ q = q->next;
+ p->next = t;
+ t->prev = p;
+ t->next = r;
+ r->prev = t;
+ }
+}
+
+/* Some convenience macros */
+#define RL_TYPE(list) ((list)->type)
+#define RL_LEN(list) ((list)->len)
+#define RL_POS(list) ((list)->pos)
+#define RL_LEVEL(list) ((list)->level)
+
+static TypeLink *
+merge_with_prev (TypeLink *second)
+{
+ TypeLink *first = second->prev;
+ first->next = second->next;
+ first->next->prev = first;
+ RL_LEN (first) += RL_LEN (second);
+ free_type_link (second);
+ return first;
+}
+
+static void
+compact_list (TypeLink *list)
+{
+ if (list->next)
+ for (list = list->next; list; list = list->next)
+ if (RL_TYPE (list->prev) == RL_TYPE (list)
+ && RL_LEVEL (list->prev) == RL_LEVEL (list))
+ list = merge_with_prev (list);
+}
+
+static void
+compact_neutrals (TypeLink *list)
+{
+ if (list->next)
+ {
+ for (list = list->next; list; list = list->next)
+ {
+ if (RL_LEVEL (list->prev) == RL_LEVEL (list)
+ &&
+ ((RL_TYPE
+ (list->prev) == RL_TYPE (list)
+ || (FRIBIDI_IS_NEUTRAL (RL_TYPE (list->prev))
+ && FRIBIDI_IS_NEUTRAL (RL_TYPE (list))))))
+ list = merge_with_prev (list);
+ }
+ }
+}
+
+/*======================================================================
+ * Frees up the rl_list, must be called after each call to
+ * fribidi_analyse_string(), after the list is not needed anymore.
+ *----------------------------------------------------------------------*/
+static void
+free_rl_list (TypeLink *type_rl_list)
+{
+ DBG ("Entering free_rl_list()\n");
+
+ if (!type_rl_list)
+ {
+ DBG ("Leaving free_rl_list()\n");
+ return;
+ }
+
+ g_slice_free_chain (TypeLink, type_rl_list, next);
+
+ DBG ("Leaving free_rl_list()\n");
+ return;
+}
+
+/*=========================================================================
+ * define macros for push and pop the status in to / out of the stack
+ *-------------------------------------------------------------------------*/
+
+/* There's some little points in pushing and poping into the status stack:
+ 1. when the embedding level is not valid (more than UNI_MAX_BIDI_LEVEL=61),
+ you must reject it, and not to push into the stack, but when you see a
+ PDF, you must find the matching code, and if it was pushed in the stack,
+ pop it, it means you must pop if and only if you have pushed the
+ matching code, the over_pushed var counts the number of rejected codes yet.
+ 2. there's a more confusing point too, when the embedding level is exactly
+ UNI_MAX_BIDI_LEVEL-1=60, an LRO or LRE must be rejected because the new
+ level would be UNI_MAX_BIDI_LEVEL+1=62, that is invalid, but an RLO or RLE
+ must be accepted because the new level is UNI_MAX_BIDI_LEVEL=61, that is
+ valid, so the rejected codes may be not continuous in the logical order,
+ in fact there is at most two continuous intervals of codes, with a RLO or
+ RLE between them. To support this case, the first_interval var counts the
+ number of rejected codes in the first interval, when it is 0, means that
+ there is only one interval yet.
+*/
+
+/* a. If this new level would be valid, then this embedding code is valid.
+ Remember (push) the current embedding level and override status.
+ Reset current level to this new level, and reset the override status to
+ new_override.
+ b. If the new level would not be valid, then this code is invalid. Don't
+ change the current level or override status.
+*/
+#define PUSH_STATUS \
+ do { \
+ if (new_level <= UNI_MAX_BIDI_LEVEL) \
+ { \
+ if (level == UNI_MAX_BIDI_LEVEL - 1) \
+ first_interval = over_pushed; \
+ status_stack[stack_size].level = level; \
+ status_stack[stack_size].override = override; \
+ stack_size++; \
+ level = new_level; \
+ override = new_override; \
+ } else \
+ over_pushed++; \
+ } while (0)
+
+/* If there was a valid matching code, restore (pop) the last remembered
+ (pushed) embedding level and directional override.
+*/
+#define POP_STATUS \
+ do { \
+ if (over_pushed || stack_size) \
+ { \
+ if (over_pushed > first_interval) \
+ over_pushed--; \
+ else \
+ { \
+ if (over_pushed == first_interval) \
+ first_interval = 0; \
+ stack_size--; \
+ level = status_stack[stack_size].level; \
+ override = status_stack[stack_size].override; \
+ } \
+ } \
+ } while (0)
+
+/*==========================================================================
+ * There was no support for sor and eor in the absence of Explicit Embedding
+ * Levels, so define macros, to support them, with as less change as needed.
+ *--------------------------------------------------------------------------*/
+
+/* Return the type of previous char or the sor, if already at the start of
+ a run level. */
+#define PREV_TYPE_OR_SOR(pp) \
+ ( \
+ RL_LEVEL(pp->prev) == RL_LEVEL(pp) ? \
+ RL_TYPE(pp->prev) : \
+ FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->prev), RL_LEVEL(pp))) \
+ )
+
+/* Return the type of next char or the eor, if already at the end of
+ a run level. */
+#define NEXT_TYPE_OR_EOR(pp) \
+ ( \
+ !pp->next ? \
+ FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(pp)) : \
+ (RL_LEVEL(pp->next) == RL_LEVEL(pp) ? \
+ RL_TYPE(pp->next) : \
+ FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->next), RL_LEVEL(pp))) \
+ ) \
+ )
+
+
+/* Return the embedding direction of a link. */
+#define FRIBIDI_EMBEDDING_DIRECTION(list) \
+ FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(list))
+
+
+/*======================================================================
+ * This function should follow the Unicode specification closely!
+ *----------------------------------------------------------------------*/
+static fribidi_boolean
+fribidi_analyse_string_utf8 ( /* input */
+ const char *str,
+ int bytelen,
+ FriBidiCharType *pbase_dir,
+ /* output */
+ FriBidiStrIndex *len,
+ TypeLink **ptype_rl_list,
+ FriBidiLevel *pmax_level)
+{
+ FriBidiLevel base_level, max_level;
+ FriBidiCharType base_dir;
+ TypeLink *type_rl_list, *explicits_list, *explicits_list_end, *pp;
+
+ DBG ("Entering fribidi_analyse_string()\n");
+
+ /* Determinate character types */
+ DBG (" Determine character types\n");
+ {
+ FriBidiCharType ored_types;
+ FriBidiCharType anded_strongs;
+
+ /* Run length encode the character types */
+ type_rl_list = run_length_encode_types_utf8 (str, bytelen, len,
+ &ored_types, &anded_strongs);
+
+ /* The case that all resolved levels will be ltr.
+ * First, all strongs should be ltr, and one of the following:
+ *
+ * o *pbase_dir doesn't have an rtl taste.
+ * o there are letters, and *pbase_dir is weak.
+ */
+ if (!FRIBIDI_IS_RTL (ored_types) &&
+ (!FRIBIDI_IS_RTL (*pbase_dir) ||
+ (FRIBIDI_IS_WEAK (*pbase_dir) && FRIBIDI_IS_LETTER (ored_types))
+ ))
+ {
+ /* all ltr */
+ free_rl_list (type_rl_list);
+
+ *ptype_rl_list = NULL;
+ *pmax_level = 0;
+ *pbase_dir = FRIBIDI_TYPE_LTR;
+
+ return 0;
+ }
+ /* The case that all resolved levels will be rtl is much more complex.
+ * First, there should be no numbers, all strongs be rtl, and one of
+ * the following:
+ *
+ * o *pbase_dir has an rtl taste (may be weak).
+ * o there are letters, and *pbase_dir is weak.
+ */
+ else if (!FRIBIDI_IS_NUMBER (ored_types) && FRIBIDI_IS_RTL (anded_strongs) &&
+ (FRIBIDI_IS_RTL (*pbase_dir) ||
+ (FRIBIDI_IS_WEAK (*pbase_dir) && FRIBIDI_IS_LETTER (ored_types))
+ ))
+ {
+ free_rl_list (type_rl_list);
+
+ *ptype_rl_list = NULL;
+ *pmax_level = 1;
+ *pbase_dir = FRIBIDI_TYPE_RTL;
+
+ return 0;
+ }
+ }
+ DBG (" Determine character types, Done\n");
+
+ init_list (&explicits_list, &explicits_list_end);
+
+ /* Find base level */
+ DBG (" Finding the base level\n");
+ if (FRIBIDI_IS_STRONG (*pbase_dir))
+ base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
+ /* P2. P3. Search for first strong character and use its direction as
+ base direction */
+ else
+ {
+ /* If no strong base_dir was found, resort to the weak direction
+ that was passed on input. */
+ base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
+ base_dir = FRIBIDI_TYPE_ON;
+ for (pp = type_rl_list; pp; pp = pp->next)
+ if (FRIBIDI_IS_LETTER (RL_TYPE (pp)))
+ {
+ base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (pp));
+ base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
+ break;
+ }
+ }
+ base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
+ DBG2 (" Base level : %c\n", fribidi_char_from_level (base_level));
+ DBG2 (" Base dir : %c\n", fribidi_char_from_type (base_dir));
+ DBG (" Finding the base level, Done\n");
+
+ /* Explicit Levels and Directions */
+ DBG ("Explicit Levels and Directions\n");
+ {
+ /* X1. Begin by setting the current embedding level to the paragraph
+ embedding level. Set the directional override status to neutral.
+ Process each character iteratively, applying rules X2 through X9.
+ Only embedding levels from 0 to 61 are valid in this phase. */
+ FriBidiLevel level, new_level;
+ FriBidiCharType override, new_override;
+ FriBidiStrIndex i;
+ int stack_size, over_pushed, first_interval;
+ LevelInfo *status_stack;
+ TypeLink temp_link;
+
+ level = base_level;
+ override = FRIBIDI_TYPE_ON;
+ /* stack */
+ stack_size = 0;
+ over_pushed = 0;
+ first_interval = 0;
+ status_stack =
+ (LevelInfo *) malloc (sizeof (LevelInfo) * (UNI_MAX_BIDI_LEVEL + 2));
+
+ for (pp = type_rl_list->next; pp->next; pp = pp->next)
+ {
+ FriBidiCharType this_type = RL_TYPE (pp);
+ if (FRIBIDI_IS_EXPLICIT_OR_BN (this_type))
+ {
+ if (FRIBIDI_IS_STRONG (this_type))
+ { /* LRE, RLE, LRO, RLO */
+ /* 1. Explicit Embeddings */
+ /* X2. With each RLE, compute the least greater odd embedding level. */
+ /* X3. With each LRE, compute the least greater even embedding level. */
+ /* 2. Explicit Overrides */
+ /* X4. With each RLO, compute the least greater odd embedding level. */
+ /* X5. With each LRO, compute the least greater even embedding level. */
+ new_override = FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR (this_type);
+ for (i = 0; i < RL_LEN (pp); i++)
+ {
+ new_level =
+ ((level + FRIBIDI_DIR_TO_LEVEL (this_type) + 2) & ~1) -
+ FRIBIDI_DIR_TO_LEVEL (this_type);
+ PUSH_STATUS;
+ }
+ }
+ else if (this_type == FRIBIDI_TYPE_PDF)
+ {
+ /* 3. Terminating Embeddings and overrides */
+ /* X7. With each PDF, determine the matching embedding or
+ override code. */
+ for (i = 0; i < RL_LEN (pp); i++)
+ POP_STATUS;
+ }
+ /* X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. */
+ /* Remove element and add it to explicits_list */
+ temp_link.next = pp->next;
+ pp->level = FRIBIDI_LEVEL_REMOVED;
+ move_element_before (pp, explicits_list_end);
+ pp = &temp_link;
+ }
+ else
+ {
+ /* X6. For all typed besides RLE, LRE, RLO, LRO, and PDF:
+ a. Set the level of the current character to the current
+ embedding level.
+ b. Whenever the directional override status is not neutral,
+ reset the current character type to the directional override
+ status. */
+ RL_LEVEL (pp) = level;
+ if (!FRIBIDI_IS_NEUTRAL (override))
+ RL_TYPE (pp) = override;
+ }
+ /* X8. All explicit directional embeddings and overrides are
+ completely terminated at the end of each paragraph. Paragraph
+ separators are not included in the embedding. */
+ /* This function is running on a single paragraph, so we can do
+ X8 after all the input is processed. */
+ }
+
+ /* Implementing X8. It has no effect on a single paragraph! */
+ level = base_level;
+ override = FRIBIDI_TYPE_ON;
+ stack_size = 0;
+ over_pushed = 0;
+
+ free (status_stack);
+ }
+ /* X10. The remaining rules are applied to each run of characters at the
+ same level. For each run, determine the start-of-level-run (sor) and
+ end-of-level-run (eor) type, either L or R. This depends on the
+ higher of the two levels on either side of the boundary (at the start
+ or end of the paragraph, the level of the 'other' run is the base
+ embedding level). If the higher level is odd, the type is R, otherwise
+ it is L. */
+ /* Resolving Implicit Levels can be done out of X10 loop, so only change
+ of Resolving Weak Types and Resolving Neutral Types is needed. */
+
+ compact_list (type_rl_list);
+
+ /* 4. Resolving weak types */
+ DBG ("Resolving weak types\n");
+ {
+ FriBidiCharType last_strong, prev_type_org;
+ fribidi_boolean w4;
+
+ last_strong = base_dir;
+
+ for (pp = type_rl_list->next; pp->next; pp = pp->next)
+ {
+ FriBidiCharType prev_type, this_type, next_type;
+
+ prev_type = PREV_TYPE_OR_SOR (pp);
+ this_type = RL_TYPE (pp);
+ next_type = NEXT_TYPE_OR_EOR (pp);
+
+ if (FRIBIDI_IS_STRONG (prev_type))
+ last_strong = prev_type;
+
+ /* W1. NSM
+ Examine each non-spacing mark (NSM) in the level run, and change the
+ type of the NSM to the type of the previous character. If the NSM
+ is at the start of the level run, it will get the type of sor. */
+ /* Implementation note: it is important that if the previous character
+ is not sor, then we should merge this run with the previous,
+ because of rules like W5, that we assume all of a sequence of
+ adjacent ETs are in one TypeLink. */
+ if (this_type == FRIBIDI_TYPE_NSM)
+ {
+ if (RL_LEVEL (pp->prev) == RL_LEVEL (pp))
+ pp = merge_with_prev (pp);
+ else
+ RL_TYPE (pp) = prev_type;
+ continue; /* As we know the next condition cannot be true. */
+ }
+
+ /* W2: European numbers. */
+ if (this_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_AL)
+ {
+ RL_TYPE (pp) = FRIBIDI_TYPE_AN;
+
+ /* Resolving dependency of loops for rules W1 and W2, so we
+ can merge them in one loop. */
+ if (next_type == FRIBIDI_TYPE_NSM)
+ RL_TYPE (pp->next) = FRIBIDI_TYPE_AN;
+ }
+ }
+
+
+ last_strong = base_dir;
+ /* Resolving dependency of loops for rules W4 and W5, W5 may
+ want to prevent W4 to take effect in the next turn, do this
+ through "w4". */
+ w4 = FRIBIDI_TRUE;
+ /* Resolving dependency of loops for rules W4 and W5 with W7,
+ W7 may change an EN to L but it sets the prev_type_org if needed,
+ so W4 and W5 in next turn can still do their works. */
+ prev_type_org = FRIBIDI_TYPE_ON;
+
+ for (pp = type_rl_list->next; pp->next; pp = pp->next)
+ {
+ FriBidiCharType prev_type, this_type, next_type;
+
+ prev_type = PREV_TYPE_OR_SOR (pp);
+ this_type = RL_TYPE (pp);
+ next_type = NEXT_TYPE_OR_EOR (pp);
+
+ if (FRIBIDI_IS_STRONG (prev_type))
+ last_strong = prev_type;
+
+ /* W3: Change ALs to R. */
+ if (this_type == FRIBIDI_TYPE_AL)
+ {
+ RL_TYPE (pp) = FRIBIDI_TYPE_RTL;
+ w4 = FRIBIDI_TRUE;
+ prev_type_org = FRIBIDI_TYPE_ON;
+ continue;
+ }
+
+ /* W4. A single european separator changes to a european number.
+ A single common separator between two numbers of the same type
+ changes to that type. */
+ if (w4
+ && RL_LEN (pp) == 1 && FRIBIDI_IS_ES_OR_CS (this_type)
+ && FRIBIDI_IS_NUMBER (prev_type_org) && prev_type_org == next_type
+ && (prev_type_org == FRIBIDI_TYPE_EN
+ || this_type == FRIBIDI_TYPE_CS))
+ {
+ RL_TYPE (pp) = prev_type;
+ this_type = RL_TYPE (pp);
+ }
+ w4 = FRIBIDI_TRUE;
+
+ /* W5. A sequence of European terminators adjacent to European
+ numbers changes to All European numbers. */
+ if (this_type == FRIBIDI_TYPE_ET
+ && (prev_type_org == FRIBIDI_TYPE_EN
+ || next_type == FRIBIDI_TYPE_EN))
+ {
+ RL_TYPE (pp) = FRIBIDI_TYPE_EN;
+ w4 = FRIBIDI_FALSE;
+ this_type = RL_TYPE (pp);
+ }
+
+ /* W6. Otherwise change separators and terminators to other neutral. */
+ if (FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR (this_type))
+ RL_TYPE (pp) = FRIBIDI_TYPE_ON;
+
+ /* W7. Change european numbers to L. */
+ if (this_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_LTR)
+ {
+ RL_TYPE (pp) = FRIBIDI_TYPE_LTR;
+ prev_type_org = (RL_LEVEL (pp) == RL_LEVEL (pp->next) ?
+ FRIBIDI_TYPE_EN : FRIBIDI_TYPE_ON);
+ }
+ else
+ prev_type_org = PREV_TYPE_OR_SOR (pp->next);
+ }
+ }
+
+ compact_neutrals (type_rl_list);
+
+ /* 5. Resolving Neutral Types */
+ DBG ("Resolving neutral types\n");
+ {
+ /* N1. and N2.
+ For each neutral, resolve it. */
+ for (pp = type_rl_list->next; pp->next; pp = pp->next)
+ {
+ FriBidiCharType prev_type, this_type, next_type;
+
+ /* "European and arabic numbers are treated as though they were R"
+ FRIBIDI_CHANGE_NUMBER_TO_RTL does this. */
+ this_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE (pp));
+ prev_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (PREV_TYPE_OR_SOR (pp));
+ next_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (NEXT_TYPE_OR_EOR (pp));
+
+ if (FRIBIDI_IS_NEUTRAL (this_type))
+ RL_TYPE (pp) = (prev_type == next_type) ?
+ /* N1. */ prev_type :
+ /* N2. */ FRIBIDI_EMBEDDING_DIRECTION (pp);
+ }
+ }
+
+ compact_list (type_rl_list);
+
+ /* 6. Resolving implicit levels */
+ DBG ("Resolving implicit levels\n");
+ {
+ max_level = base_level;
+
+ for (pp = type_rl_list->next; pp->next; pp = pp->next)
+ {
+ FriBidiCharType this_type;
+ int level;
+
+ this_type = RL_TYPE (pp);
+ level = RL_LEVEL (pp);
+
+ /* I1. Even */
+ /* I2. Odd */
+ if (FRIBIDI_IS_NUMBER (this_type))
+ RL_LEVEL (pp) = (level + 2) & ~1;
+ else
+ RL_LEVEL (pp) = (level ^ FRIBIDI_DIR_TO_LEVEL (this_type)) +
+ (level & 1);
+
+ if (RL_LEVEL (pp) > max_level)
+ max_level = RL_LEVEL (pp);
+ }
+ }
+
+ compact_list (type_rl_list);
+
+/* Reinsert the explicit codes & bn's that already removed, from the
+ explicits_list to type_rl_list. */
+ DBG ("Reinserting explicit codes\n");
+ {
+ TypeLink *p;
+
+ override_list (type_rl_list, explicits_list);
+ p = type_rl_list->next;
+ if (p->level < 0)
+ p->level = base_level;
+ for (; p->next; p = p->next)
+ if (p->level < 0)
+ p->level = p->prev->level;
+ }
+
+ DBG ("Reset the embedding levels\n");
+ {
+ int j, k, state, pos;
+ TypeLink *p, *q, *list, *list_end;
+
+ const char *strp = str + bytelen;
+
+ /* L1. Reset the embedding levels of some chars. */
+ init_list (&list, &list_end);
+ q = list_end;
+ state = 1;
+ pos = *len - 1;
+ for (j = *len - 1; j >= -1; j--)
+ {
+ /* if state is on at the very first of string, do this too. */
+ if (j >= 0)
+ k = fribidi_get_type (g_utf8_get_char (strp = g_utf8_prev_char (strp)));
+ else
+ k = FRIBIDI_TYPE_ON;
+ if (!state && FRIBIDI_IS_SEPARATOR (k))
+ {
+ state = 1;
+ pos = j;
+ }
+ else if (state && !FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS (k))
+ {
+ state = 0;
+ p = new_type_link ();
+ p->prev = p->next = NULL;
+ p->pos = j + 1;
+ p->len = pos - j;
+ p->type = base_dir;
+ p->level = base_level;
+ move_element_before (p, q);
+ q = p;
+ }
+ }
+ override_list (type_rl_list, list);
+ }
+
+ *ptype_rl_list = type_rl_list;
+ *pmax_level = max_level;
+ *pbase_dir = base_dir;
+
+ DBG ("Leaving fribidi_analyse_string()\n");
+ return 1;
+}
+
+/*======================================================================
+ * fribidi_log2vis_get_embedding_levels() is used in order to just get
+ * the embedding levels.
+ *----------------------------------------------------------------------*/
+FRIBIDI_API FriBidiLevel *
+fribidi_log2vis_get_embedding_levels_new_utf8 ( /* input */
+ const char *str,
+ int bytelen,
+ FriBidiCharType *pbase_dir)
+{
+ TypeLink *type_rl_list, *pp;
+ FriBidiLevel max_level, *embedding_level_list;
+ FriBidiStrIndex len;
+
+ DBG ("Entering fribidi_log2vis_get_embedding_levels()\n");
+
+ if (bytelen == 0)
+ {
+ DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n");
+ return NULL;
+ }
+
+ if (!fribidi_analyse_string_utf8 (str, bytelen, pbase_dir,
+ /* output */
+ &len, &type_rl_list, &max_level))
+ {
+ /* unidirectional. return all-zero or all-one embedding levels */
+
+ if (max_level)
+ {
+ embedding_level_list = g_new (FriBidiLevel, len);
+ /* assumes sizeof(FriBidiLevel) == 1, which is true! */
+ memset (embedding_level_list, max_level, len);
+ return embedding_level_list;
+ }
+ else
+ {
+ return g_new0 (FriBidiLevel, len);
+ }
+ }
+
+ embedding_level_list = g_new (FriBidiLevel, len);
+ for (pp = type_rl_list->next; pp->next; pp = pp->next)
+ {
+ FriBidiStrIndex i, pos = RL_POS (pp), len = RL_LEN (pp);
+ FriBidiLevel level = RL_LEVEL (pp);
+ for (i = 0; i < len; i++)
+ embedding_level_list[pos + i] = level;
+ }
+
+ free_rl_list (type_rl_list);
+
+ DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n");
+ return embedding_level_list;
+}
+
diff --git a/trunk/pango/mini-fribidi/fribidi.h b/trunk/pango/mini-fribidi/fribidi.h
new file mode 100644
index 00000000..cdfec5c7
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi.h
@@ -0,0 +1,56 @@
+/* FriBidi - Library of BiDi algorithm
+ * Copyright (C) 1999,2000 Dov Grobgeld, and
+ * Copyright (C) 2001,2002 Behdad Esfahbod.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library, in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ * For licensing issues, contact <dov@imagic.weizmann.ac.il> and
+ * <fwpg@sharif.edu>.
+ */
+
+#ifndef FRIBIDI_H
+#define FRIBIDI_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include "fribidi_config.h"
+#include "fribidi_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define FRIBIDI_HAVE_UTF8
+
+ FRIBIDI_API FriBidiLevel *fribidi_log2vis_get_embedding_levels_new_utf8 ( /* input */
+ const char *str,
+ int bytelen,
+ FriBidiCharType
+ *pbase_dir);
+
+/*======================================================================
+ * fribidi_get_type() returns bidi type of a character.
+ *----------------------------------------------------------------------*/
+ FRIBIDI_API FriBidiCharType fribidi_get_type (FriBidiChar uch);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FRIBIDI_H */
diff --git a/trunk/pango/mini-fribidi/fribidi.patch b/trunk/pango/mini-fribidi/fribidi.patch
new file mode 100644
index 00000000..0975dbcb
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi.patch
@@ -0,0 +1,1369 @@
+diff -rua /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi.c ./fribidi.c
+--- /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi.c 2005-09-25 18:50:30.000000000 -0400
++++ fribidi.c 2005-12-05 11:35:07.000000000 -0500
+@@ -22,15 +22,12 @@
+ */
+
+ #include <stdlib.h>
++#include <string.h>
+
+ #ifdef HAVE_CONFIG_H
+ #include <config.h>
+ #endif
+ #include "fribidi.h"
+-#include "fribidi_mem.h"
+-#ifdef DEBUG
+-#include <stdio.h>
+-#endif
+
+ /* Redefine FRIBIDI_CHUNK_SIZE in config.h to override this. */
+ #ifndef FRIBIDI_CHUNK_SIZE
+@@ -41,19 +38,8 @@
+ #endif
+ #endif
+
+-#ifdef DEBUG
+-#define DBG(s) do { if (fribidi_debug) { fprintf(stderr, s); } } while (0)
+-#define DBG2(s, t) do { if (fribidi_debug) { fprintf(stderr, s, t); } } while (0)
+-#else
+ #define DBG(s)
+ #define DBG2(s, t)
+-#endif
+-
+-#ifdef DEBUG
+-char fribidi_char_from_type (FriBidiCharType c);
+-#endif
+-
+-#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+ /*======================================================================
+ * Typedef for the run-length list.
+@@ -81,95 +67,20 @@
+ }
+ LevelInfo;
+
+-#ifdef DEBUG
+-static fribidi_boolean fribidi_debug = FRIBIDI_FALSE;
+-#endif
+-
+-fribidi_boolean
+-fribidi_set_debug (fribidi_boolean debug)
+-{
+-#ifdef DEBUG
+- fribidi_debug = debug;
+-#else
+- debug = 0;
+-#endif
+- return debug;
+-}
+-
+-static void
+-bidi_string_reverse (FriBidiChar *str,
+- FriBidiStrIndex len)
+-{
+- FriBidiStrIndex i;
+- for (i = 0; i < len / 2; i++)
+- {
+- FriBidiChar tmp = str[i];
+- str[i] = str[len - 1 - i];
+- str[len - 1 - i] = tmp;
+- }
+-}
+-
+-static void
+-index_array_reverse (FriBidiStrIndex *arr,
+- FriBidiStrIndex len)
+-{
+- FriBidiStrIndex i;
+- for (i = 0; i < len / 2; i++)
+- {
+- FriBidiStrIndex tmp = arr[i];
+- arr[i] = arr[len - 1 - i];
+- arr[len - 1 - i] = tmp;
+- }
+-}
+-
+-#ifndef USE_SIMPLE_MALLOC
+-static TypeLink *free_type_links = NULL;
+-#endif
+-
+ static TypeLink *
+ new_type_link (void)
+ {
+ TypeLink *link;
+
+-#ifdef USE_SIMPLE_MALLOC
+- link = malloc (sizeof (TypeLink));
+-#else /* !USE_SIMPLE_MALLOC */
+- if (free_type_links)
+- {
+- link = free_type_links;
+- free_type_links = free_type_links->next;
+- }
+- else
+- {
+- static FriBidiMemChunk *mem_chunk = NULL;
+-
+- if (!mem_chunk)
+- mem_chunk = fribidi_mem_chunk_create (TypeLink,
+- FRIBIDI_CHUNK_SIZE,
+- FRIBIDI_ALLOC_ONLY);
+-
+- link = fribidi_chunk_new (TypeLink,
+- mem_chunk);
+- }
+-#endif /* !USE_SIMPLE_MALLOC */
++ link = g_slice_new0 (TypeLink);
+
+- link->len = 0;
+- link->pos = 0;
+- link->level = 0;
+- link->next = NULL;
+- link->prev = NULL;
+ return link;
+ }
+
+ static void
+ free_type_link (TypeLink *link)
+ {
+-#ifdef USE_SIMPLE_MALLOC
+- free (link);
+-#else
+- link->next = free_type_links;
+- free_type_links = link;
+-#endif
++ g_slice_free (TypeLink, link);
+ }
+
+ #define FRIBIDI_ADD_TYPE_LINK(p,q) \
+@@ -181,12 +92,18 @@
+ } while (0)
+
+ static TypeLink *
+-run_length_encode_types (FriBidiCharType *char_type,
+- FriBidiStrIndex type_len)
++run_length_encode_types_utf8 (const char *s,
++ int bytelen,
++ FriBidiStrIndex *len,
++ FriBidiCharType *pored_types,
++ FriBidiCharType *panded_strongs)
+ {
+ TypeLink *list, *last, *link;
+-
++ FriBidiCharType char_type;
++ FriBidiCharType ored_types = 0;
++ FriBidiCharType anded_strongs = FRIBIDI_TYPE_RLE;
+ FriBidiStrIndex i;
++ const char *p;
+
+ /* Add the starting link */
+ list = new_type_link ();
+@@ -194,23 +111,38 @@
+ list->level = FRIBIDI_LEVEL_START;
+ last = list;
+
+- /* Sweep over the string_type s */
+- for (i = 0; i < type_len; i++)
+- if (char_type[i] != last->type)
++ /* Sweep over the string s */
++ i = 0;
++ for (p = s; p < s + bytelen; p = g_utf8_next_char(p)) {
++ char_type = fribidi_get_type (g_utf8_get_char (p));
++ ored_types |= char_type;
++ if (FRIBIDI_IS_STRONG (char_type))
++ anded_strongs &= char_type;
++ if (char_type != last->type)
+ {
+ link = new_type_link ();
+- link->type = char_type[i];
++ link->type = char_type;
+ link->pos = i;
+ FRIBIDI_ADD_TYPE_LINK (last, link);
+ }
++ i++;
++ }
+
+ /* Add the ending link */
+ link = new_type_link ();
+ link->type = FRIBIDI_TYPE_EOT;
+ link->level = FRIBIDI_LEVEL_END;
+- link->pos = type_len;
++ link->pos = i;
+ FRIBIDI_ADD_TYPE_LINK (last, link);
+
++ if (len)
++ *len = i;
++
++ if (pored_types)
++ *pored_types = ored_types;
++ if (panded_strongs)
++ *panded_strongs = anded_strongs;
++
+ return list;
+ }
+
+@@ -418,6 +350,27 @@
+ }
+ }
+
++/*======================================================================
++ * Frees up the rl_list, must be called after each call to
++ * fribidi_analyse_string(), after the list is not needed anymore.
++ *----------------------------------------------------------------------*/
++static void
++free_rl_list (TypeLink *type_rl_list)
++{
++ DBG ("Entering free_rl_list()\n");
++
++ if (!type_rl_list)
++ {
++ DBG ("Leaving free_rl_list()\n");
++ return;
++ }
++
++ g_slice_free_chain (TypeLink, type_rl_list, next);
++
++ DBG ("Leaving free_rl_list()\n");
++ return;
++}
++
+ /*=========================================================================
+ * define macros for push and pop the status in to / out of the stack
+ *-------------------------------------------------------------------------*/
+@@ -512,95 +465,22 @@
+ #define FRIBIDI_EMBEDDING_DIRECTION(list) \
+ FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(list))
+
+-#ifdef DEBUG
+-/*======================================================================
+- * For debugging, define some functions for printing the types and the
+- * levels.
+- *----------------------------------------------------------------------*/
+-
+-static char char_from_level_array[] = {
+- 'e', /* FRIBIDI_LEVEL_REMOVED, internal error, this level shouldn't be viewed. */
+- '_', /* FRIBIDI_LEVEL_START or _END, indicating start of string and end of string. */
+- /* 0-9,A-F are the only valid levels in debug mode and before resolving
+- implicits. after that the levels X, Y, Z may be appear too. */
+- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+- 'A', 'B', 'C', 'D', 'E', 'F',
+- 'X', 'Y', 'Z', /* only must appear after resolving implicits. */
+- 'o', 'o', 'o' /* overflows, this levels and higher levels show a bug!. */
+-};
+-
+-#define fribidi_char_from_level(level) char_from_level_array[(level) + 2]
+-
+-static void
+-print_types_re (TypeLink *pp)
+-{
+- fprintf (stderr, " Run types : ");
+- while (pp)
+- {
+- fprintf (stderr, "%d:l%d(%s)[%d] ",
+- pp->pos, pp->len, fribidi_type_name (pp->type), pp->level);
+- pp = pp->next;
+- }
+- fprintf (stderr, "\n");
+-}
+-
+-static void
+-print_resolved_levels (TypeLink *pp)
+-{
+- fprintf (stderr, " Res. levels: ");
+- while (pp)
+- {
+- FriBidiStrIndex i;
+- for (i = 0; i < RL_LEN (pp); i++)
+- fprintf (stderr, "%c", fribidi_char_from_level (RL_LEVEL (pp)));
+- pp = pp->next;
+- }
+- fprintf (stderr, "\n");
+-}
+-
+-static void
+-print_resolved_types (TypeLink *pp)
+-{
+- fprintf (stderr, " Res. types : ");
+- while (pp)
+- {
+- FriBidiStrIndex i;
+- for (i = 0; i < RL_LEN (pp); i++)
+- fprintf (stderr, "%c", fribidi_char_from_type (pp->type));
+- pp = pp->next;
+- }
+- fprintf (stderr, "\n");
+-}
+-
+-/* Here, only for test porpuses, we have assumed that a fribidi_string
+- ends with a 0 character */
+-static void
+-print_bidi_string (FriBidiChar *str)
+-{
+- FriBidiStrIndex i;
+- fprintf (stderr, " Org. types : ");
+- for (i = 0; str[i]; i++)
+- fprintf (stderr, "%c",
+- fribidi_char_from_type (fribidi_get_type (str[i])));
+- fprintf (stderr, "\n");
+-}
+-#endif
+
+ /*======================================================================
+ * This function should follow the Unicode specification closely!
+ *----------------------------------------------------------------------*/
+-static void
+-fribidi_analyse_string ( /* input */
+- FriBidiChar *str,
+- FriBidiStrIndex len,
++static fribidi_boolean
++fribidi_analyse_string_utf8 ( /* input */
++ const char *str,
++ int bytelen,
+ FriBidiCharType *pbase_dir,
+ /* output */
++ FriBidiStrIndex *len,
+ TypeLink **ptype_rl_list,
+ FriBidiLevel *pmax_level)
+ {
+ FriBidiLevel base_level, max_level;
+ FriBidiCharType base_dir;
+- FriBidiStrIndex i;
+ TypeLink *type_rl_list, *explicits_list, *explicits_list_end, *pp;
+
+ DBG ("Entering fribidi_analyse_string()\n");
+@@ -608,14 +488,53 @@
+ /* Determinate character types */
+ DBG (" Determine character types\n");
+ {
+- FriBidiCharType *char_type =
+- (FriBidiCharType *) malloc (len * sizeof (FriBidiCharType));
+- for (i = 0; i < len; i++)
+- char_type[i] = fribidi_get_type (str[i]);
++ FriBidiCharType ored_types;
++ FriBidiCharType anded_strongs;
+
+ /* Run length encode the character types */
+- type_rl_list = run_length_encode_types (char_type, len);
+- free (char_type);
++ type_rl_list = run_length_encode_types_utf8 (str, bytelen, len,
++ &ored_types, &anded_strongs);
++
++ /* The case that all resolved levels will be ltr.
++ * First, all strongs should be ltr, and one of the following:
++ *
++ * o *pbase_dir doesn't have an rtl taste.
++ * o there are letters, and *pbase_dir is weak.
++ */
++ if (!FRIBIDI_IS_RTL (ored_types) &&
++ (!FRIBIDI_IS_RTL (*pbase_dir) ||
++ (FRIBIDI_IS_WEAK (*pbase_dir) && FRIBIDI_IS_LETTER (ored_types))
++ ))
++ {
++ /* all ltr */
++ free_rl_list (type_rl_list);
++
++ *ptype_rl_list = NULL;
++ *pmax_level = 0;
++ *pbase_dir = FRIBIDI_TYPE_LTR;
++
++ return 0;
++ }
++ /* The case that all resolved levels will be rtl is much more complex.
++ * First, there should be no numbers, all strongs be rtl, and one of
++ * the following:
++ *
++ * o *pbase_dir has an rtl taste (may be weak).
++ * o there are letters, and *pbase_dir is weak.
++ */
++ else if (!FRIBIDI_IS_NUMBER (ored_types) && FRIBIDI_IS_RTL (anded_strongs) &&
++ (FRIBIDI_IS_RTL (*pbase_dir) ||
++ (FRIBIDI_IS_WEAK (*pbase_dir) && FRIBIDI_IS_LETTER (ored_types))
++ ))
++ {
++ free_rl_list (type_rl_list);
++
++ *ptype_rl_list = NULL;
++ *pmax_level = 1;
++ *pbase_dir = FRIBIDI_TYPE_RTL;
++
++ return 0;
++ }
+ }
+ DBG (" Determine character types, Done\n");
+
+@@ -646,13 +565,6 @@
+ DBG2 (" Base dir : %c\n", fribidi_char_from_type (base_dir));
+ DBG (" Finding the base level, Done\n");
+
+-#ifdef DEBUG
+- if (fribidi_debug)
+- {
+- print_types_re (type_rl_list);
+- }
+-#endif
+-
+ /* Explicit Levels and Directions */
+ DBG ("Explicit Levels and Directions\n");
+ {
+@@ -752,16 +664,6 @@
+
+ compact_list (type_rl_list);
+
+-#ifdef DEBUG
+- if (fribidi_debug)
+- {
+- print_types_re (type_rl_list);
+- print_bidi_string (str);
+- print_resolved_levels (type_rl_list);
+- print_resolved_types (type_rl_list);
+- }
+-#endif
+-
+ /* 4. Resolving weak types */
+ DBG ("Resolving weak types\n");
+ {
+@@ -884,14 +786,6 @@
+
+ compact_neutrals (type_rl_list);
+
+-#ifdef DEBUG
+- if (fribidi_debug)
+- {
+- print_resolved_levels (type_rl_list);
+- print_resolved_types (type_rl_list);
+- }
+-#endif
+-
+ /* 5. Resolving Neutral Types */
+ DBG ("Resolving neutral types\n");
+ {
+@@ -916,14 +810,6 @@
+
+ compact_list (type_rl_list);
+
+-#ifdef DEBUG
+- if (fribidi_debug)
+- {
+- print_resolved_levels (type_rl_list);
+- print_resolved_types (type_rl_list);
+- }
+-#endif
+-
+ /* 6. Resolving implicit levels */
+ DBG ("Resolving implicit levels\n");
+ {
+@@ -952,15 +838,6 @@
+
+ compact_list (type_rl_list);
+
+-#ifdef DEBUG
+- if (fribidi_debug)
+- {
+- print_bidi_string (str);
+- print_resolved_levels (type_rl_list);
+- print_resolved_types (type_rl_list);
+- }
+-#endif
+-
+ /* Reinsert the explicit codes & bn's that already removed, from the
+ explicits_list to type_rl_list. */
+ DBG ("Reinserting explicit codes\n");
+@@ -976,30 +853,23 @@
+ p->level = p->prev->level;
+ }
+
+-#ifdef DEBUG
+- if (fribidi_debug)
+- {
+- print_types_re (type_rl_list);
+- print_resolved_levels (type_rl_list);
+- print_resolved_types (type_rl_list);
+- }
+-#endif
+-
+ DBG ("Reset the embedding levels\n");
+ {
+ int j, k, state, pos;
+ TypeLink *p, *q, *list, *list_end;
+
++ const char *strp = str + bytelen;
++
+ /* L1. Reset the embedding levels of some chars. */
+ init_list (&list, &list_end);
+ q = list_end;
+ state = 1;
+- pos = len - 1;
+- for (j = len - 1; j >= -1; j--)
++ pos = *len - 1;
++ for (j = *len - 1; j >= -1; j--)
+ {
+ /* if state is on at the very first of string, do this too. */
+ if (j >= 0)
+- k = fribidi_get_type (str[j]);
++ k = fribidi_get_type (g_utf8_get_char (strp = g_utf8_prev_char (strp)));
+ else
+ k = FRIBIDI_TYPE_ON;
+ if (!state && FRIBIDI_IS_SEPARATOR (k))
+@@ -1023,395 +893,59 @@
+ override_list (type_rl_list, list);
+ }
+
+-#ifdef DEBUG
+- if (fribidi_debug)
+- {
+- print_types_re (type_rl_list);
+- print_resolved_levels (type_rl_list);
+- print_resolved_types (type_rl_list);
+- }
+-#endif
+-
+ *ptype_rl_list = type_rl_list;
+ *pmax_level = max_level;
+ *pbase_dir = base_dir;
+
+ DBG ("Leaving fribidi_analyse_string()\n");
+- return;
+-}
+-
+-/*======================================================================
+- * Frees up the rl_list, must be called after each call to
+- * fribidi_analyse_string(), after the list is not needed anymore.
+- *----------------------------------------------------------------------*/
+-static void
+-free_rl_list (TypeLink *type_rl_list)
+-{
+-
+- TypeLink *pp;
+-
+- DBG ("Entering free_rl_list()\n");
+-
+- if (!type_rl_list)
+- {
+- DBG ("Leaving free_rl_list()\n");
+- return;
+- }
+-
+-#ifdef USE_SIMPLE_MALLOC
+- pp = type_rl_list;
+- while (pp)
+- {
+- TypeLink *p;
+-
+- p = pp;
+- pp = pp->next;
+- free_type_link (p);
+- };
+-#else
+- for (pp = type_rl_list->next; pp->next; pp = pp->next)
+- /* Nothing */ ;
+- pp->next = free_type_links;
+- free_type_links = type_rl_list;
+- type_rl_list = NULL;
+-#endif
+-
+- DBG ("Leaving free_rl_list()\n");
+- return;
+-}
+-
+-static fribidi_boolean mirroring = FRIBIDI_TRUE;
+-
+-FRIBIDI_API fribidi_boolean
+-fribidi_mirroring_status (void)
+-{
+- return mirroring;
+-}
+-
+-FRIBIDI_API void
+-fribidi_set_mirroring (fribidi_boolean mirror)
+-{
+- mirroring = mirror;
+-}
+-
+-static fribidi_boolean reorder_nsm = FRIBIDI_FALSE;
+-
+-fribidi_boolean
+-fribidi_reorder_nsm_status (void)
+-{
+- return reorder_nsm;
+-}
+-
+-FRIBIDI_API void
+-fribidi_set_reorder_nsm (fribidi_boolean reorder)
+-{
+- reorder_nsm = reorder;
+-}
+-
+-/*======================================================================
+- * Here starts the exposed front end functions.
+- *----------------------------------------------------------------------*/
+-
+-/*======================================================================
+- * fribidi_remove_bidi_marks() removes bidirectional marks, and returns
+- * the new length, updates each of other inputs if not NULL.
+- *----------------------------------------------------------------------*/
+-FRIBIDI_API FriBidiStrIndex
+-fribidi_remove_bidi_marks (FriBidiChar *str,
+- FriBidiStrIndex length,
+- FriBidiStrIndex *position_to_this_list,
+- FriBidiStrIndex *position_from_this_list,
+- FriBidiLevel *embedding_level_list)
+-{
+- FriBidiStrIndex i, j;
+- fribidi_boolean private_from_this = FRIBIDI_FALSE;
+-
+- DBG ("Entering fribidi_remove_bidi_marks()\n");
+-
+- /* If to_this is to not null, we must have from_this as well. If it is
+- not given by the caller, we have to make a private instance of it. */
+- if (position_to_this_list && !position_from_this_list)
+- {
+- private_from_this = FRIBIDI_TRUE;
+- position_from_this_list =
+- (FriBidiStrIndex *) malloc (sizeof (FriBidiStrIndex) * length);
+- }
+-
+- j = 0;
+- for (i = 0; i < length; i++)
+- if (!FRIBIDI_IS_EXPLICIT (fribidi_get_type (str[i]))
+- && str[i] != UNI_LRM && str[i] != UNI_RLM)
+- {
+- str[j] = str[i];
+- if (embedding_level_list)
+- embedding_level_list[j] = embedding_level_list[i];
+- if (position_from_this_list)
+- position_from_this_list[j] = position_from_this_list[i];
+- j++;
+- }
+-
+- /* Convert the from_this list to to_this */
+- if (position_to_this_list)
+- {
+- DBG (" Converting from_this list to to_this\n");
+- for (i = 0; i < length; i++)
+- position_to_this_list[i] = -1;
+- for (i = 0; i < length; i++)
+- position_to_this_list[position_from_this_list[i]] = i;
+- DBG (" Converting from_this list to to_this, Done\n");
+- }
+-
+- if (private_from_this)
+- free (position_from_this_list);
+-
+- DBG ("Leaving fribidi_remove_bidi_marks()\n");
+- return j;
+-}
+-
+-
+-/*======================================================================
+- * fribidi_log2vis() calls the function_analyse_string() and then
+- * does reordering and fills in the output strings.
+- *----------------------------------------------------------------------*/
+-FRIBIDI_API fribidi_boolean
+-fribidi_log2vis ( /* input */
+- FriBidiChar *str,
+- FriBidiStrIndex len,
+- FriBidiCharType *pbase_dir,
+- /* output */
+- FriBidiChar *visual_str,
+- FriBidiStrIndex *position_L_to_V_list,
+- FriBidiStrIndex *position_V_to_L_list,
+- FriBidiLevel *embedding_level_list)
+-{
+- TypeLink *type_rl_list, *pp = NULL;
+- FriBidiLevel max_level;
+- fribidi_boolean private_V_to_L = FRIBIDI_FALSE;
+-
+- DBG ("Entering fribidi_log2vis()\n");
+-
+- if (len == 0)
+- {
+- DBG ("Leaving fribidi_log2vis()\n");
+- return FRIBIDI_TRUE;
+- }
+-
+- /* If l2v is to be calculated we must have v2l as well. If it is not
+- given by the caller, we have to make a private instance of it. */
+- if (position_L_to_V_list && !position_V_to_L_list)
+- {
+- private_V_to_L = FRIBIDI_TRUE;
+- position_V_to_L_list =
+- (FriBidiStrIndex *) malloc (sizeof (FriBidiStrIndex) * len);
+- }
+-
+- if (len > FRIBIDI_MAX_STRING_LENGTH && position_V_to_L_list)
+- {
+-#ifdef DEBUG
+- fprintf (stderr, "%s: cannot handle strings > %ld characters\n",
+- FRIBIDI_PACKAGE, (long) FRIBIDI_MAX_STRING_LENGTH);
+-#endif
+- return FRIBIDI_FALSE;
+- }
+- fribidi_analyse_string (str, len, pbase_dir,
+- /* output */
+- &type_rl_list, &max_level);
+-
+- /* 7. Reordering resolved levels */
+- DBG ("Reordering resolved levels\n");
+- {
+- FriBidiLevel level_idx;
+- FriBidiStrIndex i;
+-
+- /* Set up the ordering array to sorted order */
+- if (position_V_to_L_list)
+- {
+- DBG (" Initialize position_V_to_L_list\n");
+- for (i = 0; i < len; i++)
+- position_V_to_L_list[i] = i;
+- DBG (" Initialize position_V_to_L_list, Done\n");
+- }
+- /* Copy the logical string to the visual */
+- if (visual_str)
+- {
+- DBG (" Initialize visual_str\n");
+- for (i = 0; i < len; i++)
+- visual_str[i] = str[i];
+- visual_str[len] = 0;
+- DBG (" Initialize visual_str, Done\n");
+- }
+-
+- /* Assign the embedding level array */
+- if (embedding_level_list)
+- {
+- DBG (" Fill the embedding levels array\n");
+- for (pp = type_rl_list->next; pp->next; pp = pp->next)
+- {
+- FriBidiStrIndex i, pos, len;
+- FriBidiLevel level;
+-
+- pos = pp->pos;
+- len = pp->len;
+- level = pp->level;
+- for (i = 0; i < len; i++)
+- embedding_level_list[pos + i] = level;
+- }
+- DBG (" Fill the embedding levels array, Done\n");
+- }
+-
+- /* Reorder both the outstring and the order array */
+- if (visual_str || position_V_to_L_list)
+- {
+- if (mirroring && visual_str)
+- {
+- /* L4. Mirror all characters that are in odd levels and have mirrors. */
+- DBG (" Mirroring\n");
+- for (pp = type_rl_list->next; pp->next; pp = pp->next)
+- {
+- if (pp->level & 1)
+- {
+- FriBidiStrIndex i;
+- for (i = RL_POS (pp); i < RL_POS (pp) + RL_LEN (pp); i++)
+- {
+- FriBidiChar mirrored_ch;
+- if (fribidi_get_mirror_char
+- (visual_str[i], &mirrored_ch))
+- visual_str[i] = mirrored_ch;
+- }
+- }
+- }
+- DBG (" Mirroring, Done\n");
+- }
+-
+- if (reorder_nsm)
+- {
+- /* L3. Reorder NSMs. */
+- DBG (" Reordering NSM sequences\n");
+- /* We apply this rule before L2, so go backward in odd levels. */
+- for (pp = type_rl_list->next; pp->next; pp = pp->next)
+- {
+- if (pp->level & 1)
+- {
+- FriBidiStrIndex i, seq_end = 0;
+- fribidi_boolean is_nsm_seq;
+-
+- is_nsm_seq = FRIBIDI_FALSE;
+- for (i = RL_POS (pp) + RL_LEN (pp) - 1; i >= RL_POS (pp);
+- i--)
+- {
+- FriBidiCharType this_type;
+-
+- this_type = fribidi_get_type (str[i]);
+- if (is_nsm_seq && this_type != FRIBIDI_TYPE_NSM)
+- {
+- if (visual_str)
+- {
+- bidi_string_reverse (visual_str + i,
+- seq_end - i + 1);
+- }
+- if (position_V_to_L_list)
+- {
+- index_array_reverse (position_V_to_L_list + i,
+- seq_end - i + 1);
+- }
+- is_nsm_seq = 0;
+- }
+- else if (!is_nsm_seq && this_type == FRIBIDI_TYPE_NSM)
+- {
+- seq_end = i;
+- is_nsm_seq = 1;
+- }
+- }
+- if (is_nsm_seq)
+- {
+- DBG
+- ("Warning: NSMs at the beggining of run level.\n");
+- }
+- }
+- }
+- DBG (" Reordering NSM sequences, Done\n");
+- }
+-
+- /* L2. Reorder. */
+- DBG (" Reordering\n");
+- for (level_idx = max_level; level_idx > 0; level_idx--)
+- {
+- for (pp = type_rl_list->next; pp->next; pp = pp->next)
+- {
+- if (RL_LEVEL (pp) >= level_idx)
+- {
+- /* Find all stretches that are >= level_idx */
+- FriBidiStrIndex len = RL_LEN (pp),
+- pos = RL_POS (pp);
+- TypeLink *pp1 = pp->next;
+- while (pp1->next && RL_LEVEL (pp1) >= level_idx)
+- {
+- len += RL_LEN (pp1);
+- pp1 = pp1->next;
+- }
+- pp = pp1->prev;
+- if (visual_str)
+- bidi_string_reverse (visual_str + pos, len);
+- if (position_V_to_L_list)
+- index_array_reverse (position_V_to_L_list + pos, len);
+- }
+- }
+- }
+- DBG (" Reordering, Done\n");
+- }
+-
+- /* Convert the v2l list to l2v */
+- if (position_L_to_V_list)
+- {
+- DBG (" Converting v2l list to l2v\n");
+- for (i = 0; i < len; i++)
+- position_L_to_V_list[position_V_to_L_list[i]] = i;
+- DBG (" Converting v2l list to l2v, Done\n");
+- }
+- }
+- DBG ("Reordering resolved levels, Done\n");
+-
+- if (private_V_to_L)
+- free (position_V_to_L_list);
+-
+- free_rl_list (type_rl_list);
+-
+- DBG ("Leaving fribidi_log2vis()\n");
+- return FRIBIDI_TRUE;
+-
++ return 1;
+ }
+
+ /*======================================================================
+ * fribidi_log2vis_get_embedding_levels() is used in order to just get
+ * the embedding levels.
+ *----------------------------------------------------------------------*/
+-FRIBIDI_API fribidi_boolean
+-fribidi_log2vis_get_embedding_levels ( /* input */
+- FriBidiChar *str,
+- FriBidiStrIndex len,
+- FriBidiCharType *pbase_dir,
+- /* output */
+- FriBidiLevel *embedding_level_list)
++FRIBIDI_API FriBidiLevel *
++fribidi_log2vis_get_embedding_levels_new_utf8 ( /* input */
++ const char *str,
++ int bytelen,
++ FriBidiCharType *pbase_dir)
+ {
+ TypeLink *type_rl_list, *pp;
+- FriBidiLevel max_level;
++ FriBidiLevel max_level, *embedding_level_list;
++ FriBidiStrIndex len;
+
+ DBG ("Entering fribidi_log2vis_get_embedding_levels()\n");
+
+- if (len == 0)
++ if (bytelen == 0)
+ {
+ DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n");
+- return FRIBIDI_TRUE;
++ return NULL;
+ }
+
+- fribidi_analyse_string (str, len, pbase_dir,
++ if (!fribidi_analyse_string_utf8 (str, bytelen, pbase_dir,
+ /* output */
+- &type_rl_list, &max_level);
++ &len, &type_rl_list, &max_level))
++ {
++ /* unidirectional. return all-zero or all-one embedding levels */
++
++ if (max_level)
++ {
++ embedding_level_list = g_new (FriBidiLevel, len);
++ /* assumes sizeof(FriBidiLevel) == 1, which is true! */
++ memset (embedding_level_list, max_level, len);
++ return embedding_level_list;
++ }
++ else
++ {
++ return g_new0 (FriBidiLevel, len);
++ }
++ }
+
++ embedding_level_list = g_new (FriBidiLevel, len);
+ for (pp = type_rl_list->next; pp->next; pp = pp->next)
+ {
+- FriBidiStrIndex i, pos = RL_POS (pp),
+- len = RL_LEN (pp);
++ FriBidiStrIndex i, pos = RL_POS (pp), len = RL_LEN (pp);
+ FriBidiLevel level = RL_LEVEL (pp);
+ for (i = 0; i < len; i++)
+ embedding_level_list[pos + i] = level;
+@@ -1420,34 +954,6 @@
+ free_rl_list (type_rl_list);
+
+ DBG ("Leaving fribidi_log2vis_get_embedding_levels()\n");
+- return FRIBIDI_TRUE;
++ return embedding_level_list;
+ }
+
+-
+-
+-const char *fribidi_version_info =
+- FRIBIDI_PACKAGE " " FRIBIDI_VERSION "\n" "interface version "
+- TOSTR (FRIBIDI_INTERFACE_VERSION)
+- "\n"
+- "Unicode version " FRIBIDI_UNICODE_VERSION "\n"
+- "\n"
+- "Copyright (C) 2001,2002,2005 Behdad Esfahbod <fribidi@behdad.org>.\n"
+- "Copyright (C) 1999,2000 Dov Grobgeld\n"
+- FRIBIDI_PACKAGE " comes with NO WARRANTY, to the extent permitted by law.\n"
+- "You may redistribute copies of " FRIBIDI_PACKAGE " under the terms of\n"
+- "the GNU Lesser General Public License.\n"
+- "For more information about these matters, see the files named COPYING.\n"
+- "\n" "Configured with following options:\n"
+-#ifdef DEBUG
+- "--enable-debug\n"
+-#endif
+-#ifdef MEM_OPTIMIZED
+- "--enable-memopt\n"
+-#endif
+-#ifdef USE_SIMPLE_MALLOC
+- "--enable-malloc\n"
+-#endif
+-#ifdef FRIBIDI_NO_CHARSETS
+- "--without-charsts\n"
+-#endif
+-;
+diff -rua /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi_char_type.c ./fribidi_char_type.c
+--- /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi_char_type.c 2005-09-25 18:31:19.000000000 -0400
++++ ./fribidi_char_type.c 2005-11-03 11:30:26.000000000 -0500
+@@ -24,29 +24,6 @@
+ #endif
+ #include "fribidi.h"
+
+-/*======================================================================
+- * fribidi_get_type() returns the bidi type of a character.
+- *----------------------------------------------------------------------*/
+-FRIBIDI_API FriBidiCharType fribidi_get_type_internal (FriBidiChar uch);
+-
+-FRIBIDI_API FriBidiCharType
+-fribidi_get_type (FriBidiChar uch)
+-{
+- return fribidi_get_type_internal (uch);
+-}
+-
+-FRIBIDI_API void
+-fribidi_get_types ( /* input */
+- FriBidiChar *str, FriBidiStrIndex len,
+- /* output */
+- FriBidiCharType *type)
+-{
+- FriBidiStrIndex i;
+-
+- for (i = 0; i < len; i++)
+- type[i] = fribidi_get_type (str[i]);
+-}
+-
+ #ifdef MEM_OPTIMIZED
+
+ #if HAS_FRIBIDI_TAB_CHAR_TYPE_9_I
+diff -rua /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi.h ./fribidi.h
+--- /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi.h 2005-09-25 14:43:38.000000000 -0400
++++ ./fribidi.h 2005-11-03 11:30:26.000000000 -0500
+@@ -29,252 +29,26 @@
+ #endif
+
+ #include "fribidi_config.h"
+-#include "fribidi_unicode.h"
+ #include "fribidi_types.h"
+-#ifndef FRIBIDI_NO_CHARSETS
+-#include "fribidi_char_sets.h"
+-#endif
+
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
+- FRIBIDI_API fribidi_boolean fribidi_log2vis ( /* input */
+- FriBidiChar *str,
+- FriBidiStrIndex len,
+- FriBidiCharType *pbase_dirs,
+- /* output */
+- FriBidiChar *visual_str,
+- FriBidiStrIndex
+- *position_L_to_V_list,
+- FriBidiStrIndex
+- *position_V_to_L_list,
+- FriBidiLevel
+- *embedding_level_list);
+-
+- FRIBIDI_API fribidi_boolean fribidi_log2vis_get_embedding_levels ( /* input */
+- FriBidiChar
+- *str,
+- FriBidiStrIndex
+- len,
+- FriBidiCharType
+- *pbase_dir,
+- /* output */
+- FriBidiLevel
+- *embedding_level_list);
++#define FRIBIDI_HAVE_UTF8
+
+-/*======================================================================
+- * fribidi_remove_bidi_marks() removes bidirectional marks, and returns
+- * the new length, also updates each of other inputs if not NULL.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API FriBidiStrIndex fribidi_remove_bidi_marks (FriBidiChar *str,
+- FriBidiStrIndex
+- length,
+- FriBidiStrIndex
+- *position_to_this_list,
+- FriBidiStrIndex
+- *position_from_this_list,
+- FriBidiLevel
+- *embedding_level_list);
++ FRIBIDI_API FriBidiLevel *fribidi_log2vis_get_embedding_levels_new_utf8 ( /* input */
++ const char *str,
++ int bytelen,
++ FriBidiCharType
++ *pbase_dir);
+
+ /*======================================================================
+ * fribidi_get_type() returns bidi type of a character.
+ *----------------------------------------------------------------------*/
+ FRIBIDI_API FriBidiCharType fribidi_get_type (FriBidiChar uch);
+
+-/*======================================================================
+- * fribidi_get_types() returns bidi type of a string.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API void fribidi_get_types ( /* input */
+- FriBidiChar *str,
+- FriBidiStrIndex len,
+- /* output */
+- FriBidiCharType *type);
+-
+-/*======================================================================
+- * fribidi_get_mirror_char() returns the mirrored character, if input
+- * character has a mirror, or the input itself.
+- * if mirrored_ch is NULL, just returns if character has a mirror or not.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API fribidi_boolean fribidi_get_mirror_char ( /* Input */
+- FriBidiChar ch,
+- /* Output */
+- FriBidiChar
+- *mirrored_ch);
+-
+-/*======================================================================
+- * fribidi_mirroring_status() returns whether mirroring is on or off,
+- * default is on.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API fribidi_boolean fribidi_mirroring_status (void);
+-
+-/*======================================================================
+- * fribidi_set_mirroring() sets mirroring on or off.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API void fribidi_set_mirroring (fribidi_boolean mirror);
+-
+-/*======================================================================
+- * fribidi_reorder_nsm_status() returns whether reordering of NSM
+- * sequences is on or off, default is off.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API fribidi_boolean fribidi_reorder_nsm_status (void);
+-
+-/*======================================================================
+- * fribidi_set_reorder_nsm() sets reordering of NSM characters on or off.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API void fribidi_set_reorder_nsm (fribidi_boolean);
+-
+-/*======================================================================
+- * fribidi_set_debug() turn on or off debugging, default is off, return
+- * false is fribidi is not compiled with debug enabled.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API fribidi_boolean fribidi_set_debug (fribidi_boolean debug);
+-
+-/* fribidi_utils.c */
+-
+-/*======================================================================
+- * fribidi_find_string_changes() finds the bounding box of the section
+- * of characters that need redrawing. It returns the start and the
+- * length of the section in the new string that needs redrawing.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API void fribidi_find_string_changes ( /* input */
+- FriBidiChar *old_str,
+- FriBidiStrIndex old_len,
+- FriBidiChar *new_str,
+- FriBidiStrIndex new_len,
+- /* output */
+- FriBidiStrIndex
+- *change_start,
+- FriBidiStrIndex *change_len);
+-
+-
+-/*======================================================================
+- * The find_visual_ranges() function is used to convert between a
+- * continous span in either logical or visual space to a one, two or
+- * three discontinous spans in the other space. The function outputs
+- * the number of ranges needed to display the mapped range as
+- * well as the resolved ranges.
+- *
+- * The variable is_v2l_map indicates whether the position map is
+- * is in the direction of visual-to-logical. This information is
+- * needed in order to look up the correct character from the
+- * embedding_level_list which is assumed to be in logical order.
+- *
+- * This function is typically used to resolve a logical range to visual
+- * ranges e.g. to display the selection.
+- *
+- * Example:
+- * The selection is between logical characters 10 to 45. Calculate
+- * the corresponding visual selection(s):
+- *
+- * FriBidiStrIndex sel_span[2] = {10,45};
+- *
+- * fribidi_map_range(sel_span,
+- * TRUE,
+- * length,
+- * vis2log_map,
+- * embedding_levels,
+- * // output
+- * &num_vis_ranges, *vis_ranges);
+- **----------------------------------------------------------------------*/
+- FRIBIDI_API void fribidi_map_range (FriBidiStrIndex span[2],
+- FriBidiStrIndex len,
+- fribidi_boolean is_v2l_map,
+- FriBidiStrIndex *position_map,
+- FriBidiLevel *embedding_level_list,
+- /* output */
+- int *num_mapped_spans,
+- FriBidiStrIndex spans[3][2]);
+-
+-/*======================================================================
+- * fribidi_is_char_rtl() answers the question whether a character
+- * was resolved in the rtl direction. This simply involves asking
+- * if the embedding level for the character is odd.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API fribidi_boolean fribidi_is_char_rtl (FriBidiLevel
+- *embedding_level_list,
+- FriBidiCharType base_dir,
+- FriBidiStrIndex idx);
+-
+-/*======================================================================
+- * fribidi_xpos_resolve() does the complicated translation of
+- * an x-coordinate, e.g. as received through a mouse press event,
+- * to the logical and the visual position the xcoordinate is closest
+- * to. It will also resolve the direction of the cursor according
+- * to the embedding level of the closest character.
+- *
+- * It does this through the following logics:
+- * Here are the different possibilities:
+- *
+- * Pointer => Log Pos Vis pos
+- *
+- * Before first vis char log_pos(vis=0)L 0
+- * After last vis char log_pos(vis=n-1)R n
+- * Within 1/2 width of vis char i log_pos(vis=i)L i
+- * Within last 1/2 width of vchar i log_pos(vis=i)R i+1
+- * Border between vis chars i,i+1 resolve! i+1
+- *
+- * Input:
+- * x_pos The pixel position to be resolved measured in pixels.
+- * x_offset The x_offset is the pixel position of the left side
+- * of the leftmost visual character.
+- * len The length of the embedding level, the vis2log and
+- * the char width arrays.
+- * base_dir The resolved base direction of the line.
+- * vis2log The vis2log mapping.
+- * x_position and the character widths. The position
+- * (x_pos-x_offset) is number of pixels from the left
+- * of logical character 0.
+- * char_widths Width in pixels of each character. Note that the
+- * widths should be provided in logical order.
+- *
+- * Output:
+- * res_log_pos Resolved logical position.
+- * res_vis_pos Resolved visual position
+- * res_cursor_x_pos The resolved pixel position to the left or
+- * the right of the character position x_pos.
+- * res_cursor_dir_is_rtl Whether the resolved dir of the character
+- * at position x_pos is rtl.
+- * res_attach_before Whether the x_pos is cutting the bounding
+- * box in such a way that the visual cursor should be
+- * be positioned before the following logical character.
+- * Note that in the bidi context, the positions "after
+- * a logical character" and "before the following logical
+- * character" is not necessarily the same. If x_pos is
+- * beyond the end of the line, res_attach_before is true.
+- *
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API void fribidi_xpos_resolve (int x_pos,
+- int x_offset,
+- FriBidiStrIndex len,
+- FriBidiLevel *embedding_level_list,
+- FriBidiCharType base_dir,
+- FriBidiStrIndex *vis2log,
+- int *char_widths,
+- /* output */
+- FriBidiStrIndex *res_log_pos,
+- FriBidiStrIndex *res_vis_pos,
+- int *res_cursor_x_pos,
+- fribidi_boolean
+- *res_cursor_dir_is_rtl,
+- fribidi_boolean *res_attach_before);
+-
+-/*======================================================================
+- * fribidi_runs_log2vis takes a list of logical runs and returns a
+- * a list of visual runs. A run is defined as a sequence that has
+- * the same attributes.
+- *----------------------------------------------------------------------*/
+- FRIBIDI_API void fribidi_runs_log2vis ( /* input */
+- FriBidiList *logical_runs, /* List of FriBidiRunType */
+-
+- FriBidiStrIndex len,
+- FriBidiStrIndex *log2vis,
+- FriBidiCharType base_dir,
+- /* output */
+- FriBidiList **visual_runs);
+-
+-
+ #ifdef __cplusplus
+ }
+ #endif
+diff -rua /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi_types.c ./fribidi_types.c
+--- /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi_types.c 2005-09-25 16:41:35.000000000 -0400
++++ ./fribidi_types.c 2005-11-03 11:30:26.000000000 -0500
+@@ -80,44 +80,6 @@
+
+ #endif
+
+-char *
+-fribidi_type_name (FriBidiCharType c)
+-{
+-#define _FRIBIDI_CASE(type) case FRIBIDI_TYPE_##type: return #type
+- switch (c)
+- {
+- _FRIBIDI_CASE (LTR);
+- _FRIBIDI_CASE (RTL);
+- _FRIBIDI_CASE (AL);
+-
+- _FRIBIDI_CASE (EN);
+- _FRIBIDI_CASE (AN);
+- _FRIBIDI_CASE (ES);
+- _FRIBIDI_CASE (ET);
+- _FRIBIDI_CASE (CS);
+- _FRIBIDI_CASE (NSM);
+- _FRIBIDI_CASE (BN);
+-
+- _FRIBIDI_CASE (BS);
+- _FRIBIDI_CASE (SS);
+- _FRIBIDI_CASE (WS);
+- _FRIBIDI_CASE (ON);
+-
+- _FRIBIDI_CASE (LRE);
+- _FRIBIDI_CASE (RLE);
+- _FRIBIDI_CASE (LRO);
+- _FRIBIDI_CASE (RLO);
+- _FRIBIDI_CASE (PDF);
+-
+- _FRIBIDI_CASE (SOT);
+- _FRIBIDI_CASE (EOT);
+-
+- default:
+- return "?";
+- }
+-#undef _FRIBIDI_CASE
+-}
+-
+ /* Map fribidi_prop_types to fribidi_types. */
+ const FriBidiCharType fribidi_prop_to_type[] = {
+ #define _FRIBIDI_ADD_TYPE(TYPE) FRIBIDI_TYPE_##TYPE,
+diff -rua /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi_types.h ./fribidi_types.h
+--- /home/behdad/src/fdo/fribidi/fribidi.stable/fribidi_types.h 2005-09-25 18:49:59.000000000 -0400
++++ ./fribidi_types.h 2005-11-03 11:30:26.000000000 -0500
+@@ -25,44 +25,26 @@
+
+ #include "fribidi_config.h"
+
+-#define FRIBIDI_INT8 char
+-#if FRIBIDI_SIZEOF_INT+0 == 2
+-# define FRIBIDI_INT16 int
+-#elif FRIBIDI_SIZEOF_SHORT+0 == 2
+-# define FRIBIDI_INT16 short
+-#else
+-# error cannot determine a 16-bit integer type. check fribidi_config.h
+-#endif
+-#if FRIBIDI_SIZEOF_INT+0 == 4
+-# define FRIBIDI_INT32 int
+-#elif FRIBIDI_SIZEOF_LONG+0 == 4
+-# define FRIBIDI_INT32 long
+-#else
+-# error cannot determine a 32-bit integer type. check fribidi_config.h
+-#endif
+-
+-
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
+- typedef int fribidi_boolean;
+-
+- typedef signed FRIBIDI_INT8 fribidi_int8;
+- typedef unsigned FRIBIDI_INT8 fribidi_uint8;
+- typedef signed FRIBIDI_INT16 fribidi_int16;
+- typedef unsigned FRIBIDI_INT16 fribidi_uint16;
+- typedef signed FRIBIDI_INT32 fribidi_int32;
+- typedef unsigned FRIBIDI_INT32 fribidi_uint32;
++ typedef gboolean fribidi_boolean;
+
+- typedef signed int fribidi_int;
+- typedef unsigned int fribidi_uint;
++ typedef gint8 fribidi_int8;
++ typedef guint8 fribidi_uint8;
++ typedef gint16 fribidi_int16;
++ typedef guint16 fribidi_uint16;
++ typedef gint32 fribidi_int32;
++ typedef guint32 fribidi_uint32;
++ typedef gint fribidi_int;
++ typedef guint fribidi_uint;
+
+
+ typedef fribidi_int8 FriBidiLevel;
+- typedef fribidi_uint32 FriBidiChar;
+- typedef fribidi_int FriBidiStrIndex;
++ typedef gunichar FriBidiChar;
++ typedef gsize FriBidiStrIndex;
+ typedef fribidi_int32 FriBidiMaskType;
+ typedef FriBidiMaskType FriBidiCharType;
+
diff --git a/trunk/pango/mini-fribidi/fribidi_char_type.c b/trunk/pango/mini-fribidi/fribidi_char_type.c
new file mode 100644
index 00000000..dcf2d06e
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi_char_type.c
@@ -0,0 +1,75 @@
+/* FriBidi - Library of BiDi algorithm
+ * Copyright (C) 2001,2002 Behdad Esfahbod.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library, in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ * For licensing issues, contact <fwpg@sharif.edu>.
+ */
+
+#include <config.h>
+#include "fribidi.h"
+
+#ifdef MEM_OPTIMIZED
+
+#if HAS_FRIBIDI_TAB_CHAR_TYPE_9_I
+#include "fribidi_tab_char_type_9.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_8_I
+#include "fribidi_tab_char_type_8.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_7_I
+#include "fribidi_tab_char_type_7.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_6_I
+#include "fribidi_tab_char_type_6.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_5_I
+#include "fribidi_tab_char_type_5.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_4_I
+#include "fribidi_tab_char_type_4.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_3_I
+#include "fribidi_tab_char_type_3.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_2_I
+#include "fribidi_tab_char_type_2.i"
+#else
+#error You have no fribidi_tab_char_type_*.i file, please first make one by \
+ make fribidi_tab_char_type_n.i which n is the compress level, a digit \
+ between 2 and 9, or simply run make fribidi_tab_char_type_small, \
+ retry to make.
+#endif
+
+#else
+
+#if HAS_FRIBIDI_TAB_CHAR_TYPE_2_I
+#include "fribidi_tab_char_type_2.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_3_I
+#include "fribidi_tab_char_type_3.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_4_I
+#include "fribidi_tab_char_type_4.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_5_I
+#include "fribidi_tab_char_type_5.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_6_I
+#include "fribidi_tab_char_type_6.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_7_I
+#include "fribidi_tab_char_type_7.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_8_I
+#include "fribidi_tab_char_type_8.i"
+#elif HAS_FRIBIDI_TAB_CHAR_TYPE_9_I
+#include "fribidi_tab_char_type_9.i"
+#else
+#error You have no fribidi_tab_char_type_*.i file, please first make one by \
+ make fribidi_tab_char_type_n.i which n is the compress level, a digit \
+ between 2 and 9, or simply run make fribidi_tab_char_type_large, \
+ retry to make.
+#endif
+
+#endif
diff --git a/trunk/pango/mini-fribidi/fribidi_config.h b/trunk/pango/mini-fribidi/fribidi_config.h
new file mode 100644
index 00000000..82e4da17
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi_config.h
@@ -0,0 +1,24 @@
+#include <glib.h>
+
+#define FRIBIDI_TRUE TRUE
+#define FRIBIDI_FALSE FALSE
+#define HAS_FRIBIDI_TAB_CHAR_TYPE_2_I 1
+#define FRIBIDI_API
+
+/* this was in fribidi_unicode.h. we only need these bits from that
+ * file, so moved here. */
+#define UNI_MAX_BIDI_LEVEL 61
+
+/* ripped off debugging functions, make sure it's not triggerred. */
+#undef DEBUG
+
+/* g_malloc and g_free verbatim */
+#define malloc g_malloc
+#define free g_free
+
+/* rename symbols to pango internal namespace */
+#define fribidi_log2vis_get_embedding_levels_new_utf8 _pango_fribidi_log2vis_get_embedding_levels_new_utf8
+#define fribidi_prop_to_type _pango_fribidi_prop_to_type
+#define fribidi_get_type _pango_fribidi_get_type
+#define fribidi_get_type_internal fribidi_get_type
+
diff --git a/trunk/pango/mini-fribidi/fribidi_tab_char_type_2.i b/trunk/pango/mini-fribidi/fribidi_tab_char_type_2.i
new file mode 100644
index 00000000..dbb91cb5
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi_tab_char_type_2.i
@@ -0,0 +1,5607 @@
+/*
+ This file was automatically created from UnicodeData.txt version 5.0.0
+ by fribidi_create_char_types
+*/
+
+#ifndef FRIBIDI_TAB_CHAR_TYPE_2_I
+#define FRIBIDI_TAB_CHAR_TYPE_2_I
+
+#include "fribidi.h"
+
+#define LTR FRIBIDI_PROP_TYPE_LTR
+#define RTL FRIBIDI_PROP_TYPE_RTL
+#define AL FRIBIDI_PROP_TYPE_AL
+#define ON FRIBIDI_PROP_TYPE_ON
+#define BN FRIBIDI_PROP_TYPE_BN
+#define AN FRIBIDI_PROP_TYPE_AN
+#define BS FRIBIDI_PROP_TYPE_BS
+#define CS FRIBIDI_PROP_TYPE_CS
+#define EN FRIBIDI_PROP_TYPE_EN
+#define ES FRIBIDI_PROP_TYPE_ES
+#define ET FRIBIDI_PROP_TYPE_ET
+#define LRE FRIBIDI_PROP_TYPE_LRE
+#define LRO FRIBIDI_PROP_TYPE_LRO
+#define NSM FRIBIDI_PROP_TYPE_NSM
+#define PDF FRIBIDI_PROP_TYPE_PDF
+#define RLE FRIBIDI_PROP_TYPE_RLE
+#define RLO FRIBIDI_PROP_TYPE_RLO
+#define SS FRIBIDI_PROP_TYPE_SS
+#define WS FRIBIDI_PROP_TYPE_WS
+
+#define PACKTAB_UINT8 fribidi_uint8
+#define PACKTAB_UINT16 fribidi_uint16
+#define PACKTAB_UINT32 fribidi_uint32
+/*
+ Automatically generated by packtab.c version 2
+
+ just use FRIBIDI_GET_TYPE(key)
+
+ assumed sizeof(FriBidiPropCharType) == 1
+ required memory: 24320
+ lookups: 2
+ partition shape: FriBidiPropertyBlock[4352][256]
+ different table entries: 1 61
+*/
+
+/* *INDENT-OFF* */
+
+static const FriBidiPropCharType FriBidiPropertyBlockLevel1[256*61] = {
+
+#define FriBidiPropertyBlockLevel1_0000 0x0
+
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, SS, BS, SS, WS, BS, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BS, BS, BS, SS,
+ WS, ON, ON, ET, ET, ET, ON, ON, ON, ON, ON, ES, CS, ES, CS, CS,
+ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, CS, ON, ON, ON, ON, ON,
+ ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, ON,
+ ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, BN,
+ BN, BN, BN, BN, BN, BS, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ CS, ON, ET, ET, ET, ET, ON, ON, ON, ON,LTR, ON, ON, BN, ON, ON,
+ ET, ET, EN, EN, ON,LTR, ON, ON, ON, EN,LTR, ON, ON, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0100 0x100
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0200 0x200
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ LTR,LTR, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_0300 0x300
+
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ LTR,LTR,LTR,LTR, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON,LTR,
+ LTR,LTR,LTR,LTR, ON, ON,LTR, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0400 0x400
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,NSM,NSM,NSM,NSM,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0500 0x500
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON,LTR,LTR,LTR,LTR,LTR,
+ RTL,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,RTL,NSM,
+ RTL,NSM,NSM,RTL,NSM,NSM,RTL,NSM,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+
+#define FriBidiPropertyBlockLevel1_0600 0x600
+
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, CS, AL, ON, ON,
+ NSM,NSM,NSM,NSM,NSM,NSM, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM, AL,
+ AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, ET, AN, AN, AL, AL, AL,
+ NSM, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL,NSM,NSM,NSM,NSM,NSM,NSM,NSM, AL,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM, AL, AL,NSM,NSM, ON,NSM,NSM,NSM,NSM, AL, AL,
+ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, AL, AL, AL, AL, AL, AL,
+
+#define FriBidiPropertyBlockLevel1_0700 0x700
+
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, BN,
+ AL,NSM, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,RTL,RTL, ON, ON, ON, ON,RTL,RTL,RTL,RTL,RTL,RTL,
+
+#define FriBidiPropertyBlockLevel1_0800 0x800
+
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+
+#define FriBidiPropertyBlockLevel1_0900 0x900
+
+ LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,
+ LTR,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,NSM,LTR,LTR,
+ LTR,NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,
+ LTR,NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR, ET, ET,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0A00 0xA00
+
+ LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,
+ LTR,NSM,NSM,LTR,LTR,LTR,LTR,NSM,NSM,LTR,LTR,NSM,NSM,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,
+ LTR,NSM,NSM,NSM,NSM,NSM,LTR,NSM,NSM,LTR,LTR,LTR,LTR,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR, ET,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0B00 0xB00
+
+ LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,NSM,
+ LTR,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR, ON, ON, ON, ON, ON, ON, ET, ON,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0C00 0xC00
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,
+ NSM,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,LTR,NSM,NSM,NSM,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0D00 0xD00
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,NSM,LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0E00 0xE00
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,NSM,LTR,LTR,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR, ET,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,NSM,LTR,LTR,NSM,NSM,NSM,NSM,NSM,NSM,LTR,NSM,NSM,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,NSM,NSM,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_0F00 0xF00
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,NSM,LTR,NSM,LTR,NSM, ON, ON, ON, ON,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,
+ NSM,NSM,NSM,NSM,NSM,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1000 0x1000
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,
+ NSM,LTR,NSM,LTR,LTR,LTR,NSM,NSM,LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1300 0x1100
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1600 0x1200
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ WS,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1700 0x1300
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ET,LTR,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1800 0x1400
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,NSM,NSM,NSM, WS,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1900 0x1500
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ NSM,NSM,NSM,LTR,LTR,LTR,LTR,NSM,NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,
+ LTR,LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,LTR,LTR,LTR,LTR,
+ ON,LTR,LTR,LTR, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_1A00 0x1600
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1B00 0x1700
+
+ NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,NSM,LTR,NSM,NSM,NSM,NSM,NSM,LTR,NSM,LTR,LTR,LTR,
+ LTR,LTR,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1D00 0x1800
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,
+
+#define FriBidiPropertyBlockLevel1_1F00 0x1900
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON,LTR, ON,
+ ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON,LTR,
+
+#define FriBidiPropertyBlockLevel1_2000 0x1A00
+
+ WS, WS, WS, WS, WS, WS, WS, WS, WS, WS, WS, BN, BN, BN,LTR,RTL,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, WS, BS,LRE,RLE,PDF,LRO,RLO, CS,
+ ET, ET, ET, ET, ET, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, CS, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, WS,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ EN,LTR,LTR,LTR, EN, EN, EN, EN, EN, EN, ES, ES, ON, ON, ON,LTR,
+ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, ES, ES, ON, ON, ON,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ET, ET, ET, ET, ET, ET, ET, ET, ET, ET, ET, ET, ET, ET, ET, ET,
+ ET, ET, ET, ET, ET, ET,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_2100 0x1B00
+
+ ON, ON,LTR, ON, ON, ON, ON,LTR, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR, ON,LTR, ON, ON, ON,LTR,LTR,LTR,LTR,LTR, ON, ON,
+ ON, ON, ON, ON,LTR, ON,LTR, ON,LTR, ON,LTR,LTR,LTR,LTR, ET,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON,LTR,LTR,
+ LTR,LTR,LTR, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_2200 0x1C00
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ES, ET, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_2300 0x1D00
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON,LTR, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_2400 0x1E00
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, EN, EN, EN, EN, EN, EN, EN, EN,
+ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_2500 0x1F00
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_2600 0x2000
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR, ON, ON, ON,
+ ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_2700 0x2100
+
+ LTR, ON, ON, ON, ON,LTR, ON, ON, ON, ON,LTR,LTR, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON,LTR, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR, ON,LTR, ON,
+ ON, ON, ON,LTR,LTR,LTR, ON,LTR, ON, ON, ON, ON, ON, ON, ON,LTR,
+ LTR, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON,LTR,LTR,LTR, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ LTR, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_2B00 0x2200
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_2C00 0x2300
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_2E00 0x2400
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR, ON, ON,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_2F00 0x2500
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_3000 0x2600
+
+ WS, ON, ON, ON, ON,LTR,LTR,LTR, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,NSM,NSM,NSM,
+ ON,LTR,LTR,LTR,LTR,LTR, ON, ON,LTR,LTR,LTR,LTR,LTR, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM, ON, ON,LTR,LTR,LTR,
+ ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_3100 0x2700
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_3200 0x2800
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_3300 0x2900
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON,
+
+#define FriBidiPropertyBlockLevel1_4D00 0x2A00
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+
+#define FriBidiPropertyBlockLevel1_A400 0x2B00
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_A700 0x2C00
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,
+ ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_A800 0x2D00
+
+ LTR,LTR,NSM,LTR,LTR,LTR,NSM,LTR,LTR,LTR,LTR,NSM,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,NSM,NSM,LTR, ON, ON, ON, ON,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_FB00 0x2E00
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,RTL,NSM,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL, ES,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+
+#define FriBidiPropertyBlockLevel1_FC00 0x2F00
+
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+
+#define FriBidiPropertyBlockLevel1_FD00 0x3000
+
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, ON, ON,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, ON, AL, AL,
+
+#define FriBidiPropertyBlockLevel1_FE00 0x3100
+
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,
+ NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ CS, ON, CS,LTR, ON, CS, ON, ON, ON, ON, ON, ON, ON, ON, ON, ET,
+ ON, ON, ES, ES, ON, ON, ON,LTR, ON, ET, ET, ON,LTR,LTR,LTR,LTR,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,
+ AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, BN,
+
+#define FriBidiPropertyBlockLevel1_FF00 0x3200
+
+ LTR, ON, ON, ET, ET, ET, ON, ON, ON, ON, ON, ES, CS, ES, CS, CS,
+ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, CS, ON, ON, ON, ON, ON,
+ ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, ON,
+ ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ET, ET, ON, ON, ON, ET, ET,LTR, ON, ON, ON, ON, ON, ON, ON,LTR,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, ON, ON, ON, ON, ON, BN, BN,
+
+#define FriBidiPropertyBlockLevel1_10100 0x3300
+
+ LTR, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_10900 0x3400
+
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL, ON,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+
+#define FriBidiPropertyBlockLevel1_10A00 0x3500
+
+ RTL,NSM,NSM,NSM,RTL,NSM,NSM,RTL,RTL,RTL,RTL,RTL,NSM,NSM,NSM,NSM,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,NSM,NSM,NSM,RTL,RTL,RTL,RTL,NSM,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+ RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,
+
+#define FriBidiPropertyBlockLevel1_1D100 0x3600
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR, BN, BN, BN, BN, BN, BN, BN, BN,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,LTR,LTR,NSM,NSM,NSM,NSM,NSM,NSM,NSM,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,NSM,NSM,NSM,NSM,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1D200 0x3700
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON,NSM,NSM,NSM, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1D300 0x3800
+
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,
+ ON, ON, ON, ON, ON, ON, ON,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+
+#define FriBidiPropertyBlockLevel1_1D700 0x3900
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, EN, EN,
+ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN,
+ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN,
+ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EN,
+
+#define FriBidiPropertyBlockLevel1_1FF00 0x3A00
+
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,
+ LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, BN, BN,
+
+#define FriBidiPropertyBlockLevel1_E0000 0x3B00
+
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+
+#define FriBidiPropertyBlockLevel1_E0100 0x3C00
+
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,NSM,
+ BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN, BN,
+};
+
+static const PACKTAB_UINT16 FriBidiPropertyBlockLevel0[4352*1] = {
+
+#define FriBidiPropertyBlockLevel0_0000 0x0
+
+ FriBidiPropertyBlockLevel1_0000, /* 0000..00FF */
+ FriBidiPropertyBlockLevel1_0100, /* 0100..01FF */
+ FriBidiPropertyBlockLevel1_0200, /* 0200..02FF */
+ FriBidiPropertyBlockLevel1_0300, /* 0300..03FF */
+ FriBidiPropertyBlockLevel1_0400, /* 0400..04FF */
+ FriBidiPropertyBlockLevel1_0500, /* 0500..05FF */
+ FriBidiPropertyBlockLevel1_0600, /* 0600..06FF */
+ FriBidiPropertyBlockLevel1_0700, /* 0700..07FF */
+ FriBidiPropertyBlockLevel1_0800, /* 0800..08FF */
+ FriBidiPropertyBlockLevel1_0900, /* 0900..09FF */
+ FriBidiPropertyBlockLevel1_0A00, /* 0A00..0AFF */
+ FriBidiPropertyBlockLevel1_0B00, /* 0B00..0BFF */
+ FriBidiPropertyBlockLevel1_0C00, /* 0C00..0CFF */
+ FriBidiPropertyBlockLevel1_0D00, /* 0D00..0DFF */
+ FriBidiPropertyBlockLevel1_0E00, /* 0E00..0EFF */
+ FriBidiPropertyBlockLevel1_0F00, /* 0F00..0FFF */
+ FriBidiPropertyBlockLevel1_1000, /* 1000..10FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1100..11FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1200..12FF */
+ FriBidiPropertyBlockLevel1_1300, /* 1300..13FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1400..14FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1500..15FF */
+ FriBidiPropertyBlockLevel1_1600, /* 1600..16FF */
+ FriBidiPropertyBlockLevel1_1700, /* 1700..17FF */
+ FriBidiPropertyBlockLevel1_1800, /* 1800..18FF */
+ FriBidiPropertyBlockLevel1_1900, /* 1900..19FF */
+ FriBidiPropertyBlockLevel1_1A00, /* 1A00..1AFF */
+ FriBidiPropertyBlockLevel1_1B00, /* 1B00..1BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C00..1CFF */
+ FriBidiPropertyBlockLevel1_1D00, /* 1D00..1DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E00..1EFF */
+ FriBidiPropertyBlockLevel1_1F00, /* 1F00..1FFF */
+ FriBidiPropertyBlockLevel1_2000, /* 2000..20FF */
+ FriBidiPropertyBlockLevel1_2100, /* 2100..21FF */
+ FriBidiPropertyBlockLevel1_2200, /* 2200..22FF */
+ FriBidiPropertyBlockLevel1_2300, /* 2300..23FF */
+ FriBidiPropertyBlockLevel1_2400, /* 2400..24FF */
+ FriBidiPropertyBlockLevel1_2500, /* 2500..25FF */
+ FriBidiPropertyBlockLevel1_2600, /* 2600..26FF */
+ FriBidiPropertyBlockLevel1_2700, /* 2700..27FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2800..28FF */
+ FriBidiPropertyBlockLevel1_2500, /* 2900..29FF */
+ FriBidiPropertyBlockLevel1_2500, /* 2A00..2AFF */
+ FriBidiPropertyBlockLevel1_2B00, /* 2B00..2BFF */
+ FriBidiPropertyBlockLevel1_2C00, /* 2C00..2CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D00..2DFF */
+ FriBidiPropertyBlockLevel1_2E00, /* 2E00..2EFF */
+ FriBidiPropertyBlockLevel1_2F00, /* 2F00..2FFF */
+ FriBidiPropertyBlockLevel1_3000, /* 3000..30FF */
+ FriBidiPropertyBlockLevel1_3100, /* 3100..31FF */
+ FriBidiPropertyBlockLevel1_3200, /* 3200..32FF */
+ FriBidiPropertyBlockLevel1_3300, /* 3300..33FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3400..34FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3500..35FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3600..36FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3700..37FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3800..38FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3900..39FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A00..3AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B00..3BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C00..3CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D00..3DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E00..3EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F00..3FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4000..40FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4100..41FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4200..42FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4300..43FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4400..44FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4500..45FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4600..46FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4700..47FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4800..48FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4900..49FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A00..4AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B00..4BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C00..4CFF */
+ FriBidiPropertyBlockLevel1_4D00, /* 4D00..4DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E00..4EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F00..4FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5000..50FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5100..51FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5200..52FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5300..53FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5400..54FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5500..55FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5600..56FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5700..57FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5800..58FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5900..59FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A00..5AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B00..5BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C00..5CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D00..5DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E00..5EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F00..5FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6000..60FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6100..61FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6200..62FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6300..63FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6400..64FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6500..65FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6600..66FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6700..67FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6800..68FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6900..69FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A00..6AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B00..6BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C00..6CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D00..6DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E00..6EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F00..6FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7000..70FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7100..71FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7200..72FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7300..73FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7400..74FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7500..75FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7600..76FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7700..77FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7800..78FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7900..79FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A00..7AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B00..7BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C00..7CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D00..7DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E00..7EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F00..7FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8000..80FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8100..81FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8200..82FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8300..83FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8400..84FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8500..85FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8600..86FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8700..87FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8800..88FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8900..89FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A00..8AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B00..8BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C00..8CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D00..8DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E00..8EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F00..8FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9000..90FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9100..91FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9200..92FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9300..93FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9400..94FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9500..95FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9600..96FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9700..97FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9800..98FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9900..99FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A00..9AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B00..9BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C00..9CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D00..9DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E00..9EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F00..9FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A000..A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* A100..A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* A200..A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* A300..A3FF */
+ FriBidiPropertyBlockLevel1_A400, /* A400..A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* A500..A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* A600..A6FF */
+ FriBidiPropertyBlockLevel1_A700, /* A700..A7FF */
+ FriBidiPropertyBlockLevel1_A800, /* A800..A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* A900..A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA00..AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* AB00..ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* AC00..ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* AD00..ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* AE00..AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* AF00..AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* B000..B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* B100..B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* B200..B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* B300..B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* B400..B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* B500..B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* B600..B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* B700..B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* B800..B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* B900..B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA00..BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* BB00..BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* BC00..BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* BD00..BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* BE00..BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* BF00..BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* C000..C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* C100..C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* C200..C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* C300..C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* C400..C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* C500..C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* C600..C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* C700..C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* C800..C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* C900..C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA00..CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* CB00..CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* CC00..CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* CD00..CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* CE00..CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* CF00..CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* D000..D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* D100..D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* D200..D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* D300..D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* D400..D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* D500..D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* D600..D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* D700..D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* D800..D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* D900..D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA00..DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* DB00..DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* DC00..DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* DD00..DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* DE00..DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* DF00..DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* E000..E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* E100..E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* E200..E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* E300..E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* E400..E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* E500..E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* E600..E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* E700..E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* E800..E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* E900..E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA00..EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* EB00..EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* EC00..ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* ED00..EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* EE00..EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* EF00..EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* F000..F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* F100..F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* F200..F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* F300..F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* F400..F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* F500..F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* F600..F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* F700..F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* F800..F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* F900..F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA00..FAFF */
+ FriBidiPropertyBlockLevel1_FB00, /* FB00..FBFF */
+ FriBidiPropertyBlockLevel1_FC00, /* FC00..FCFF */
+ FriBidiPropertyBlockLevel1_FD00, /* FD00..FDFF */
+ FriBidiPropertyBlockLevel1_FE00, /* FE00..FEFF */
+ FriBidiPropertyBlockLevel1_FF00, /* FF00..FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10000..100FF */
+ FriBidiPropertyBlockLevel1_10100, /* 10100..101FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10200..102FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10300..103FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10400..104FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10500..105FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10600..106FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10700..107FF */
+ FriBidiPropertyBlockLevel1_0800, /* 10800..108FF */
+ FriBidiPropertyBlockLevel1_10900, /* 10900..109FF */
+ FriBidiPropertyBlockLevel1_10A00, /* 10A00..10AFF */
+ FriBidiPropertyBlockLevel1_0800, /* 10B00..10BFF */
+ FriBidiPropertyBlockLevel1_0800, /* 10C00..10CFF */
+ FriBidiPropertyBlockLevel1_0800, /* 10D00..10DFF */
+ FriBidiPropertyBlockLevel1_0800, /* 10E00..10EFF */
+ FriBidiPropertyBlockLevel1_0800, /* 10F00..10FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 11000..110FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11100..111FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11200..112FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11300..113FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11400..114FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11500..115FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11600..116FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11700..117FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11800..118FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11900..119FF */
+ FriBidiPropertyBlockLevel1_0100, /* 11A00..11AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 11B00..11BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 11C00..11CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 11D00..11DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 11E00..11EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 11F00..11FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 12000..120FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12100..121FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12200..122FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12300..123FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12400..124FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12500..125FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12600..126FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12700..127FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12800..128FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12900..129FF */
+ FriBidiPropertyBlockLevel1_0100, /* 12A00..12AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 12B00..12BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 12C00..12CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 12D00..12DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 12E00..12EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 12F00..12FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 13000..130FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13100..131FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13200..132FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13300..133FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13400..134FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13500..135FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13600..136FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13700..137FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13800..138FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13900..139FF */
+ FriBidiPropertyBlockLevel1_0100, /* 13A00..13AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 13B00..13BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 13C00..13CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 13D00..13DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 13E00..13EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 13F00..13FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 14000..140FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14100..141FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14200..142FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14300..143FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14400..144FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14500..145FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14600..146FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14700..147FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14800..148FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14900..149FF */
+ FriBidiPropertyBlockLevel1_0100, /* 14A00..14AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 14B00..14BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 14C00..14CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 14D00..14DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 14E00..14EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 14F00..14FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 15000..150FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15100..151FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15200..152FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15300..153FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15400..154FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15500..155FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15600..156FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15700..157FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15800..158FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15900..159FF */
+ FriBidiPropertyBlockLevel1_0100, /* 15A00..15AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 15B00..15BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 15C00..15CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 15D00..15DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 15E00..15EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 15F00..15FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 16000..160FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16100..161FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16200..162FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16300..163FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16400..164FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16500..165FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16600..166FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16700..167FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16800..168FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16900..169FF */
+ FriBidiPropertyBlockLevel1_0100, /* 16A00..16AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 16B00..16BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 16C00..16CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 16D00..16DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 16E00..16EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 16F00..16FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 17000..170FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17100..171FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17200..172FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17300..173FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17400..174FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17500..175FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17600..176FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17700..177FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17800..178FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17900..179FF */
+ FriBidiPropertyBlockLevel1_0100, /* 17A00..17AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 17B00..17BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 17C00..17CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 17D00..17DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 17E00..17EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 17F00..17FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 18000..180FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18100..181FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18200..182FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18300..183FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18400..184FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18500..185FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18600..186FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18700..187FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18800..188FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18900..189FF */
+ FriBidiPropertyBlockLevel1_0100, /* 18A00..18AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 18B00..18BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 18C00..18CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 18D00..18DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 18E00..18EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 18F00..18FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 19000..190FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19100..191FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19200..192FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19300..193FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19400..194FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19500..195FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19600..196FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19700..197FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19800..198FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19900..199FF */
+ FriBidiPropertyBlockLevel1_0100, /* 19A00..19AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 19B00..19BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 19C00..19CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 19D00..19DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 19E00..19EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 19F00..19FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A000..1A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A100..1A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A200..1A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A300..1A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A400..1A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A500..1A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A600..1A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A700..1A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A800..1A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1A900..1A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1AA00..1AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1AB00..1ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1AC00..1ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1AD00..1ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1AE00..1AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1AF00..1AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B000..1B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B100..1B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B200..1B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B300..1B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B400..1B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B500..1B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B600..1B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B700..1B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B800..1B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1B900..1B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1BA00..1BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1BB00..1BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1BC00..1BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1BD00..1BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1BE00..1BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1BF00..1BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C000..1C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C100..1C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C200..1C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C300..1C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C400..1C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C500..1C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C600..1C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C700..1C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C800..1C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1C900..1C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1CA00..1CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1CB00..1CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1CC00..1CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1CD00..1CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1CE00..1CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1CF00..1CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1D000..1D0FF */
+ FriBidiPropertyBlockLevel1_1D100, /* 1D100..1D1FF */
+ FriBidiPropertyBlockLevel1_1D200, /* 1D200..1D2FF */
+ FriBidiPropertyBlockLevel1_1D300, /* 1D300..1D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1D400..1D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1D500..1D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1D600..1D6FF */
+ FriBidiPropertyBlockLevel1_1D700, /* 1D700..1D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1D800..1D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1D900..1D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1DA00..1DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1DB00..1DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1DC00..1DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1DD00..1DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1DE00..1DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1DF00..1DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E000..1E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E100..1E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E200..1E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E300..1E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E400..1E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E500..1E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E600..1E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E700..1E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E800..1E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1E900..1E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1EA00..1EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1EB00..1EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1EC00..1ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1ED00..1EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1EE00..1EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1EF00..1EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F000..1F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F100..1F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F200..1F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F300..1F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F400..1F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F500..1F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F600..1F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F700..1F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F800..1F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1F900..1F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 1FA00..1FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1FB00..1FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1FC00..1FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1FD00..1FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 1FE00..1FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 1FF00..1FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 20000..200FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20100..201FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20200..202FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20300..203FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20400..204FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20500..205FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20600..206FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20700..207FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20800..208FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20900..209FF */
+ FriBidiPropertyBlockLevel1_0100, /* 20A00..20AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 20B00..20BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 20C00..20CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 20D00..20DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 20E00..20EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 20F00..20FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 21000..210FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21100..211FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21200..212FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21300..213FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21400..214FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21500..215FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21600..216FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21700..217FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21800..218FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21900..219FF */
+ FriBidiPropertyBlockLevel1_0100, /* 21A00..21AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 21B00..21BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 21C00..21CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 21D00..21DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 21E00..21EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 21F00..21FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 22000..220FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22100..221FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22200..222FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22300..223FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22400..224FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22500..225FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22600..226FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22700..227FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22800..228FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22900..229FF */
+ FriBidiPropertyBlockLevel1_0100, /* 22A00..22AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 22B00..22BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 22C00..22CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 22D00..22DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 22E00..22EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 22F00..22FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 23000..230FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23100..231FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23200..232FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23300..233FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23400..234FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23500..235FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23600..236FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23700..237FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23800..238FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23900..239FF */
+ FriBidiPropertyBlockLevel1_0100, /* 23A00..23AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 23B00..23BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 23C00..23CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 23D00..23DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 23E00..23EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 23F00..23FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 24000..240FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24100..241FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24200..242FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24300..243FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24400..244FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24500..245FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24600..246FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24700..247FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24800..248FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24900..249FF */
+ FriBidiPropertyBlockLevel1_0100, /* 24A00..24AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 24B00..24BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 24C00..24CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 24D00..24DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 24E00..24EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 24F00..24FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 25000..250FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25100..251FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25200..252FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25300..253FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25400..254FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25500..255FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25600..256FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25700..257FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25800..258FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25900..259FF */
+ FriBidiPropertyBlockLevel1_0100, /* 25A00..25AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 25B00..25BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 25C00..25CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 25D00..25DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 25E00..25EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 25F00..25FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 26000..260FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26100..261FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26200..262FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26300..263FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26400..264FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26500..265FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26600..266FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26700..267FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26800..268FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26900..269FF */
+ FriBidiPropertyBlockLevel1_0100, /* 26A00..26AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 26B00..26BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 26C00..26CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 26D00..26DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 26E00..26EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 26F00..26FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 27000..270FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27100..271FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27200..272FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27300..273FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27400..274FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27500..275FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27600..276FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27700..277FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27800..278FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27900..279FF */
+ FriBidiPropertyBlockLevel1_0100, /* 27A00..27AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 27B00..27BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 27C00..27CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 27D00..27DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 27E00..27EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 27F00..27FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 28000..280FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28100..281FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28200..282FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28300..283FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28400..284FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28500..285FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28600..286FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28700..287FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28800..288FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28900..289FF */
+ FriBidiPropertyBlockLevel1_0100, /* 28A00..28AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 28B00..28BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 28C00..28CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 28D00..28DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 28E00..28EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 28F00..28FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 29000..290FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29100..291FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29200..292FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29300..293FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29400..294FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29500..295FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29600..296FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29700..297FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29800..298FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29900..299FF */
+ FriBidiPropertyBlockLevel1_0100, /* 29A00..29AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 29B00..29BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 29C00..29CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 29D00..29DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 29E00..29EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 29F00..29FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A000..2A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A100..2A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A200..2A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A300..2A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A400..2A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A500..2A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A600..2A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A700..2A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A800..2A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2A900..2A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2AA00..2AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2AB00..2ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2AC00..2ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2AD00..2ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2AE00..2AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2AF00..2AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B000..2B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B100..2B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B200..2B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B300..2B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B400..2B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B500..2B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B600..2B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B700..2B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B800..2B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2B900..2B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2BA00..2BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2BB00..2BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2BC00..2BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2BD00..2BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2BE00..2BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2BF00..2BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C000..2C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C100..2C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C200..2C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C300..2C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C400..2C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C500..2C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C600..2C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C700..2C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C800..2C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2C900..2C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2CA00..2CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2CB00..2CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2CC00..2CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2CD00..2CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2CE00..2CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2CF00..2CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D000..2D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D100..2D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D200..2D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D300..2D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D400..2D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D500..2D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D600..2D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D700..2D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D800..2D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2D900..2D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2DA00..2DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2DB00..2DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2DC00..2DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2DD00..2DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2DE00..2DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2DF00..2DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E000..2E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E100..2E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E200..2E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E300..2E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E400..2E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E500..2E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E600..2E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E700..2E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E800..2E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2E900..2E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2EA00..2EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2EB00..2EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2EC00..2ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2ED00..2EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2EE00..2EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2EF00..2EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F000..2F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F100..2F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F200..2F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F300..2F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F400..2F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F500..2F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F600..2F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F700..2F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F800..2F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2F900..2F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 2FA00..2FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2FB00..2FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2FC00..2FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2FD00..2FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 2FE00..2FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 2FF00..2FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 30000..300FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30100..301FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30200..302FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30300..303FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30400..304FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30500..305FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30600..306FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30700..307FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30800..308FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30900..309FF */
+ FriBidiPropertyBlockLevel1_0100, /* 30A00..30AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 30B00..30BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 30C00..30CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 30D00..30DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 30E00..30EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 30F00..30FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 31000..310FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31100..311FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31200..312FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31300..313FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31400..314FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31500..315FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31600..316FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31700..317FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31800..318FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31900..319FF */
+ FriBidiPropertyBlockLevel1_0100, /* 31A00..31AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 31B00..31BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 31C00..31CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 31D00..31DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 31E00..31EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 31F00..31FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 32000..320FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32100..321FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32200..322FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32300..323FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32400..324FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32500..325FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32600..326FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32700..327FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32800..328FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32900..329FF */
+ FriBidiPropertyBlockLevel1_0100, /* 32A00..32AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 32B00..32BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 32C00..32CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 32D00..32DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 32E00..32EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 32F00..32FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 33000..330FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33100..331FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33200..332FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33300..333FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33400..334FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33500..335FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33600..336FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33700..337FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33800..338FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33900..339FF */
+ FriBidiPropertyBlockLevel1_0100, /* 33A00..33AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 33B00..33BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 33C00..33CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 33D00..33DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 33E00..33EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 33F00..33FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 34000..340FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34100..341FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34200..342FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34300..343FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34400..344FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34500..345FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34600..346FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34700..347FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34800..348FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34900..349FF */
+ FriBidiPropertyBlockLevel1_0100, /* 34A00..34AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 34B00..34BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 34C00..34CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 34D00..34DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 34E00..34EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 34F00..34FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 35000..350FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35100..351FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35200..352FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35300..353FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35400..354FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35500..355FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35600..356FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35700..357FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35800..358FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35900..359FF */
+ FriBidiPropertyBlockLevel1_0100, /* 35A00..35AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 35B00..35BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 35C00..35CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 35D00..35DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 35E00..35EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 35F00..35FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 36000..360FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36100..361FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36200..362FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36300..363FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36400..364FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36500..365FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36600..366FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36700..367FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36800..368FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36900..369FF */
+ FriBidiPropertyBlockLevel1_0100, /* 36A00..36AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 36B00..36BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 36C00..36CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 36D00..36DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 36E00..36EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 36F00..36FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 37000..370FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37100..371FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37200..372FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37300..373FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37400..374FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37500..375FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37600..376FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37700..377FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37800..378FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37900..379FF */
+ FriBidiPropertyBlockLevel1_0100, /* 37A00..37AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 37B00..37BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 37C00..37CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 37D00..37DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 37E00..37EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 37F00..37FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 38000..380FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38100..381FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38200..382FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38300..383FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38400..384FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38500..385FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38600..386FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38700..387FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38800..388FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38900..389FF */
+ FriBidiPropertyBlockLevel1_0100, /* 38A00..38AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 38B00..38BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 38C00..38CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 38D00..38DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 38E00..38EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 38F00..38FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 39000..390FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39100..391FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39200..392FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39300..393FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39400..394FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39500..395FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39600..396FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39700..397FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39800..398FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39900..399FF */
+ FriBidiPropertyBlockLevel1_0100, /* 39A00..39AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 39B00..39BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 39C00..39CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 39D00..39DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 39E00..39EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 39F00..39FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A000..3A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A100..3A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A200..3A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A300..3A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A400..3A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A500..3A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A600..3A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A700..3A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A800..3A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3A900..3A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3AA00..3AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3AB00..3ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3AC00..3ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3AD00..3ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3AE00..3AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3AF00..3AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B000..3B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B100..3B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B200..3B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B300..3B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B400..3B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B500..3B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B600..3B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B700..3B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B800..3B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3B900..3B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3BA00..3BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3BB00..3BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3BC00..3BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3BD00..3BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3BE00..3BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3BF00..3BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C000..3C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C100..3C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C200..3C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C300..3C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C400..3C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C500..3C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C600..3C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C700..3C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C800..3C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3C900..3C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3CA00..3CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3CB00..3CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3CC00..3CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3CD00..3CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3CE00..3CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3CF00..3CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D000..3D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D100..3D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D200..3D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D300..3D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D400..3D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D500..3D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D600..3D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D700..3D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D800..3D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3D900..3D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3DA00..3DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3DB00..3DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3DC00..3DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3DD00..3DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3DE00..3DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3DF00..3DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E000..3E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E100..3E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E200..3E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E300..3E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E400..3E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E500..3E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E600..3E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E700..3E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E800..3E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3E900..3E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3EA00..3EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3EB00..3EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3EC00..3ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3ED00..3EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3EE00..3EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3EF00..3EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F000..3F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F100..3F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F200..3F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F300..3F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F400..3F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F500..3F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F600..3F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F700..3F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F800..3F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3F900..3F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 3FA00..3FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3FB00..3FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3FC00..3FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3FD00..3FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 3FE00..3FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 3FF00..3FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 40000..400FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40100..401FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40200..402FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40300..403FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40400..404FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40500..405FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40600..406FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40700..407FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40800..408FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40900..409FF */
+ FriBidiPropertyBlockLevel1_0100, /* 40A00..40AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 40B00..40BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 40C00..40CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 40D00..40DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 40E00..40EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 40F00..40FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 41000..410FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41100..411FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41200..412FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41300..413FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41400..414FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41500..415FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41600..416FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41700..417FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41800..418FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41900..419FF */
+ FriBidiPropertyBlockLevel1_0100, /* 41A00..41AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 41B00..41BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 41C00..41CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 41D00..41DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 41E00..41EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 41F00..41FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 42000..420FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42100..421FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42200..422FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42300..423FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42400..424FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42500..425FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42600..426FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42700..427FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42800..428FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42900..429FF */
+ FriBidiPropertyBlockLevel1_0100, /* 42A00..42AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 42B00..42BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 42C00..42CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 42D00..42DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 42E00..42EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 42F00..42FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 43000..430FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43100..431FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43200..432FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43300..433FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43400..434FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43500..435FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43600..436FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43700..437FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43800..438FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43900..439FF */
+ FriBidiPropertyBlockLevel1_0100, /* 43A00..43AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 43B00..43BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 43C00..43CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 43D00..43DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 43E00..43EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 43F00..43FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 44000..440FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44100..441FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44200..442FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44300..443FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44400..444FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44500..445FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44600..446FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44700..447FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44800..448FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44900..449FF */
+ FriBidiPropertyBlockLevel1_0100, /* 44A00..44AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 44B00..44BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 44C00..44CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 44D00..44DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 44E00..44EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 44F00..44FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 45000..450FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45100..451FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45200..452FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45300..453FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45400..454FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45500..455FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45600..456FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45700..457FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45800..458FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45900..459FF */
+ FriBidiPropertyBlockLevel1_0100, /* 45A00..45AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 45B00..45BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 45C00..45CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 45D00..45DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 45E00..45EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 45F00..45FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 46000..460FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46100..461FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46200..462FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46300..463FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46400..464FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46500..465FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46600..466FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46700..467FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46800..468FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46900..469FF */
+ FriBidiPropertyBlockLevel1_0100, /* 46A00..46AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 46B00..46BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 46C00..46CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 46D00..46DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 46E00..46EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 46F00..46FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 47000..470FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47100..471FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47200..472FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47300..473FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47400..474FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47500..475FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47600..476FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47700..477FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47800..478FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47900..479FF */
+ FriBidiPropertyBlockLevel1_0100, /* 47A00..47AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 47B00..47BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 47C00..47CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 47D00..47DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 47E00..47EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 47F00..47FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 48000..480FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48100..481FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48200..482FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48300..483FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48400..484FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48500..485FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48600..486FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48700..487FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48800..488FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48900..489FF */
+ FriBidiPropertyBlockLevel1_0100, /* 48A00..48AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 48B00..48BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 48C00..48CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 48D00..48DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 48E00..48EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 48F00..48FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 49000..490FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49100..491FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49200..492FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49300..493FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49400..494FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49500..495FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49600..496FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49700..497FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49800..498FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49900..499FF */
+ FriBidiPropertyBlockLevel1_0100, /* 49A00..49AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 49B00..49BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 49C00..49CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 49D00..49DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 49E00..49EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 49F00..49FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A000..4A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A100..4A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A200..4A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A300..4A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A400..4A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A500..4A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A600..4A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A700..4A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A800..4A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4A900..4A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4AA00..4AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4AB00..4ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4AC00..4ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4AD00..4ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4AE00..4AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4AF00..4AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B000..4B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B100..4B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B200..4B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B300..4B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B400..4B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B500..4B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B600..4B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B700..4B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B800..4B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4B900..4B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4BA00..4BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4BB00..4BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4BC00..4BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4BD00..4BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4BE00..4BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4BF00..4BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C000..4C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C100..4C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C200..4C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C300..4C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C400..4C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C500..4C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C600..4C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C700..4C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C800..4C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4C900..4C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4CA00..4CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4CB00..4CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4CC00..4CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4CD00..4CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4CE00..4CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4CF00..4CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D000..4D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D100..4D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D200..4D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D300..4D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D400..4D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D500..4D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D600..4D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D700..4D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D800..4D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4D900..4D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4DA00..4DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4DB00..4DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4DC00..4DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4DD00..4DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4DE00..4DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4DF00..4DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E000..4E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E100..4E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E200..4E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E300..4E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E400..4E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E500..4E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E600..4E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E700..4E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E800..4E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4E900..4E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4EA00..4EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4EB00..4EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4EC00..4ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4ED00..4EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4EE00..4EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4EF00..4EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F000..4F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F100..4F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F200..4F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F300..4F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F400..4F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F500..4F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F600..4F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F700..4F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F800..4F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4F900..4F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 4FA00..4FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4FB00..4FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4FC00..4FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4FD00..4FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 4FE00..4FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 4FF00..4FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 50000..500FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50100..501FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50200..502FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50300..503FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50400..504FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50500..505FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50600..506FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50700..507FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50800..508FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50900..509FF */
+ FriBidiPropertyBlockLevel1_0100, /* 50A00..50AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 50B00..50BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 50C00..50CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 50D00..50DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 50E00..50EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 50F00..50FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 51000..510FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51100..511FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51200..512FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51300..513FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51400..514FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51500..515FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51600..516FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51700..517FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51800..518FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51900..519FF */
+ FriBidiPropertyBlockLevel1_0100, /* 51A00..51AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 51B00..51BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 51C00..51CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 51D00..51DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 51E00..51EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 51F00..51FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 52000..520FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52100..521FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52200..522FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52300..523FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52400..524FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52500..525FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52600..526FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52700..527FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52800..528FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52900..529FF */
+ FriBidiPropertyBlockLevel1_0100, /* 52A00..52AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 52B00..52BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 52C00..52CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 52D00..52DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 52E00..52EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 52F00..52FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 53000..530FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53100..531FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53200..532FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53300..533FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53400..534FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53500..535FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53600..536FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53700..537FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53800..538FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53900..539FF */
+ FriBidiPropertyBlockLevel1_0100, /* 53A00..53AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 53B00..53BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 53C00..53CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 53D00..53DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 53E00..53EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 53F00..53FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 54000..540FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54100..541FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54200..542FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54300..543FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54400..544FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54500..545FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54600..546FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54700..547FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54800..548FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54900..549FF */
+ FriBidiPropertyBlockLevel1_0100, /* 54A00..54AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 54B00..54BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 54C00..54CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 54D00..54DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 54E00..54EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 54F00..54FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 55000..550FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55100..551FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55200..552FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55300..553FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55400..554FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55500..555FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55600..556FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55700..557FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55800..558FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55900..559FF */
+ FriBidiPropertyBlockLevel1_0100, /* 55A00..55AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 55B00..55BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 55C00..55CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 55D00..55DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 55E00..55EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 55F00..55FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 56000..560FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56100..561FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56200..562FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56300..563FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56400..564FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56500..565FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56600..566FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56700..567FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56800..568FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56900..569FF */
+ FriBidiPropertyBlockLevel1_0100, /* 56A00..56AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 56B00..56BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 56C00..56CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 56D00..56DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 56E00..56EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 56F00..56FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 57000..570FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57100..571FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57200..572FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57300..573FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57400..574FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57500..575FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57600..576FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57700..577FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57800..578FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57900..579FF */
+ FriBidiPropertyBlockLevel1_0100, /* 57A00..57AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 57B00..57BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 57C00..57CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 57D00..57DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 57E00..57EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 57F00..57FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 58000..580FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58100..581FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58200..582FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58300..583FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58400..584FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58500..585FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58600..586FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58700..587FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58800..588FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58900..589FF */
+ FriBidiPropertyBlockLevel1_0100, /* 58A00..58AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 58B00..58BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 58C00..58CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 58D00..58DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 58E00..58EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 58F00..58FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 59000..590FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59100..591FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59200..592FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59300..593FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59400..594FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59500..595FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59600..596FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59700..597FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59800..598FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59900..599FF */
+ FriBidiPropertyBlockLevel1_0100, /* 59A00..59AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 59B00..59BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 59C00..59CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 59D00..59DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 59E00..59EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 59F00..59FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A000..5A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A100..5A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A200..5A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A300..5A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A400..5A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A500..5A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A600..5A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A700..5A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A800..5A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5A900..5A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5AA00..5AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5AB00..5ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5AC00..5ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5AD00..5ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5AE00..5AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5AF00..5AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B000..5B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B100..5B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B200..5B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B300..5B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B400..5B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B500..5B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B600..5B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B700..5B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B800..5B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5B900..5B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5BA00..5BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5BB00..5BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5BC00..5BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5BD00..5BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5BE00..5BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5BF00..5BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C000..5C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C100..5C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C200..5C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C300..5C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C400..5C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C500..5C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C600..5C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C700..5C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C800..5C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5C900..5C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5CA00..5CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5CB00..5CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5CC00..5CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5CD00..5CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5CE00..5CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5CF00..5CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D000..5D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D100..5D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D200..5D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D300..5D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D400..5D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D500..5D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D600..5D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D700..5D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D800..5D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5D900..5D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5DA00..5DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5DB00..5DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5DC00..5DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5DD00..5DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5DE00..5DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5DF00..5DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E000..5E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E100..5E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E200..5E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E300..5E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E400..5E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E500..5E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E600..5E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E700..5E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E800..5E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5E900..5E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5EA00..5EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5EB00..5EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5EC00..5ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5ED00..5EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5EE00..5EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5EF00..5EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F000..5F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F100..5F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F200..5F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F300..5F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F400..5F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F500..5F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F600..5F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F700..5F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F800..5F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5F900..5F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 5FA00..5FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5FB00..5FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5FC00..5FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5FD00..5FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 5FE00..5FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 5FF00..5FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 60000..600FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60100..601FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60200..602FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60300..603FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60400..604FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60500..605FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60600..606FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60700..607FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60800..608FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60900..609FF */
+ FriBidiPropertyBlockLevel1_0100, /* 60A00..60AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 60B00..60BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 60C00..60CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 60D00..60DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 60E00..60EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 60F00..60FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 61000..610FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61100..611FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61200..612FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61300..613FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61400..614FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61500..615FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61600..616FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61700..617FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61800..618FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61900..619FF */
+ FriBidiPropertyBlockLevel1_0100, /* 61A00..61AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 61B00..61BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 61C00..61CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 61D00..61DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 61E00..61EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 61F00..61FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 62000..620FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62100..621FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62200..622FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62300..623FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62400..624FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62500..625FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62600..626FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62700..627FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62800..628FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62900..629FF */
+ FriBidiPropertyBlockLevel1_0100, /* 62A00..62AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 62B00..62BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 62C00..62CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 62D00..62DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 62E00..62EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 62F00..62FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 63000..630FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63100..631FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63200..632FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63300..633FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63400..634FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63500..635FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63600..636FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63700..637FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63800..638FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63900..639FF */
+ FriBidiPropertyBlockLevel1_0100, /* 63A00..63AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 63B00..63BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 63C00..63CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 63D00..63DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 63E00..63EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 63F00..63FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 64000..640FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64100..641FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64200..642FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64300..643FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64400..644FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64500..645FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64600..646FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64700..647FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64800..648FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64900..649FF */
+ FriBidiPropertyBlockLevel1_0100, /* 64A00..64AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 64B00..64BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 64C00..64CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 64D00..64DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 64E00..64EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 64F00..64FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 65000..650FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65100..651FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65200..652FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65300..653FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65400..654FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65500..655FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65600..656FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65700..657FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65800..658FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65900..659FF */
+ FriBidiPropertyBlockLevel1_0100, /* 65A00..65AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 65B00..65BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 65C00..65CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 65D00..65DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 65E00..65EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 65F00..65FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 66000..660FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66100..661FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66200..662FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66300..663FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66400..664FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66500..665FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66600..666FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66700..667FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66800..668FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66900..669FF */
+ FriBidiPropertyBlockLevel1_0100, /* 66A00..66AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 66B00..66BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 66C00..66CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 66D00..66DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 66E00..66EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 66F00..66FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 67000..670FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67100..671FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67200..672FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67300..673FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67400..674FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67500..675FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67600..676FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67700..677FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67800..678FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67900..679FF */
+ FriBidiPropertyBlockLevel1_0100, /* 67A00..67AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 67B00..67BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 67C00..67CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 67D00..67DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 67E00..67EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 67F00..67FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 68000..680FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68100..681FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68200..682FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68300..683FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68400..684FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68500..685FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68600..686FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68700..687FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68800..688FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68900..689FF */
+ FriBidiPropertyBlockLevel1_0100, /* 68A00..68AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 68B00..68BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 68C00..68CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 68D00..68DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 68E00..68EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 68F00..68FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 69000..690FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69100..691FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69200..692FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69300..693FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69400..694FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69500..695FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69600..696FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69700..697FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69800..698FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69900..699FF */
+ FriBidiPropertyBlockLevel1_0100, /* 69A00..69AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 69B00..69BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 69C00..69CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 69D00..69DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 69E00..69EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 69F00..69FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A000..6A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A100..6A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A200..6A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A300..6A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A400..6A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A500..6A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A600..6A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A700..6A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A800..6A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6A900..6A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6AA00..6AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6AB00..6ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6AC00..6ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6AD00..6ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6AE00..6AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6AF00..6AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B000..6B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B100..6B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B200..6B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B300..6B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B400..6B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B500..6B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B600..6B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B700..6B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B800..6B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6B900..6B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6BA00..6BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6BB00..6BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6BC00..6BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6BD00..6BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6BE00..6BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6BF00..6BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C000..6C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C100..6C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C200..6C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C300..6C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C400..6C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C500..6C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C600..6C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C700..6C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C800..6C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6C900..6C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6CA00..6CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6CB00..6CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6CC00..6CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6CD00..6CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6CE00..6CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6CF00..6CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D000..6D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D100..6D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D200..6D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D300..6D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D400..6D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D500..6D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D600..6D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D700..6D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D800..6D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6D900..6D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6DA00..6DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6DB00..6DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6DC00..6DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6DD00..6DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6DE00..6DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6DF00..6DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E000..6E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E100..6E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E200..6E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E300..6E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E400..6E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E500..6E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E600..6E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E700..6E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E800..6E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6E900..6E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6EA00..6EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6EB00..6EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6EC00..6ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6ED00..6EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6EE00..6EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6EF00..6EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F000..6F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F100..6F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F200..6F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F300..6F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F400..6F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F500..6F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F600..6F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F700..6F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F800..6F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6F900..6F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 6FA00..6FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6FB00..6FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6FC00..6FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6FD00..6FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 6FE00..6FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 6FF00..6FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 70000..700FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70100..701FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70200..702FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70300..703FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70400..704FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70500..705FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70600..706FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70700..707FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70800..708FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70900..709FF */
+ FriBidiPropertyBlockLevel1_0100, /* 70A00..70AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 70B00..70BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 70C00..70CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 70D00..70DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 70E00..70EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 70F00..70FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 71000..710FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71100..711FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71200..712FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71300..713FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71400..714FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71500..715FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71600..716FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71700..717FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71800..718FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71900..719FF */
+ FriBidiPropertyBlockLevel1_0100, /* 71A00..71AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 71B00..71BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 71C00..71CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 71D00..71DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 71E00..71EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 71F00..71FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 72000..720FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72100..721FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72200..722FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72300..723FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72400..724FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72500..725FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72600..726FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72700..727FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72800..728FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72900..729FF */
+ FriBidiPropertyBlockLevel1_0100, /* 72A00..72AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 72B00..72BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 72C00..72CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 72D00..72DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 72E00..72EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 72F00..72FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 73000..730FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73100..731FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73200..732FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73300..733FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73400..734FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73500..735FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73600..736FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73700..737FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73800..738FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73900..739FF */
+ FriBidiPropertyBlockLevel1_0100, /* 73A00..73AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 73B00..73BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 73C00..73CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 73D00..73DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 73E00..73EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 73F00..73FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 74000..740FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74100..741FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74200..742FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74300..743FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74400..744FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74500..745FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74600..746FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74700..747FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74800..748FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74900..749FF */
+ FriBidiPropertyBlockLevel1_0100, /* 74A00..74AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 74B00..74BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 74C00..74CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 74D00..74DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 74E00..74EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 74F00..74FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 75000..750FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75100..751FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75200..752FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75300..753FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75400..754FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75500..755FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75600..756FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75700..757FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75800..758FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75900..759FF */
+ FriBidiPropertyBlockLevel1_0100, /* 75A00..75AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 75B00..75BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 75C00..75CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 75D00..75DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 75E00..75EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 75F00..75FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 76000..760FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76100..761FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76200..762FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76300..763FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76400..764FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76500..765FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76600..766FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76700..767FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76800..768FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76900..769FF */
+ FriBidiPropertyBlockLevel1_0100, /* 76A00..76AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 76B00..76BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 76C00..76CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 76D00..76DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 76E00..76EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 76F00..76FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 77000..770FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77100..771FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77200..772FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77300..773FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77400..774FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77500..775FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77600..776FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77700..777FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77800..778FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77900..779FF */
+ FriBidiPropertyBlockLevel1_0100, /* 77A00..77AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 77B00..77BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 77C00..77CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 77D00..77DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 77E00..77EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 77F00..77FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 78000..780FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78100..781FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78200..782FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78300..783FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78400..784FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78500..785FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78600..786FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78700..787FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78800..788FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78900..789FF */
+ FriBidiPropertyBlockLevel1_0100, /* 78A00..78AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 78B00..78BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 78C00..78CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 78D00..78DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 78E00..78EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 78F00..78FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 79000..790FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79100..791FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79200..792FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79300..793FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79400..794FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79500..795FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79600..796FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79700..797FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79800..798FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79900..799FF */
+ FriBidiPropertyBlockLevel1_0100, /* 79A00..79AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 79B00..79BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 79C00..79CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 79D00..79DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 79E00..79EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 79F00..79FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A000..7A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A100..7A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A200..7A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A300..7A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A400..7A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A500..7A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A600..7A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A700..7A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A800..7A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7A900..7A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7AA00..7AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7AB00..7ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7AC00..7ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7AD00..7ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7AE00..7AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7AF00..7AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B000..7B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B100..7B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B200..7B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B300..7B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B400..7B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B500..7B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B600..7B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B700..7B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B800..7B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7B900..7B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7BA00..7BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7BB00..7BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7BC00..7BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7BD00..7BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7BE00..7BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7BF00..7BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C000..7C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C100..7C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C200..7C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C300..7C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C400..7C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C500..7C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C600..7C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C700..7C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C800..7C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7C900..7C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7CA00..7CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7CB00..7CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7CC00..7CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7CD00..7CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7CE00..7CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7CF00..7CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D000..7D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D100..7D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D200..7D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D300..7D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D400..7D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D500..7D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D600..7D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D700..7D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D800..7D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7D900..7D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7DA00..7DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7DB00..7DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7DC00..7DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7DD00..7DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7DE00..7DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7DF00..7DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E000..7E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E100..7E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E200..7E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E300..7E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E400..7E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E500..7E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E600..7E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E700..7E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E800..7E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7E900..7E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7EA00..7EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7EB00..7EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7EC00..7ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7ED00..7EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7EE00..7EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7EF00..7EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F000..7F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F100..7F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F200..7F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F300..7F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F400..7F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F500..7F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F600..7F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F700..7F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F800..7F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7F900..7F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 7FA00..7FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7FB00..7FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7FC00..7FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7FD00..7FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 7FE00..7FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 7FF00..7FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 80000..800FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80100..801FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80200..802FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80300..803FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80400..804FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80500..805FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80600..806FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80700..807FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80800..808FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80900..809FF */
+ FriBidiPropertyBlockLevel1_0100, /* 80A00..80AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 80B00..80BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 80C00..80CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 80D00..80DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 80E00..80EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 80F00..80FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 81000..810FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81100..811FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81200..812FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81300..813FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81400..814FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81500..815FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81600..816FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81700..817FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81800..818FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81900..819FF */
+ FriBidiPropertyBlockLevel1_0100, /* 81A00..81AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 81B00..81BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 81C00..81CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 81D00..81DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 81E00..81EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 81F00..81FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 82000..820FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82100..821FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82200..822FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82300..823FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82400..824FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82500..825FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82600..826FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82700..827FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82800..828FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82900..829FF */
+ FriBidiPropertyBlockLevel1_0100, /* 82A00..82AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 82B00..82BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 82C00..82CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 82D00..82DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 82E00..82EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 82F00..82FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 83000..830FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83100..831FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83200..832FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83300..833FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83400..834FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83500..835FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83600..836FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83700..837FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83800..838FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83900..839FF */
+ FriBidiPropertyBlockLevel1_0100, /* 83A00..83AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 83B00..83BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 83C00..83CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 83D00..83DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 83E00..83EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 83F00..83FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 84000..840FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84100..841FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84200..842FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84300..843FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84400..844FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84500..845FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84600..846FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84700..847FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84800..848FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84900..849FF */
+ FriBidiPropertyBlockLevel1_0100, /* 84A00..84AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 84B00..84BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 84C00..84CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 84D00..84DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 84E00..84EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 84F00..84FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 85000..850FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85100..851FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85200..852FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85300..853FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85400..854FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85500..855FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85600..856FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85700..857FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85800..858FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85900..859FF */
+ FriBidiPropertyBlockLevel1_0100, /* 85A00..85AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 85B00..85BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 85C00..85CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 85D00..85DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 85E00..85EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 85F00..85FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 86000..860FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86100..861FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86200..862FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86300..863FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86400..864FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86500..865FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86600..866FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86700..867FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86800..868FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86900..869FF */
+ FriBidiPropertyBlockLevel1_0100, /* 86A00..86AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 86B00..86BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 86C00..86CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 86D00..86DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 86E00..86EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 86F00..86FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 87000..870FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87100..871FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87200..872FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87300..873FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87400..874FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87500..875FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87600..876FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87700..877FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87800..878FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87900..879FF */
+ FriBidiPropertyBlockLevel1_0100, /* 87A00..87AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 87B00..87BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 87C00..87CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 87D00..87DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 87E00..87EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 87F00..87FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 88000..880FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88100..881FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88200..882FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88300..883FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88400..884FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88500..885FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88600..886FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88700..887FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88800..888FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88900..889FF */
+ FriBidiPropertyBlockLevel1_0100, /* 88A00..88AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 88B00..88BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 88C00..88CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 88D00..88DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 88E00..88EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 88F00..88FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 89000..890FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89100..891FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89200..892FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89300..893FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89400..894FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89500..895FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89600..896FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89700..897FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89800..898FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89900..899FF */
+ FriBidiPropertyBlockLevel1_0100, /* 89A00..89AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 89B00..89BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 89C00..89CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 89D00..89DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 89E00..89EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 89F00..89FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A000..8A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A100..8A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A200..8A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A300..8A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A400..8A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A500..8A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A600..8A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A700..8A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A800..8A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8A900..8A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8AA00..8AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8AB00..8ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8AC00..8ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8AD00..8ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8AE00..8AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8AF00..8AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B000..8B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B100..8B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B200..8B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B300..8B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B400..8B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B500..8B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B600..8B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B700..8B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B800..8B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8B900..8B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8BA00..8BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8BB00..8BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8BC00..8BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8BD00..8BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8BE00..8BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8BF00..8BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C000..8C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C100..8C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C200..8C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C300..8C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C400..8C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C500..8C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C600..8C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C700..8C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C800..8C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8C900..8C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8CA00..8CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8CB00..8CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8CC00..8CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8CD00..8CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8CE00..8CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8CF00..8CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D000..8D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D100..8D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D200..8D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D300..8D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D400..8D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D500..8D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D600..8D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D700..8D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D800..8D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8D900..8D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8DA00..8DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8DB00..8DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8DC00..8DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8DD00..8DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8DE00..8DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8DF00..8DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E000..8E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E100..8E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E200..8E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E300..8E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E400..8E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E500..8E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E600..8E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E700..8E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E800..8E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8E900..8E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8EA00..8EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8EB00..8EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8EC00..8ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8ED00..8EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8EE00..8EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8EF00..8EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F000..8F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F100..8F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F200..8F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F300..8F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F400..8F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F500..8F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F600..8F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F700..8F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F800..8F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8F900..8F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 8FA00..8FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8FB00..8FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8FC00..8FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8FD00..8FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 8FE00..8FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 8FF00..8FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 90000..900FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90100..901FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90200..902FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90300..903FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90400..904FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90500..905FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90600..906FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90700..907FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90800..908FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90900..909FF */
+ FriBidiPropertyBlockLevel1_0100, /* 90A00..90AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 90B00..90BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 90C00..90CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 90D00..90DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 90E00..90EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 90F00..90FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 91000..910FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91100..911FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91200..912FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91300..913FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91400..914FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91500..915FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91600..916FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91700..917FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91800..918FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91900..919FF */
+ FriBidiPropertyBlockLevel1_0100, /* 91A00..91AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 91B00..91BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 91C00..91CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 91D00..91DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 91E00..91EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 91F00..91FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 92000..920FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92100..921FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92200..922FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92300..923FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92400..924FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92500..925FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92600..926FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92700..927FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92800..928FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92900..929FF */
+ FriBidiPropertyBlockLevel1_0100, /* 92A00..92AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 92B00..92BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 92C00..92CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 92D00..92DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 92E00..92EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 92F00..92FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 93000..930FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93100..931FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93200..932FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93300..933FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93400..934FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93500..935FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93600..936FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93700..937FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93800..938FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93900..939FF */
+ FriBidiPropertyBlockLevel1_0100, /* 93A00..93AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 93B00..93BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 93C00..93CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 93D00..93DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 93E00..93EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 93F00..93FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 94000..940FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94100..941FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94200..942FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94300..943FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94400..944FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94500..945FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94600..946FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94700..947FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94800..948FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94900..949FF */
+ FriBidiPropertyBlockLevel1_0100, /* 94A00..94AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 94B00..94BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 94C00..94CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 94D00..94DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 94E00..94EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 94F00..94FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 95000..950FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95100..951FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95200..952FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95300..953FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95400..954FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95500..955FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95600..956FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95700..957FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95800..958FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95900..959FF */
+ FriBidiPropertyBlockLevel1_0100, /* 95A00..95AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 95B00..95BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 95C00..95CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 95D00..95DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 95E00..95EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 95F00..95FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 96000..960FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96100..961FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96200..962FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96300..963FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96400..964FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96500..965FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96600..966FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96700..967FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96800..968FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96900..969FF */
+ FriBidiPropertyBlockLevel1_0100, /* 96A00..96AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 96B00..96BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 96C00..96CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 96D00..96DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 96E00..96EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 96F00..96FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 97000..970FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97100..971FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97200..972FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97300..973FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97400..974FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97500..975FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97600..976FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97700..977FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97800..978FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97900..979FF */
+ FriBidiPropertyBlockLevel1_0100, /* 97A00..97AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 97B00..97BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 97C00..97CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 97D00..97DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 97E00..97EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 97F00..97FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 98000..980FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98100..981FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98200..982FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98300..983FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98400..984FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98500..985FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98600..986FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98700..987FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98800..988FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98900..989FF */
+ FriBidiPropertyBlockLevel1_0100, /* 98A00..98AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 98B00..98BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 98C00..98CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 98D00..98DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 98E00..98EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 98F00..98FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 99000..990FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99100..991FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99200..992FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99300..993FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99400..994FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99500..995FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99600..996FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99700..997FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99800..998FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99900..999FF */
+ FriBidiPropertyBlockLevel1_0100, /* 99A00..99AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 99B00..99BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 99C00..99CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 99D00..99DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 99E00..99EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 99F00..99FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A000..9A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A100..9A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A200..9A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A300..9A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A400..9A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A500..9A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A600..9A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A700..9A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A800..9A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9A900..9A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9AA00..9AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9AB00..9ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9AC00..9ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9AD00..9ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9AE00..9AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9AF00..9AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B000..9B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B100..9B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B200..9B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B300..9B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B400..9B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B500..9B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B600..9B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B700..9B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B800..9B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9B900..9B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9BA00..9BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9BB00..9BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9BC00..9BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9BD00..9BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9BE00..9BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9BF00..9BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C000..9C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C100..9C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C200..9C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C300..9C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C400..9C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C500..9C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C600..9C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C700..9C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C800..9C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9C900..9C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9CA00..9CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9CB00..9CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9CC00..9CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9CD00..9CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9CE00..9CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9CF00..9CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D000..9D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D100..9D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D200..9D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D300..9D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D400..9D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D500..9D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D600..9D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D700..9D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D800..9D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9D900..9D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9DA00..9DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9DB00..9DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9DC00..9DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9DD00..9DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9DE00..9DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9DF00..9DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E000..9E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E100..9E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E200..9E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E300..9E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E400..9E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E500..9E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E600..9E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E700..9E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E800..9E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9E900..9E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9EA00..9EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9EB00..9EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9EC00..9ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9ED00..9EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9EE00..9EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9EF00..9EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F000..9F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F100..9F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F200..9F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F300..9F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F400..9F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F500..9F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F600..9F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F700..9F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F800..9F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9F900..9F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 9FA00..9FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9FB00..9FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9FC00..9FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9FD00..9FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 9FE00..9FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 9FF00..9FFFF */
+ FriBidiPropertyBlockLevel1_0100, /* A0000..A00FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0100..A01FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0200..A02FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0300..A03FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0400..A04FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0500..A05FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0600..A06FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0700..A07FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0800..A08FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0900..A09FF */
+ FriBidiPropertyBlockLevel1_0100, /* A0A00..A0AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A0B00..A0BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A0C00..A0CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A0D00..A0DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A0E00..A0EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A0F00..A0FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A1000..A10FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1100..A11FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1200..A12FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1300..A13FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1400..A14FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1500..A15FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1600..A16FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1700..A17FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1800..A18FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1900..A19FF */
+ FriBidiPropertyBlockLevel1_0100, /* A1A00..A1AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A1B00..A1BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A1C00..A1CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A1D00..A1DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A1E00..A1EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A1F00..A1FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A2000..A20FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2100..A21FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2200..A22FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2300..A23FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2400..A24FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2500..A25FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2600..A26FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2700..A27FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2800..A28FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2900..A29FF */
+ FriBidiPropertyBlockLevel1_0100, /* A2A00..A2AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A2B00..A2BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A2C00..A2CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A2D00..A2DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A2E00..A2EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A2F00..A2FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A3000..A30FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3100..A31FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3200..A32FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3300..A33FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3400..A34FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3500..A35FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3600..A36FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3700..A37FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3800..A38FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3900..A39FF */
+ FriBidiPropertyBlockLevel1_0100, /* A3A00..A3AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A3B00..A3BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A3C00..A3CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A3D00..A3DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A3E00..A3EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A3F00..A3FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A4000..A40FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4100..A41FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4200..A42FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4300..A43FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4400..A44FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4500..A45FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4600..A46FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4700..A47FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4800..A48FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4900..A49FF */
+ FriBidiPropertyBlockLevel1_0100, /* A4A00..A4AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A4B00..A4BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A4C00..A4CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A4D00..A4DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A4E00..A4EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A4F00..A4FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A5000..A50FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5100..A51FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5200..A52FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5300..A53FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5400..A54FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5500..A55FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5600..A56FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5700..A57FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5800..A58FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5900..A59FF */
+ FriBidiPropertyBlockLevel1_0100, /* A5A00..A5AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A5B00..A5BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A5C00..A5CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A5D00..A5DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A5E00..A5EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A5F00..A5FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A6000..A60FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6100..A61FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6200..A62FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6300..A63FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6400..A64FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6500..A65FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6600..A66FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6700..A67FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6800..A68FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6900..A69FF */
+ FriBidiPropertyBlockLevel1_0100, /* A6A00..A6AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A6B00..A6BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A6C00..A6CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A6D00..A6DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A6E00..A6EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A6F00..A6FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A7000..A70FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7100..A71FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7200..A72FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7300..A73FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7400..A74FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7500..A75FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7600..A76FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7700..A77FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7800..A78FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7900..A79FF */
+ FriBidiPropertyBlockLevel1_0100, /* A7A00..A7AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A7B00..A7BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A7C00..A7CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A7D00..A7DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A7E00..A7EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A7F00..A7FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A8000..A80FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8100..A81FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8200..A82FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8300..A83FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8400..A84FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8500..A85FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8600..A86FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8700..A87FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8800..A88FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8900..A89FF */
+ FriBidiPropertyBlockLevel1_0100, /* A8A00..A8AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A8B00..A8BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A8C00..A8CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A8D00..A8DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A8E00..A8EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A8F00..A8FFF */
+ FriBidiPropertyBlockLevel1_0100, /* A9000..A90FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9100..A91FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9200..A92FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9300..A93FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9400..A94FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9500..A95FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9600..A96FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9700..A97FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9800..A98FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9900..A99FF */
+ FriBidiPropertyBlockLevel1_0100, /* A9A00..A9AFF */
+ FriBidiPropertyBlockLevel1_0100, /* A9B00..A9BFF */
+ FriBidiPropertyBlockLevel1_0100, /* A9C00..A9CFF */
+ FriBidiPropertyBlockLevel1_0100, /* A9D00..A9DFF */
+ FriBidiPropertyBlockLevel1_0100, /* A9E00..A9EFF */
+ FriBidiPropertyBlockLevel1_0100, /* A9F00..A9FFF */
+ FriBidiPropertyBlockLevel1_0100, /* AA000..AA0FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA100..AA1FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA200..AA2FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA300..AA3FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA400..AA4FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA500..AA5FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA600..AA6FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA700..AA7FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA800..AA8FF */
+ FriBidiPropertyBlockLevel1_0100, /* AA900..AA9FF */
+ FriBidiPropertyBlockLevel1_0100, /* AAA00..AAAFF */
+ FriBidiPropertyBlockLevel1_0100, /* AAB00..AABFF */
+ FriBidiPropertyBlockLevel1_0100, /* AAC00..AACFF */
+ FriBidiPropertyBlockLevel1_0100, /* AAD00..AADFF */
+ FriBidiPropertyBlockLevel1_0100, /* AAE00..AAEFF */
+ FriBidiPropertyBlockLevel1_0100, /* AAF00..AAFFF */
+ FriBidiPropertyBlockLevel1_0100, /* AB000..AB0FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB100..AB1FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB200..AB2FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB300..AB3FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB400..AB4FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB500..AB5FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB600..AB6FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB700..AB7FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB800..AB8FF */
+ FriBidiPropertyBlockLevel1_0100, /* AB900..AB9FF */
+ FriBidiPropertyBlockLevel1_0100, /* ABA00..ABAFF */
+ FriBidiPropertyBlockLevel1_0100, /* ABB00..ABBFF */
+ FriBidiPropertyBlockLevel1_0100, /* ABC00..ABCFF */
+ FriBidiPropertyBlockLevel1_0100, /* ABD00..ABDFF */
+ FriBidiPropertyBlockLevel1_0100, /* ABE00..ABEFF */
+ FriBidiPropertyBlockLevel1_0100, /* ABF00..ABFFF */
+ FriBidiPropertyBlockLevel1_0100, /* AC000..AC0FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC100..AC1FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC200..AC2FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC300..AC3FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC400..AC4FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC500..AC5FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC600..AC6FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC700..AC7FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC800..AC8FF */
+ FriBidiPropertyBlockLevel1_0100, /* AC900..AC9FF */
+ FriBidiPropertyBlockLevel1_0100, /* ACA00..ACAFF */
+ FriBidiPropertyBlockLevel1_0100, /* ACB00..ACBFF */
+ FriBidiPropertyBlockLevel1_0100, /* ACC00..ACCFF */
+ FriBidiPropertyBlockLevel1_0100, /* ACD00..ACDFF */
+ FriBidiPropertyBlockLevel1_0100, /* ACE00..ACEFF */
+ FriBidiPropertyBlockLevel1_0100, /* ACF00..ACFFF */
+ FriBidiPropertyBlockLevel1_0100, /* AD000..AD0FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD100..AD1FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD200..AD2FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD300..AD3FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD400..AD4FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD500..AD5FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD600..AD6FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD700..AD7FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD800..AD8FF */
+ FriBidiPropertyBlockLevel1_0100, /* AD900..AD9FF */
+ FriBidiPropertyBlockLevel1_0100, /* ADA00..ADAFF */
+ FriBidiPropertyBlockLevel1_0100, /* ADB00..ADBFF */
+ FriBidiPropertyBlockLevel1_0100, /* ADC00..ADCFF */
+ FriBidiPropertyBlockLevel1_0100, /* ADD00..ADDFF */
+ FriBidiPropertyBlockLevel1_0100, /* ADE00..ADEFF */
+ FriBidiPropertyBlockLevel1_0100, /* ADF00..ADFFF */
+ FriBidiPropertyBlockLevel1_0100, /* AE000..AE0FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE100..AE1FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE200..AE2FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE300..AE3FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE400..AE4FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE500..AE5FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE600..AE6FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE700..AE7FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE800..AE8FF */
+ FriBidiPropertyBlockLevel1_0100, /* AE900..AE9FF */
+ FriBidiPropertyBlockLevel1_0100, /* AEA00..AEAFF */
+ FriBidiPropertyBlockLevel1_0100, /* AEB00..AEBFF */
+ FriBidiPropertyBlockLevel1_0100, /* AEC00..AECFF */
+ FriBidiPropertyBlockLevel1_0100, /* AED00..AEDFF */
+ FriBidiPropertyBlockLevel1_0100, /* AEE00..AEEFF */
+ FriBidiPropertyBlockLevel1_0100, /* AEF00..AEFFF */
+ FriBidiPropertyBlockLevel1_0100, /* AF000..AF0FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF100..AF1FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF200..AF2FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF300..AF3FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF400..AF4FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF500..AF5FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF600..AF6FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF700..AF7FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF800..AF8FF */
+ FriBidiPropertyBlockLevel1_0100, /* AF900..AF9FF */
+ FriBidiPropertyBlockLevel1_0100, /* AFA00..AFAFF */
+ FriBidiPropertyBlockLevel1_0100, /* AFB00..AFBFF */
+ FriBidiPropertyBlockLevel1_0100, /* AFC00..AFCFF */
+ FriBidiPropertyBlockLevel1_0100, /* AFD00..AFDFF */
+ FriBidiPropertyBlockLevel1_0100, /* AFE00..AFEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* AFF00..AFFFF */
+ FriBidiPropertyBlockLevel1_0100, /* B0000..B00FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0100..B01FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0200..B02FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0300..B03FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0400..B04FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0500..B05FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0600..B06FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0700..B07FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0800..B08FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0900..B09FF */
+ FriBidiPropertyBlockLevel1_0100, /* B0A00..B0AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B0B00..B0BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B0C00..B0CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B0D00..B0DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B0E00..B0EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B0F00..B0FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B1000..B10FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1100..B11FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1200..B12FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1300..B13FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1400..B14FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1500..B15FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1600..B16FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1700..B17FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1800..B18FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1900..B19FF */
+ FriBidiPropertyBlockLevel1_0100, /* B1A00..B1AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B1B00..B1BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B1C00..B1CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B1D00..B1DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B1E00..B1EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B1F00..B1FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B2000..B20FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2100..B21FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2200..B22FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2300..B23FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2400..B24FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2500..B25FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2600..B26FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2700..B27FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2800..B28FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2900..B29FF */
+ FriBidiPropertyBlockLevel1_0100, /* B2A00..B2AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B2B00..B2BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B2C00..B2CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B2D00..B2DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B2E00..B2EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B2F00..B2FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B3000..B30FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3100..B31FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3200..B32FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3300..B33FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3400..B34FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3500..B35FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3600..B36FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3700..B37FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3800..B38FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3900..B39FF */
+ FriBidiPropertyBlockLevel1_0100, /* B3A00..B3AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B3B00..B3BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B3C00..B3CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B3D00..B3DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B3E00..B3EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B3F00..B3FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B4000..B40FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4100..B41FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4200..B42FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4300..B43FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4400..B44FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4500..B45FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4600..B46FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4700..B47FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4800..B48FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4900..B49FF */
+ FriBidiPropertyBlockLevel1_0100, /* B4A00..B4AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B4B00..B4BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B4C00..B4CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B4D00..B4DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B4E00..B4EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B4F00..B4FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B5000..B50FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5100..B51FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5200..B52FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5300..B53FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5400..B54FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5500..B55FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5600..B56FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5700..B57FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5800..B58FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5900..B59FF */
+ FriBidiPropertyBlockLevel1_0100, /* B5A00..B5AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B5B00..B5BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B5C00..B5CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B5D00..B5DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B5E00..B5EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B5F00..B5FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B6000..B60FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6100..B61FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6200..B62FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6300..B63FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6400..B64FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6500..B65FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6600..B66FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6700..B67FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6800..B68FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6900..B69FF */
+ FriBidiPropertyBlockLevel1_0100, /* B6A00..B6AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B6B00..B6BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B6C00..B6CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B6D00..B6DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B6E00..B6EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B6F00..B6FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B7000..B70FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7100..B71FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7200..B72FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7300..B73FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7400..B74FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7500..B75FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7600..B76FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7700..B77FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7800..B78FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7900..B79FF */
+ FriBidiPropertyBlockLevel1_0100, /* B7A00..B7AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B7B00..B7BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B7C00..B7CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B7D00..B7DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B7E00..B7EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B7F00..B7FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B8000..B80FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8100..B81FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8200..B82FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8300..B83FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8400..B84FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8500..B85FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8600..B86FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8700..B87FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8800..B88FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8900..B89FF */
+ FriBidiPropertyBlockLevel1_0100, /* B8A00..B8AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B8B00..B8BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B8C00..B8CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B8D00..B8DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B8E00..B8EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B8F00..B8FFF */
+ FriBidiPropertyBlockLevel1_0100, /* B9000..B90FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9100..B91FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9200..B92FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9300..B93FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9400..B94FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9500..B95FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9600..B96FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9700..B97FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9800..B98FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9900..B99FF */
+ FriBidiPropertyBlockLevel1_0100, /* B9A00..B9AFF */
+ FriBidiPropertyBlockLevel1_0100, /* B9B00..B9BFF */
+ FriBidiPropertyBlockLevel1_0100, /* B9C00..B9CFF */
+ FriBidiPropertyBlockLevel1_0100, /* B9D00..B9DFF */
+ FriBidiPropertyBlockLevel1_0100, /* B9E00..B9EFF */
+ FriBidiPropertyBlockLevel1_0100, /* B9F00..B9FFF */
+ FriBidiPropertyBlockLevel1_0100, /* BA000..BA0FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA100..BA1FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA200..BA2FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA300..BA3FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA400..BA4FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA500..BA5FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA600..BA6FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA700..BA7FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA800..BA8FF */
+ FriBidiPropertyBlockLevel1_0100, /* BA900..BA9FF */
+ FriBidiPropertyBlockLevel1_0100, /* BAA00..BAAFF */
+ FriBidiPropertyBlockLevel1_0100, /* BAB00..BABFF */
+ FriBidiPropertyBlockLevel1_0100, /* BAC00..BACFF */
+ FriBidiPropertyBlockLevel1_0100, /* BAD00..BADFF */
+ FriBidiPropertyBlockLevel1_0100, /* BAE00..BAEFF */
+ FriBidiPropertyBlockLevel1_0100, /* BAF00..BAFFF */
+ FriBidiPropertyBlockLevel1_0100, /* BB000..BB0FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB100..BB1FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB200..BB2FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB300..BB3FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB400..BB4FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB500..BB5FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB600..BB6FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB700..BB7FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB800..BB8FF */
+ FriBidiPropertyBlockLevel1_0100, /* BB900..BB9FF */
+ FriBidiPropertyBlockLevel1_0100, /* BBA00..BBAFF */
+ FriBidiPropertyBlockLevel1_0100, /* BBB00..BBBFF */
+ FriBidiPropertyBlockLevel1_0100, /* BBC00..BBCFF */
+ FriBidiPropertyBlockLevel1_0100, /* BBD00..BBDFF */
+ FriBidiPropertyBlockLevel1_0100, /* BBE00..BBEFF */
+ FriBidiPropertyBlockLevel1_0100, /* BBF00..BBFFF */
+ FriBidiPropertyBlockLevel1_0100, /* BC000..BC0FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC100..BC1FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC200..BC2FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC300..BC3FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC400..BC4FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC500..BC5FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC600..BC6FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC700..BC7FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC800..BC8FF */
+ FriBidiPropertyBlockLevel1_0100, /* BC900..BC9FF */
+ FriBidiPropertyBlockLevel1_0100, /* BCA00..BCAFF */
+ FriBidiPropertyBlockLevel1_0100, /* BCB00..BCBFF */
+ FriBidiPropertyBlockLevel1_0100, /* BCC00..BCCFF */
+ FriBidiPropertyBlockLevel1_0100, /* BCD00..BCDFF */
+ FriBidiPropertyBlockLevel1_0100, /* BCE00..BCEFF */
+ FriBidiPropertyBlockLevel1_0100, /* BCF00..BCFFF */
+ FriBidiPropertyBlockLevel1_0100, /* BD000..BD0FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD100..BD1FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD200..BD2FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD300..BD3FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD400..BD4FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD500..BD5FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD600..BD6FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD700..BD7FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD800..BD8FF */
+ FriBidiPropertyBlockLevel1_0100, /* BD900..BD9FF */
+ FriBidiPropertyBlockLevel1_0100, /* BDA00..BDAFF */
+ FriBidiPropertyBlockLevel1_0100, /* BDB00..BDBFF */
+ FriBidiPropertyBlockLevel1_0100, /* BDC00..BDCFF */
+ FriBidiPropertyBlockLevel1_0100, /* BDD00..BDDFF */
+ FriBidiPropertyBlockLevel1_0100, /* BDE00..BDEFF */
+ FriBidiPropertyBlockLevel1_0100, /* BDF00..BDFFF */
+ FriBidiPropertyBlockLevel1_0100, /* BE000..BE0FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE100..BE1FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE200..BE2FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE300..BE3FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE400..BE4FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE500..BE5FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE600..BE6FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE700..BE7FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE800..BE8FF */
+ FriBidiPropertyBlockLevel1_0100, /* BE900..BE9FF */
+ FriBidiPropertyBlockLevel1_0100, /* BEA00..BEAFF */
+ FriBidiPropertyBlockLevel1_0100, /* BEB00..BEBFF */
+ FriBidiPropertyBlockLevel1_0100, /* BEC00..BECFF */
+ FriBidiPropertyBlockLevel1_0100, /* BED00..BEDFF */
+ FriBidiPropertyBlockLevel1_0100, /* BEE00..BEEFF */
+ FriBidiPropertyBlockLevel1_0100, /* BEF00..BEFFF */
+ FriBidiPropertyBlockLevel1_0100, /* BF000..BF0FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF100..BF1FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF200..BF2FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF300..BF3FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF400..BF4FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF500..BF5FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF600..BF6FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF700..BF7FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF800..BF8FF */
+ FriBidiPropertyBlockLevel1_0100, /* BF900..BF9FF */
+ FriBidiPropertyBlockLevel1_0100, /* BFA00..BFAFF */
+ FriBidiPropertyBlockLevel1_0100, /* BFB00..BFBFF */
+ FriBidiPropertyBlockLevel1_0100, /* BFC00..BFCFF */
+ FriBidiPropertyBlockLevel1_0100, /* BFD00..BFDFF */
+ FriBidiPropertyBlockLevel1_0100, /* BFE00..BFEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* BFF00..BFFFF */
+ FriBidiPropertyBlockLevel1_0100, /* C0000..C00FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0100..C01FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0200..C02FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0300..C03FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0400..C04FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0500..C05FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0600..C06FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0700..C07FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0800..C08FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0900..C09FF */
+ FriBidiPropertyBlockLevel1_0100, /* C0A00..C0AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C0B00..C0BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C0C00..C0CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C0D00..C0DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C0E00..C0EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C0F00..C0FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C1000..C10FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1100..C11FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1200..C12FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1300..C13FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1400..C14FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1500..C15FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1600..C16FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1700..C17FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1800..C18FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1900..C19FF */
+ FriBidiPropertyBlockLevel1_0100, /* C1A00..C1AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C1B00..C1BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C1C00..C1CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C1D00..C1DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C1E00..C1EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C1F00..C1FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C2000..C20FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2100..C21FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2200..C22FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2300..C23FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2400..C24FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2500..C25FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2600..C26FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2700..C27FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2800..C28FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2900..C29FF */
+ FriBidiPropertyBlockLevel1_0100, /* C2A00..C2AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C2B00..C2BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C2C00..C2CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C2D00..C2DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C2E00..C2EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C2F00..C2FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C3000..C30FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3100..C31FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3200..C32FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3300..C33FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3400..C34FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3500..C35FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3600..C36FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3700..C37FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3800..C38FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3900..C39FF */
+ FriBidiPropertyBlockLevel1_0100, /* C3A00..C3AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C3B00..C3BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C3C00..C3CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C3D00..C3DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C3E00..C3EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C3F00..C3FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C4000..C40FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4100..C41FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4200..C42FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4300..C43FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4400..C44FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4500..C45FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4600..C46FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4700..C47FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4800..C48FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4900..C49FF */
+ FriBidiPropertyBlockLevel1_0100, /* C4A00..C4AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C4B00..C4BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C4C00..C4CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C4D00..C4DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C4E00..C4EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C4F00..C4FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C5000..C50FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5100..C51FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5200..C52FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5300..C53FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5400..C54FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5500..C55FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5600..C56FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5700..C57FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5800..C58FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5900..C59FF */
+ FriBidiPropertyBlockLevel1_0100, /* C5A00..C5AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C5B00..C5BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C5C00..C5CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C5D00..C5DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C5E00..C5EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C5F00..C5FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C6000..C60FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6100..C61FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6200..C62FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6300..C63FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6400..C64FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6500..C65FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6600..C66FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6700..C67FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6800..C68FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6900..C69FF */
+ FriBidiPropertyBlockLevel1_0100, /* C6A00..C6AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C6B00..C6BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C6C00..C6CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C6D00..C6DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C6E00..C6EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C6F00..C6FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C7000..C70FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7100..C71FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7200..C72FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7300..C73FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7400..C74FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7500..C75FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7600..C76FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7700..C77FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7800..C78FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7900..C79FF */
+ FriBidiPropertyBlockLevel1_0100, /* C7A00..C7AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C7B00..C7BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C7C00..C7CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C7D00..C7DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C7E00..C7EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C7F00..C7FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C8000..C80FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8100..C81FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8200..C82FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8300..C83FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8400..C84FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8500..C85FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8600..C86FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8700..C87FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8800..C88FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8900..C89FF */
+ FriBidiPropertyBlockLevel1_0100, /* C8A00..C8AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C8B00..C8BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C8C00..C8CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C8D00..C8DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C8E00..C8EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C8F00..C8FFF */
+ FriBidiPropertyBlockLevel1_0100, /* C9000..C90FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9100..C91FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9200..C92FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9300..C93FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9400..C94FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9500..C95FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9600..C96FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9700..C97FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9800..C98FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9900..C99FF */
+ FriBidiPropertyBlockLevel1_0100, /* C9A00..C9AFF */
+ FriBidiPropertyBlockLevel1_0100, /* C9B00..C9BFF */
+ FriBidiPropertyBlockLevel1_0100, /* C9C00..C9CFF */
+ FriBidiPropertyBlockLevel1_0100, /* C9D00..C9DFF */
+ FriBidiPropertyBlockLevel1_0100, /* C9E00..C9EFF */
+ FriBidiPropertyBlockLevel1_0100, /* C9F00..C9FFF */
+ FriBidiPropertyBlockLevel1_0100, /* CA000..CA0FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA100..CA1FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA200..CA2FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA300..CA3FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA400..CA4FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA500..CA5FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA600..CA6FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA700..CA7FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA800..CA8FF */
+ FriBidiPropertyBlockLevel1_0100, /* CA900..CA9FF */
+ FriBidiPropertyBlockLevel1_0100, /* CAA00..CAAFF */
+ FriBidiPropertyBlockLevel1_0100, /* CAB00..CABFF */
+ FriBidiPropertyBlockLevel1_0100, /* CAC00..CACFF */
+ FriBidiPropertyBlockLevel1_0100, /* CAD00..CADFF */
+ FriBidiPropertyBlockLevel1_0100, /* CAE00..CAEFF */
+ FriBidiPropertyBlockLevel1_0100, /* CAF00..CAFFF */
+ FriBidiPropertyBlockLevel1_0100, /* CB000..CB0FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB100..CB1FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB200..CB2FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB300..CB3FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB400..CB4FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB500..CB5FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB600..CB6FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB700..CB7FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB800..CB8FF */
+ FriBidiPropertyBlockLevel1_0100, /* CB900..CB9FF */
+ FriBidiPropertyBlockLevel1_0100, /* CBA00..CBAFF */
+ FriBidiPropertyBlockLevel1_0100, /* CBB00..CBBFF */
+ FriBidiPropertyBlockLevel1_0100, /* CBC00..CBCFF */
+ FriBidiPropertyBlockLevel1_0100, /* CBD00..CBDFF */
+ FriBidiPropertyBlockLevel1_0100, /* CBE00..CBEFF */
+ FriBidiPropertyBlockLevel1_0100, /* CBF00..CBFFF */
+ FriBidiPropertyBlockLevel1_0100, /* CC000..CC0FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC100..CC1FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC200..CC2FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC300..CC3FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC400..CC4FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC500..CC5FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC600..CC6FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC700..CC7FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC800..CC8FF */
+ FriBidiPropertyBlockLevel1_0100, /* CC900..CC9FF */
+ FriBidiPropertyBlockLevel1_0100, /* CCA00..CCAFF */
+ FriBidiPropertyBlockLevel1_0100, /* CCB00..CCBFF */
+ FriBidiPropertyBlockLevel1_0100, /* CCC00..CCCFF */
+ FriBidiPropertyBlockLevel1_0100, /* CCD00..CCDFF */
+ FriBidiPropertyBlockLevel1_0100, /* CCE00..CCEFF */
+ FriBidiPropertyBlockLevel1_0100, /* CCF00..CCFFF */
+ FriBidiPropertyBlockLevel1_0100, /* CD000..CD0FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD100..CD1FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD200..CD2FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD300..CD3FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD400..CD4FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD500..CD5FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD600..CD6FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD700..CD7FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD800..CD8FF */
+ FriBidiPropertyBlockLevel1_0100, /* CD900..CD9FF */
+ FriBidiPropertyBlockLevel1_0100, /* CDA00..CDAFF */
+ FriBidiPropertyBlockLevel1_0100, /* CDB00..CDBFF */
+ FriBidiPropertyBlockLevel1_0100, /* CDC00..CDCFF */
+ FriBidiPropertyBlockLevel1_0100, /* CDD00..CDDFF */
+ FriBidiPropertyBlockLevel1_0100, /* CDE00..CDEFF */
+ FriBidiPropertyBlockLevel1_0100, /* CDF00..CDFFF */
+ FriBidiPropertyBlockLevel1_0100, /* CE000..CE0FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE100..CE1FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE200..CE2FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE300..CE3FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE400..CE4FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE500..CE5FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE600..CE6FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE700..CE7FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE800..CE8FF */
+ FriBidiPropertyBlockLevel1_0100, /* CE900..CE9FF */
+ FriBidiPropertyBlockLevel1_0100, /* CEA00..CEAFF */
+ FriBidiPropertyBlockLevel1_0100, /* CEB00..CEBFF */
+ FriBidiPropertyBlockLevel1_0100, /* CEC00..CECFF */
+ FriBidiPropertyBlockLevel1_0100, /* CED00..CEDFF */
+ FriBidiPropertyBlockLevel1_0100, /* CEE00..CEEFF */
+ FriBidiPropertyBlockLevel1_0100, /* CEF00..CEFFF */
+ FriBidiPropertyBlockLevel1_0100, /* CF000..CF0FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF100..CF1FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF200..CF2FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF300..CF3FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF400..CF4FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF500..CF5FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF600..CF6FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF700..CF7FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF800..CF8FF */
+ FriBidiPropertyBlockLevel1_0100, /* CF900..CF9FF */
+ FriBidiPropertyBlockLevel1_0100, /* CFA00..CFAFF */
+ FriBidiPropertyBlockLevel1_0100, /* CFB00..CFBFF */
+ FriBidiPropertyBlockLevel1_0100, /* CFC00..CFCFF */
+ FriBidiPropertyBlockLevel1_0100, /* CFD00..CFDFF */
+ FriBidiPropertyBlockLevel1_0100, /* CFE00..CFEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* CFF00..CFFFF */
+ FriBidiPropertyBlockLevel1_0100, /* D0000..D00FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0100..D01FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0200..D02FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0300..D03FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0400..D04FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0500..D05FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0600..D06FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0700..D07FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0800..D08FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0900..D09FF */
+ FriBidiPropertyBlockLevel1_0100, /* D0A00..D0AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D0B00..D0BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D0C00..D0CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D0D00..D0DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D0E00..D0EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D0F00..D0FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D1000..D10FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1100..D11FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1200..D12FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1300..D13FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1400..D14FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1500..D15FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1600..D16FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1700..D17FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1800..D18FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1900..D19FF */
+ FriBidiPropertyBlockLevel1_0100, /* D1A00..D1AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D1B00..D1BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D1C00..D1CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D1D00..D1DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D1E00..D1EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D1F00..D1FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D2000..D20FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2100..D21FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2200..D22FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2300..D23FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2400..D24FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2500..D25FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2600..D26FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2700..D27FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2800..D28FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2900..D29FF */
+ FriBidiPropertyBlockLevel1_0100, /* D2A00..D2AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D2B00..D2BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D2C00..D2CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D2D00..D2DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D2E00..D2EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D2F00..D2FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D3000..D30FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3100..D31FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3200..D32FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3300..D33FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3400..D34FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3500..D35FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3600..D36FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3700..D37FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3800..D38FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3900..D39FF */
+ FriBidiPropertyBlockLevel1_0100, /* D3A00..D3AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D3B00..D3BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D3C00..D3CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D3D00..D3DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D3E00..D3EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D3F00..D3FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D4000..D40FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4100..D41FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4200..D42FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4300..D43FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4400..D44FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4500..D45FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4600..D46FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4700..D47FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4800..D48FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4900..D49FF */
+ FriBidiPropertyBlockLevel1_0100, /* D4A00..D4AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D4B00..D4BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D4C00..D4CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D4D00..D4DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D4E00..D4EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D4F00..D4FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D5000..D50FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5100..D51FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5200..D52FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5300..D53FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5400..D54FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5500..D55FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5600..D56FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5700..D57FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5800..D58FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5900..D59FF */
+ FriBidiPropertyBlockLevel1_0100, /* D5A00..D5AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D5B00..D5BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D5C00..D5CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D5D00..D5DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D5E00..D5EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D5F00..D5FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D6000..D60FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6100..D61FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6200..D62FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6300..D63FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6400..D64FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6500..D65FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6600..D66FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6700..D67FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6800..D68FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6900..D69FF */
+ FriBidiPropertyBlockLevel1_0100, /* D6A00..D6AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D6B00..D6BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D6C00..D6CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D6D00..D6DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D6E00..D6EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D6F00..D6FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D7000..D70FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7100..D71FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7200..D72FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7300..D73FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7400..D74FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7500..D75FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7600..D76FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7700..D77FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7800..D78FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7900..D79FF */
+ FriBidiPropertyBlockLevel1_0100, /* D7A00..D7AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D7B00..D7BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D7C00..D7CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D7D00..D7DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D7E00..D7EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D7F00..D7FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D8000..D80FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8100..D81FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8200..D82FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8300..D83FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8400..D84FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8500..D85FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8600..D86FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8700..D87FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8800..D88FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8900..D89FF */
+ FriBidiPropertyBlockLevel1_0100, /* D8A00..D8AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D8B00..D8BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D8C00..D8CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D8D00..D8DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D8E00..D8EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D8F00..D8FFF */
+ FriBidiPropertyBlockLevel1_0100, /* D9000..D90FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9100..D91FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9200..D92FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9300..D93FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9400..D94FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9500..D95FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9600..D96FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9700..D97FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9800..D98FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9900..D99FF */
+ FriBidiPropertyBlockLevel1_0100, /* D9A00..D9AFF */
+ FriBidiPropertyBlockLevel1_0100, /* D9B00..D9BFF */
+ FriBidiPropertyBlockLevel1_0100, /* D9C00..D9CFF */
+ FriBidiPropertyBlockLevel1_0100, /* D9D00..D9DFF */
+ FriBidiPropertyBlockLevel1_0100, /* D9E00..D9EFF */
+ FriBidiPropertyBlockLevel1_0100, /* D9F00..D9FFF */
+ FriBidiPropertyBlockLevel1_0100, /* DA000..DA0FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA100..DA1FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA200..DA2FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA300..DA3FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA400..DA4FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA500..DA5FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA600..DA6FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA700..DA7FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA800..DA8FF */
+ FriBidiPropertyBlockLevel1_0100, /* DA900..DA9FF */
+ FriBidiPropertyBlockLevel1_0100, /* DAA00..DAAFF */
+ FriBidiPropertyBlockLevel1_0100, /* DAB00..DABFF */
+ FriBidiPropertyBlockLevel1_0100, /* DAC00..DACFF */
+ FriBidiPropertyBlockLevel1_0100, /* DAD00..DADFF */
+ FriBidiPropertyBlockLevel1_0100, /* DAE00..DAEFF */
+ FriBidiPropertyBlockLevel1_0100, /* DAF00..DAFFF */
+ FriBidiPropertyBlockLevel1_0100, /* DB000..DB0FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB100..DB1FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB200..DB2FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB300..DB3FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB400..DB4FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB500..DB5FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB600..DB6FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB700..DB7FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB800..DB8FF */
+ FriBidiPropertyBlockLevel1_0100, /* DB900..DB9FF */
+ FriBidiPropertyBlockLevel1_0100, /* DBA00..DBAFF */
+ FriBidiPropertyBlockLevel1_0100, /* DBB00..DBBFF */
+ FriBidiPropertyBlockLevel1_0100, /* DBC00..DBCFF */
+ FriBidiPropertyBlockLevel1_0100, /* DBD00..DBDFF */
+ FriBidiPropertyBlockLevel1_0100, /* DBE00..DBEFF */
+ FriBidiPropertyBlockLevel1_0100, /* DBF00..DBFFF */
+ FriBidiPropertyBlockLevel1_0100, /* DC000..DC0FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC100..DC1FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC200..DC2FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC300..DC3FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC400..DC4FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC500..DC5FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC600..DC6FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC700..DC7FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC800..DC8FF */
+ FriBidiPropertyBlockLevel1_0100, /* DC900..DC9FF */
+ FriBidiPropertyBlockLevel1_0100, /* DCA00..DCAFF */
+ FriBidiPropertyBlockLevel1_0100, /* DCB00..DCBFF */
+ FriBidiPropertyBlockLevel1_0100, /* DCC00..DCCFF */
+ FriBidiPropertyBlockLevel1_0100, /* DCD00..DCDFF */
+ FriBidiPropertyBlockLevel1_0100, /* DCE00..DCEFF */
+ FriBidiPropertyBlockLevel1_0100, /* DCF00..DCFFF */
+ FriBidiPropertyBlockLevel1_0100, /* DD000..DD0FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD100..DD1FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD200..DD2FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD300..DD3FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD400..DD4FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD500..DD5FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD600..DD6FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD700..DD7FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD800..DD8FF */
+ FriBidiPropertyBlockLevel1_0100, /* DD900..DD9FF */
+ FriBidiPropertyBlockLevel1_0100, /* DDA00..DDAFF */
+ FriBidiPropertyBlockLevel1_0100, /* DDB00..DDBFF */
+ FriBidiPropertyBlockLevel1_0100, /* DDC00..DDCFF */
+ FriBidiPropertyBlockLevel1_0100, /* DDD00..DDDFF */
+ FriBidiPropertyBlockLevel1_0100, /* DDE00..DDEFF */
+ FriBidiPropertyBlockLevel1_0100, /* DDF00..DDFFF */
+ FriBidiPropertyBlockLevel1_0100, /* DE000..DE0FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE100..DE1FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE200..DE2FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE300..DE3FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE400..DE4FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE500..DE5FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE600..DE6FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE700..DE7FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE800..DE8FF */
+ FriBidiPropertyBlockLevel1_0100, /* DE900..DE9FF */
+ FriBidiPropertyBlockLevel1_0100, /* DEA00..DEAFF */
+ FriBidiPropertyBlockLevel1_0100, /* DEB00..DEBFF */
+ FriBidiPropertyBlockLevel1_0100, /* DEC00..DECFF */
+ FriBidiPropertyBlockLevel1_0100, /* DED00..DEDFF */
+ FriBidiPropertyBlockLevel1_0100, /* DEE00..DEEFF */
+ FriBidiPropertyBlockLevel1_0100, /* DEF00..DEFFF */
+ FriBidiPropertyBlockLevel1_0100, /* DF000..DF0FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF100..DF1FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF200..DF2FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF300..DF3FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF400..DF4FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF500..DF5FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF600..DF6FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF700..DF7FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF800..DF8FF */
+ FriBidiPropertyBlockLevel1_0100, /* DF900..DF9FF */
+ FriBidiPropertyBlockLevel1_0100, /* DFA00..DFAFF */
+ FriBidiPropertyBlockLevel1_0100, /* DFB00..DFBFF */
+ FriBidiPropertyBlockLevel1_0100, /* DFC00..DFCFF */
+ FriBidiPropertyBlockLevel1_0100, /* DFD00..DFDFF */
+ FriBidiPropertyBlockLevel1_0100, /* DFE00..DFEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* DFF00..DFFFF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0000..E00FF */
+ FriBidiPropertyBlockLevel1_E0100, /* E0100..E01FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0200..E02FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0300..E03FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0400..E04FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0500..E05FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0600..E06FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0700..E07FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0800..E08FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0900..E09FF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0A00..E0AFF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0B00..E0BFF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0C00..E0CFF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0D00..E0DFF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0E00..E0EFF */
+ FriBidiPropertyBlockLevel1_E0000, /* E0F00..E0FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E1000..E10FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1100..E11FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1200..E12FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1300..E13FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1400..E14FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1500..E15FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1600..E16FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1700..E17FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1800..E18FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1900..E19FF */
+ FriBidiPropertyBlockLevel1_0100, /* E1A00..E1AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E1B00..E1BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E1C00..E1CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E1D00..E1DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E1E00..E1EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E1F00..E1FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E2000..E20FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2100..E21FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2200..E22FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2300..E23FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2400..E24FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2500..E25FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2600..E26FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2700..E27FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2800..E28FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2900..E29FF */
+ FriBidiPropertyBlockLevel1_0100, /* E2A00..E2AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E2B00..E2BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E2C00..E2CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E2D00..E2DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E2E00..E2EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E2F00..E2FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E3000..E30FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3100..E31FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3200..E32FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3300..E33FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3400..E34FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3500..E35FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3600..E36FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3700..E37FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3800..E38FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3900..E39FF */
+ FriBidiPropertyBlockLevel1_0100, /* E3A00..E3AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E3B00..E3BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E3C00..E3CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E3D00..E3DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E3E00..E3EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E3F00..E3FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E4000..E40FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4100..E41FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4200..E42FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4300..E43FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4400..E44FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4500..E45FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4600..E46FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4700..E47FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4800..E48FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4900..E49FF */
+ FriBidiPropertyBlockLevel1_0100, /* E4A00..E4AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E4B00..E4BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E4C00..E4CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E4D00..E4DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E4E00..E4EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E4F00..E4FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E5000..E50FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5100..E51FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5200..E52FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5300..E53FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5400..E54FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5500..E55FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5600..E56FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5700..E57FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5800..E58FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5900..E59FF */
+ FriBidiPropertyBlockLevel1_0100, /* E5A00..E5AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E5B00..E5BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E5C00..E5CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E5D00..E5DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E5E00..E5EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E5F00..E5FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E6000..E60FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6100..E61FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6200..E62FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6300..E63FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6400..E64FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6500..E65FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6600..E66FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6700..E67FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6800..E68FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6900..E69FF */
+ FriBidiPropertyBlockLevel1_0100, /* E6A00..E6AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E6B00..E6BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E6C00..E6CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E6D00..E6DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E6E00..E6EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E6F00..E6FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E7000..E70FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7100..E71FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7200..E72FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7300..E73FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7400..E74FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7500..E75FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7600..E76FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7700..E77FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7800..E78FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7900..E79FF */
+ FriBidiPropertyBlockLevel1_0100, /* E7A00..E7AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E7B00..E7BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E7C00..E7CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E7D00..E7DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E7E00..E7EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E7F00..E7FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E8000..E80FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8100..E81FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8200..E82FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8300..E83FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8400..E84FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8500..E85FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8600..E86FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8700..E87FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8800..E88FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8900..E89FF */
+ FriBidiPropertyBlockLevel1_0100, /* E8A00..E8AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E8B00..E8BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E8C00..E8CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E8D00..E8DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E8E00..E8EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E8F00..E8FFF */
+ FriBidiPropertyBlockLevel1_0100, /* E9000..E90FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9100..E91FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9200..E92FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9300..E93FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9400..E94FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9500..E95FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9600..E96FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9700..E97FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9800..E98FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9900..E99FF */
+ FriBidiPropertyBlockLevel1_0100, /* E9A00..E9AFF */
+ FriBidiPropertyBlockLevel1_0100, /* E9B00..E9BFF */
+ FriBidiPropertyBlockLevel1_0100, /* E9C00..E9CFF */
+ FriBidiPropertyBlockLevel1_0100, /* E9D00..E9DFF */
+ FriBidiPropertyBlockLevel1_0100, /* E9E00..E9EFF */
+ FriBidiPropertyBlockLevel1_0100, /* E9F00..E9FFF */
+ FriBidiPropertyBlockLevel1_0100, /* EA000..EA0FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA100..EA1FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA200..EA2FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA300..EA3FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA400..EA4FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA500..EA5FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA600..EA6FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA700..EA7FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA800..EA8FF */
+ FriBidiPropertyBlockLevel1_0100, /* EA900..EA9FF */
+ FriBidiPropertyBlockLevel1_0100, /* EAA00..EAAFF */
+ FriBidiPropertyBlockLevel1_0100, /* EAB00..EABFF */
+ FriBidiPropertyBlockLevel1_0100, /* EAC00..EACFF */
+ FriBidiPropertyBlockLevel1_0100, /* EAD00..EADFF */
+ FriBidiPropertyBlockLevel1_0100, /* EAE00..EAEFF */
+ FriBidiPropertyBlockLevel1_0100, /* EAF00..EAFFF */
+ FriBidiPropertyBlockLevel1_0100, /* EB000..EB0FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB100..EB1FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB200..EB2FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB300..EB3FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB400..EB4FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB500..EB5FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB600..EB6FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB700..EB7FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB800..EB8FF */
+ FriBidiPropertyBlockLevel1_0100, /* EB900..EB9FF */
+ FriBidiPropertyBlockLevel1_0100, /* EBA00..EBAFF */
+ FriBidiPropertyBlockLevel1_0100, /* EBB00..EBBFF */
+ FriBidiPropertyBlockLevel1_0100, /* EBC00..EBCFF */
+ FriBidiPropertyBlockLevel1_0100, /* EBD00..EBDFF */
+ FriBidiPropertyBlockLevel1_0100, /* EBE00..EBEFF */
+ FriBidiPropertyBlockLevel1_0100, /* EBF00..EBFFF */
+ FriBidiPropertyBlockLevel1_0100, /* EC000..EC0FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC100..EC1FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC200..EC2FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC300..EC3FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC400..EC4FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC500..EC5FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC600..EC6FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC700..EC7FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC800..EC8FF */
+ FriBidiPropertyBlockLevel1_0100, /* EC900..EC9FF */
+ FriBidiPropertyBlockLevel1_0100, /* ECA00..ECAFF */
+ FriBidiPropertyBlockLevel1_0100, /* ECB00..ECBFF */
+ FriBidiPropertyBlockLevel1_0100, /* ECC00..ECCFF */
+ FriBidiPropertyBlockLevel1_0100, /* ECD00..ECDFF */
+ FriBidiPropertyBlockLevel1_0100, /* ECE00..ECEFF */
+ FriBidiPropertyBlockLevel1_0100, /* ECF00..ECFFF */
+ FriBidiPropertyBlockLevel1_0100, /* ED000..ED0FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED100..ED1FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED200..ED2FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED300..ED3FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED400..ED4FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED500..ED5FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED600..ED6FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED700..ED7FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED800..ED8FF */
+ FriBidiPropertyBlockLevel1_0100, /* ED900..ED9FF */
+ FriBidiPropertyBlockLevel1_0100, /* EDA00..EDAFF */
+ FriBidiPropertyBlockLevel1_0100, /* EDB00..EDBFF */
+ FriBidiPropertyBlockLevel1_0100, /* EDC00..EDCFF */
+ FriBidiPropertyBlockLevel1_0100, /* EDD00..EDDFF */
+ FriBidiPropertyBlockLevel1_0100, /* EDE00..EDEFF */
+ FriBidiPropertyBlockLevel1_0100, /* EDF00..EDFFF */
+ FriBidiPropertyBlockLevel1_0100, /* EE000..EE0FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE100..EE1FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE200..EE2FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE300..EE3FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE400..EE4FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE500..EE5FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE600..EE6FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE700..EE7FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE800..EE8FF */
+ FriBidiPropertyBlockLevel1_0100, /* EE900..EE9FF */
+ FriBidiPropertyBlockLevel1_0100, /* EEA00..EEAFF */
+ FriBidiPropertyBlockLevel1_0100, /* EEB00..EEBFF */
+ FriBidiPropertyBlockLevel1_0100, /* EEC00..EECFF */
+ FriBidiPropertyBlockLevel1_0100, /* EED00..EEDFF */
+ FriBidiPropertyBlockLevel1_0100, /* EEE00..EEEFF */
+ FriBidiPropertyBlockLevel1_0100, /* EEF00..EEFFF */
+ FriBidiPropertyBlockLevel1_0100, /* EF000..EF0FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF100..EF1FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF200..EF2FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF300..EF3FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF400..EF4FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF500..EF5FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF600..EF6FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF700..EF7FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF800..EF8FF */
+ FriBidiPropertyBlockLevel1_0100, /* EF900..EF9FF */
+ FriBidiPropertyBlockLevel1_0100, /* EFA00..EFAFF */
+ FriBidiPropertyBlockLevel1_0100, /* EFB00..EFBFF */
+ FriBidiPropertyBlockLevel1_0100, /* EFC00..EFCFF */
+ FriBidiPropertyBlockLevel1_0100, /* EFD00..EFDFF */
+ FriBidiPropertyBlockLevel1_0100, /* EFE00..EFEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* EFF00..EFFFF */
+ FriBidiPropertyBlockLevel1_0100, /* F0000..F00FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0100..F01FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0200..F02FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0300..F03FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0400..F04FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0500..F05FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0600..F06FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0700..F07FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0800..F08FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0900..F09FF */
+ FriBidiPropertyBlockLevel1_0100, /* F0A00..F0AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F0B00..F0BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F0C00..F0CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F0D00..F0DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F0E00..F0EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F0F00..F0FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F1000..F10FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1100..F11FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1200..F12FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1300..F13FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1400..F14FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1500..F15FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1600..F16FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1700..F17FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1800..F18FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1900..F19FF */
+ FriBidiPropertyBlockLevel1_0100, /* F1A00..F1AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F1B00..F1BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F1C00..F1CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F1D00..F1DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F1E00..F1EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F1F00..F1FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F2000..F20FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2100..F21FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2200..F22FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2300..F23FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2400..F24FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2500..F25FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2600..F26FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2700..F27FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2800..F28FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2900..F29FF */
+ FriBidiPropertyBlockLevel1_0100, /* F2A00..F2AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F2B00..F2BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F2C00..F2CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F2D00..F2DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F2E00..F2EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F2F00..F2FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F3000..F30FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3100..F31FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3200..F32FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3300..F33FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3400..F34FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3500..F35FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3600..F36FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3700..F37FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3800..F38FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3900..F39FF */
+ FriBidiPropertyBlockLevel1_0100, /* F3A00..F3AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F3B00..F3BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F3C00..F3CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F3D00..F3DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F3E00..F3EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F3F00..F3FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F4000..F40FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4100..F41FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4200..F42FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4300..F43FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4400..F44FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4500..F45FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4600..F46FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4700..F47FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4800..F48FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4900..F49FF */
+ FriBidiPropertyBlockLevel1_0100, /* F4A00..F4AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F4B00..F4BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F4C00..F4CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F4D00..F4DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F4E00..F4EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F4F00..F4FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F5000..F50FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5100..F51FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5200..F52FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5300..F53FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5400..F54FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5500..F55FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5600..F56FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5700..F57FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5800..F58FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5900..F59FF */
+ FriBidiPropertyBlockLevel1_0100, /* F5A00..F5AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F5B00..F5BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F5C00..F5CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F5D00..F5DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F5E00..F5EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F5F00..F5FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F6000..F60FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6100..F61FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6200..F62FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6300..F63FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6400..F64FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6500..F65FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6600..F66FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6700..F67FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6800..F68FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6900..F69FF */
+ FriBidiPropertyBlockLevel1_0100, /* F6A00..F6AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F6B00..F6BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F6C00..F6CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F6D00..F6DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F6E00..F6EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F6F00..F6FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F7000..F70FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7100..F71FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7200..F72FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7300..F73FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7400..F74FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7500..F75FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7600..F76FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7700..F77FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7800..F78FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7900..F79FF */
+ FriBidiPropertyBlockLevel1_0100, /* F7A00..F7AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F7B00..F7BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F7C00..F7CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F7D00..F7DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F7E00..F7EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F7F00..F7FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F8000..F80FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8100..F81FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8200..F82FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8300..F83FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8400..F84FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8500..F85FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8600..F86FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8700..F87FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8800..F88FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8900..F89FF */
+ FriBidiPropertyBlockLevel1_0100, /* F8A00..F8AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F8B00..F8BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F8C00..F8CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F8D00..F8DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F8E00..F8EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F8F00..F8FFF */
+ FriBidiPropertyBlockLevel1_0100, /* F9000..F90FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9100..F91FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9200..F92FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9300..F93FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9400..F94FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9500..F95FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9600..F96FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9700..F97FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9800..F98FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9900..F99FF */
+ FriBidiPropertyBlockLevel1_0100, /* F9A00..F9AFF */
+ FriBidiPropertyBlockLevel1_0100, /* F9B00..F9BFF */
+ FriBidiPropertyBlockLevel1_0100, /* F9C00..F9CFF */
+ FriBidiPropertyBlockLevel1_0100, /* F9D00..F9DFF */
+ FriBidiPropertyBlockLevel1_0100, /* F9E00..F9EFF */
+ FriBidiPropertyBlockLevel1_0100, /* F9F00..F9FFF */
+ FriBidiPropertyBlockLevel1_0100, /* FA000..FA0FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA100..FA1FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA200..FA2FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA300..FA3FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA400..FA4FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA500..FA5FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA600..FA6FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA700..FA7FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA800..FA8FF */
+ FriBidiPropertyBlockLevel1_0100, /* FA900..FA9FF */
+ FriBidiPropertyBlockLevel1_0100, /* FAA00..FAAFF */
+ FriBidiPropertyBlockLevel1_0100, /* FAB00..FABFF */
+ FriBidiPropertyBlockLevel1_0100, /* FAC00..FACFF */
+ FriBidiPropertyBlockLevel1_0100, /* FAD00..FADFF */
+ FriBidiPropertyBlockLevel1_0100, /* FAE00..FAEFF */
+ FriBidiPropertyBlockLevel1_0100, /* FAF00..FAFFF */
+ FriBidiPropertyBlockLevel1_0100, /* FB000..FB0FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB100..FB1FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB200..FB2FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB300..FB3FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB400..FB4FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB500..FB5FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB600..FB6FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB700..FB7FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB800..FB8FF */
+ FriBidiPropertyBlockLevel1_0100, /* FB900..FB9FF */
+ FriBidiPropertyBlockLevel1_0100, /* FBA00..FBAFF */
+ FriBidiPropertyBlockLevel1_0100, /* FBB00..FBBFF */
+ FriBidiPropertyBlockLevel1_0100, /* FBC00..FBCFF */
+ FriBidiPropertyBlockLevel1_0100, /* FBD00..FBDFF */
+ FriBidiPropertyBlockLevel1_0100, /* FBE00..FBEFF */
+ FriBidiPropertyBlockLevel1_0100, /* FBF00..FBFFF */
+ FriBidiPropertyBlockLevel1_0100, /* FC000..FC0FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC100..FC1FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC200..FC2FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC300..FC3FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC400..FC4FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC500..FC5FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC600..FC6FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC700..FC7FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC800..FC8FF */
+ FriBidiPropertyBlockLevel1_0100, /* FC900..FC9FF */
+ FriBidiPropertyBlockLevel1_0100, /* FCA00..FCAFF */
+ FriBidiPropertyBlockLevel1_0100, /* FCB00..FCBFF */
+ FriBidiPropertyBlockLevel1_0100, /* FCC00..FCCFF */
+ FriBidiPropertyBlockLevel1_0100, /* FCD00..FCDFF */
+ FriBidiPropertyBlockLevel1_0100, /* FCE00..FCEFF */
+ FriBidiPropertyBlockLevel1_0100, /* FCF00..FCFFF */
+ FriBidiPropertyBlockLevel1_0100, /* FD000..FD0FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD100..FD1FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD200..FD2FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD300..FD3FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD400..FD4FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD500..FD5FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD600..FD6FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD700..FD7FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD800..FD8FF */
+ FriBidiPropertyBlockLevel1_0100, /* FD900..FD9FF */
+ FriBidiPropertyBlockLevel1_0100, /* FDA00..FDAFF */
+ FriBidiPropertyBlockLevel1_0100, /* FDB00..FDBFF */
+ FriBidiPropertyBlockLevel1_0100, /* FDC00..FDCFF */
+ FriBidiPropertyBlockLevel1_0100, /* FDD00..FDDFF */
+ FriBidiPropertyBlockLevel1_0100, /* FDE00..FDEFF */
+ FriBidiPropertyBlockLevel1_0100, /* FDF00..FDFFF */
+ FriBidiPropertyBlockLevel1_0100, /* FE000..FE0FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE100..FE1FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE200..FE2FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE300..FE3FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE400..FE4FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE500..FE5FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE600..FE6FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE700..FE7FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE800..FE8FF */
+ FriBidiPropertyBlockLevel1_0100, /* FE900..FE9FF */
+ FriBidiPropertyBlockLevel1_0100, /* FEA00..FEAFF */
+ FriBidiPropertyBlockLevel1_0100, /* FEB00..FEBFF */
+ FriBidiPropertyBlockLevel1_0100, /* FEC00..FECFF */
+ FriBidiPropertyBlockLevel1_0100, /* FED00..FEDFF */
+ FriBidiPropertyBlockLevel1_0100, /* FEE00..FEEFF */
+ FriBidiPropertyBlockLevel1_0100, /* FEF00..FEFFF */
+ FriBidiPropertyBlockLevel1_0100, /* FF000..FF0FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF100..FF1FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF200..FF2FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF300..FF3FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF400..FF4FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF500..FF5FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF600..FF6FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF700..FF7FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF800..FF8FF */
+ FriBidiPropertyBlockLevel1_0100, /* FF900..FF9FF */
+ FriBidiPropertyBlockLevel1_0100, /* FFA00..FFAFF */
+ FriBidiPropertyBlockLevel1_0100, /* FFB00..FFBFF */
+ FriBidiPropertyBlockLevel1_0100, /* FFC00..FFCFF */
+ FriBidiPropertyBlockLevel1_0100, /* FFD00..FFDFF */
+ FriBidiPropertyBlockLevel1_0100, /* FFE00..FFEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* FFF00..FFFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 100000..1000FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100100..1001FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100200..1002FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100300..1003FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100400..1004FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100500..1005FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100600..1006FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100700..1007FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100800..1008FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100900..1009FF */
+ FriBidiPropertyBlockLevel1_0100, /* 100A00..100AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 100B00..100BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 100C00..100CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 100D00..100DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 100E00..100EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 100F00..100FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 101000..1010FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101100..1011FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101200..1012FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101300..1013FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101400..1014FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101500..1015FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101600..1016FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101700..1017FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101800..1018FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101900..1019FF */
+ FriBidiPropertyBlockLevel1_0100, /* 101A00..101AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 101B00..101BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 101C00..101CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 101D00..101DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 101E00..101EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 101F00..101FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 102000..1020FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102100..1021FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102200..1022FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102300..1023FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102400..1024FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102500..1025FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102600..1026FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102700..1027FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102800..1028FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102900..1029FF */
+ FriBidiPropertyBlockLevel1_0100, /* 102A00..102AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 102B00..102BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 102C00..102CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 102D00..102DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 102E00..102EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 102F00..102FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 103000..1030FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103100..1031FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103200..1032FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103300..1033FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103400..1034FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103500..1035FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103600..1036FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103700..1037FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103800..1038FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103900..1039FF */
+ FriBidiPropertyBlockLevel1_0100, /* 103A00..103AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 103B00..103BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 103C00..103CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 103D00..103DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 103E00..103EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 103F00..103FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 104000..1040FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104100..1041FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104200..1042FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104300..1043FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104400..1044FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104500..1045FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104600..1046FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104700..1047FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104800..1048FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104900..1049FF */
+ FriBidiPropertyBlockLevel1_0100, /* 104A00..104AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 104B00..104BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 104C00..104CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 104D00..104DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 104E00..104EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 104F00..104FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 105000..1050FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105100..1051FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105200..1052FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105300..1053FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105400..1054FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105500..1055FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105600..1056FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105700..1057FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105800..1058FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105900..1059FF */
+ FriBidiPropertyBlockLevel1_0100, /* 105A00..105AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 105B00..105BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 105C00..105CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 105D00..105DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 105E00..105EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 105F00..105FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 106000..1060FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106100..1061FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106200..1062FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106300..1063FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106400..1064FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106500..1065FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106600..1066FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106700..1067FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106800..1068FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106900..1069FF */
+ FriBidiPropertyBlockLevel1_0100, /* 106A00..106AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 106B00..106BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 106C00..106CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 106D00..106DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 106E00..106EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 106F00..106FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 107000..1070FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107100..1071FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107200..1072FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107300..1073FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107400..1074FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107500..1075FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107600..1076FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107700..1077FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107800..1078FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107900..1079FF */
+ FriBidiPropertyBlockLevel1_0100, /* 107A00..107AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 107B00..107BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 107C00..107CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 107D00..107DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 107E00..107EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 107F00..107FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 108000..1080FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108100..1081FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108200..1082FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108300..1083FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108400..1084FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108500..1085FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108600..1086FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108700..1087FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108800..1088FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108900..1089FF */
+ FriBidiPropertyBlockLevel1_0100, /* 108A00..108AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 108B00..108BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 108C00..108CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 108D00..108DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 108E00..108EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 108F00..108FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 109000..1090FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109100..1091FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109200..1092FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109300..1093FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109400..1094FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109500..1095FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109600..1096FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109700..1097FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109800..1098FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109900..1099FF */
+ FriBidiPropertyBlockLevel1_0100, /* 109A00..109AFF */
+ FriBidiPropertyBlockLevel1_0100, /* 109B00..109BFF */
+ FriBidiPropertyBlockLevel1_0100, /* 109C00..109CFF */
+ FriBidiPropertyBlockLevel1_0100, /* 109D00..109DFF */
+ FriBidiPropertyBlockLevel1_0100, /* 109E00..109EFF */
+ FriBidiPropertyBlockLevel1_0100, /* 109F00..109FFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A000..10A0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A100..10A1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A200..10A2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A300..10A3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A400..10A4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A500..10A5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A600..10A6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A700..10A7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A800..10A8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10A900..10A9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10AA00..10AAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10AB00..10ABFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10AC00..10ACFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10AD00..10ADFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10AE00..10AEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10AF00..10AFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B000..10B0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B100..10B1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B200..10B2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B300..10B3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B400..10B4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B500..10B5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B600..10B6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B700..10B7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B800..10B8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10B900..10B9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10BA00..10BAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10BB00..10BBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10BC00..10BCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10BD00..10BDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10BE00..10BEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10BF00..10BFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C000..10C0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C100..10C1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C200..10C2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C300..10C3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C400..10C4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C500..10C5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C600..10C6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C700..10C7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C800..10C8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10C900..10C9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10CA00..10CAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10CB00..10CBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10CC00..10CCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10CD00..10CDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10CE00..10CEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10CF00..10CFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D000..10D0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D100..10D1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D200..10D2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D300..10D3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D400..10D4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D500..10D5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D600..10D6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D700..10D7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D800..10D8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10D900..10D9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10DA00..10DAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10DB00..10DBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10DC00..10DCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10DD00..10DDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10DE00..10DEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10DF00..10DFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E000..10E0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E100..10E1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E200..10E2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E300..10E3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E400..10E4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E500..10E5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E600..10E6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E700..10E7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E800..10E8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10E900..10E9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10EA00..10EAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10EB00..10EBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10EC00..10ECFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10ED00..10EDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10EE00..10EEFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10EF00..10EFFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F000..10F0FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F100..10F1FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F200..10F2FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F300..10F3FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F400..10F4FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F500..10F5FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F600..10F6FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F700..10F7FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F800..10F8FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10F900..10F9FF */
+ FriBidiPropertyBlockLevel1_0100, /* 10FA00..10FAFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10FB00..10FBFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10FC00..10FCFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10FD00..10FDFF */
+ FriBidiPropertyBlockLevel1_0100, /* 10FE00..10FEFF */
+ FriBidiPropertyBlockLevel1_1FF00, /* 10FF00..10FFFF */
+};
+
+/* *INDENT-ON* */
+
+#define FRIBIDI_GET_TYPE(x) \
+ FriBidiPropertyBlockLevel1[(x)%256 + \
+ FriBidiPropertyBlockLevel0[(x)/256]]
+
+#undef WS
+#undef SS
+#undef RLO
+#undef RLE
+#undef PDF
+#undef NSM
+#undef LRO
+#undef LRE
+#undef ET
+#undef ES
+#undef EN
+#undef CS
+#undef BS
+#undef AN
+#undef BN
+#undef ON
+#undef AL
+#undef RTL
+#undef LTR
+/*======================================================================
+ * fribidi_get_type_internal() returns the bidi type of a character.
+ *----------------------------------------------------------------------*/
+FRIBIDI_API FriBidiCharType
+fribidi_get_type_internal (FriBidiChar uch)
+{
+ if (uch < 0x110000)
+ return fribidi_prop_to_type[(unsigned char)FRIBIDI_GET_TYPE (uch)];
+ else
+ return FRIBIDI_TYPE_LTR;
+ /* Non-Unicode chars */
+}
+
+
+#endif /* FRIBIDI_TAB_CHAR_TYPE_2_I */
diff --git a/trunk/pango/mini-fribidi/fribidi_types.c b/trunk/pango/mini-fribidi/fribidi_types.c
new file mode 100644
index 00000000..303c0d03
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi_types.c
@@ -0,0 +1,86 @@
+/* FriBidi - Library of BiDi algorithm
+ * Copyright (C) 2001,2002 Behdad Esfahbod.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library, in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ * For licensing issues, contact <fwpg@sharif.edu>.
+ */
+
+#include <config.h>
+#include "fribidi.h"
+
+#ifdef DEBUG
+
+char
+fribidi_char_from_type (FriBidiCharType c)
+{
+ switch (c)
+ {
+ case FRIBIDI_TYPE_LTR:
+ return 'L';
+ case FRIBIDI_TYPE_RTL:
+ return 'R';
+ case FRIBIDI_TYPE_AL:
+ return 'A';
+
+ case FRIBIDI_TYPE_EN:
+ return '1';
+ case FRIBIDI_TYPE_AN:
+ return '9';
+ case FRIBIDI_TYPE_ES:
+ return 'w';
+ case FRIBIDI_TYPE_ET:
+ return 'w';
+ case FRIBIDI_TYPE_CS:
+ return 'w';
+ case FRIBIDI_TYPE_NSM:
+ return '`';
+ case FRIBIDI_TYPE_BN:
+ return 'b';
+
+ case FRIBIDI_TYPE_BS:
+ return 'B';
+ case FRIBIDI_TYPE_SS:
+ return 'S';
+ case FRIBIDI_TYPE_WS:
+ return '_';
+ case FRIBIDI_TYPE_ON:
+ return 'n';
+
+ case FRIBIDI_TYPE_LRE:
+ return '+';
+ case FRIBIDI_TYPE_RLE:
+ return '+';
+ case FRIBIDI_TYPE_LRO:
+ return '+';
+ case FRIBIDI_TYPE_RLO:
+ return '+';
+ case FRIBIDI_TYPE_PDF:
+ return '-';
+
+ default:
+ return '?';
+ }
+};
+
+#endif
+
+/* Map fribidi_prop_types to fribidi_types. */
+const FriBidiCharType fribidi_prop_to_type[] = {
+#define _FRIBIDI_ADD_TYPE(TYPE) FRIBIDI_TYPE_##TYPE,
+#include "fribidi_types.i"
+#undef _FRIBIDI_ADD_TYPE
+};
diff --git a/trunk/pango/mini-fribidi/fribidi_types.h b/trunk/pango/mini-fribidi/fribidi_types.h
new file mode 100644
index 00000000..dc41865b
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi_types.h
@@ -0,0 +1,313 @@
+/* FriBidi - Library of BiDi algorithm
+ * Copyright (C) 1999,2000 Dov Grobgeld, and
+ * Copyright (C) 2001,2002 Behdad Esfahbod.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library, in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ * For licensing issues, contact <dov@imagic.weizmann.ac.il> and
+ * <fwpg@sharif.edu>.
+ */
+#ifndef FRIBIDI_TYPES_H
+#define FRIBIDI_TYPES_H
+
+#include "fribidi_config.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef gboolean fribidi_boolean;
+
+ typedef gint8 fribidi_int8;
+ typedef guint8 fribidi_uint8;
+ typedef gint16 fribidi_int16;
+ typedef guint16 fribidi_uint16;
+ typedef gint32 fribidi_int32;
+ typedef guint32 fribidi_uint32;
+ typedef gint fribidi_int;
+ typedef guint fribidi_uint;
+
+
+ typedef fribidi_int8 FriBidiLevel;
+ typedef gunichar FriBidiChar;
+ typedef gsize FriBidiStrIndex;
+ typedef fribidi_int32 FriBidiMaskType;
+ typedef FriBidiMaskType FriBidiCharType;
+
+ char *fribidi_type_name (FriBidiCharType c);
+
+/* The following type is used by fribidi_utils */
+ typedef struct
+ {
+ FriBidiStrIndex length;
+ void *attribute;
+ }
+ FriBidiRunType;
+
+/* The following type is used by fribdi_utils */
+ typedef struct _FriBidiList FriBidiList;
+ struct _FriBidiList
+ {
+ void *data;
+ FriBidiList *next;
+ FriBidiList *prev;
+ };
+
+#ifndef FRIBIDI_MAX_STRING_LENGTH
+#define FRIBIDI_MAX_STRING_LENGTH (FriBidiStrIndex) \
+ (sizeof (FriBidiStrIndex) == 2 ? \
+ 0x7FFE : (sizeof (FriBidiStrIndex) == 1 ? \
+ 0x7E : 0x7FFFFFFEL))
+#endif
+
+
+/*
+ * Define some bit masks, that character types are based on, each one has
+ * only one bit on.
+ */
+
+/* Do not use enum, because 16bit processors do not allow 32bit enum values. */
+
+#define FRIBIDI_MASK_RTL 0x00000001L /* Is right to left */
+#define FRIBIDI_MASK_ARABIC 0x00000002L /* Is arabic */
+
+/* Each char can be only one of the three following. */
+#define FRIBIDI_MASK_STRONG 0x00000010L /* Is strong */
+#define FRIBIDI_MASK_WEAK 0x00000020L /* Is weak */
+#define FRIBIDI_MASK_NEUTRAL 0x00000040L /* Is neutral */
+#define FRIBIDI_MASK_SENTINEL 0x00000080L /* Is sentinel: SOT, EOT */
+/* Sentinels are not valid chars, just identify the start and end of strings. */
+
+/* Each char can be only one of the five following. */
+#define FRIBIDI_MASK_LETTER 0x00000100L /* Is letter: L, R, AL */
+#define FRIBIDI_MASK_NUMBER 0x00000200L /* Is number: EN, AN */
+#define FRIBIDI_MASK_NUMSEPTER 0x00000400L /* Is number separator or terminator: ES, ET, CS */
+#define FRIBIDI_MASK_SPACE 0x00000800L /* Is space: BN, BS, SS, WS */
+#define FRIBIDI_MASK_EXPLICIT 0x00001000L /* Is expilict mark: LRE, RLE, LRO, RLO, PDF */
+
+/* Can be on only if FRIBIDI_MASK_SPACE is also on. */
+#define FRIBIDI_MASK_SEPARATOR 0x00002000L /* Is test separator: BS, SS */
+/* Can be on only if FRIBIDI_MASK_EXPLICIT is also on. */
+#define FRIBIDI_MASK_OVERRIDE 0x00004000L /* Is explicit override: LRO, RLO */
+
+/* The following must be to make types pairwise different, some of them can
+ be removed but are here because of efficiency (make queries faster). */
+
+#define FRIBIDI_MASK_ES 0x00010000L
+#define FRIBIDI_MASK_ET 0x00020000L
+#define FRIBIDI_MASK_CS 0x00040000L
+
+#define FRIBIDI_MASK_NSM 0x00080000L
+#define FRIBIDI_MASK_BN 0x00100000L
+
+#define FRIBIDI_MASK_BS 0x00200000L
+#define FRIBIDI_MASK_SS 0x00400000L
+#define FRIBIDI_MASK_WS 0x00800000L
+
+/* We reserve the sign bit for user's private use: we will never use it,
+ then negative character types will be never assigned. */
+
+
+/*
+ * Define values for FriBidiCharType
+ */
+
+/* Strong left to right */
+#define FRIBIDI_TYPE_LTR ( FRIBIDI_MASK_STRONG + FRIBIDI_MASK_LETTER )
+/* Right to left characters */
+#define FRIBIDI_TYPE_RTL ( FRIBIDI_MASK_STRONG + FRIBIDI_MASK_LETTER \
+ + FRIBIDI_MASK_RTL)
+/* Arabic characters */
+#define FRIBIDI_TYPE_AL ( FRIBIDI_MASK_STRONG + FRIBIDI_MASK_LETTER \
+ + FRIBIDI_MASK_RTL + FRIBIDI_MASK_ARABIC )
+/* Left-To-Right embedding */
+#define FRIBIDI_TYPE_LRE (FRIBIDI_MASK_STRONG + FRIBIDI_MASK_EXPLICIT)
+/* Right-To-Left embedding */
+#define FRIBIDI_TYPE_RLE ( FRIBIDI_MASK_STRONG + FRIBIDI_MASK_EXPLICIT \
+ + FRIBIDI_MASK_RTL )
+/* Left-To-Right override */
+#define FRIBIDI_TYPE_LRO ( FRIBIDI_MASK_STRONG + FRIBIDI_MASK_EXPLICIT \
+ + FRIBIDI_MASK_OVERRIDE )
+/* Right-To-Left override */
+#define FRIBIDI_TYPE_RLO ( FRIBIDI_MASK_STRONG + FRIBIDI_MASK_EXPLICIT \
+ + FRIBIDI_MASK_RTL + FRIBIDI_MASK_OVERRIDE )
+
+/* Pop directional override */
+#define FRIBIDI_TYPE_PDF ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_EXPLICIT )
+/* European digit */
+#define FRIBIDI_TYPE_EN ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_NUMBER )
+/* Arabic digit */
+#define FRIBIDI_TYPE_AN ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_NUMBER \
+ + FRIBIDI_MASK_ARABIC )
+/* European number separator */
+#define FRIBIDI_TYPE_ES ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_NUMSEPTER \
+ + FRIBIDI_MASK_ES )
+/* European number terminator */
+#define FRIBIDI_TYPE_ET ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_NUMSEPTER \
+ + FRIBIDI_MASK_ET )
+/* Common Separator */
+#define FRIBIDI_TYPE_CS ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_NUMSEPTER \
+ + FRIBIDI_MASK_CS )
+/* Non spacing mark */
+#define FRIBIDI_TYPE_NSM ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_NSM )
+/* Boundary neutral */
+#define FRIBIDI_TYPE_BN ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_SPACE \
+ + FRIBIDI_MASK_BN )
+
+/* Block separator */
+#define FRIBIDI_TYPE_BS ( FRIBIDI_MASK_NEUTRAL + FRIBIDI_MASK_SPACE \
+ + FRIBIDI_MASK_SEPARATOR + FRIBIDI_MASK_BS )
+/* Segment separator */
+#define FRIBIDI_TYPE_SS ( FRIBIDI_MASK_NEUTRAL + FRIBIDI_MASK_SPACE \
+ + FRIBIDI_MASK_SEPARATOR + FRIBIDI_MASK_SS )
+/* Whitespace */
+#define FRIBIDI_TYPE_WS ( FRIBIDI_MASK_NEUTRAL + FRIBIDI_MASK_SPACE \
+ + FRIBIDI_MASK_WS )
+/* Other Neutral */
+#define FRIBIDI_TYPE_ON ( FRIBIDI_MASK_NEUTRAL )
+
+/* The following are used to identify the paragraph direction,
+ types L, R, N are not used internally anymore, and recommended to use
+ LTR, RTL and ON instead, didn't removed because of compatability. */
+#define FRIBIDI_TYPE_L ( FRIBIDI_TYPE_LTR )
+#define FRIBIDI_TYPE_R ( FRIBIDI_TYPE_RTL )
+#define FRIBIDI_TYPE_N ( FRIBIDI_TYPE_ON )
+/* Weak left to right */
+#define FRIBIDI_TYPE_WL ( FRIBIDI_MASK_WEAK )
+/* Weak right to left */
+#define FRIBIDI_TYPE_WR ( FRIBIDI_MASK_WEAK + FRIBIDI_MASK_RTL )
+
+/* The following are only used internally */
+
+/* Start of text */
+#define FRIBIDI_TYPE_SOT ( FRIBIDI_MASK_SENTINEL )
+/* End of text */
+#define FRIBIDI_TYPE_EOT ( FRIBIDI_MASK_SENTINEL + FRIBIDI_MASK_RTL )
+
+/*
+ * End of define values for FriBidiCharType
+ */
+
+
+/*
+ * Defining macros for needed queries, It is fully dependent on the
+ * implementation of FriBidiCharType.
+ */
+
+
+/* Is private-use value? */
+#define FRIBIDI_TYPE_PRIVATE(p) ((p) < 0)
+
+/* Return the direction of the level number, FRIBIDI_TYPE_LTR for even and
+ FRIBIDI_TYPE_RTL for odds. */
+#define FRIBIDI_LEVEL_TO_DIR(lev) (FRIBIDI_TYPE_LTR | (lev & 1))
+
+/* Return the minimum level of the direction, 0 for FRIBIDI_TYPE_LTR and
+ 1 for FRIBIDI_TYPE_RTL and FRIBIDI_TYPE_AL. */
+#define FRIBIDI_DIR_TO_LEVEL(dir) ((FriBidiLevel)(dir & 1))
+
+/* Is right to left? */
+#define FRIBIDI_IS_RTL(p) ((p) & FRIBIDI_MASK_RTL)
+/* Is arabic? */
+#define FRIBIDI_IS_ARABIC(p) ((p) & FRIBIDI_MASK_ARABIC)
+
+/* Is strong? */
+#define FRIBIDI_IS_STRONG(p) ((p) & FRIBIDI_MASK_STRONG)
+/* Is weak? */
+#define FRIBIDI_IS_WEAK(p) ((p) & FRIBIDI_MASK_WEAK)
+/* Is neutral? */
+#define FRIBIDI_IS_NEUTRAL(p) ((p) & FRIBIDI_MASK_NEUTRAL)
+/* Is sentinel? */
+#define FRIBIDI_IS_SENTINEL(p) ((p) & FRIBIDI_MASK_SENTINEL)
+
+/* Is letter: L, R, AL? */
+#define FRIBIDI_IS_LETTER(p) ((p) & FRIBIDI_MASK_LETTER)
+/* Is number: EN, AN? */
+#define FRIBIDI_IS_NUMBER(p) ((p) & FRIBIDI_MASK_NUMBER)
+/* Is number separator or terminator: ES, ET, CS? */
+#define FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR(p) \
+ ((p) & FRIBIDI_MASK_NUMSEPTER)
+/* Is space: BN, BS, SS, WS? */
+#define FRIBIDI_IS_SPACE(p) ((p) & FRIBIDI_MASK_SPACE)
+/* Is explicit mark: LRE, RLE, LRO, RLO, PDF? */
+#define FRIBIDI_IS_EXPLICIT(p) ((p) & FRIBIDI_MASK_EXPLICIT)
+
+/* Is test separator: BS, SS? */
+#define FRIBIDI_IS_SEPARATOR(p) ((p) & FRIBIDI_MASK_SEPARATOR)
+
+/* Is explicit override: LRO, RLO? */
+#define FRIBIDI_IS_OVERRIDE(p) ((p) & FRIBIDI_MASK_OVERRIDE)
+
+/* Some more: */
+
+/* Is left to right letter: LTR? */
+#define FRIBIDI_IS_LTR_LETTER(p) \
+ ((p) & (FRIBIDI_MASK_LETTER | FRIBIDI_MASK_RTL) == FRIBIDI_MASK_LETTER)
+
+/* Is right to left letter: RTL, AL? */
+#define FRIBIDI_IS_RTL_LETTER(p) \
+ ((p) & (FRIBIDI_MASK_LETTER | FRIBIDI_MASK_RTL) \
+ == (FRIBIDI_MASK_LETTER | FRIBIDI_MASK_RTL))
+
+/* Is ES or CS: ES, CS? */
+#define FRIBIDI_IS_ES_OR_CS(p) \
+ ((p) & (FRIBIDI_MASK_ES | FRIBIDI_MASK_CS))
+
+/* Is explicit or BN: LRE, RLE, LRO, RLO, PDF, BN? */
+#define FRIBIDI_IS_EXPLICIT_OR_BN(p) \
+ ((p) & (FRIBIDI_MASK_EXPLICIT | FRIBIDI_MASK_BN))
+
+/* Is explicit or separator or BN or WS: LRE, RLE, LRO, RLO, PDF, BS, SS, BN, WS? */
+#define FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS(p) \
+ ((p) & (FRIBIDI_MASK_EXPLICIT | FRIBIDI_MASK_SEPARATOR \
+ | FRIBIDI_MASK_BN | FRIBIDI_MASK_WS))
+
+/* Define some conversions. */
+
+/* Change numbers: EN, AN to RTL. */
+#define FRIBIDI_CHANGE_NUMBER_TO_RTL(p) \
+ (FRIBIDI_IS_NUMBER(p) ? FRIBIDI_TYPE_RTL : (p))
+
+/* Override status of an explicit mark: LRO->LTR, RLO->RTL, otherwise->ON. */
+#define FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR(p) \
+ (FRIBIDI_IS_OVERRIDE(p) ? FRIBIDI_LEVEL_TO_DIR(FRIBIDI_DIR_TO_LEVEL(p)) \
+ : FRIBIDI_TYPE_ON)
+
+
+/*
+ * Define character types that char_type_tables use.
+ * define them to be 0, 1, 2, ... and then in fribidi_char_type.c map them
+ * to FriBidiCharTypes.
+ */
+ typedef char FriBidiPropCharType;
+
+ enum FriBidiPropEnum
+ {
+#define _FRIBIDI_ADD_TYPE(TYPE) FRIBIDI_PROP_TYPE_##TYPE,
+#include "fribidi_types.i"
+#undef _FRIBIDI_ADD_TYPE
+ FRIBIDI_TYPES_COUNT /* Number of different character types */
+ };
+
+/* Map fribidi_prop_types to fribidi_types */
+ extern const FriBidiCharType fribidi_prop_to_type[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/trunk/pango/mini-fribidi/fribidi_types.i b/trunk/pango/mini-fribidi/fribidi_types.i
new file mode 100644
index 00000000..562bae39
--- /dev/null
+++ b/trunk/pango/mini-fribidi/fribidi_types.i
@@ -0,0 +1,21 @@
+_FRIBIDI_ADD_TYPE(LTR) /* Strong left to right */
+_FRIBIDI_ADD_TYPE(RTL) /* Right to left characters */
+_FRIBIDI_ADD_TYPE(AL) /* Arabic characters */
+_FRIBIDI_ADD_TYPE(LRE) /* Left-To-Right embedding */
+_FRIBIDI_ADD_TYPE(RLE) /* Right-To-Left embedding */
+_FRIBIDI_ADD_TYPE(LRO) /* Left-To-Right override */
+_FRIBIDI_ADD_TYPE(RLO) /* Right-To-Left override */
+_FRIBIDI_ADD_TYPE(PDF) /* Pop directional override */
+_FRIBIDI_ADD_TYPE(EN) /* European digit */
+_FRIBIDI_ADD_TYPE(AN) /* Arabic digit */
+_FRIBIDI_ADD_TYPE(ES) /* European number separator */
+_FRIBIDI_ADD_TYPE(ET) /* European number terminator */
+_FRIBIDI_ADD_TYPE(CS) /* Common Separator */
+_FRIBIDI_ADD_TYPE(NSM) /* Non spacing mark */
+_FRIBIDI_ADD_TYPE(BN) /* Boundary neutral */
+_FRIBIDI_ADD_TYPE(BS) /* Block separator */
+_FRIBIDI_ADD_TYPE(SS) /* Segment separator */
+_FRIBIDI_ADD_TYPE(WS) /* Whitespace */
+_FRIBIDI_ADD_TYPE(ON) /* Other Neutral */
+_FRIBIDI_ADD_TYPE(WL) /* Weak left to right */
+_FRIBIDI_ADD_TYPE(WR) /* Weak right to left */
diff --git a/trunk/pango/module-defs-fc.c.win32 b/trunk/pango/module-defs-fc.c.win32
new file mode 100644
index 00000000..a6ae1cff
--- /dev/null
+++ b/trunk/pango/module-defs-fc.c.win32
@@ -0,0 +1,31 @@
+/* Hand-written. Once the GNU configure mechanism is used
+ * on Win32, too, can be generated.
+*/
+
+#include "modules.h"
+
+#ifdef PANGO_MODULE_PREFIX
+/* by defining PANGO_MODULE_PREFIX the basic module gets include in the
+ * backend library, here ../modules/basic/basic-fc.c
+ * It helps the backend to not fall on its nose even with a screwed module
+ * configuration. There should be at least enough fonts available to show
+ * an error message ...
+ */
+void _pango_basic_ft2_script_engine_list (PangoEngineInfo **engines,
+ gint *n_engines);
+void _pango_basic_ft2_script_engine_init (GTypeModule *module);
+void _pango_basic_ft2_script_engine_exit (void);
+PangoEngine *_pango_basic_ft2_script_engine_create (const char *id);
+#endif
+
+PangoIncludedModule _pango_included_fc_modules[] = {
+#ifdef PANGO_MODULE_PREFIX
+ {
+ _pango_basic_ft2_script_engine_list,
+ _pango_basic_ft2_script_engine_init,
+ _pango_basic_ft2_script_engine_exit,
+ _pango_basic_ft2_script_engine_create
+ },
+#endif
+ { NULL, NULL, NULL },
+};
diff --git a/trunk/pango/module-defs-win32.c.win32 b/trunk/pango/module-defs-win32.c.win32
new file mode 100644
index 00000000..80fc90a3
--- /dev/null
+++ b/trunk/pango/module-defs-win32.c.win32
@@ -0,0 +1,25 @@
+/* Hand-written, for builds using Microsoft's compiler and makefile.msc,
+ * where the configure mechanism isn't used.
+ */
+
+#include "modules.h"
+
+#ifdef PANGO_MODULE_PREFIX
+void _pango_basic_win32_script_engine_list (PangoEngineInfo **engines,
+ gint *n_engines);
+void _pango_basic_win32_script_engine_init (GTypeModule *module);
+void _pango_basic_win32_script_engine_exit (void);
+PangoEngine *_pango_basic_win32_script_engine_create (const char *id);
+#endif
+
+PangoIncludedModule _pango_included_win32_modules[] = {
+#ifdef PANGO_MODULE_PREFIX
+ {
+ _pango_basic_win32_script_engine_list,
+ _pango_basic_win32_script_engine_init,
+ _pango_basic_win32_script_engine_exit,
+ _pango_basic_win32_script_engine_create
+ },
+#endif
+ { NULL, NULL, NULL },
+};
diff --git a/trunk/pango/modules.c b/trunk/pango/modules.c
new file mode 100644
index 00000000..5a9d6883
--- /dev/null
+++ b/trunk/pango/modules.c
@@ -0,0 +1,763 @@
+/* Pango
+ * modules.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <gmodule.h>
+#include <glib/gstdio.h>
+
+#include "pango-enum-types.h"
+#include "pango-modules.h"
+#include "pango-impl-utils.h"
+#include "modules.h"
+
+typedef struct _PangoModule PangoModule;
+typedef struct _PangoModuleClass PangoModuleClass;
+
+#define PANGO_TYPE_MODULE (pango_module_get_type ())
+#define PANGO_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), PANGO_TYPE_MODULE, PangoModule))
+#define PANGO_IS_MODULE(module) (G_TYPE_CHECK_INSTANCE_TYPE ((module), PANGO_TYPE_MODULE))
+
+typedef struct _PangoMapInfo PangoMapInfo;
+typedef struct _PangoEnginePair PangoEnginePair;
+typedef struct _PangoSubmap PangoSubmap;
+
+struct _PangoMap
+{
+ GArray *entries;
+};
+
+struct _PangoMapEntry
+{
+ GSList *exact;
+ GSList *fallback;
+};
+
+struct _PangoMapInfo
+{
+ PangoLanguage *language;
+ guint engine_type_id;
+ guint render_type_id;
+ PangoMap *map;
+};
+
+struct _PangoEnginePair
+{
+ PangoEngineInfo info;
+ PangoModule *module;
+ PangoEngine *engine;
+};
+
+struct _PangoModule
+{
+ GTypeModule parent_instance;
+
+ char *path;
+ GModule *library;
+
+ void (*list) (PangoEngineInfo **engines, gint *n_engines);
+ void (*init) (GTypeModule *module);
+ void (*exit) (void);
+ PangoEngine *(*create) (const gchar *id);
+};
+
+struct _PangoModuleClass
+{
+ GTypeModuleClass parent_class;
+};
+
+static GList *maps = NULL;
+static GSList *registered_engines = NULL;
+static GSList *dlloaded_engines = NULL;
+static GHashTable *dlloaded_modules;
+
+static GObjectClass *parent_class;
+
+static void build_map (PangoMapInfo *info);
+static void init_modules (void);
+
+static GType pango_module_get_type (void);
+
+/**
+ * pango_find_map:
+ * @language: the language tag for which to find the map
+ * @engine_type_id: the engine type for the map to find
+ * @render_type_id: the render type for the map to find
+ *
+ * Locate a #PangoMap for a particular engine type and render
+ * type. The resulting map can be used to determine the engine
+ * for each character.
+ *
+ * Return value: the suitable #PangoMap.
+ **/
+PangoMap *
+pango_find_map (PangoLanguage *language,
+ guint engine_type_id,
+ guint render_type_id)
+{
+ GList *tmp_list = maps;
+ PangoMapInfo *map_info = NULL;
+ gboolean found_earlier = FALSE;
+
+ while (tmp_list)
+ {
+ map_info = tmp_list->data;
+ if (map_info->engine_type_id == engine_type_id &&
+ map_info->render_type_id == render_type_id)
+ {
+ if (map_info->language == language)
+ break;
+ else
+ found_earlier = TRUE;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list)
+ {
+ map_info = g_slice_new (PangoMapInfo);
+ map_info->language = language;
+ map_info->engine_type_id = engine_type_id;
+ map_info->render_type_id = render_type_id;
+
+ build_map (map_info);
+
+ maps = g_list_prepend (maps, map_info);
+ }
+ else if (found_earlier)
+ {
+ /* Move the found map to the beginning of the list
+ * for speed next time around if we had to do
+ * any failing comparison. (No longer so important,
+ * since we don't strcmp.)
+ */
+ maps = g_list_remove_link(maps, tmp_list);
+ maps = g_list_prepend(maps, tmp_list->data);
+ g_list_free_1(tmp_list);
+ }
+
+ return map_info->map;
+}
+
+static gboolean
+pango_module_load (GTypeModule *module)
+{
+ PangoModule *pango_module = PANGO_MODULE (module);
+
+ if (pango_module->path)
+ {
+ pango_module->library = g_module_open (pango_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+ if (!pango_module->library)
+ {
+ g_warning ("%s", g_module_error());
+ return FALSE;
+ }
+
+ /* extract symbols from the lib */
+ if (!g_module_symbol (pango_module->library, "script_engine_init",
+ (gpointer *)&pango_module->init) ||
+ !g_module_symbol (pango_module->library, "script_engine_exit",
+ (gpointer *)&pango_module->exit) ||
+ !g_module_symbol (pango_module->library, "script_engine_list",
+ (gpointer *)&pango_module->list) ||
+ !g_module_symbol (pango_module->library, "script_engine_create",
+ (gpointer *)&pango_module->create))
+ {
+ g_warning ("%s", g_module_error());
+ g_module_close (pango_module->library);
+
+ return FALSE;
+ }
+ }
+
+ /* call the module's init function to let it */
+ /* setup anything it needs to set up. */
+ pango_module->init (module);
+
+ return TRUE;
+}
+
+static void
+pango_module_unload (GTypeModule *module)
+{
+ PangoModule *pango_module = PANGO_MODULE (module);
+
+ pango_module->exit();
+
+ if (pango_module->path)
+ {
+ g_module_close (pango_module->library);
+ pango_module->library = NULL;
+
+ pango_module->init = NULL;
+ pango_module->exit = NULL;
+ pango_module->list = NULL;
+ pango_module->create = NULL;
+ }
+}
+
+/* This only will ever be called if an error occurs during
+ * initialization
+ */
+static void
+pango_module_finalize (GObject *object)
+{
+ PangoModule *module = PANGO_MODULE (object);
+
+ g_free (module->path);
+
+ parent_class->finalize (object);
+}
+
+static void
+pango_module_class_init (PangoModuleClass *class)
+{
+ GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class));
+
+ module_class->load = pango_module_load;
+ module_class->unload = pango_module_unload;
+
+ gobject_class->finalize = pango_module_finalize;
+}
+
+static PANGO_DEFINE_TYPE (PangoModule, pango_module,
+ pango_module_class_init, NULL,
+ G_TYPE_TYPE_MODULE)
+
+static PangoEngine *
+pango_engine_pair_get_engine (PangoEnginePair *pair)
+{
+ if (!pair->engine)
+ {
+ if (g_type_module_use (G_TYPE_MODULE (pair->module)))
+ {
+ pair->engine = pair->module->create (pair->info.id);
+ g_type_module_unuse (G_TYPE_MODULE (pair->module));
+ }
+
+ if (!pair->engine)
+ {
+ /* If a module cannot be used, or doesn't not create an engine
+ * correctly, we print out an error containing module name and id,
+ * but to not flood the terminal with zillions of the message, we
+ * set a flag on the module to only err once per module.
+ */
+ static GQuark warned_quark = 0;
+
+ if (!warned_quark)
+ warned_quark = g_quark_from_static_string ("pango-module-warned");
+
+ if (!g_object_get_qdata (G_OBJECT (pair->module), warned_quark))
+ {
+ g_warning ("Failed to load Pango module '%s' for id '%s'", pair->module->path, pair->info.id);
+
+ g_object_set_qdata_full (G_OBJECT (pair->module), warned_quark,
+ GINT_TO_POINTER (1), NULL);
+ }
+ }
+ }
+
+ return pair->engine;
+}
+
+static void
+handle_included_module (PangoIncludedModule *included_module,
+ GSList **engine_list)
+{
+ PangoModule *module = g_object_new (PANGO_TYPE_MODULE, NULL);
+ PangoEngineInfo *engine_info;
+ int n_engines;
+ int i;
+
+ module->list = included_module->list;
+ module->init = included_module->init;
+ module->exit = included_module->exit;
+ module->create = included_module->create;
+
+ module->list (&engine_info, &n_engines);
+
+ for (i = 0; i < n_engines; i++)
+ {
+ PangoEnginePair *pair = g_slice_new (PangoEnginePair);
+
+ pair->info = engine_info[i];
+ pair->module = module;
+ pair->engine = NULL;
+
+ *engine_list = g_slist_prepend (*engine_list, pair);
+ }
+}
+
+static PangoModule *
+find_or_create_module (const char *raw_path)
+{
+ PangoModule *module;
+ char *path;
+
+#if defined(G_OS_WIN32) && defined(LIBDIR)
+ if (strncmp (raw_path,
+ LIBDIR "/pango/" MODULE_VERSION "/modules/",
+ strlen (LIBDIR "/pango/" MODULE_VERSION "/modules/")) == 0)
+ {
+ /* This is an entry put there by make install on the
+ * packager's system. On Windows a prebuilt Pango
+ * package can be installed in a random
+ * location. The pango.modules file distributed in
+ * such a package contains paths from the package
+ * builder's machine. Replace the path with the real
+ * one on this machine. */
+ path =
+ g_strconcat (pango_get_lib_subdirectory (),
+ "\\" MODULE_VERSION "\\modules\\",
+ raw_path + strlen (LIBDIR "/pango/" MODULE_VERSION "/modules/"),
+ NULL);
+ }
+ else
+#endif
+ {
+ path = g_strdup (raw_path);
+ }
+
+ module = g_hash_table_lookup (dlloaded_modules, path);
+ if (module)
+ g_free (path);
+ else
+ {
+ module = g_object_new (PANGO_TYPE_MODULE, NULL);
+ module->path = path;
+ g_hash_table_insert (dlloaded_modules, path, module);
+ }
+
+ return module;
+}
+
+static PangoScript
+script_from_string (const char *str)
+{
+ static GEnumClass *class = NULL;
+ GEnumValue *value;
+ if (!class)
+ class = g_type_class_ref (PANGO_TYPE_SCRIPT);
+
+ value = g_enum_get_value_by_nick (class, str);
+ if (!value)
+ return PANGO_SCRIPT_INVALID_CODE;
+
+ return value->value;
+}
+
+static void
+script_info_free (PangoEngineScriptInfo *script_info, gpointer data)
+{
+ g_slice_free (PangoEngineScriptInfo, script_info);
+}
+
+static gboolean /* Returns true if succeeded, false if failed */
+process_module_file (FILE *module_file)
+{
+ GString *line_buf = g_string_new (NULL);
+ GString *tmp_buf = g_string_new (NULL);
+ gboolean have_error = FALSE;
+
+ while (pango_read_line (module_file, line_buf))
+ {
+ PangoEnginePair *pair = g_slice_new (PangoEnginePair);
+ PangoEngineScriptInfo *script_info;
+ PangoScript script;
+ GList *scripts = NULL;
+ GList *tmp_list;
+
+ const char *p;
+ char *q;
+ int i;
+
+ p = line_buf->str;
+
+ if (!pango_skip_space (&p))
+ {
+ g_slice_free (PangoEnginePair, pair);
+ continue;
+ }
+
+ i = 0;
+ while (1)
+ {
+ if (!pango_scan_string (&p, tmp_buf))
+ {
+ have_error = TRUE;
+ goto error;
+ }
+
+ switch (i)
+ {
+ case 0:
+ pair->module = find_or_create_module (tmp_buf->str);
+ break;
+ case 1:
+ pair->info.id = g_strdup (tmp_buf->str);
+ break;
+ case 2:
+ pair->info.engine_type = g_strdup (tmp_buf->str);
+ break;
+ case 3:
+ pair->info.render_type = g_strdup (tmp_buf->str);
+ break;
+ default:
+ q = strchr (tmp_buf->str, ':');
+ if (!q)
+ {
+ have_error = TRUE;
+ goto error;
+ }
+ *q = '\0';
+ script = script_from_string (tmp_buf->str);
+ if (script == PANGO_SCRIPT_INVALID_CODE)
+ {
+ have_error = TRUE;
+ goto error;
+ }
+
+ script_info = g_slice_new (PangoEngineScriptInfo);
+ script_info->script = script;
+ script_info->langs = g_strdup (q + 1);
+
+ scripts = g_list_prepend (scripts, script_info);
+ }
+
+ if (!pango_skip_space (&p))
+ break;
+
+ i++;
+ }
+
+ if (i<3)
+ {
+ have_error = TRUE;
+ goto error;
+ }
+
+ scripts = g_list_reverse (scripts);
+ pair->info.n_scripts = g_list_length (scripts);
+ pair->info.scripts = g_new (PangoEngineScriptInfo, pair->info.n_scripts);
+
+ tmp_list = scripts;
+ for (i=0; i<pair->info.n_scripts; i++)
+ {
+ pair->info.scripts[i] = *(PangoEngineScriptInfo *)tmp_list->data;
+ tmp_list = tmp_list->next;
+ }
+
+ pair->engine = NULL;
+
+ dlloaded_engines = g_slist_prepend (dlloaded_engines, pair);
+
+ error:
+ g_list_foreach (scripts, (GFunc)script_info_free, NULL);
+ g_list_free (scripts);
+
+ if (have_error)
+ {
+ g_printerr ("Error reading Pango modules file\n");
+ g_slice_free(PangoEnginePair, pair);
+ break;
+ }
+ }
+
+ g_string_free (line_buf, TRUE);
+ g_string_free (tmp_buf, TRUE);
+
+ return !have_error;
+}
+
+static void
+read_modules (void)
+{
+ FILE *module_file;
+
+ char *file_str = pango_config_key_get ("Pango/ModuleFiles");
+ char **files;
+ int n;
+
+ dlloaded_modules = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (!file_str)
+ file_str = g_build_filename (pango_get_sysconf_subdirectory (),
+ "pango.modules",
+ NULL);
+
+ files = pango_split_file_list (file_str);
+
+ n = 0;
+ while (files[n])
+ n++;
+
+ while (n-- > 0)
+ {
+ module_file = g_fopen (files[n], "r");
+ if (module_file)
+ {
+ process_module_file(module_file);
+ fclose(module_file);
+ }
+ }
+
+ g_strfreev (files);
+ g_free (file_str);
+
+ dlloaded_engines = g_slist_reverse (dlloaded_engines);
+}
+
+static void
+init_modules (void)
+{
+ static gboolean init = FALSE;
+ int i;
+
+ if (init)
+ return;
+ else
+ init = TRUE;
+
+ /* Make sure that the type system is initialized */
+ g_type_init ();
+
+ for (i = 0; _pango_included_lang_modules[i].list; i++)
+ pango_module_register (&_pango_included_lang_modules[i]);
+ read_modules ();
+}
+
+static void
+map_add_engine (PangoMapInfo *info,
+ PangoEnginePair *pair)
+{
+ PangoMap *map = info->map;
+ int i;
+
+ for (i=0; i<pair->info.n_scripts; i++)
+ {
+ PangoScript script;
+ PangoMapEntry *entry;
+ gboolean is_exact = FALSE;
+
+ if (pair->info.scripts[i].langs)
+ {
+ if (pango_language_matches (info->language, pair->info.scripts[i].langs))
+ is_exact = TRUE;
+ }
+
+ script = pair->info.scripts[i].script;
+ if ((guint)script >= map->entries->len)
+ g_array_set_size (map->entries, script + 1);
+
+ entry = &g_array_index (map->entries, PangoMapEntry, script);
+
+ if (is_exact)
+ entry->exact = g_slist_prepend (entry->exact, pair);
+ else
+ entry->exact = g_slist_prepend (entry->fallback, pair);
+ }
+}
+
+static void
+map_add_engine_list (PangoMapInfo *info,
+ GSList *engines,
+ const char *engine_type,
+ const char *render_type)
+{
+ GSList *tmp_list = engines;
+
+ while (tmp_list)
+ {
+ PangoEnginePair *pair = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (strcmp (pair->info.engine_type, engine_type) == 0 &&
+ strcmp (pair->info.render_type, render_type) == 0)
+ {
+ map_add_engine (info, pair);
+ }
+ }
+}
+
+static void
+build_map (PangoMapInfo *info)
+{
+ const char *engine_type = g_quark_to_string (info->engine_type_id);
+ const char *render_type = g_quark_to_string (info->render_type_id);
+
+ init_modules();
+
+ if (!dlloaded_engines && !registered_engines)
+ {
+ static gboolean no_module_warning = FALSE;
+ if (!no_module_warning)
+ {
+ gchar *filename = g_build_filename (pango_get_sysconf_subdirectory (),
+ "pango.modules",
+ NULL);
+ g_warning ("No builtin or dynamically\n"
+ "loaded modules were found. Pango will not work correctly.\n"
+ "This probably means there was an error in the creation of:\n"
+ " '%s'\n"
+ "You should create this file by running pango-querymodules.",
+ filename);
+ g_free (filename);
+
+ no_module_warning = TRUE;
+ }
+ }
+
+ info->map = g_slice_new (PangoMap);
+ info->map->entries = g_array_new (FALSE, TRUE, sizeof (PangoMapEntry));
+
+ map_add_engine_list (info, dlloaded_engines, engine_type, render_type);
+ map_add_engine_list (info, registered_engines, engine_type, render_type);
+}
+
+/**
+ * pango_map_get_engine:
+ * @map: a #PangoMap
+ * @script: a #PangoScript
+ *
+ * Returns the best engine listed in the map for a given script
+ *
+ * Return value: the best engine, if one is listed for the script,
+ * or %NULL. The lookup may cause the engine to be loaded;
+ * once an engine is loaded, it won't be unloaded. If multiple
+ * engines are exact for the script, the choice of which is
+ * returned is arbitrary.
+ **/
+PangoEngine *
+pango_map_get_engine (PangoMap *map,
+ PangoScript script)
+{
+ PangoMapEntry *entry = NULL;
+ PangoMapEntry *common_entry = NULL;
+
+ if ((guint)script < map->entries->len)
+ entry = &g_array_index (map->entries, PangoMapEntry, script);
+
+ if (PANGO_SCRIPT_COMMON < map->entries->len)
+ common_entry = &g_array_index (map->entries, PangoMapEntry, PANGO_SCRIPT_COMMON);
+
+ if (entry && entry->exact)
+ return pango_engine_pair_get_engine (entry->exact->data);
+ else if (common_entry && common_entry->exact)
+ return pango_engine_pair_get_engine (common_entry->exact->data);
+ else if (entry && entry->fallback)
+ return pango_engine_pair_get_engine (entry->fallback->data);
+ else if (common_entry && common_entry->fallback)
+ return pango_engine_pair_get_engine (common_entry->fallback->data);
+ else
+ return NULL;
+}
+
+static void
+append_engines (GSList **engine_list,
+ GSList *pair_list)
+{
+ GSList *l;
+
+ for (l = pair_list; l; l = l->next)
+ {
+ PangoEngine *engine = pango_engine_pair_get_engine (l->data);
+ if (engine)
+ *engine_list = g_slist_append (*engine_list, engine);
+ }
+}
+
+/**
+ * pango_map_get_engines:
+ * @map: a #PangoMap
+ * @script: a #PangoScript
+ * @exact_engines: location to store list of engines that exactly
+ * handle this script.
+ * @fallback_engines: location to store list of engines that approximately
+ * handle this script.
+ *
+ * Finds engines in the map that handle the given script. The returned
+ * lists should be freed with g_slist_free, but the engines in the
+ * lists are owned by GLib and will be kept around permanently, so
+ * they should not be unref'ed.
+ *
+ * Since: 1.4
+ **/
+void
+pango_map_get_engines (PangoMap *map,
+ PangoScript script,
+ GSList **exact_engines,
+ GSList **fallback_engines)
+{
+ PangoMapEntry *entry = NULL;
+ PangoMapEntry *common_entry = NULL;
+
+ if ((guint)script < map->entries->len)
+ entry = &g_array_index (map->entries, PangoMapEntry, script);
+
+ if (PANGO_SCRIPT_COMMON < map->entries->len)
+ common_entry = &g_array_index (map->entries, PangoMapEntry, PANGO_SCRIPT_COMMON);
+
+ if (exact_engines)
+ {
+ *exact_engines = NULL;
+ if (entry && entry->exact)
+ append_engines (exact_engines, entry->exact);
+ else if (common_entry && common_entry->exact)
+ append_engines (exact_engines, common_entry->exact);
+ }
+
+ if (fallback_engines)
+ {
+ *fallback_engines = NULL;
+ if (entry && entry->fallback)
+ append_engines (fallback_engines, entry->fallback);
+ else if (common_entry && common_entry->fallback)
+ append_engines (fallback_engines, common_entry->fallback);
+ }
+}
+
+/**
+ * pango_module_register:
+ * @module: a #PangoIncludedModule
+ *
+ * Registers a statically linked module with Pango. The
+ * #PangoIncludedModule structure that is passed in contains the
+ * functions that would otherwise be loaded from a dynamically loaded
+ * module.
+ **/
+void
+pango_module_register (PangoIncludedModule *module)
+{
+ GSList *tmp_list = NULL;
+
+ handle_included_module (module, &tmp_list);
+
+ registered_engines = g_slist_concat (registered_engines,
+ g_slist_reverse (tmp_list));
+}
diff --git a/trunk/pango/modules.h b/trunk/pango/modules.h
new file mode 100644
index 00000000..ca22701b
--- /dev/null
+++ b/trunk/pango/modules.h
@@ -0,0 +1,34 @@
+/* Pango
+ * modules.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <pango/pango-engine.h>
+#include <pango/pango-modules.h>
+
+#ifndef __MODULES_H__
+#define __MODULES_H__
+
+extern PangoIncludedModule _pango_included_lang_modules[];
+extern PangoIncludedModule _pango_included_x_modules[];
+extern PangoIncludedModule _pango_included_fc_modules[];
+extern PangoIncludedModule _pango_included_win32_modules[];
+extern PangoIncludedModule _pango_included_atsui_modules[];
+
+#endif /* __MODULES_H__ */
diff --git a/trunk/pango/opentype/COPYING b/trunk/pango/opentype/COPYING
new file mode 100644
index 00000000..cde91010
--- /dev/null
+++ b/trunk/pango/opentype/COPYING
@@ -0,0 +1,15 @@
+HarfBuzz is distributed under two mutually exclusive open-source licenses.
+This means that *you* must choose *one* of the two licenses described
+below, then obey all its terms and conditions when using HarfBuzz in
+any of your projects or products.
+
+ - The FreeType License, found in the file `COPYING.FTL', which is similar to
+ the original BSD license *with* an advertising clause that forces you to
+ explicitly cite the FreeType project in your product's documentation.
+ All details are in the license file. This license is suited to
+ products which don't use the GNU General Public License.
+
+ - The GNU General Public License version 2, found in `COPYING.GPL' (any
+ later version can be used also), for programs which already use the GPL.
+ Note that the FTL is incompatible with the GPL due to its
+ advertisement clause.
diff --git a/trunk/pango/opentype/COPYING.FTL b/trunk/pango/opentype/COPYING.FTL
new file mode 100644
index 00000000..459bda32
--- /dev/null
+++ b/trunk/pango/opentype/COPYING.FTL
@@ -0,0 +1,174 @@
+ The FreeType Project LICENSE
+ ----------------------------
+
+ 2002-Apr-11
+
+ Copyright 1996-2002 by
+ David Turner, Robert Wilhelm, and Werner Lemberg
+
+
+
+Introduction
+============
+
+ The FreeType Project is distributed in several archive packages;
+ some of them may contain, in addition to the FreeType font engine,
+ various tools and contributions which rely on, or relate to, the
+ FreeType Project.
+
+ This license applies to all files found in such packages, and
+ which do not fall under their own explicit license. The license
+ affects thus the FreeType font engine, the test programs,
+ documentation and makefiles, at the very least.
+
+ This license was inspired by the BSD, Artistic, and IJG
+ (Independent JPEG Group) licenses, which all encourage inclusion
+ and use of free software in commercial and freeware products
+ alike. As a consequence, its main points are that:
+
+ o We don't promise that this software works. However, we will be
+ interested in any kind of bug reports. (`as is' distribution)
+
+ o You can use this software for whatever you want, in parts or
+ full form, without having to pay us. (`royalty-free' usage)
+
+ o You may not pretend that you wrote this software. If you use
+ it, or only parts of it, in a program, you must acknowledge
+ somewhere in your documentation that you have used the
+ FreeType code. (`credits')
+
+ We specifically permit and encourage the inclusion of this
+ software, with or without modifications, in commercial products.
+ We disclaim all warranties covering The FreeType Project and
+ assume no liability related to The FreeType Project.
+
+
+ Finally, many people asked us for a preferred form for a
+ credit/disclaimer to use in compliance with this license. We thus
+ encourage you to use the following text:
+
+ """
+ Portions of this software are copyright © 1996-2002 The FreeType
+ Project (www.freetype.org). All rights reserved.
+ """
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+ Throughout this license, the terms `package', `FreeType Project',
+ and `FreeType archive' refer to the set of files originally
+ distributed by the authors (David Turner, Robert Wilhelm, and
+ Werner Lemberg) as the `FreeType Project', be they named as alpha,
+ beta or final release.
+
+ `You' refers to the licensee, or person using the project, where
+ `using' is a generic term including compiling the project's source
+ code as well as linking it to form a `program' or `executable'.
+ This program is referred to as `a program using the FreeType
+ engine'.
+
+ This license applies to all files distributed in the original
+ FreeType Project, including all source code, binaries and
+ documentation, unless otherwise stated in the file in its
+ original, unmodified form as distributed in the original archive.
+ If you are unsure whether or not a particular file is covered by
+ this license, you must contact us to verify this.
+
+ The FreeType Project is copyright (C) 1996-2000 by David Turner,
+ Robert Wilhelm, and Werner Lemberg. All rights reserved except as
+ specified below.
+
+1. No Warranty
+--------------
+
+ THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO
+ USE, OF THE FREETYPE PROJECT.
+
+2. Redistribution
+-----------------
+
+ This license grants a worldwide, royalty-free, perpetual and
+ irrevocable right and license to use, execute, perform, compile,
+ display, copy, create derivative works of, distribute and
+ sublicense the FreeType Project (in both source and object code
+ forms) and derivative works thereof for any purpose; and to
+ authorize others to exercise some or all of the rights granted
+ herein, subject to the following conditions:
+
+ o Redistribution of source code must retain this license file
+ (`FTL.TXT') unaltered; any additions, deletions or changes to
+ the original files must be clearly indicated in accompanying
+ documentation. The copyright notices of the unaltered,
+ original files must be preserved in all copies of source
+ files.
+
+ o Redistribution in binary form must provide a disclaimer that
+ states that the software is based in part of the work of the
+ FreeType Team, in the distribution documentation. We also
+ encourage you to put an URL to the FreeType web page in your
+ documentation, though this isn't mandatory.
+
+ These conditions apply to any software derived from or based on
+ the FreeType Project, not just the unmodified files. If you use
+ our work, you must acknowledge us. However, no fee need be paid
+ to us.
+
+3. Advertising
+--------------
+
+ Neither the FreeType authors and contributors nor you shall use
+ the name of the other for commercial, advertising, or promotional
+ purposes without specific prior written permission.
+
+ We suggest, but do not require, that you use one or more of the
+ following phrases to refer to this software in your documentation
+ or advertising materials: `FreeType Project', `FreeType Engine',
+ `FreeType library', or `FreeType Distribution'.
+
+ As you have not signed this license, you are not required to
+ accept it. However, as the FreeType Project is copyrighted
+ material, only this license, or another one contracted with the
+ authors, grants you the right to use, distribute, and modify it.
+ Therefore, by using, distributing, or modifying the FreeType
+ Project, you indicate that you understand and accept all the terms
+ of this license.
+
+4. Contacts
+-----------
+
+ There are two mailing lists related to FreeType:
+
+ o freetype@freetype.org
+
+ Discusses general use and applications of FreeType, as well as
+ future and wanted additions to the library and distribution.
+ If you are looking for support, start in this list if you
+ haven't found anything to help you in the documentation.
+
+ o devel@freetype.org
+
+ Discusses bugs, as well as engine internals, design issues,
+ specific licenses, porting, etc.
+
+ o http://www.freetype.org
+
+ Holds the current FreeType web page, which will allow you to
+ download our latest development version and read online
+ documentation.
+
+ You can also contact us individually at:
+
+ David Turner <david.turner@freetype.org>
+ Robert Wilhelm <robert.wilhelm@freetype.org>
+ Werner Lemberg <werner.lemberg@freetype.org>
+
+
+--- end of FTL.TXT ---
diff --git a/trunk/pango/opentype/COPYING.GPL b/trunk/pango/opentype/COPYING.GPL
new file mode 100644
index 00000000..14db8fc7
--- /dev/null
+++ b/trunk/pango/opentype/COPYING.GPL
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/trunk/pango/opentype/Makefile.am b/trunk/pango/opentype/Makefile.am
new file mode 100644
index 00000000..84de2606
--- /dev/null
+++ b/trunk/pango/opentype/Makefile.am
@@ -0,0 +1,59 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = \
+ $(FREETYPE_CFLAGS)
+
+noinst_LTLIBRARIES = libharfbuzz-1.la
+
+MAINSOURCES = \
+ ftglue.c \
+ harfbuzz-buffer.c \
+ harfbuzz-dump.c \
+ harfbuzz-gdef.c \
+ harfbuzz-gpos.c \
+ harfbuzz-gsub.c \
+ harfbuzz-open.c
+
+EXTRA_SOURCES = harfbuzz.c
+
+PUBLICHEADERS = \
+ harfbuzz.h \
+ harfbuzz-buffer.h \
+ harfbuzz-dump.h \
+ harfbuzz-gdef.h \
+ harfbuzz-gpos.h \
+ harfbuzz-gsub.h \
+ harfbuzz-open.h
+
+PRIVATEHEADERS = \
+ ftglue.h \
+ harfbuzz-impl.h \
+ harfbuzz-gdef-private.h \
+ harfbuzz-gpos-private.h \
+ harfbuzz-gsub-private.h \
+ harfbuzz-open-private.h
+
+libharfbuzz_1_la_SOURCES = \
+ $(MAINSOURCES) \
+ $(PUBLICHEADERS) \
+ $(PRIVATEHEADERS)
+
+libharfbuzz_1_la_LIBADD = \
+ $(FREETYPE_LIBS)
+
+noinst_PROGRAMS = harfbuzz-dump
+
+harfbuzz_dump_SOURCES = \
+ harfbuzz-dump-main.c
+
+harfbuzz_dump_LDADD = \
+ $(libharfbuzz_1_la_LIBADD) \
+ libharfbuzz-1.la
+
+EXTRA_DIST = \
+ README \
+ COPYING.FTL \
+ COPYING.GPL \
+ COPYING \
+ $(EXTRA_SOURCES)
+
diff --git a/trunk/pango/opentype/README b/trunk/pango/opentype/README
new file mode 100644
index 00000000..f7746efc
--- /dev/null
+++ b/trunk/pango/opentype/README
@@ -0,0 +1,18 @@
+This is HarfBuzz, an OpenType Layout engine.
+
+It was derived originally from the OpenType code in FreeType-1.x, ported to
+FreeType2. (This code has been abandoned for FreeType2, but until something
+better comes along, should serve our purposes.) In addition to porting to
+FreeType-2, it has been modified in various other ways.
+
+It also includes a partial XML dumper for OpenType Layout tables useful for
+figuring out what is going on. Please extend to cover additional parts of the
+tables as you encounter fonts using them. The dumper is written by Owen Taylor.
+
+Bug reports on these files should be sent to the HarfBuzz mailing list as
+listed on http://freedesktop.org/wiki/Software/harfbuzz
+
+For license information, see the file COPYING.
+
+Behdad Esfahbod
+April 1st, 2006
diff --git a/trunk/pango/opentype/ftglue.c b/trunk/pango/opentype/ftglue.c
new file mode 100644
index 00000000..6444e67d
--- /dev/null
+++ b/trunk/pango/opentype/ftglue.c
@@ -0,0 +1,300 @@
+/* ftglue.c: Glue code for compiling the OpenType code from
+ * FreeType 1 using only the public API of FreeType 2
+ *
+ * By David Turner, The FreeType Project (www.freetype.org)
+ *
+ * This code is explicitely put in the public domain
+ *
+ * See ftglue.h for more information.
+ */
+
+#include "ftglue.h"
+
+#if 0
+#include <stdio.h>
+#define LOG(x) _hb_ftglue_log x
+
+static void
+_hb_ftglue_log( const char* format, ... )
+{
+ va_list ap;
+
+ va_start( ap, format );
+ vfprintf( stderr, format, ap );
+ va_end( ap );
+}
+
+#else
+#define LOG(x) do {} while (0)
+#endif
+
+/* only used internally */
+static FT_Pointer
+_hb_ftglue_qalloc( FT_Memory memory,
+ FT_ULong size,
+ FT_Error *perror )
+{
+ FT_Error error = 0;
+ FT_Pointer block = NULL;
+
+ if ( size > 0 )
+ {
+ block = memory->alloc( memory, size );
+ if ( !block )
+ error = FT_Err_Out_Of_Memory;
+ }
+
+ *perror = error;
+ return block;
+}
+
+#undef QALLOC /* just in case */
+#define QALLOC(ptr,size) ( (ptr) = _hb_ftglue_qalloc( memory, (size), &error ), error != 0 )
+
+
+FTGLUE_APIDEF( FT_Pointer )
+_hb_ftglue_alloc( FT_Memory memory,
+ FT_ULong size,
+ FT_Error *perror )
+{
+ FT_Error error = 0;
+ FT_Pointer block = NULL;
+
+ if ( size > 0 )
+ {
+ block = memory->alloc( memory, size );
+ if ( !block )
+ error = FT_Err_Out_Of_Memory;
+ else
+ memset( (char*)block, 0, (size_t)size );
+ }
+
+ *perror = error;
+ return block;
+}
+
+
+FTGLUE_APIDEF( FT_Pointer )
+_hb_ftglue_realloc( FT_Memory memory,
+ FT_Pointer block,
+ FT_ULong old_size,
+ FT_ULong new_size,
+ FT_Error *perror )
+{
+ FT_Pointer block2 = NULL;
+ FT_Error error = 0;
+
+ if ( old_size == 0 || block == NULL )
+ {
+ block2 = _hb_ftglue_alloc( memory, new_size, &error );
+ }
+ else if ( new_size == 0 )
+ {
+ _hb_ftglue_free( memory, block );
+ }
+ else
+ {
+ block2 = memory->realloc( memory, old_size, new_size, block );
+ if ( block2 == NULL )
+ error = FT_Err_Out_Of_Memory;
+ else if ( new_size > old_size )
+ memset( (char*)block2 + old_size, 0, (size_t)(new_size - old_size) );
+ }
+
+ if ( !error )
+ block = block2;
+
+ *perror = error;
+ return block;
+}
+
+
+FTGLUE_APIDEF( void )
+_hb_ftglue_free( FT_Memory memory,
+ FT_Pointer block )
+{
+ if ( block )
+ memory->free( memory, block );
+}
+
+
+FTGLUE_APIDEF( FT_Long )
+_hb_ftglue_stream_pos( FT_Stream stream )
+{
+ LOG(( "ftglue:stream:pos() -> %ld\n", stream->pos ));
+ return stream->pos;
+}
+
+
+FTGLUE_APIDEF( FT_Error )
+_hb_ftglue_stream_seek( FT_Stream stream,
+ FT_Long pos )
+{
+ FT_Error error = 0;
+
+ stream->pos = pos;
+ if ( stream->read )
+ {
+ if ( stream->read( stream, pos, NULL, 0 ) )
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+ else if ( pos > (FT_Long)stream->size )
+ error = FT_Err_Invalid_Stream_Operation;
+
+ LOG(( "ftglue:stream:seek(%ld) -> %d\n", pos, error ));
+ return error;
+}
+
+
+FTGLUE_APIDEF( FT_Error )
+_hb_ftglue_stream_frame_enter( FT_Stream stream,
+ FT_ULong count )
+{
+ FT_Error error = FT_Err_Ok;
+ FT_ULong read_bytes;
+
+ if ( stream->read )
+ {
+ /* allocate the frame in memory */
+ FT_Memory memory = stream->memory;
+
+
+ if ( QALLOC( stream->base, count ) )
+ goto Exit;
+
+ /* read it */
+ read_bytes = stream->read( stream, stream->pos,
+ stream->base, count );
+ if ( read_bytes < count )
+ {
+ FREE( stream->base );
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+ stream->cursor = stream->base;
+ stream->limit = stream->cursor + count;
+ stream->pos += read_bytes;
+ }
+ else
+ {
+ /* check current and new position */
+ if ( stream->pos >= stream->size ||
+ stream->pos + count > stream->size )
+ {
+ error = FT_Err_Invalid_Stream_Operation;
+ goto Exit;
+ }
+
+ /* set cursor */
+ stream->cursor = stream->base + stream->pos;
+ stream->limit = stream->cursor + count;
+ stream->pos += count;
+ }
+
+Exit:
+ LOG(( "ftglue:stream:frame_enter(%ld) -> %d\n", count, error ));
+ return error;
+}
+
+
+FTGLUE_APIDEF( void )
+_hb_ftglue_stream_frame_exit( FT_Stream stream )
+{
+ if ( stream->read )
+ {
+ FT_Memory memory = stream->memory;
+
+ FREE( stream->base );
+ }
+ stream->cursor = NULL;
+ stream->limit = NULL;
+
+ LOG(( "ftglue:stream:frame_exit()\n" ));
+}
+
+
+FTGLUE_APIDEF( FT_Error )
+_hb_ftglue_face_goto_table( FT_Face face,
+ FT_ULong the_tag,
+ FT_Stream stream )
+{
+ FT_Error error;
+
+ LOG(( "_hb_ftglue_face_goto_table( %p, %c%c%c%c, %p )\n",
+ face,
+ (int)((the_tag >> 24) & 0xFF),
+ (int)((the_tag >> 16) & 0xFF),
+ (int)((the_tag >> 8) & 0xFF),
+ (int)(the_tag & 0xFF),
+ stream ));
+
+ if ( !FT_IS_SFNT(face) )
+ {
+ LOG(( "not a SFNT face !!\n" ));
+ error = FT_Err_Invalid_Face_Handle;
+ }
+ else
+ {
+ /* parse the directory table directly, without using
+ * FreeType's built-in data structures
+ */
+ FT_ULong offset = 0;
+ FT_UInt count, nn;
+
+ if ( face->num_faces > 1 )
+ {
+ /* deal with TrueType collections */
+ LOG(( ">> This is a TrueType Collection\n" ));
+
+ if ( FILE_Seek( 12 + face->face_index*4 ) ||
+ ACCESS_Frame( 4 ) )
+ goto Exit;
+
+ offset = GET_ULong();
+
+ FORGET_Frame();
+ }
+
+ LOG(( "TrueType offset = %ld\n", offset ));
+
+ if ( FILE_Seek( offset+4 ) ||
+ ACCESS_Frame( 2 ) )
+ goto Exit;
+
+ count = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( FILE_Seek( offset+12 ) ||
+ ACCESS_Frame( count*16 ) )
+ goto Exit;
+
+ for ( nn = 0; nn < count; nn++ )
+ {
+ FT_ULong tag = GET_ULong();
+ FT_ULong checksum = GET_ULong();
+ FT_ULong start = GET_ULong();
+ FT_ULong size = GET_ULong();
+
+ FT_UNUSED(checksum);
+ FT_UNUSED(size);
+
+ if ( tag == the_tag )
+ {
+ LOG(( "TrueType table (start: %ld) (size: %ld)\n", start, size ));
+ error = _hb_ftglue_stream_seek( stream, start );
+ goto FoundIt;
+ }
+ }
+ error = FT_Err_Table_Missing;
+
+ FoundIt:
+ FORGET_Frame();
+ }
+
+Exit:
+ LOG(( "TrueType error=%d\n", error ));
+
+ return error;
+}
+
+#undef QALLOC
diff --git a/trunk/pango/opentype/ftglue.h b/trunk/pango/opentype/ftglue.h
new file mode 100644
index 00000000..84de7f35
--- /dev/null
+++ b/trunk/pango/opentype/ftglue.h
@@ -0,0 +1,150 @@
+/* ftglue.h: Glue code for compiling the OpenType code from
+ * FreeType 1 using only the public API of FreeType 2
+ *
+ * By David Turner, The FreeType Project (www.freetype.org)
+ *
+ * This code is explicitely put in the public domain
+ *
+ * ==========================================================================
+ *
+ * the OpenType parser codes was originally written as an extension to
+ * FreeType 1.x. As such, its source code was embedded within the library,
+ * and used many internal FreeType functions to deal with memory and
+ * stream i/o.
+ *
+ * When it was 'salvaged' for Pango and Qt, the code was "ported" to FreeType 2,
+ * which basically means that some macro tricks were performed in order to
+ * directly access FT2 _internal_ functions.
+ *
+ * these functions were never part of FT2 public API, and _did_ change between
+ * various releases. This created chaos for many users: when they upgraded the
+ * FreeType library on their system, they couldn't run Gnome anymore since
+ * Pango refused to link.
+ *
+ * Very fortunately, it's possible to completely avoid this problem because
+ * the FT_StreamRec and FT_MemoryRec structure types, which describe how
+ * memory and stream implementations interface with the rest of the font
+ * library, have always been part of the public API, and never changed.
+ *
+ * What we do thus is re-implement, within the OpenType parser, the few
+ * functions that depend on them. This only adds one or two kilobytes of
+ * code, and ensures that the parser can work with _any_ version
+ * of FreeType installed on your system. How sweet... !
+ *
+ * Note that we assume that Pango doesn't use any other internal functions
+ * from FreeType. It used to in old versions, but this should no longer
+ * be the case. (crossing my fingers).
+ *
+ * - David Turner
+ * - The FreeType Project (www.freetype.org)
+ *
+ * PS: This "glue" code is explicitely put in the public domain
+ */
+#ifndef FTGLUE_H
+#define FTGLUE_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+FT_BEGIN_HEADER
+
+
+/* utility macros */
+
+#define SET_ERR(c) ( (error = (c)) != 0 )
+
+#ifndef FTGLUE_API
+#define FTGLUE_API(x) extern x
+#endif
+
+#ifndef FTGLUE_APIDEF
+#define FTGLUE_APIDEF(x) x
+#endif
+
+/* stream macros used by the OpenType parser */
+#define FILE_Pos() _hb_ftglue_stream_pos( stream )
+#define FILE_Seek(pos) SET_ERR( _hb_ftglue_stream_seek( stream, pos ) )
+#define ACCESS_Frame(size) SET_ERR( _hb_ftglue_stream_frame_enter( stream, size ) )
+#define FORGET_Frame() _hb_ftglue_stream_frame_exit( stream )
+
+#define GET_Byte() (*stream->cursor++)
+#define GET_Short() (stream->cursor += 2, (FT_Short)( \
+ (*(((FT_Byte*)stream->cursor)-2) << 8) | \
+ *(((FT_Byte*)stream->cursor)-1) \
+ ))
+#define GET_Long() (stream->cursor += 4, (FT_Long)( \
+ (*(((FT_Byte*)stream->cursor)-4) << 24) | \
+ (*(((FT_Byte*)stream->cursor)-3) << 16) | \
+ (*(((FT_Byte*)stream->cursor)-2) << 8) | \
+ *(((FT_Byte*)stream->cursor)-1) \
+ ))
+
+
+#define GET_Char() ((FT_Char)GET_Byte())
+#define GET_UShort() ((FT_UShort)GET_Short())
+#define GET_ULong() ((FT_ULong)GET_Long())
+#define GET_Tag4() GET_ULong()
+
+FTGLUE_API( FT_Long )
+_hb_ftglue_stream_pos( FT_Stream stream );
+
+FTGLUE_API( FT_Error )
+_hb_ftglue_stream_seek( FT_Stream stream,
+ FT_Long pos );
+
+FTGLUE_API( FT_Error )
+_hb_ftglue_stream_frame_enter( FT_Stream stream,
+ FT_ULong size );
+
+FTGLUE_API( void )
+_hb_ftglue_stream_frame_exit( FT_Stream stream );
+
+FTGLUE_API( FT_Error )
+_hb_ftglue_face_goto_table( FT_Face face,
+ FT_ULong tag,
+ FT_Stream stream );
+
+/* memory macros used by the OpenType parser */
+#define ALLOC(_ptr,_size) \
+ ( (_ptr) = _hb_ftglue_alloc( memory, _size, &error ), error != 0 )
+
+#define REALLOC(_ptr,_oldsz,_newsz) \
+ ( (_ptr) = _hb_ftglue_realloc( memory, (_ptr), (_oldsz), (_newsz), &error ), error != 0 )
+
+#define FREE(_ptr) \
+ do { \
+ if ( (_ptr) ) \
+ { \
+ _hb_ftglue_free( memory, _ptr ); \
+ _ptr = NULL; \
+ } \
+ } while (0)
+
+#define ALLOC_ARRAY(_ptr,_count,_type) \
+ ALLOC(_ptr,(_count)*sizeof(_type))
+
+#define REALLOC_ARRAY(_ptr,_oldcnt,_newcnt,_type) \
+ REALLOC(_ptr,(_oldcnt)*sizeof(_type),(_newcnt)*sizeof(_type))
+
+#define MEM_Copy(dest,source,count) memcpy( (char*)(dest), (const char*)(source), (size_t)(count) )
+
+
+FTGLUE_API( FT_Pointer )
+_hb_ftglue_alloc( FT_Memory memory,
+ FT_ULong size,
+ FT_Error *perror_ );
+
+FTGLUE_API( FT_Pointer )
+_hb_ftglue_realloc( FT_Memory memory,
+ FT_Pointer block,
+ FT_ULong old_size,
+ FT_ULong new_size,
+ FT_Error *perror_ );
+
+FTGLUE_API( void )
+_hb_ftglue_free( FT_Memory memory,
+ FT_Pointer block );
+
+FT_END_HEADER
+
+#endif /* FTGLUE_H */
diff --git a/trunk/pango/opentype/harfbuzz-buffer.c b/trunk/pango/opentype/harfbuzz-buffer.c
new file mode 100644
index 00000000..3d233b4a
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-buffer.c
@@ -0,0 +1,227 @@
+/* harfbuzz-buffer.c: Buffer of glyphs for substitution/positioning
+ *
+ * Copyright 2004 Red Hat Software
+ *
+ * Portions Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ */
+
+#include "harfbuzz-impl.h"
+#include "harfbuzz-buffer.h"
+#include "harfbuzz-gsub-private.h"
+#include "harfbuzz-gpos-private.h"
+
+static FT_Error
+hb_buffer_ensure( HB_Buffer buffer,
+ FT_ULong size )
+{
+ FT_Memory memory = buffer->memory;
+ FT_ULong new_allocated = buffer->allocated;
+
+ if (size > new_allocated)
+ {
+ FT_Error error;
+
+ while (size > new_allocated)
+ new_allocated += (new_allocated >> 1) + 8;
+
+ if ( REALLOC_ARRAY( buffer->in_string, buffer->allocated, new_allocated, HB_GlyphItemRec ) )
+ return error;
+ if ( REALLOC_ARRAY( buffer->out_string, buffer->allocated, new_allocated, HB_GlyphItemRec ) )
+ return error;
+ if ( REALLOC_ARRAY( buffer->positions, buffer->allocated, new_allocated, HB_PositionRec ) )
+ return error;
+
+ buffer->allocated = new_allocated;
+ }
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_new( FT_Memory memory,
+ HB_Buffer *buffer )
+{
+ FT_Error error;
+
+ if ( ALLOC( *buffer, sizeof( HB_BufferRec ) ) )
+ return error;
+
+ (*buffer)->memory = memory;
+ (*buffer)->in_length = 0;
+ (*buffer)->out_length = 0;
+ (*buffer)->allocated = 0;
+ (*buffer)->in_pos = 0;
+ (*buffer)->out_pos = 0;
+
+ (*buffer)->in_string = NULL;
+ (*buffer)->out_string = NULL;
+ (*buffer)->positions = NULL;
+ (*buffer)->max_ligID = 0;
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_swap( HB_Buffer buffer )
+{
+ HB_GlyphItem tmp_string;
+
+ tmp_string = buffer->in_string;
+ buffer->in_string = buffer->out_string;
+ buffer->out_string = tmp_string;
+
+ buffer->in_length = buffer->out_length;
+ buffer->out_length = 0;
+
+ buffer->in_pos = 0;
+ buffer->out_pos = 0;
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_free( HB_Buffer buffer )
+{
+ FT_Memory memory = buffer->memory;
+
+ FREE( buffer->in_string );
+ FREE( buffer->out_string );
+ FREE( buffer->positions );
+ FREE( buffer );
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_clear( HB_Buffer buffer )
+{
+ buffer->in_length = 0;
+ buffer->out_length = 0;
+ buffer->in_pos = 0;
+ buffer->out_pos = 0;
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_add_glyph( HB_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UInt properties,
+ FT_UInt cluster )
+{
+ FT_Error error;
+ HB_GlyphItem glyph;
+
+ error = hb_buffer_ensure( buffer, buffer->in_length + 1 );
+ if ( error )
+ return error;
+
+ glyph = &buffer->in_string[buffer->in_length];
+ glyph->gindex = glyph_index;
+ glyph->properties = properties;
+ glyph->cluster = cluster;
+ glyph->component = 0;
+ glyph->ligID = 0;
+ glyph->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;
+
+ buffer->in_length++;
+
+ return FT_Err_Ok;
+}
+
+/* The following function copies `num_out' elements from `glyph_data'
+ to `buffer->out_string', advancing the in array pointer in the structure
+ by `num_in' elements, and the out array pointer by `num_out' elements.
+ Finally, it sets the `length' field of `out' equal to
+ `pos' of the `out' structure.
+
+ If `component' is 0xFFFF, the component value from buffer->in_pos
+ will copied `num_out' times, otherwise `component' itself will
+ be used to fill the `component' fields.
+
+ If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
+ will copied `num_out' times, otherwise `ligID' itself will
+ be used to fill the `ligID' fields.
+
+ The properties for all replacement glyphs are taken
+ from the glyph at position `buffer->in_pos'.
+
+ The cluster value for the glyph at position buffer->in_pos is used
+ for all replacement glyphs */
+FT_Error
+hb_buffer_add_output_glyphs( HB_Buffer buffer,
+ FT_UShort num_in,
+ FT_UShort num_out,
+ FT_UShort *glyph_data,
+ FT_UShort component,
+ FT_UShort ligID )
+{
+ FT_Error error;
+ FT_UShort i;
+ FT_UInt properties;
+ FT_UInt cluster;
+
+ error = hb_buffer_ensure( buffer, buffer->out_pos + num_out );
+ if ( error )
+ return error;
+
+ properties = buffer->in_string[buffer->in_pos].properties;
+ cluster = buffer->in_string[buffer->in_pos].cluster;
+ if ( component == 0xFFFF )
+ component = buffer->in_string[buffer->in_pos].component;
+ if ( ligID == 0xFFFF )
+ ligID = buffer->in_string[buffer->in_pos].ligID;
+
+ for ( i = 0; i < num_out; i++ )
+ {
+ HB_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
+
+ item->gindex = glyph_data[i];
+ item->properties = properties;
+ item->cluster = cluster;
+ item->component = component;
+ item->ligID = ligID;
+ item->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;
+ }
+
+ buffer->in_pos += num_in;
+ buffer->out_pos += num_out;
+
+ buffer->out_length = buffer->out_pos;
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_add_output_glyph( HB_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UShort component,
+ FT_UShort ligID )
+{
+ FT_UShort glyph_data = glyph_index;
+
+ return hb_buffer_add_output_glyphs ( buffer, 1, 1,
+ &glyph_data, component, ligID );
+}
+
+FT_Error
+hb_buffer_copy_output_glyph ( HB_Buffer buffer )
+{
+ FT_Error error;
+
+ error = hb_buffer_ensure( buffer, buffer->out_pos + 1 );
+ if ( error )
+ return error;
+
+ buffer->out_string[buffer->out_pos++] = buffer->in_string[buffer->in_pos++];
+ buffer->out_length = buffer->out_pos;
+
+ return FT_Err_Ok;
+}
+
+FT_UShort
+hb_buffer_allocate_ligid( HB_Buffer buffer )
+{
+ return buffer->max_ligID++;
+}
diff --git a/trunk/pango/opentype/harfbuzz-buffer.h b/trunk/pango/opentype/harfbuzz-buffer.h
new file mode 100644
index 00000000..c7478e38
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-buffer.h
@@ -0,0 +1,106 @@
+/* harfbuzz-buffer.h: Buffer of glyphs for substitution/positioning
+ *
+ * Copyrigh 2004 Red Hat Software
+ *
+ * Portions Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ */
+#ifndef HARFBUZZ_BUFFER_H
+#define HARFBUZZ_BUFFER_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+FT_BEGIN_HEADER
+
+#define HB_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
+
+typedef struct HB_GlyphItemRec_ {
+ FT_UInt gindex;
+ FT_UInt properties;
+ FT_UInt cluster;
+ FT_UShort component;
+ FT_UShort ligID;
+ FT_UShort gproperties;
+} HB_GlyphItemRec, *HB_GlyphItem;
+
+typedef struct HB_PositionRec_ {
+ FT_Pos x_pos;
+ FT_Pos y_pos;
+ FT_Pos x_advance;
+ FT_Pos y_advance;
+ FT_UShort back; /* number of glyphs to go back
+ for drawing current glyph */
+ FT_Bool new_advance; /* if set, the advance width values are
+ absolute, i.e., they won't be
+ added to the original glyph's value
+ but rather replace them. */
+ FT_Short cursive_chain; /* character to which this connects,
+ may be positive or negative; used
+ only internally */
+} HB_PositionRec, *HB_Position;
+
+
+typedef struct HB_BufferRec_{
+ FT_Memory memory;
+ FT_ULong allocated;
+
+ FT_ULong in_length;
+ FT_ULong out_length;
+ FT_ULong in_pos;
+ FT_ULong out_pos;
+
+ HB_GlyphItem in_string;
+ HB_GlyphItem out_string;
+ HB_Position positions;
+ FT_UShort max_ligID;
+} HB_BufferRec, *HB_Buffer;
+
+FT_Error
+hb_buffer_new( FT_Memory memory,
+ HB_Buffer *buffer );
+
+FT_Error
+hb_buffer_swap( HB_Buffer buffer );
+
+FT_Error
+hb_buffer_free( HB_Buffer buffer );
+
+FT_Error
+hb_buffer_clear( HB_Buffer buffer );
+
+FT_Error
+hb_buffer_add_glyph( HB_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UInt properties,
+ FT_UInt cluster );
+
+FT_Error
+hb_buffer_add_output_glyphs( HB_Buffer buffer,
+ FT_UShort num_in,
+ FT_UShort num_out,
+ FT_UShort *glyph_data,
+ FT_UShort component,
+ FT_UShort ligID );
+
+FT_Error
+hb_buffer_add_output_glyph ( HB_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UShort component,
+ FT_UShort ligID );
+
+FT_Error
+hb_buffer_copy_output_glyph ( HB_Buffer buffer );
+
+FT_UShort
+hb_buffer_allocate_ligid( HB_Buffer buffer );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_BUFFER_H */
diff --git a/trunk/pango/opentype/harfbuzz-dump-main.c b/trunk/pango/opentype/harfbuzz-dump-main.c
new file mode 100644
index 00000000..81fecf43
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-dump-main.c
@@ -0,0 +1,272 @@
+/* harfbuzz-dump-main.c: Test program for OpenType
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "harfbuzz-open.h"
+
+#include "harfbuzz-dump.h"
+
+#define N_ELEMENTS(arr) (sizeof(arr)/ sizeof((arr)[0]))
+
+static int
+croak (const char *situation, FT_Error error)
+{
+ fprintf (stderr, "%s: Error %d\n", situation, error);
+
+ exit (1);
+}
+
+#if 0
+enum {
+ I = 1 << 0,
+ M = 1 << 1,
+ F = 1 << 2,
+ L = 1 << 3
+};
+
+static void
+print_tag (FT_ULong tag)
+{
+ fprintf (stderr, "%c%c%c%c",
+ (unsigned char)(tag >> 24),
+ (unsigned char)((tag >> 16) & 0xff),
+ (unsigned char)((tag >> 8) & 0xff),
+ (unsigned char)(tag & 0xff));
+}
+
+static void
+maybe_add_feature (HB_GSUB gsub,
+ FT_UShort script_index,
+ FT_ULong tag,
+ FT_UShort property)
+{
+ FT_Error error;
+ FT_UShort feature_index;
+
+ /* 0xffff == default language system */
+ error = HB_GSUB_Select_Feature (gsub, tag, script_index, 0xffff, &feature_index);
+
+ if (error)
+ {
+ if (error == HB_Err_Not_Covered)
+ {
+ print_tag (tag);
+ fprintf (stderr, " not covered, ignored\n");
+ return;
+ }
+
+ croak ("HB_GSUB_Select_Feature", error);
+ }
+
+ if ((error = HB_GSUB_Add_Feature (gsub, feature_index, property)))
+ croak ("HB_GSUB_Add_Feature", error);
+}
+
+static void
+select_cmap (FT_Face face)
+{
+ FT_UShort i;
+ FT_CharMap cmap = NULL;
+
+ for (i = 0; i < face->num_charmaps; i++)
+ {
+ if (face->charmaps[i]->platform_id == 3 && face->charmaps[i]->encoding_id == 1)
+ {
+ cmap = face->charmaps[i];
+ break;
+ }
+ }
+
+ /* we try only pid/eid (0,0) if no (3,1) map is found -- many Windows
+ fonts have only rudimentary (0,0) support. */
+
+ if (!cmap)
+ for (i = 0; i < face->num_charmaps; i++)
+ {
+ if (face->charmaps[i]->platform_id == 3 && face->charmaps[i]->encoding_id == 1)
+ {
+ cmap = face->charmaps[i];
+ break;
+ }
+ }
+
+ if (cmap)
+ FT_Set_Charmap (face, cmap);
+ else
+ {
+ fprintf (stderr, "Sorry, but this font doesn't contain"
+ " any Unicode mapping table.\n");
+ exit (1);
+ }
+}
+
+static void
+add_features (HB_GSUB gsub)
+{
+ FT_Error error;
+ FT_ULong tag = FT_MAKE_TAG ('a', 'r', 'a', 'b');
+ FT_UShort script_index;
+
+ error = HB_GSUB_Select_Script (gsub, tag, &script_index);
+
+ if (error)
+ {
+ if (error == HB_Err_Not_Covered)
+ {
+ fprintf (stderr, "Arabic not covered, no features used\n");
+ return;
+ }
+
+ croak ("HB_GSUB_Select_Script", error);
+ }
+
+ maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('i', 'n', 'i', 't'), I);
+ maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('m', 'e', 'd', 'i'), M);
+ maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('f', 'i', 'n', 'a'), F);
+ maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('l', 'i', 'g', 'a'), L);
+}
+#endif
+
+#if 0
+void
+dump_string (HB_GSUB_String *str)
+{
+ FT_ULong i;
+
+ fprintf (stderr, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
+ for (i = 0; i < str->length; i++)
+ {
+ fprintf (stderr, "%2lu: %#06x %#06x %4d %4d\n",
+ i,
+ str->string[i],
+ str->properties[i],
+ str->components[i],
+ str->ligIDs[i]);
+ }
+ fprintf (stderr, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+}
+
+FT_UShort arabic_str[] = { 0x645, 0x643, 0x64a, 0x644, 0x639, 0x20, 0x645, 0x627, 0x644, 0x633, 0x644, 0x627 };
+FT_UShort arabic_props[] = { I|L, M|L, M|L, M|L, M|L, F|L, I|L, M|L, M|L, M|L, M|L, F|L };
+
+void
+try_string (FT_Library library,
+ FT_Face face,
+ HB_GSUB gsub)
+{
+ FT_Error error;
+ HB_GSUB_String *in_str;
+ HB_GSUB_String *out_str;
+ FT_ULong i;
+
+ if ((error = HB_GSUB_String_New (face->memory, &in_str)))
+ croak ("HB_GSUB_String_New", error);
+ if ((error = HB_GSUB_String_New (face->memory, &out_str)))
+ croak ("HB_GSUB_String_New", error);
+
+ if ((error = HB_GSUB_String_Set_Length (in_str, N_ELEMENTS (arabic_str))))
+ croak ("HB_GSUB_String_Set_Length", error);
+
+ for (i=0; i < N_ELEMENTS (arabic_str); i++)
+ {
+ in_str->string[i] = FT_Get_Char_Index (face, arabic_str[i]);
+ in_str->properties[i] = arabic_props[i];
+ in_str->components[i] = i;
+ in_str->ligIDs[i] = i;
+ }
+
+ if ((error = HB_GSUB_Apply_String (gsub, in_str, out_str)))
+ croak ("HB_GSUB_Apply_String", error);
+
+ dump_string (in_str);
+ dump_string (out_str);
+
+ if ((error = HB_GSUB_String_Done (in_str)))
+ croak ("HB_GSUB_String_New", error);
+ if ((error = HB_GSUB_String_Done (out_str)))
+ croak ("HB_GSUB_String_New", error);
+}
+#endif
+
+int
+main (int argc, char **argv)
+{
+ FT_Error error;
+ FT_Library library;
+ FT_Face face;
+ HB_GSUB gsub;
+ HB_GPOS gpos;
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage: ottest MYFONT.TTF\n");
+ exit(1);
+ }
+
+ if ((error = FT_Init_FreeType (&library)))
+ croak ("FT_Init_FreeType", error);
+
+ if ((error = FT_New_Face (library, argv[1], 0, &face)))
+ croak ("FT_New_Face", error);
+
+ printf ("<?xml version=\"1.0\"?>\n");
+ printf ("<OpenType>\n");
+
+ if (!(error = HB_Load_GSUB_Table (face, &gsub, NULL)))
+ {
+ HB_Dump_GSUB_Table (gsub, stdout);
+
+ if ((error = HB_Done_GSUB_Table (gsub)))
+ croak ("HB_Done_GSUB_Table", error);
+ }
+ else if (error != FT_Err_Table_Missing)
+ fprintf (stderr, "HB_Load_GSUB_Table %x\n", error);
+
+ if (!(error = HB_Load_GPOS_Table (face, &gpos, NULL)))
+ {
+ HB_Dump_GPOS_Table (gpos, stdout);
+
+ if ((error = HB_Done_GPOS_Table (gpos)))
+ croak ("HB_Done_GPOS_Table", error);
+ }
+ else if (error != FT_Err_Table_Missing)
+ fprintf (stderr, "HB_Load_GPOS_Table %x\n", error);
+
+ printf ("</OpenType>\n");
+
+#if 0
+ select_cmap (face);
+
+ add_features (gsub);
+ try_string (library, face, gsub);
+#endif
+
+
+ if ((error = FT_Done_Face (face)))
+ croak ("FT_Done_Face", error);
+
+ if ((error = FT_Done_FreeType (library)))
+ croak ("FT_Done_FreeType", error);
+
+ return 0;
+}
+
diff --git a/trunk/pango/opentype/harfbuzz-dump.c b/trunk/pango/opentype/harfbuzz-dump.c
new file mode 100644
index 00000000..bf30f66b
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-dump.c
@@ -0,0 +1,748 @@
+/* harfbuzz-dump.c: Dump OpenType layout tables
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "harfbuzz-impl.h"
+#include "harfbuzz-dump.h"
+#include "harfbuzz-gdef-private.h"
+#include "harfbuzz-gsub-private.h"
+#include "harfbuzz-gpos-private.h"
+#include "harfbuzz-open-private.h"
+#include <stdarg.h>
+
+#define DUMP(format) dump (stream, indent, format)
+#define DUMP1(format, arg1) dump (stream, indent, format, arg1)
+#define DUMP2(format, arg1, arg2) dump (stream, indent, format, arg1, arg2)
+#define DUMP3(format, arg1, arg2, arg3) dump (stream, indent, format, arg1, arg2, arg3)
+
+#define DUMP_FINT(strct,fld) dump (stream, indent, "<" #fld ">%d</" #fld ">\n", (strct)->fld)
+#define DUMP_FUINT(strct,fld) dump (stream, indent, "<" #fld ">%u</" #fld ">\n", (strct)->fld)
+#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#06x</" #fld ">\n", (strct)->fld)
+#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#06x</" #fld ">\n", (strct)->fld)
+#define DUMP_USHORT_ARRAY(strct,fld,cnt) Dump_UShort_Array ((strct)->fld, cnt, #fld, stream, indent);
+
+#define DEF_DUMP(type) static void Dump_ ## type (HB_ ## type *type, FILE *stream, int indent, HB_Type hb_type)
+#define RECURSE(name, type, val) do { DUMP ("<" #name ">\n"); Dump_ ## type (val, stream, indent + 1, hb_type); DUMP ("</" #name ">\n"); } while (0)
+#define RECURSE_NUM(name, i, type, val) do { DUMP1 ("<" #name "> <!-- %d -->\n", i); Dump_ ## type (val, stream, indent + 1, hb_type); DUMP ("</" #name ">\n"); } while (0)
+#define DUMP_VALUE_RECORD(val, frmt) do { DUMP ("<ValueRecord>\n"); Dump_ValueRecord (val, stream, indent + 1, hb_type, frmt); DUMP ("</ValueRecord>\n"); } while (0)
+
+static void
+do_indent (FILE *stream, int indent)
+{
+ fprintf (stream, "%*s", indent * 3, "");
+}
+
+static void
+dump (FILE *stream, int indent, const char *format, ...)
+{
+ va_list list;
+
+ do_indent (stream, indent);
+
+ va_start (list, format);
+ vfprintf (stream, format, list);
+ va_end (list);
+}
+
+static void
+Dump_UShort_Array (FT_UShort *array, int count, const char *name, FILE *stream, int indent)
+{
+ int i;
+
+ do_indent (stream, indent);
+
+ fprintf (stream, "<%s>", name);
+ for (i = 0; i < count; i++)
+ fprintf (stream, "%d%s", array[i], i == 0 ? "" : " ");
+ fprintf (stream, "</%s>\n", name);
+}
+
+static void
+Print_Tag (FT_ULong tag, FILE *stream)
+{
+ fprintf (stream, "%c%c%c%c",
+ (unsigned char)(tag >> 24),
+ (unsigned char)((tag >> 16) & 0xff),
+ (unsigned char)((tag >> 8) & 0xff),
+ (unsigned char)(tag & 0xff));
+}
+
+DEF_DUMP (LangSys)
+{
+ int i;
+
+ FT_UNUSED(hb_type);
+
+ DUMP_FUINT (LangSys, LookupOrderOffset);
+ DUMP_FUINT (LangSys, ReqFeatureIndex);
+ DUMP_FUINT (LangSys, FeatureCount);
+
+ for (i=0; i < LangSys->FeatureCount; i++)
+ DUMP1("<FeatureIndex>%d</FeatureIndex>\n", LangSys->FeatureIndex[i]);
+}
+
+DEF_DUMP (Script)
+{
+ int i;
+
+ RECURSE (DefaultLangSys, LangSys, &Script->DefaultLangSys);
+
+ DUMP_FUINT (Script, LangSysCount);
+
+ for (i=0; i < Script->LangSysCount; i++)
+ {
+ do_indent (stream, indent);
+ fprintf (stream, "<LangSysTag>");
+ Print_Tag (Script->LangSysRecord[i].LangSysTag, stream);
+ fprintf (stream, "</LangSysTag>\n");
+ RECURSE_NUM (LangSys, i, LangSys, &Script->LangSysRecord[i].LangSys);
+ }
+}
+
+DEF_DUMP (ScriptList)
+{
+ int i;
+
+ DUMP_FUINT (ScriptList, ScriptCount);
+
+ for (i=0; i < ScriptList->ScriptCount; i++)
+ {
+ do_indent (stream, indent);
+ fprintf (stream, "<ScriptTag>");
+ Print_Tag (ScriptList->ScriptRecord[i].ScriptTag, stream);
+ fprintf (stream, "</ScriptTag>\n");
+ RECURSE_NUM (Script, i, Script, &ScriptList->ScriptRecord[i].Script);
+ }
+}
+
+DEF_DUMP (Feature)
+{
+ int i;
+
+ FT_UNUSED(hb_type);
+
+ DUMP_FUINT (Feature, FeatureParams);
+ DUMP_FUINT (Feature, LookupListCount);
+
+ for (i=0; i < Feature->LookupListCount; i++)
+ DUMP1("<LookupIndex>%d</LookupIndex>\n", Feature->LookupListIndex[i]);
+}
+
+DEF_DUMP (MarkRecord)
+{
+ FT_UNUSED(hb_type);
+
+ DUMP_FUINT (MarkRecord, Class);
+ DUMP1("<Anchor>%d</Anchor>\n", MarkRecord->MarkAnchor.PosFormat );
+}
+
+DEF_DUMP (MarkArray)
+{
+ int i;
+
+ DUMP_FUINT (MarkArray, MarkCount);
+
+ for (i=0; i < MarkArray->MarkCount; i++)
+ RECURSE_NUM (MarkRecord, i, MarkRecord, &MarkArray->MarkRecord[i]);
+}
+
+DEF_DUMP (FeatureList)
+{
+ int i;
+
+ DUMP_FUINT (FeatureList, FeatureCount);
+
+ for (i=0; i < FeatureList->FeatureCount; i++)
+ {
+ do_indent (stream, indent);
+ fprintf (stream, "<FeatureTag>");
+ Print_Tag (FeatureList->FeatureRecord[i].FeatureTag, stream);
+ fprintf (stream, "</FeatureTag> <!-- %d -->\n", i);
+ RECURSE_NUM (Feature, i, Feature, &FeatureList->FeatureRecord[i].Feature);
+ }
+}
+
+DEF_DUMP (Coverage)
+{
+ FT_UNUSED(hb_type);
+
+ DUMP_FUINT (Coverage, CoverageFormat);
+
+ if (Coverage->CoverageFormat == 1)
+ {
+ int i;
+ DUMP_FUINT (&Coverage->cf.cf1, GlyphCount);
+
+ for (i = 0; i < Coverage->cf.cf1.GlyphCount; i++)
+ DUMP2("<Glyph>%#06x</Glyph> <!-- %d -->\n",
+ Coverage->cf.cf1.GlyphArray[i], i);
+ }
+ else
+ {
+ int i;
+ DUMP_FUINT (&Coverage->cf.cf2, RangeCount);
+
+ for ( i = 0; i < Coverage->cf.cf2.RangeCount; i++ )
+ DUMP3("<Glyph>%#06x - %#06x</Glyph> <!-- %d -->\n",
+ Coverage->cf.cf2.RangeRecord[i].Start,
+ Coverage->cf.cf2.RangeRecord[i].End, i);
+ }
+}
+
+DEF_DUMP (ClassRangeRecord)
+{
+ FT_UNUSED(hb_type);
+
+ DUMP_FGLYPH (ClassRangeRecord, Start);
+ DUMP_FGLYPH (ClassRangeRecord, End);
+ DUMP_FUINT (ClassRangeRecord, Class);
+}
+
+DEF_DUMP (ClassDefinition)
+{
+ FT_UNUSED(hb_type);
+
+ DUMP_FUINT( ClassDefinition, ClassFormat);
+ DUMP_FUINT( ClassDefinition, loaded);
+
+ if (ClassDefinition->ClassFormat == 1)
+ {
+ int i;
+ HB_ClassDefFormat1 *ClassDefFormat1 = &ClassDefinition->cd.cd1;
+ DUMP("<ClassDefinition>\n");
+ DUMP_FUINT (ClassDefFormat1, StartGlyph );
+ DUMP_FUINT (ClassDefFormat1, GlyphCount );
+ for (i = 0; i < ClassDefFormat1->GlyphCount; i++)
+ DUMP2(" <Class>%d</Class> <!-- %#06x -->", ClassDefFormat1->ClassValueArray[i],
+ ClassDefFormat1->StartGlyph+i );
+ }
+ else if (ClassDefinition->ClassFormat == 2)
+ {
+ int i;
+ HB_ClassDefFormat2 *ClassDefFormat2 = &ClassDefinition->cd.cd2;
+ DUMP_FUINT (ClassDefFormat2, ClassRangeCount);
+
+ for (i = 0; i < ClassDefFormat2->ClassRangeCount; i++)
+ RECURSE_NUM (ClassRangeRecord, i, ClassRangeRecord, &ClassDefFormat2->ClassRangeRecord[i]);
+ }
+ else
+ fprintf(stderr, "invalid class def table!!!\n");
+}
+
+DEF_DUMP (SubstLookupRecord)
+{
+ FT_UNUSED(hb_type);
+
+ DUMP_FUINT (SubstLookupRecord, SequenceIndex);
+ DUMP_FUINT (SubstLookupRecord, LookupListIndex);
+}
+
+DEF_DUMP (ChainSubClassRule)
+{
+ int i;
+
+ DUMP_USHORT_ARRAY (ChainSubClassRule, Backtrack, ChainSubClassRule->BacktrackGlyphCount);
+ DUMP_USHORT_ARRAY (ChainSubClassRule, Input, ChainSubClassRule->InputGlyphCount - 1);
+ DUMP_USHORT_ARRAY (ChainSubClassRule, Lookahead, ChainSubClassRule->LookaheadGlyphCount);
+
+ for (i = 0; i < ChainSubClassRule->SubstCount; i++)
+ RECURSE_NUM (SubstLookupRecord, i, SubstLookupRecord, &ChainSubClassRule->SubstLookupRecord[i]);
+
+ indent--;
+}
+
+DEF_DUMP (ChainSubClassSet)
+{
+ int i;
+
+ DUMP_FUINT( ChainSubClassSet, ChainSubClassRuleCount );
+ for (i = 0; i < ChainSubClassSet->ChainSubClassRuleCount; i++)
+ RECURSE_NUM (ChainSubClassRule, i, ChainSubClassRule, &ChainSubClassSet->ChainSubClassRule[i]);
+}
+
+static void
+Dump_GSUB_Lookup_Single (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
+{
+ HB_SingleSubst *SingleSubst = &subtable->st.gsub.single;
+
+ DUMP_FUINT (SingleSubst, SubstFormat);
+ RECURSE (Coverage, Coverage, &SingleSubst->Coverage);
+
+ if (SingleSubst->SubstFormat == 1)
+ {
+ DUMP_FINT (&SingleSubst->ssf.ssf1, DeltaGlyphID);
+ }
+ else
+ {
+ int i;
+
+ DUMP_FINT (&SingleSubst->ssf.ssf2, GlyphCount);
+ for (i=0; i < SingleSubst->ssf.ssf2.GlyphCount; i++)
+ DUMP2("<Substitute>%#06x</Substitute> <!-- %d -->\n", SingleSubst->ssf.ssf2.Substitute[i], i);
+ }
+}
+
+DEF_DUMP (Ligature)
+{
+ int i;
+
+ FT_UNUSED(hb_type);
+
+ DUMP_FGLYPH (Ligature, LigGlyph);
+ DUMP_FUINT (Ligature, ComponentCount);
+
+ for (i=0; i < Ligature->ComponentCount - 1; i++)
+ DUMP1("<Component>%#06x</Component>\n", Ligature->Component[i]);
+}
+
+DEF_DUMP (LigatureSet)
+{
+ int i;
+
+ DUMP_FUINT (LigatureSet, LigatureCount);
+
+ for (i=0; i < LigatureSet->LigatureCount; i++)
+ RECURSE_NUM (Ligature, i, Ligature, &LigatureSet->Ligature[i]);
+}
+
+static void
+Dump_GSUB_Lookup_Ligature (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
+{
+ int i;
+ HB_LigatureSubst *LigatureSubst = &subtable->st.gsub.ligature;
+
+ DUMP_FUINT (LigatureSubst, SubstFormat);
+ RECURSE (Coverage, Coverage, &LigatureSubst->Coverage);
+
+ DUMP_FUINT (LigatureSubst, LigatureSetCount);
+
+ for (i=0; i < LigatureSubst->LigatureSetCount; i++)
+ RECURSE_NUM (LigatureSet, i, LigatureSet, &LigatureSubst->LigatureSet[i]);
+}
+
+DEF_DUMP (ContextSubstFormat1)
+{
+ FT_UNUSED(hb_type);
+ FT_UNUSED(ContextSubstFormat1);
+
+
+ DUMP("<!-- Not implemented!!! -->\n");
+}
+
+DEF_DUMP (ContextSubstFormat2)
+{
+ DUMP_FUINT (ContextSubstFormat2, MaxContextLength);
+ RECURSE (Coverage, Coverage, &ContextSubstFormat2->Coverage);
+ RECURSE (ClassDefinition, ClassDefinition, &ContextSubstFormat2->ClassDef);
+}
+
+DEF_DUMP (ContextSubstFormat3)
+{
+ FT_UNUSED(hb_type);
+ FT_UNUSED(ContextSubstFormat3);
+
+ DUMP("<!-- Not implemented!!! -->\n");
+}
+
+static void
+Dump_GSUB_Lookup_Context (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
+{
+ HB_ContextSubst *ContextSubst = &subtable->st.gsub.context;
+
+ DUMP_FUINT (ContextSubst, SubstFormat);
+ switch( ContextSubst->SubstFormat )
+ {
+ case 1:
+ Dump_ContextSubstFormat1 (&ContextSubst->csf.csf1, stream, indent+2, hb_type);
+ break;
+ case 2:
+ Dump_ContextSubstFormat2 (&ContextSubst->csf.csf2, stream, indent+2, hb_type);
+ break;
+ case 3:
+ Dump_ContextSubstFormat3 (&ContextSubst->csf.csf3, stream, indent+2, hb_type);
+ break;
+ default:
+ fprintf(stderr, "invalid subformat!!!!!\n");
+ }
+}
+
+DEF_DUMP (ChainContextSubstFormat1)
+{
+ FT_UNUSED(hb_type);
+ FT_UNUSED(ChainContextSubstFormat1);
+
+ DUMP("<!-- Not implemented!!! -->\n");
+}
+
+DEF_DUMP (ChainContextSubstFormat2)
+{
+ int i;
+
+ RECURSE (Coverage, Coverage, &ChainContextSubstFormat2->Coverage);
+ DUMP_FUINT (ChainContextSubstFormat2, MaxBacktrackLength);
+ RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->BacktrackClassDef);
+ DUMP_FUINT (ChainContextSubstFormat2, MaxInputLength);
+ RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->InputClassDef);
+ DUMP_FUINT (ChainContextSubstFormat2, MaxLookaheadLength);
+ RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->LookaheadClassDef);
+
+ DUMP_FUINT (ChainContextSubstFormat2, ChainSubClassSetCount);
+ for (i = 0; i < ChainContextSubstFormat2->ChainSubClassSetCount; i++)
+ RECURSE (ChainSubClassSet, ChainSubClassSet, &ChainContextSubstFormat2->ChainSubClassSet[i]);
+}
+
+DEF_DUMP (ChainContextSubstFormat3)
+{
+ int i;
+
+ DUMP_FUINT (ChainContextSubstFormat3, BacktrackGlyphCount);
+ for (i = 0; i < ChainContextSubstFormat3->BacktrackGlyphCount; i++)
+ RECURSE (BacktrackCoverage, Coverage, &ChainContextSubstFormat3->BacktrackCoverage[i]);
+ DUMP_FUINT (ChainContextSubstFormat3, InputGlyphCount);
+ for (i = 0; i < ChainContextSubstFormat3->InputGlyphCount; i++)
+ RECURSE (InputCoverage, Coverage, &ChainContextSubstFormat3->InputCoverage[i]);
+ DUMP_FUINT (ChainContextSubstFormat3, LookaheadGlyphCount);
+ for (i = 0; i < ChainContextSubstFormat3->LookaheadGlyphCount; i++)
+ RECURSE (LookaheadCoverage, Coverage, &ChainContextSubstFormat3->LookaheadCoverage[i]);
+
+ for (i = 0; i < ChainContextSubstFormat3->SubstCount; i++)
+ RECURSE_NUM (SubstLookupRecord, i, SubstLookupRecord, &ChainContextSubstFormat3->SubstLookupRecord[i]);
+
+}
+
+static void
+Dump_GSUB_Lookup_Chain (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
+{
+ HB_ChainContextSubst *chain = &subtable->st.gsub.chain;
+
+ DUMP_FUINT (chain, SubstFormat);
+ switch (chain->SubstFormat)
+ {
+ case 1:
+ Dump_ChainContextSubstFormat1 (&chain->ccsf.ccsf1, stream, indent+2, hb_type);
+ break;
+ case 2:
+ Dump_ChainContextSubstFormat2 (&chain->ccsf.ccsf2, stream, indent+2, hb_type);
+ break;
+ case 3:
+ Dump_ChainContextSubstFormat3 (&chain->ccsf.ccsf3, stream, indent+2, hb_type);
+ break;
+ default:
+ fprintf(stderr, "invalid subformat!!!!!\n");
+ }
+}
+
+static void
+Dump_Device (HB_Device *Device, FILE *stream, int indent, HB_Type hb_type)
+{
+ int i;
+ int bits = 0;
+ int n_per;
+ unsigned int mask;
+
+ FT_UNUSED(hb_type);
+
+ DUMP_FUINT (Device, StartSize);
+ DUMP_FUINT (Device, EndSize);
+ DUMP_FUINT (Device, DeltaFormat);
+ switch (Device->DeltaFormat)
+ {
+ case 1:
+ bits = 2;
+ break;
+ case 2:
+ bits = 4;
+ break;
+ case 3:
+ bits = 8;
+ break;
+ }
+
+ DUMP ("<DeltaValue>");
+ if (!bits)
+ {
+
+ fprintf(stderr, "invalid DeltaFormat!!!!!\n");
+ }
+ else
+ {
+ n_per = 16 / bits;
+ mask = (1 << bits) - 1;
+ mask = mask << (16 - bits);
+
+ for (i = Device->StartSize; i <= Device->EndSize ; i++)
+ {
+ FT_UShort val = Device->DeltaValue[i / n_per];
+ FT_Short signed_val = ((val << ((i % n_per) * bits)) & mask);
+ dump (stream, indent, "%d", signed_val >> (16 - bits));
+ if (i != Device->EndSize)
+ DUMP (", ");
+ }
+ }
+ DUMP ("</DeltaValue>\n");
+}
+
+static void
+Dump_ValueRecord (HB_ValueRecord *ValueRecord, FILE *stream, int indent, HB_Type hb_type, FT_UShort value_format)
+{
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT)
+ DUMP_FINT (ValueRecord, XPlacement);
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT)
+ DUMP_FINT (ValueRecord, YPlacement);
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE)
+ DUMP_FINT (ValueRecord, XAdvance);
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE)
+ DUMP_FINT (ValueRecord, XAdvance);
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE)
+ RECURSE (Device, Device, &ValueRecord->XPlacementDevice);
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE)
+ RECURSE (Device, Device, &ValueRecord->YPlacementDevice);
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE)
+ RECURSE (Device, Device, &ValueRecord->XAdvanceDevice);
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE)
+ RECURSE (Device, Device, &ValueRecord->YAdvanceDevice);
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT)
+ DUMP_FUINT (ValueRecord, XIdPlacement);
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT)
+ DUMP_FUINT (ValueRecord, YIdPlacement);
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE)
+ DUMP_FUINT (ValueRecord, XIdAdvance);
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE)
+ DUMP_FUINT (ValueRecord, XIdAdvance);
+}
+
+static void
+Dump_GPOS_Lookup_Single (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
+{
+ HB_SinglePos *SinglePos = &subtable->st.gpos.single;
+
+ DUMP_FUINT (SinglePos, PosFormat);
+ RECURSE (Coverage, Coverage, &SinglePos->Coverage);
+
+ DUMP_FUINT (SinglePos, ValueFormat);
+
+ if (SinglePos->PosFormat == 1)
+ {
+ DUMP_VALUE_RECORD (&SinglePos->spf.spf1.Value, SinglePos->ValueFormat);
+ }
+ else
+ {
+ int i;
+
+ DUMP_FUINT (&SinglePos->spf.spf2, ValueCount);
+ for (i = 0; i < SinglePos->spf.spf2.ValueCount; i++)
+ DUMP_VALUE_RECORD (&SinglePos->spf.spf2.Value[i], SinglePos->ValueFormat);
+ }
+}
+
+static void
+Dump_PairValueRecord (HB_PairValueRecord *PairValueRecord, FILE *stream, int indent, HB_Type hb_type, FT_UShort ValueFormat1, FT_UShort ValueFormat2)
+{
+ DUMP_FUINT (PairValueRecord, SecondGlyph);
+ DUMP_VALUE_RECORD (&PairValueRecord->Value1, ValueFormat1);
+ DUMP_VALUE_RECORD (&PairValueRecord->Value2, ValueFormat2);
+}
+
+static void
+Dump_PairSet (HB_PairSet *PairSet, FILE *stream, int indent, HB_Type hb_type, FT_UShort ValueFormat1, FT_UShort ValueFormat2)
+{
+ int i;
+ DUMP_FUINT (PairSet, PairValueCount);
+
+ for (i = 0; i < PairSet->PairValueCount; i++)
+ {
+ DUMP ("<PairValueRecord>\n");
+ Dump_PairValueRecord (&PairSet->PairValueRecord[i], stream, indent + 1, hb_type, ValueFormat1, ValueFormat2);
+ DUMP ("</PairValueRecord>\n");
+ }
+}
+
+static void
+Dump_GPOS_Lookup_Pair (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
+{
+ HB_PairPos *PairPos = &subtable->st.gpos.pair;
+
+ DUMP_FUINT (PairPos, PosFormat);
+ RECURSE (Coverage, Coverage, &PairPos->Coverage);
+
+ DUMP_FUINT (PairPos, ValueFormat1);
+ DUMP_FUINT (PairPos, ValueFormat2);
+
+ if (PairPos->PosFormat == 1)
+ {
+ int i;
+
+ DUMP_FUINT (&PairPos->ppf.ppf1, PairSetCount);
+ for (i = 0; i < PairPos->ppf.ppf1.PairSetCount; i++)
+ {
+ DUMP ("<PairSet>\n");
+ Dump_PairSet (&PairPos->ppf.ppf1.PairSet[i], stream, indent + 1, hb_type, PairPos->ValueFormat1, PairPos->ValueFormat2);
+ DUMP ("</PairSet>\n");
+ }
+ }
+ else
+ {
+ }
+}
+
+static void
+Dump_GPOS_Lookup_Markbase (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
+{
+ int i;
+ HB_MarkBasePos *markbase = &subtable->st.gpos.markbase;
+
+ DUMP_FUINT (markbase, PosFormat);
+ RECURSE (Coverage, Coverage, &markbase->MarkCoverage);
+ RECURSE (Coverage, Coverage, &markbase->BaseCoverage);
+ DUMP_FUINT (markbase, ClassCount);
+ RECURSE (MarkArray, MarkArray, &markbase->MarkArray);
+
+ DUMP ("<BaseArray>\n");
+ indent++;
+
+ DUMP_FUINT (&markbase->BaseArray, BaseCount);
+ for (i = 0; i < markbase->BaseArray.BaseCount; i++)
+ {
+ int j;
+ HB_BaseRecord *r = &markbase->BaseArray.BaseRecord[i];
+ DUMP1 ("<BaseRecord> <!-- %d -->\n", i);
+ for (j = 0; j < markbase->ClassCount; j++)
+ DUMP1 (" <Anchor>%d</Anchor>\n", r->BaseAnchor->PosFormat);
+ DUMP ("<BaseRecord>\n");
+ }
+
+ indent--;
+ DUMP ("</BaseArray>\n");
+}
+
+DEF_DUMP (Lookup)
+{
+ int i;
+ const char *lookup_name = NULL;
+ void (*lookup_func) (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) = NULL;
+
+ if (hb_type == HB_Type_GSUB)
+ {
+ switch (Lookup->LookupType)
+ {
+ case HB_GSUB_LOOKUP_SINGLE:
+ lookup_name = "SINGLE";
+ lookup_func = Dump_GSUB_Lookup_Single;
+ break;
+ case HB_GSUB_LOOKUP_MULTIPLE:
+ lookup_name = "MULTIPLE";
+ break;
+ case HB_GSUB_LOOKUP_ALTERNATE:
+ lookup_name = "ALTERNATE";
+ break;
+ case HB_GSUB_LOOKUP_LIGATURE:
+ lookup_name = "LIGATURE";
+ lookup_func = Dump_GSUB_Lookup_Ligature;
+ break;
+ case HB_GSUB_LOOKUP_CONTEXT:
+ lookup_name = "CONTEXT";
+ lookup_func = Dump_GSUB_Lookup_Context;
+ break;
+ case HB_GSUB_LOOKUP_CHAIN:
+ lookup_name = "CHAIN";
+ lookup_func = Dump_GSUB_Lookup_Chain;
+ break;
+ }
+ }
+ else
+ {
+ switch (Lookup->LookupType)
+ {
+ case HB_GPOS_LOOKUP_SINGLE:
+ lookup_name = "SINGLE";
+ lookup_func = Dump_GPOS_Lookup_Single;
+ break;
+ case HB_GPOS_LOOKUP_PAIR:
+ lookup_name = "PAIR";
+ lookup_func = Dump_GPOS_Lookup_Pair;
+ break;
+ case HB_GPOS_LOOKUP_CURSIVE:
+ lookup_name = "CURSIVE";
+ break;
+ case HB_GPOS_LOOKUP_MARKBASE:
+ lookup_name = "MARKBASE";
+ lookup_func = Dump_GPOS_Lookup_Markbase;
+ break;
+ case HB_GPOS_LOOKUP_MARKLIG:
+ lookup_name = "MARKLIG";
+ break;
+ case HB_GPOS_LOOKUP_MARKMARK:
+ lookup_name = "MARKMARK";
+ break;
+ case HB_GPOS_LOOKUP_CONTEXT:
+ lookup_name = "CONTEXT";
+ break;
+ case HB_GPOS_LOOKUP_CHAIN:
+ lookup_name = "CHAIN";
+ break;
+ }
+ }
+
+ DUMP2("<LookupType>%s</LookupType> <!-- %d -->\n", lookup_name, Lookup->LookupType);
+ DUMP1("<LookupFlag>%#06x</LookupFlag>\n", Lookup->LookupFlag);
+
+ for (i=0; i < Lookup->SubTableCount; i++)
+ {
+ DUMP ("<Subtable>\n");
+ if (lookup_func)
+ (*lookup_func) (&Lookup->SubTable[i], stream, indent + 1, hb_type);
+ DUMP ("</Subtable>\n");
+ }
+}
+
+DEF_DUMP (LookupList)
+{
+ int i;
+
+ DUMP_FUINT (LookupList, LookupCount);
+
+ for (i=0; i < LookupList->LookupCount; i++)
+ RECURSE_NUM (Lookup, i, Lookup, &LookupList->Lookup[i]);
+}
+
+void
+HB_Dump_GSUB_Table (HB_GSUB gsub, FILE *stream)
+{
+ int indent = 1;
+ HB_Type hb_type = HB_Type_GSUB;
+
+ do_indent (stream, indent);
+ fprintf(stream, "<!-- GSUB -->\n");
+ RECURSE (ScriptList, ScriptList, &gsub->ScriptList);
+ RECURSE (FeatureList, FeatureList, &gsub->FeatureList);
+ RECURSE (LookupList, LookupList, &gsub->LookupList);
+}
+
+void
+HB_Dump_GPOS_Table (HB_GPOS gpos, FILE *stream)
+{
+ int indent = 1;
+ HB_Type hb_type = HB_Type_GPOS;
+
+ do_indent (stream, indent);
+ fprintf(stream, "<!-- GPOS -->\n");
+ RECURSE (ScriptList, ScriptList, &gpos->ScriptList);
+ RECURSE (FeatureList, FeatureList, &gpos->FeatureList);
+ RECURSE (LookupList, LookupList, &gpos->LookupList);
+}
diff --git a/trunk/pango/opentype/harfbuzz-dump.h b/trunk/pango/opentype/harfbuzz-dump.h
new file mode 100644
index 00000000..c41ca683
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-dump.h
@@ -0,0 +1,34 @@
+/* harfbuzz-dump.h: Dump OpenType layout tables
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef HARFBUZZ_DUMP_H
+#define HARFBUZZ_DUMP_H
+
+#include <stdio.h>
+#include "harfbuzz-gsub.h"
+#include "harfbuzz-gpos.h"
+
+FT_BEGIN_HEADER
+
+void HB_Dump_GSUB_Table (HB_GSUB gsub, FILE *stream);
+void HB_Dump_GPOS_Table (HB_GPOS gpos, FILE *stream);
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_DUMP_H */
diff --git a/trunk/pango/opentype/harfbuzz-gdef-private.h b/trunk/pango/opentype/harfbuzz-gdef-private.h
new file mode 100644
index 00000000..e07e2364
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gdef-private.h
@@ -0,0 +1,101 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GDEF_PRIVATE_H
+#define HARFBUZZ_GDEF_PRIVATE_H
+
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-buffer.h"
+
+FT_BEGIN_HEADER
+
+
+/* Attachment related structures */
+
+struct HB_AttachPoint_
+{
+ FT_UShort PointCount; /* size of the PointIndex array */
+ FT_UShort* PointIndex; /* array of contour points */
+};
+
+/* Ligature Caret related structures */
+
+struct HB_CaretValueFormat1_
+{
+ FT_Short Coordinate; /* x or y value (in design units) */
+};
+
+typedef struct HB_CaretValueFormat1_ HB_CaretValueFormat1;
+
+
+struct HB_CaretValueFormat2_
+{
+ FT_UShort CaretValuePoint; /* contour point index on glyph */
+};
+
+typedef struct HB_CaretValueFormat2_ HB_CaretValueFormat2;
+
+
+struct HB_CaretValueFormat3_
+{
+ FT_Short Coordinate; /* x or y value (in design units) */
+ HB_Device Device; /* Device table for x or y value */
+};
+
+typedef struct HB_CaretValueFormat3_ HB_CaretValueFormat3;
+
+
+struct HB_CaretValueFormat4_
+{
+ FT_UShort IdCaretValue; /* metric ID */
+};
+
+typedef struct HB_CaretValueFormat4_ HB_CaretValueFormat4;
+
+
+struct HB_CaretValue_
+{
+ FT_UShort CaretValueFormat; /* 1, 2, 3, or 4 */
+
+ union
+ {
+ HB_CaretValueFormat1 cvf1;
+ HB_CaretValueFormat2 cvf2;
+ HB_CaretValueFormat3 cvf3;
+ HB_CaretValueFormat4 cvf4;
+ } cvf;
+};
+
+typedef struct HB_CaretValue_ HB_CaretValue;
+
+
+struct HB_LigGlyph_
+{
+ FT_Bool loaded;
+
+ FT_UShort CaretCount; /* number of caret values */
+ HB_CaretValue* CaretValue; /* array of caret values */
+};
+
+
+FT_Error _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort property );
+
+FT_Error _HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
+ HB_GlyphItem item,
+ FT_UShort flags,
+ FT_UShort* property );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GDEF_PRIVATE_H */
diff --git a/trunk/pango/opentype/harfbuzz-gdef.c b/trunk/pango/opentype/harfbuzz-gdef.c
new file mode 100644
index 00000000..7a30d8bd
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gdef.c
@@ -0,0 +1,1228 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+#include "harfbuzz-gdef-private.h"
+#include "harfbuzz-open-private.h"
+
+static FT_Error Load_AttachList( HB_AttachList* al,
+ FT_Stream stream );
+static FT_Error Load_LigCaretList( HB_LigCaretList* lcl,
+ FT_Stream stream );
+
+static void Free_AttachList( HB_AttachList* al,
+ FT_Memory memory );
+static void Free_LigCaretList( HB_LigCaretList* lcl,
+ FT_Memory memory );
+
+static void Free_NewGlyphClasses( HB_GDEFHeader* gdef,
+ FT_Memory memory );
+
+
+
+/**********************
+ * Extension Functions
+ **********************/
+
+#if 0
+#define GDEF_ID Build_Extension_ID( 'G', 'D', 'E', 'F' )
+
+
+static FT_Error GDEF_Create( void* ext,
+ PFace face )
+{
+ DEFINE_LOAD_LOCALS( face->stream );
+
+ HB_GDEFHeader* gdef = (HB_GDEFHeader*)ext;
+ Long table;
+
+
+ /* by convention */
+
+ if ( !gdef )
+ return FT_Err_Ok;
+
+ /* a null offset indicates that there is no GDEF table */
+
+ gdef->offset = 0;
+
+ /* we store the start offset and the size of the subtable */
+
+ table = HB_LookUp_Table( face, TTAG_GDEF );
+ if ( table < 0 )
+ return FT_Err_Ok; /* The table is optional */
+
+ if ( FILE_Seek( face->dirTables[table].Offset ) ||
+ ACCESS_Frame( 4L ) )
+ return error;
+
+ gdef->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */
+ gdef->Version = GET_ULong();
+
+ FORGET_Frame();
+
+ gdef->loaded = FALSE;
+
+ return FT_Err_Ok;
+}
+
+
+static FT_Error GDEF_Destroy( void* ext,
+ PFace face )
+{
+ HB_GDEFHeader* gdef = (HB_GDEFHeader*)ext;
+
+
+ /* by convention */
+
+ if ( !gdef )
+ return FT_Err_Ok;
+
+ if ( gdef->loaded )
+ {
+ Free_LigCaretList( &gdef->LigCaretList, memory );
+ Free_AttachList( &gdef->AttachList, memory );
+ _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef, memory );
+
+ Free_NewGlyphClasses( gdef, memory );
+ }
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_Init_GDEF_Extension( HB_Engine engine )
+{
+ PEngine_Instance _engine = HANDLE_Engine( engine );
+
+
+ if ( !_engine )
+ return FT_Err_Invalid_Engine;
+
+ return HB_Register_Extension( _engine,
+ GDEF_ID,
+ sizeof ( HB_GDEFHeader ),
+ GDEF_Create,
+ GDEF_Destroy );
+}
+#endif
+/* GDEF glyph classes */
+
+#define UNCLASSIFIED_GLYPH 0
+#define SIMPLE_GLYPH 1
+#define LIGATURE_GLYPH 2
+#define MARK_GLYPH 3
+#define COMPONENT_GLYPH 4
+
+
+
+
+
+
+FT_Error HB_New_GDEF_Table( FT_Face face,
+ HB_GDEFHeader** retptr )
+{
+ FT_Error error;
+ FT_Memory memory = face->memory;
+
+ HB_GDEFHeader* gdef;
+
+ if ( !retptr )
+ return FT_Err_Invalid_Argument;
+
+ if ( ALLOC( gdef, sizeof( *gdef ) ) )
+ return error;
+
+ gdef->memory = face->memory;
+
+ gdef->GlyphClassDef.loaded = FALSE;
+ gdef->AttachList.loaded = FALSE;
+ gdef->LigCaretList.loaded = FALSE;
+ gdef->MarkAttachClassDef_offset = 0;
+ gdef->MarkAttachClassDef.loaded = FALSE;
+
+ gdef->LastGlyph = 0;
+ gdef->NewGlyphClasses = NULL;
+
+ *retptr = gdef;
+
+ return FT_Err_Ok;
+}
+
+
+FT_Error HB_Load_GDEF_Table( FT_Face face,
+ HB_GDEFHeader** retptr )
+{
+ FT_Error error;
+ FT_Memory memory = face->memory;
+ FT_Stream stream = face->stream;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_GDEFHeader* gdef;
+
+
+ if ( !retptr )
+ return FT_Err_Invalid_Argument;
+
+ if (( error = _hb_ftglue_face_goto_table( face, TTAG_GDEF, stream ) ))
+ return error;
+
+ if (( error = HB_New_GDEF_Table ( face, &gdef ) ))
+ return error;
+
+ base_offset = FILE_Pos();
+
+ /* skip version */
+
+ if ( FILE_Seek( base_offset + 4L ) ||
+ ACCESS_Frame( 2L ) )
+ goto Fail0;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ /* all GDEF subtables are optional */
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ /* only classes 1-4 are allowed here */
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5,
+ stream ) ) != FT_Err_Ok )
+ goto Fail0;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_AttachList( &gdef->AttachList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigCaretList( &gdef->LigCaretList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We
+ first have to scan the LookupFlag values to find out whether we
+ must load it or not. Here we only store the offset of the table. */
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ gdef->MarkAttachClassDef_offset = new_offset + base_offset;
+ else
+ gdef->MarkAttachClassDef_offset = 0;
+
+ *retptr = gdef;
+
+ return FT_Err_Ok;
+
+Fail3:
+ Free_LigCaretList( &gdef->LigCaretList, memory );
+
+Fail2:
+ Free_AttachList( &gdef->AttachList, memory );
+
+Fail1:
+ _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory );
+
+Fail0:
+ FREE( gdef );
+
+ return error;
+}
+
+
+FT_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef )
+{
+ FT_Memory memory = gdef->memory;
+
+ Free_LigCaretList( &gdef->LigCaretList, memory );
+ Free_AttachList( &gdef->AttachList, memory );
+ _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef, memory );
+
+ Free_NewGlyphClasses( gdef, memory );
+
+ FREE( gdef );
+
+ return FT_Err_Ok;
+}
+
+
+
+
+/*******************************
+ * AttachList related functions
+ *******************************/
+
+
+/* AttachPoint */
+
+static FT_Error Load_AttachPoint( HB_AttachPoint* ap,
+ FT_Stream stream )
+{
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_UShort n, count;
+ FT_UShort* pi;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ap->PointCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ap->PointIndex = NULL;
+
+ if ( count )
+ {
+ if ( ALLOC_ARRAY( ap->PointIndex, count, FT_UShort ) )
+ return error;
+
+ pi = ap->PointIndex;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( pi );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ pi[n] = GET_UShort();
+
+ FORGET_Frame();
+ }
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_AttachPoint( HB_AttachPoint* ap,
+ FT_Memory memory )
+{
+ FREE( ap->PointIndex );
+}
+
+
+/* AttachList */
+
+static FT_Error Load_AttachList( HB_AttachList* al,
+ FT_Stream stream )
+{
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_AttachPoint* ap;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = al->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ al->AttachPoint = NULL;
+
+ if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) )
+ goto Fail2;
+
+ ap = al->AttachPoint;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_AttachPoint( &ap[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ al->loaded = TRUE;
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_AttachPoint( &ap[m], memory );
+
+ FREE( ap );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &al->Coverage, memory );
+ return error;
+}
+
+
+static void Free_AttachList( HB_AttachList* al,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_AttachPoint* ap;
+
+
+ if ( !al->loaded )
+ return;
+
+ if ( al->AttachPoint )
+ {
+ count = al->GlyphCount;
+ ap = al->AttachPoint;
+
+ for ( n = 0; n < count; n++ )
+ Free_AttachPoint( &ap[n], memory );
+
+ FREE( ap );
+ }
+
+ _HB_OPEN_Free_Coverage( &al->Coverage, memory );
+}
+
+
+
+/*********************************
+ * LigCaretList related functions
+ *********************************/
+
+
+/* CaretValueFormat1 */
+/* CaretValueFormat2 */
+/* CaretValueFormat3 */
+/* CaretValueFormat4 */
+
+static FT_Error Load_CaretValue( HB_CaretValue* cv,
+ FT_Stream stream )
+{
+ FT_Error error;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cv->CaretValueFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( cv->CaretValueFormat )
+ {
+ case 1:
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cv->cvf.cvf1.Coordinate = GET_Short();
+
+ FORGET_Frame();
+
+ break;
+
+ case 2:
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cv->cvf.cvf2.CaretValuePoint = GET_UShort();
+
+ FORGET_Frame();
+
+ break;
+
+ case 3:
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ cv->cvf.cvf3.Coordinate = GET_Short();
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ break;
+
+ case 4:
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cv->cvf.cvf4.IdCaretValue = GET_UShort();
+
+ FORGET_Frame();
+ break;
+
+ default:
+ return HB_Err_Invalid_GDEF_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_CaretValue( HB_CaretValue* cv,
+ FT_Memory memory )
+{
+ if ( cv->CaretValueFormat == 3 )
+ _HB_OPEN_Free_Device( &cv->cvf.cvf3.Device, memory );
+}
+
+
+/* LigGlyph */
+
+static FT_Error Load_LigGlyph( HB_LigGlyph* lg,
+ FT_Stream stream )
+{
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_CaretValue* cv;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = lg->CaretCount = GET_UShort();
+
+ FORGET_Frame();
+
+ lg->CaretValue = NULL;
+
+ if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) )
+ return error;
+
+ cv = lg->CaretValue;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_CaretValue( &cv[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_CaretValue( &cv[m], memory );
+
+ FREE( cv );
+ return error;
+}
+
+
+static void Free_LigGlyph( HB_LigGlyph* lg,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_CaretValue* cv;
+
+
+ if ( lg->CaretValue )
+ {
+ count = lg->CaretCount;
+ cv = lg->CaretValue;
+
+ for ( n = 0; n < count; n++ )
+ Free_CaretValue( &cv[n], memory );
+
+ FREE( cv );
+ }
+}
+
+
+/* LigCaretList */
+
+static FT_Error Load_LigCaretList( HB_LigCaretList* lcl,
+ FT_Stream stream )
+{
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_UShort m, n, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_LigGlyph* lg;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &lcl->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = lcl->LigGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ lcl->LigGlyph = NULL;
+
+ if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) )
+ goto Fail2;
+
+ lg = lcl->LigGlyph;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigGlyph( &lg[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ lcl->loaded = TRUE;
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_LigGlyph( &lg[m], memory );
+
+ FREE( lg );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &lcl->Coverage, memory );
+ return error;
+}
+
+
+static void Free_LigCaretList( HB_LigCaretList* lcl,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_LigGlyph* lg;
+
+
+ if ( !lcl->loaded )
+ return;
+
+ if ( lcl->LigGlyph )
+ {
+ count = lcl->LigGlyphCount;
+ lg = lcl->LigGlyph;
+
+ for ( n = 0; n < count; n++ )
+ Free_LigGlyph( &lg[n], memory );
+
+ FREE( lg );
+ }
+
+ _HB_OPEN_Free_Coverage( &lcl->Coverage, memory );
+}
+
+
+
+/***********
+ * GDEF API
+ ***********/
+
+
+static FT_UShort Get_New_Class( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort index )
+{
+ FT_UShort glyph_index, array_index, count;
+ FT_UShort byte, bits;
+
+ HB_ClassRangeRecord* gcrr;
+ FT_UShort** ngc;
+
+
+ if ( glyphID >= gdef->LastGlyph )
+ return 0;
+
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
+ gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
+ ngc = gdef->NewGlyphClasses;
+
+ if ( index < count && glyphID < gcrr[index].Start )
+ {
+ array_index = index;
+ if ( index == 0 )
+ glyph_index = glyphID;
+ else
+ glyph_index = glyphID - gcrr[index - 1].End - 1;
+ }
+ else
+ {
+ array_index = index + 1;
+ glyph_index = glyphID - gcrr[index].End - 1;
+ }
+
+ byte = ngc[array_index][glyph_index / 4];
+ bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
+
+ return bits & 0x000F;
+}
+
+
+
+FT_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort* property )
+{
+ FT_UShort class, index;
+
+ FT_Error error;
+
+
+ if ( !gdef || !property )
+ return FT_Err_Invalid_Argument;
+
+ /* first, we check for mark attach classes */
+
+ if ( gdef->MarkAttachClassDef.loaded )
+ {
+ error = _HB_OPEN_Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ if ( !error )
+ {
+ *property = class << 8;
+ return FT_Err_Ok;
+ }
+ }
+
+ error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ /* if we have a constructed class table, check whether additional
+ values have been assigned */
+
+ if ( error == HB_Err_Not_Covered && gdef->NewGlyphClasses )
+ class = Get_New_Class( gdef, glyphID, index );
+
+ switch ( class )
+ {
+ case UNCLASSIFIED_GLYPH:
+ *property = 0;
+ break;
+
+ case SIMPLE_GLYPH:
+ *property = HB_GDEF_BASE_GLYPH;
+ break;
+
+ case LIGATURE_GLYPH:
+ *property = HB_GDEF_LIGATURE;
+ break;
+
+ case MARK_GLYPH:
+ *property = HB_GDEF_MARK;
+ break;
+
+ case COMPONENT_GLYPH:
+ *property = HB_GDEF_COMPONENT;
+ break;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+static FT_Error Make_ClassRange( HB_ClassDefinition* cd,
+ FT_UShort start,
+ FT_UShort end,
+ FT_UShort class,
+ FT_Memory memory )
+{
+ FT_Error error;
+ FT_UShort index;
+
+ HB_ClassDefFormat2* cdf2;
+ HB_ClassRangeRecord* crr;
+
+
+ cdf2 = &cd->cd.cd2;
+
+ if ( REALLOC_ARRAY( cdf2->ClassRangeRecord,
+ cdf2->ClassRangeCount,
+ cdf2->ClassRangeCount + 1 ,
+ HB_ClassRangeRecord ) )
+ return error;
+
+ cdf2->ClassRangeCount++;
+
+ crr = cdf2->ClassRangeRecord;
+ index = cdf2->ClassRangeCount - 1;
+
+ crr[index].Start = start;
+ crr[index].End = end;
+ crr[index].Class = class;
+
+ cd->Defined[class] = TRUE;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,
+ FT_UShort num_glyphs,
+ FT_UShort glyph_count,
+ FT_UShort* glyph_array,
+ FT_UShort* class_array )
+{
+ FT_UShort start, curr_glyph, curr_class;
+ FT_UShort n, m, count;
+ FT_Error error;
+ FT_Memory memory;
+
+ HB_ClassDefinition* gcd;
+ HB_ClassRangeRecord* gcrr;
+ FT_UShort** ngc;
+
+
+ if ( !gdef || !glyph_array || !class_array )
+ return FT_Err_Invalid_Argument;
+
+ memory = gdef->memory;
+ gcd = &gdef->GlyphClassDef;
+
+ /* We build a format 2 table */
+
+ gcd->ClassFormat = 2;
+
+ /* A GlyphClassDef table contains at most 5 different class values */
+
+ if ( ALLOC_ARRAY( gcd->Defined, 5, FT_Bool ) )
+ return error;
+
+ gcd->cd.cd2.ClassRangeCount = 0;
+ gcd->cd.cd2.ClassRangeRecord = NULL;
+
+ start = glyph_array[0];
+ curr_class = class_array[0];
+ curr_glyph = start;
+
+ if ( curr_class >= 5 )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail4;
+ }
+
+ glyph_count--;
+
+ for ( n = 0; n <= glyph_count; n++ )
+ {
+ if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] )
+ {
+ if ( n == glyph_count )
+ {
+ if ( ( error = Make_ClassRange( gcd, start,
+ curr_glyph,
+ curr_class,
+ memory ) ) != FT_Err_Ok )
+ goto Fail3;
+ }
+ else
+ {
+ if ( curr_glyph == 0xFFFF )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail3;
+ }
+ else
+ curr_glyph++;
+ }
+ }
+ else
+ {
+ if ( ( error = Make_ClassRange( gcd, start,
+ curr_glyph - 1,
+ curr_class,
+ memory ) ) != FT_Err_Ok )
+ goto Fail3;
+
+ if ( curr_glyph > glyph_array[n] )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail3;
+ }
+
+ start = glyph_array[n];
+ curr_class = class_array[n];
+ curr_glyph = start;
+
+ if ( curr_class >= 5 )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail3;
+ }
+
+ if ( n == glyph_count )
+ {
+ if ( ( error = Make_ClassRange( gcd, start,
+ curr_glyph,
+ curr_class,
+ memory ) ) != FT_Err_Ok )
+ goto Fail3;
+ }
+ else
+ {
+ if ( curr_glyph == 0xFFFF )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail3;
+ }
+ else
+ curr_glyph++;
+ }
+ }
+ }
+
+ /* now prepare the arrays for class values assigned during the lookup
+ process */
+
+ if ( ALLOC_ARRAY( gdef->NewGlyphClasses,
+ gcd->cd.cd2.ClassRangeCount + 1, FT_UShort* ) )
+ goto Fail3;
+
+ count = gcd->cd.cd2.ClassRangeCount;
+ gcrr = gcd->cd.cd2.ClassRangeRecord;
+ ngc = gdef->NewGlyphClasses;
+
+ /* We allocate arrays for all glyphs not covered by the class range
+ records. Each element holds four class values. */
+
+ if ( count > 0 )
+ {
+ if ( gcrr[0].Start )
+ {
+ if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, FT_UShort ) )
+ goto Fail2;
+ }
+
+ for ( n = 1; n < count; n++ )
+ {
+ if ( gcrr[n].Start - gcrr[n - 1].End > 1 )
+ if ( ALLOC_ARRAY( ngc[n],
+ ( gcrr[n].Start - gcrr[n - 1].End + 2 ) / 4,
+ FT_UShort ) )
+ goto Fail1;
+ }
+
+ if ( gcrr[count - 1].End != num_glyphs - 1 )
+ {
+ if ( ALLOC_ARRAY( ngc[count],
+ ( num_glyphs - gcrr[count - 1].End + 2 ) / 4,
+ FT_UShort ) )
+ goto Fail1;
+ }
+ }
+ else if ( num_glyphs > 0 )
+ {
+ if ( ALLOC_ARRAY( ngc[count],
+ ( num_glyphs + 3 ) / 4,
+ FT_UShort ) )
+ goto Fail2;
+ }
+
+ gdef->LastGlyph = num_glyphs - 1;
+
+ gdef->MarkAttachClassDef_offset = 0L;
+ gdef->MarkAttachClassDef.loaded = FALSE;
+
+ gcd->loaded = TRUE;
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ FREE( ngc[m] );
+
+Fail2:
+ FREE( gdef->NewGlyphClasses );
+
+Fail3:
+ FREE( gcd->cd.cd2.ClassRangeRecord );
+
+Fail4:
+ FREE( gcd->Defined );
+ return error;
+}
+
+
+static void Free_NewGlyphClasses( HB_GDEFHeader* gdef,
+ FT_Memory memory )
+{
+ FT_UShort** ngc;
+ FT_UShort n, count;
+
+
+ if ( gdef->NewGlyphClasses )
+ {
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1;
+ ngc = gdef->NewGlyphClasses;
+
+ for ( n = 0; n < count; n++ )
+ FREE( ngc[n] );
+
+ FREE( ngc );
+ }
+}
+
+
+FT_Error _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort property )
+{
+ FT_Error error;
+ FT_UShort class, new_class, index;
+ FT_UShort byte, bits, mask;
+ FT_UShort array_index, glyph_index, count;
+
+ HB_ClassRangeRecord* gcrr;
+ FT_UShort** ngc;
+
+
+ error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ /* we don't accept glyphs covered in `GlyphClassDef' */
+
+ if ( !error )
+ return HB_Err_Not_Covered;
+
+ switch ( property )
+ {
+ case 0:
+ new_class = UNCLASSIFIED_GLYPH;
+ break;
+
+ case HB_GDEF_BASE_GLYPH:
+ new_class = SIMPLE_GLYPH;
+ break;
+
+ case HB_GDEF_LIGATURE:
+ new_class = LIGATURE_GLYPH;
+ break;
+
+ case HB_GDEF_MARK:
+ new_class = MARK_GLYPH;
+ break;
+
+ case HB_GDEF_COMPONENT:
+ new_class = COMPONENT_GLYPH;
+ break;
+
+ default:
+ return FT_Err_Invalid_Argument;
+ }
+
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
+ gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
+ ngc = gdef->NewGlyphClasses;
+
+ if ( index < count && glyphID < gcrr[index].Start )
+ {
+ array_index = index;
+ if ( index == 0 )
+ glyph_index = glyphID;
+ else
+ glyph_index = glyphID - gcrr[index - 1].End - 1;
+ }
+ else
+ {
+ array_index = index + 1;
+ glyph_index = glyphID - gcrr[index].End - 1;
+ }
+
+ byte = ngc[array_index][glyph_index / 4];
+ bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
+ class = bits & 0x000F;
+
+ /* we don't overwrite existing entries */
+
+ if ( !class )
+ {
+ bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 );
+ mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) );
+
+ ngc[array_index][glyph_index / 4] &= mask;
+ ngc[array_index][glyph_index / 4] |= bits;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+FT_Error _HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
+ HB_GlyphItem gitem,
+ FT_UShort flags,
+ FT_UShort* property )
+{
+ FT_Error error;
+
+ if ( gdef )
+ {
+ FT_UShort basic_glyph_class;
+ FT_UShort desired_attachment_class;
+
+ if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN )
+ {
+ error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties );
+ if ( error )
+ return error;
+ }
+
+ *property = gitem->gproperties;
+
+ /* If the glyph was found in the MarkAttachmentClass table,
+ * then that class value is the high byte of the result,
+ * otherwise the low byte contains the basic type of the glyph
+ * as defined by the GlyphClassDef table.
+ */
+ if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ basic_glyph_class = HB_GDEF_MARK;
+ else
+ basic_glyph_class = *property;
+
+ /* Return Not_Covered, if, for example, basic_glyph_class
+ * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES
+ */
+ if ( flags & basic_glyph_class )
+ return HB_Err_Not_Covered;
+
+ /* The high byte of LookupFlags has the meaning
+ * "ignore marks of attachment type different than
+ * the attachment type specified."
+ */
+ desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS;
+ if ( desired_attachment_class )
+ {
+ if ( basic_glyph_class == HB_GDEF_MARK &&
+ *property != desired_attachment_class )
+ return HB_Err_Not_Covered;
+ }
+ } else {
+ *property = 0;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* END */
diff --git a/trunk/pango/opentype/harfbuzz-gdef.h b/trunk/pango/opentype/harfbuzz-gdef.h
new file mode 100644
index 00000000..e126e826
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gdef.h
@@ -0,0 +1,127 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GDEF_H
+#define HARFBUZZ_GDEF_H
+
+#include "harfbuzz-open.h"
+
+FT_BEGIN_HEADER
+
+#define HB_Err_Invalid_GDEF_SubTable_Format 0x1030
+#define HB_Err_Invalid_GDEF_SubTable 0x1031
+
+
+/* GDEF glyph properties. Note that HB_GDEF_COMPONENT has no corresponding
+ * flag in the LookupFlag field. */
+#define HB_GDEF_BASE_GLYPH 0x0002
+#define HB_GDEF_LIGATURE 0x0004
+#define HB_GDEF_MARK 0x0008
+#define HB_GDEF_COMPONENT 0x0010
+
+
+typedef struct HB_AttachPoint_ HB_AttachPoint;
+
+
+struct HB_AttachList_
+{
+ FT_Bool loaded;
+
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort GlyphCount; /* number of glyphs with
+ attachments */
+ HB_AttachPoint* AttachPoint; /* array of AttachPoint tables */
+};
+
+typedef struct HB_AttachList_ HB_AttachList;
+
+typedef struct HB_LigGlyph_ HB_LigGlyph;
+
+struct HB_LigCaretList_
+{
+ FT_Bool loaded;
+
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort LigGlyphCount; /* number of ligature glyphs */
+ HB_LigGlyph* LigGlyph; /* array of LigGlyph tables */
+};
+
+typedef struct HB_LigCaretList_ HB_LigCaretList;
+
+
+
+/* The `NewGlyphClasses' field is not defined in the TTO specification.
+ We use it for fonts with a constructed `GlyphClassDef' structure
+ (i.e., which don't have a GDEF table) to collect glyph classes
+ assigned during the lookup process. The number of arrays in this
+ pointer array is GlyphClassDef->cd.cd2.ClassRangeCount+1; the nth
+ array then contains the glyph class values of the glyphs not covered
+ by the ClassRangeRecords structures with index n-1 and n. We store
+ glyph class values for four glyphs in a single array element.
+
+ `LastGlyph' is identical to the number of glyphs minus one in the
+ font; we need it only if `NewGlyphClasses' is not NULL (to have an
+ upper bound for the last array).
+
+ Note that we first store the file offset to the `MarkAttachClassDef'
+ field (which has been introduced in OpenType 1.2) -- since the
+ `Version' field value hasn't been increased to indicate that we have
+ one more field for some obscure reason, we must parse the GSUB table
+ to find out whether class values refer to this table. Only then we
+ can finally load the MarkAttachClassDef structure if necessary. */
+
+struct HB_GDEFHeader_
+{
+ FT_Memory memory;
+ FT_ULong offset;
+
+ FT_Fixed Version;
+
+ HB_ClassDefinition GlyphClassDef;
+ HB_AttachList AttachList;
+ HB_LigCaretList LigCaretList;
+ FT_ULong MarkAttachClassDef_offset;
+ HB_ClassDefinition MarkAttachClassDef; /* new in OT 1.2 */
+
+ FT_UShort LastGlyph;
+ FT_UShort** NewGlyphClasses;
+};
+
+typedef struct HB_GDEFHeader_ HB_GDEFHeader;
+typedef struct HB_GDEFHeader_* HB_GDEF;
+
+
+FT_Error HB_New_GDEF_Table( FT_Face face,
+ HB_GDEFHeader** retptr );
+
+
+FT_Error HB_Load_GDEF_Table( FT_Face face,
+ HB_GDEFHeader** gdef );
+
+
+FT_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef );
+
+
+FT_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort* property );
+
+FT_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,
+ FT_UShort num_glyphs,
+ FT_UShort glyph_count,
+ FT_UShort* glyph_array,
+ FT_UShort* class_array );
+
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GDEF_H */
diff --git a/trunk/pango/opentype/harfbuzz-gpos-private.h b/trunk/pango/opentype/harfbuzz-gpos-private.h
new file mode 100644
index 00000000..a04416f5
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gpos-private.h
@@ -0,0 +1,683 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GPOS_PRIVATE_H
+#define HARFBUZZ_GPOS_PRIVATE_H
+
+#include "harfbuzz-gpos.h"
+
+FT_BEGIN_HEADER
+
+
+/* shared tables */
+
+struct HB_ValueRecord_
+{
+ FT_Short XPlacement; /* horizontal adjustment for
+ placement */
+ FT_Short YPlacement; /* vertical adjustment for
+ placement */
+ FT_Short XAdvance; /* horizontal adjustment for
+ advance */
+ FT_Short YAdvance; /* vertical adjustment for
+ advance */
+ HB_Device XPlacementDevice; /* device table for horizontal
+ placement */
+ HB_Device YPlacementDevice; /* device table for vertical
+ placement */
+ HB_Device XAdvanceDevice; /* device table for horizontal
+ advance */
+ HB_Device YAdvanceDevice; /* device table for vertical
+ advance */
+ FT_UShort XIdPlacement; /* horizontal placement metric ID */
+ FT_UShort YIdPlacement; /* vertical placement metric ID */
+ FT_UShort XIdAdvance; /* horizontal advance metric ID */
+ FT_UShort YIdAdvance; /* vertical advance metric ID */
+};
+
+typedef struct HB_ValueRecord_ HB_ValueRecord;
+
+
+/* Mask values to scan the value format of the ValueRecord structure.
+ We always expand compressed ValueRecords of the font. */
+
+#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT 0x0001
+#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT 0x0002
+#define HB_GPOS_FORMAT_HAVE_X_ADVANCE 0x0004
+#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE 0x0008
+#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE 0x0010
+#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE 0x0020
+#define HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE 0x0040
+#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE 0x0080
+#define HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT 0x0100
+#define HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT 0x0200
+#define HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE 0x0400
+#define HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE 0x0800
+
+
+struct HB_AnchorFormat1_
+{
+ FT_Short XCoordinate; /* horizontal value */
+ FT_Short YCoordinate; /* vertical value */
+};
+
+typedef struct HB_AnchorFormat1_ HB_AnchorFormat1;
+
+
+struct HB_AnchorFormat2_
+{
+ FT_Short XCoordinate; /* horizontal value */
+ FT_Short YCoordinate; /* vertical value */
+ FT_UShort AnchorPoint; /* index to glyph contour point */
+};
+
+typedef struct HB_AnchorFormat2_ HB_AnchorFormat2;
+
+
+struct HB_AnchorFormat3_
+{
+ FT_Short XCoordinate; /* horizontal value */
+ FT_Short YCoordinate; /* vertical value */
+ HB_Device XDeviceTable; /* device table for X coordinate */
+ HB_Device YDeviceTable; /* device table for Y coordinate */
+};
+
+typedef struct HB_AnchorFormat3_ HB_AnchorFormat3;
+
+
+struct HB_AnchorFormat4_
+{
+ FT_UShort XIdAnchor; /* horizontal metric ID */
+ FT_UShort YIdAnchor; /* vertical metric ID */
+};
+
+typedef struct HB_AnchorFormat4_ HB_AnchorFormat4;
+
+
+struct HB_Anchor_
+{
+ FT_UShort PosFormat; /* 1, 2, 3, or 4 -- 0 indicates
+ that there is no Anchor table */
+
+ union
+ {
+ HB_AnchorFormat1 af1;
+ HB_AnchorFormat2 af2;
+ HB_AnchorFormat3 af3;
+ HB_AnchorFormat4 af4;
+ } af;
+};
+
+typedef struct HB_Anchor_ HB_Anchor;
+
+
+struct HB_MarkRecord_
+{
+ FT_UShort Class; /* mark class */
+ HB_Anchor MarkAnchor; /* anchor table */
+};
+
+typedef struct HB_MarkRecord_ HB_MarkRecord;
+
+
+struct HB_MarkArray_
+{
+ FT_UShort MarkCount; /* number of MarkRecord tables */
+ HB_MarkRecord* MarkRecord; /* array of MarkRecord tables */
+};
+
+typedef struct HB_MarkArray_ HB_MarkArray;
+
+
+/* LookupType 1 */
+
+struct HB_SinglePosFormat1_
+{
+ HB_ValueRecord Value; /* ValueRecord for all covered
+ glyphs */
+};
+
+typedef struct HB_SinglePosFormat1_ HB_SinglePosFormat1;
+
+
+struct HB_SinglePosFormat2_
+{
+ FT_UShort ValueCount; /* number of ValueRecord tables */
+ HB_ValueRecord* Value; /* array of ValueRecord tables */
+};
+
+typedef struct HB_SinglePosFormat2_ HB_SinglePosFormat2;
+
+
+struct HB_SinglePos_
+{
+ FT_UShort PosFormat; /* 1 or 2 */
+ HB_Coverage Coverage; /* Coverage table */
+
+ FT_UShort ValueFormat; /* format of ValueRecord table */
+
+ union
+ {
+ HB_SinglePosFormat1 spf1;
+ HB_SinglePosFormat2 spf2;
+ } spf;
+};
+
+typedef struct HB_SinglePos_ HB_SinglePos;
+
+
+/* LookupType 2 */
+
+struct HB_PairValueRecord_
+{
+ FT_UShort SecondGlyph; /* glyph ID for second glyph */
+ HB_ValueRecord Value1; /* pos. data for first glyph */
+ HB_ValueRecord Value2; /* pos. data for second glyph */
+};
+
+typedef struct HB_PairValueRecord_ HB_PairValueRecord;
+
+
+struct HB_PairSet_
+{
+ FT_UShort PairValueCount;
+ /* number of PairValueRecord tables */
+ HB_PairValueRecord* PairValueRecord;
+ /* array of PairValueRecord tables */
+};
+
+typedef struct HB_PairSet_ HB_PairSet;
+
+
+struct HB_PairPosFormat1_
+{
+ FT_UShort PairSetCount; /* number of PairSet tables */
+ HB_PairSet* PairSet; /* array of PairSet tables */
+};
+
+typedef struct HB_PairPosFormat1_ HB_PairPosFormat1;
+
+
+struct HB_Class2Record_
+{
+ HB_ValueRecord Value1; /* pos. data for first glyph */
+ HB_ValueRecord Value2; /* pos. data for second glyph */
+};
+
+typedef struct HB_Class2Record_ HB_Class2Record;
+
+
+struct HB_Class1Record_
+{
+ HB_Class2Record* Class2Record; /* array of Class2Record tables */
+};
+
+typedef struct HB_Class1Record_ HB_Class1Record;
+
+
+struct HB_PairPosFormat2_
+{
+ HB_ClassDefinition ClassDef1; /* class def. for first glyph */
+ HB_ClassDefinition ClassDef2; /* class def. for second glyph */
+ FT_UShort Class1Count; /* number of classes in ClassDef1
+ table */
+ FT_UShort Class2Count; /* number of classes in ClassDef2
+ table */
+ HB_Class1Record* Class1Record; /* array of Class1Record tables */
+};
+
+typedef struct HB_PairPosFormat2_ HB_PairPosFormat2;
+
+
+struct HB_PairPos_
+{
+ FT_UShort PosFormat; /* 1 or 2 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort ValueFormat1; /* format of ValueRecord table
+ for first glyph */
+ FT_UShort ValueFormat2; /* format of ValueRecord table
+ for second glyph */
+
+ union
+ {
+ HB_PairPosFormat1 ppf1;
+ HB_PairPosFormat2 ppf2;
+ } ppf;
+};
+
+typedef struct HB_PairPos_ HB_PairPos;
+
+
+/* LookupType 3 */
+
+struct HB_EntryExitRecord_
+{
+ HB_Anchor EntryAnchor; /* entry Anchor table */
+ HB_Anchor ExitAnchor; /* exit Anchor table */
+};
+
+
+typedef struct HB_EntryExitRecord_ HB_EntryExitRecord;
+
+struct HB_CursivePos_
+{
+ FT_UShort PosFormat; /* always 1 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort EntryExitCount;
+ /* number of EntryExitRecord tables */
+ HB_EntryExitRecord* EntryExitRecord;
+ /* array of EntryExitRecord tables */
+};
+
+typedef struct HB_CursivePos_ HB_CursivePos;
+
+
+/* LookupType 4 */
+
+struct HB_BaseRecord_
+{
+ HB_Anchor* BaseAnchor; /* array of base glyph anchor
+ tables */
+};
+
+typedef struct HB_BaseRecord_ HB_BaseRecord;
+
+
+struct HB_BaseArray_
+{
+ FT_UShort BaseCount; /* number of BaseRecord tables */
+ HB_BaseRecord* BaseRecord; /* array of BaseRecord tables */
+};
+
+typedef struct HB_BaseArray_ HB_BaseArray;
+
+
+struct HB_MarkBasePos_
+{
+ FT_UShort PosFormat; /* always 1 */
+ HB_Coverage MarkCoverage; /* mark glyph coverage table */
+ HB_Coverage BaseCoverage; /* base glyph coverage table */
+ FT_UShort ClassCount; /* number of mark classes */
+ HB_MarkArray MarkArray; /* mark array table */
+ HB_BaseArray BaseArray; /* base array table */
+};
+
+typedef struct HB_MarkBasePos_ HB_MarkBasePos;
+
+
+/* LookupType 5 */
+
+struct HB_ComponentRecord_
+{
+ HB_Anchor* LigatureAnchor; /* array of ligature glyph anchor
+ tables */
+};
+
+typedef struct HB_ComponentRecord_ HB_ComponentRecord;
+
+
+struct HB_LigatureAttach_
+{
+ FT_UShort ComponentCount;
+ /* number of ComponentRecord tables */
+ HB_ComponentRecord* ComponentRecord;
+ /* array of ComponentRecord tables */
+};
+
+typedef struct HB_LigatureAttach_ HB_LigatureAttach;
+
+
+struct HB_LigatureArray_
+{
+ FT_UShort LigatureCount; /* number of LigatureAttach tables */
+ HB_LigatureAttach* LigatureAttach;
+ /* array of LigatureAttach tables */
+};
+
+typedef struct HB_LigatureArray_ HB_LigatureArray;
+
+
+struct HB_MarkLigPos_
+{
+ FT_UShort PosFormat; /* always 1 */
+ HB_Coverage MarkCoverage; /* mark glyph coverage table */
+ HB_Coverage LigatureCoverage;
+ /* ligature glyph coverage table */
+ FT_UShort ClassCount; /* number of mark classes */
+ HB_MarkArray MarkArray; /* mark array table */
+ HB_LigatureArray LigatureArray; /* ligature array table */
+};
+
+typedef struct HB_MarkLigPos_ HB_MarkLigPos;
+
+
+/* LookupType 6 */
+
+struct HB_Mark2Record_
+{
+ HB_Anchor* Mark2Anchor; /* array of mark glyph anchor
+ tables */
+};
+
+typedef struct HB_Mark2Record_ HB_Mark2Record;
+
+
+struct HB_Mark2Array_
+{
+ FT_UShort Mark2Count; /* number of Mark2Record tables */
+ HB_Mark2Record* Mark2Record; /* array of Mark2Record tables */
+};
+
+typedef struct HB_Mark2Array_ HB_Mark2Array;
+
+
+struct HB_MarkMarkPos_
+{
+ FT_UShort PosFormat; /* always 1 */
+ HB_Coverage Mark1Coverage; /* first mark glyph coverage table */
+ HB_Coverage Mark2Coverage; /* second mark glyph coverave table */
+ FT_UShort ClassCount; /* number of combining mark classes */
+ HB_MarkArray Mark1Array; /* MarkArray table for first mark */
+ HB_Mark2Array Mark2Array; /* MarkArray table for second mark */
+};
+
+typedef struct HB_MarkMarkPos_ HB_MarkMarkPos;
+
+
+/* needed by both lookup type 7 and 8 */
+
+struct HB_PosLookupRecord_
+{
+ FT_UShort SequenceIndex; /* index into current
+ glyph sequence */
+ FT_UShort LookupListIndex; /* Lookup to apply to that pos. */
+};
+
+typedef struct HB_PosLookupRecord_ HB_PosLookupRecord;
+
+
+/* LookupType 7 */
+
+struct HB_PosRule_
+{
+ FT_UShort GlyphCount; /* total number of input glyphs */
+ FT_UShort PosCount; /* number of PosLookupRecord tables */
+ FT_UShort* Input; /* array of input glyph IDs */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of PosLookupRecord tables */
+};
+
+typedef struct HB_PosRule_ HB_PosRule;
+
+
+struct HB_PosRuleSet_
+{
+ FT_UShort PosRuleCount; /* number of PosRule tables */
+ HB_PosRule* PosRule; /* array of PosRule tables */
+};
+
+typedef struct HB_PosRuleSet_ HB_PosRuleSet;
+
+
+struct HB_ContextPosFormat1_
+{
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort PosRuleSetCount; /* number of PosRuleSet tables */
+ HB_PosRuleSet* PosRuleSet; /* array of PosRuleSet tables */
+};
+
+typedef struct HB_ContextPosFormat1_ HB_ContextPosFormat1;
+
+
+struct HB_PosClassRule_
+{
+ FT_UShort GlyphCount; /* total number of context classes */
+ FT_UShort PosCount; /* number of PosLookupRecord tables */
+ FT_UShort* Class; /* array of classes */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of PosLookupRecord tables */
+};
+
+typedef struct HB_PosClassRule_ HB_PosClassRule;
+
+
+struct HB_PosClassSet_
+{
+ FT_UShort PosClassRuleCount;
+ /* number of PosClassRule tables */
+ HB_PosClassRule* PosClassRule; /* array of PosClassRule tables */
+};
+
+typedef struct HB_PosClassSet_ HB_PosClassSet;
+
+
+/* The `MaxContextLength' field is not defined in the TTO specification
+ but simplifies the implementation of this format. It holds the
+ maximal context length used in the context rules. */
+
+struct HB_ContextPosFormat2_
+{
+ FT_UShort MaxContextLength;
+ /* maximal context length */
+ HB_Coverage Coverage; /* Coverage table */
+ HB_ClassDefinition ClassDef; /* ClassDef table */
+ FT_UShort PosClassSetCount;
+ /* number of PosClassSet tables */
+ HB_PosClassSet* PosClassSet; /* array of PosClassSet tables */
+};
+
+typedef struct HB_ContextPosFormat2_ HB_ContextPosFormat2;
+
+
+struct HB_ContextPosFormat3_
+{
+ FT_UShort GlyphCount; /* number of input glyphs */
+ FT_UShort PosCount; /* number of PosLookupRecord tables */
+ HB_Coverage* Coverage; /* array of Coverage tables */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of PosLookupRecord tables */
+};
+
+typedef struct HB_ContextPosFormat3_ HB_ContextPosFormat3;
+
+
+struct HB_ContextPos_
+{
+ FT_UShort PosFormat; /* 1, 2, or 3 */
+
+ union
+ {
+ HB_ContextPosFormat1 cpf1;
+ HB_ContextPosFormat2 cpf2;
+ HB_ContextPosFormat3 cpf3;
+ } cpf;
+};
+
+typedef struct HB_ContextPos_ HB_ContextPos;
+
+
+/* LookupType 8 */
+
+struct HB_ChainPosRule_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* total number of backtrack glyphs */
+ FT_UShort* Backtrack; /* array of backtrack glyph IDs */
+ FT_UShort InputGlyphCount;
+ /* total number of input glyphs */
+ FT_UShort* Input; /* array of input glyph IDs */
+ FT_UShort LookaheadGlyphCount;
+ /* total number of lookahead glyphs */
+ FT_UShort* Lookahead; /* array of lookahead glyph IDs */
+ FT_UShort PosCount; /* number of PosLookupRecords */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of PosLookupRecords */
+};
+
+typedef struct HB_ChainPosRule_ HB_ChainPosRule;
+
+
+struct HB_ChainPosRuleSet_
+{
+ FT_UShort ChainPosRuleCount;
+ /* number of ChainPosRule tables */
+ HB_ChainPosRule* ChainPosRule; /* array of ChainPosRule tables */
+};
+
+typedef struct HB_ChainPosRuleSet_ HB_ChainPosRuleSet;
+
+
+struct HB_ChainContextPosFormat1_
+{
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort ChainPosRuleSetCount;
+ /* number of ChainPosRuleSet tables */
+ HB_ChainPosRuleSet* ChainPosRuleSet;
+ /* array of ChainPosRuleSet tables */
+};
+
+typedef struct HB_ChainContextPosFormat1_ HB_ChainContextPosFormat1;
+
+
+struct HB_ChainPosClassRule_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* total number of backtrack
+ classes */
+ FT_UShort* Backtrack; /* array of backtrack classes */
+ FT_UShort InputGlyphCount;
+ /* total number of context classes */
+ FT_UShort* Input; /* array of context classes */
+ FT_UShort LookaheadGlyphCount;
+ /* total number of lookahead
+ classes */
+ FT_UShort* Lookahead; /* array of lookahead classes */
+ FT_UShort PosCount; /* number of PosLookupRecords */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ChainPosClassRule_ HB_ChainPosClassRule;
+
+
+struct HB_ChainPosClassSet_
+{
+ FT_UShort ChainPosClassRuleCount;
+ /* number of ChainPosClassRule
+ tables */
+ HB_ChainPosClassRule* ChainPosClassRule;
+ /* array of ChainPosClassRule
+ tables */
+};
+
+typedef struct HB_ChainPosClassSet_ HB_ChainPosClassSet;
+
+
+/* The `MaxXXXLength' fields are not defined in the TTO specification
+ but simplifies the implementation of this format. It holds the
+ maximal context length used in the specific context rules. */
+
+struct HB_ChainContextPosFormat2_
+{
+ HB_Coverage Coverage; /* Coverage table */
+
+ FT_UShort MaxBacktrackLength;
+ /* maximal backtrack length */
+ HB_ClassDefinition BacktrackClassDef;
+ /* BacktrackClassDef table */
+ FT_UShort MaxInputLength;
+ /* maximal input length */
+ HB_ClassDefinition InputClassDef;
+ /* InputClassDef table */
+ FT_UShort MaxLookaheadLength;
+ /* maximal lookahead length */
+ HB_ClassDefinition LookaheadClassDef;
+ /* LookaheadClassDef table */
+
+ FT_UShort ChainPosClassSetCount;
+ /* number of ChainPosClassSet
+ tables */
+ HB_ChainPosClassSet* ChainPosClassSet;
+ /* array of ChainPosClassSet
+ tables */
+};
+
+typedef struct HB_ChainContextPosFormat2_ HB_ChainContextPosFormat2;
+
+
+struct HB_ChainContextPosFormat3_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* number of backtrack glyphs */
+ HB_Coverage* BacktrackCoverage;
+ /* array of backtrack Coverage
+ tables */
+ FT_UShort InputGlyphCount;
+ /* number of input glyphs */
+ HB_Coverage* InputCoverage;
+ /* array of input coverage
+ tables */
+ FT_UShort LookaheadGlyphCount;
+ /* number of lookahead glyphs */
+ HB_Coverage* LookaheadCoverage;
+ /* array of lookahead coverage
+ tables */
+ FT_UShort PosCount; /* number of PosLookupRecords */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ChainContextPosFormat3_ HB_ChainContextPosFormat3;
+
+
+struct HB_ChainContextPos_
+{
+ FT_UShort PosFormat; /* 1, 2, or 3 */
+
+ union
+ {
+ HB_ChainContextPosFormat1 ccpf1;
+ HB_ChainContextPosFormat2 ccpf2;
+ HB_ChainContextPosFormat3 ccpf3;
+ } ccpf;
+};
+
+typedef struct HB_ChainContextPos_ HB_ChainContextPos;
+
+
+union HB_GPOS_SubTable_
+{
+ HB_SinglePos single;
+ HB_PairPos pair;
+ HB_CursivePos cursive;
+ HB_MarkBasePos markbase;
+ HB_MarkLigPos marklig;
+ HB_MarkMarkPos markmark;
+ HB_ContextPos context;
+ HB_ChainContextPos chain;
+};
+
+typedef union HB_GPOS_SubTable_ HB_GPOS_SubTable;
+
+
+
+FT_Error _HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
+ FT_Stream stream,
+ FT_UShort lookup_type );
+
+void _HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
+ FT_Memory memory,
+ FT_UShort lookup_type );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GPOS_PRIVATE_H */
diff --git a/trunk/pango/opentype/harfbuzz-gpos.c b/trunk/pango/opentype/harfbuzz-gpos.c
new file mode 100644
index 00000000..513f3fb5
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gpos.c
@@ -0,0 +1,6304 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+#include "harfbuzz-gpos-private.h"
+#include "harfbuzz-open-private.h"
+#include "harfbuzz-gdef-private.h"
+
+struct GPOS_Instance_
+{
+ HB_GPOSHeader* gpos;
+ FT_Face face;
+ FT_Bool dvi;
+ FT_UShort load_flags; /* how the glyph should be loaded */
+ FT_Bool r2l;
+
+ FT_UShort last; /* the last valid glyph -- used
+ with cursive positioning */
+ FT_Pos anchor_x; /* the coordinates of the anchor point */
+ FT_Pos anchor_y; /* of the last valid glyph */
+};
+
+typedef struct GPOS_Instance_ GPOS_Instance;
+
+
+static FT_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,
+ FT_UShort lookup_index,
+ HB_Buffer buffer,
+ FT_UShort context_length,
+ int nesting_level );
+
+
+
+/* the client application must replace this with something more
+ meaningful if multiple master fonts are to be supported. */
+
+static FT_Error default_mmfunc( FT_Face face,
+ FT_UShort metric_id,
+ FT_Pos* metric_value,
+ void* data )
+{
+ FT_UNUSED(face);
+ FT_UNUSED(metric_id);
+ FT_UNUSED(metric_value);
+ FT_UNUSED(data);
+ return HB_Err_No_MM_Interpreter;
+}
+
+
+
+FT_Error HB_Load_GPOS_Table( FT_Face face,
+ HB_GPOSHeader** retptr,
+ HB_GDEFHeader* gdef )
+{
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ FT_UShort i, num_lookups;
+ HB_GPOSHeader* gpos;
+ HB_Lookup* lo;
+
+ FT_Stream stream = face->stream;
+ FT_Error error;
+ FT_Memory memory = face->memory;
+
+
+ if ( !retptr )
+ return FT_Err_Invalid_Argument;
+
+ if ( !stream )
+ return FT_Err_Invalid_Face_Handle;
+
+ if (( error = _hb_ftglue_face_goto_table( face, TTAG_GPOS, stream ) ))
+ return error;
+
+ base_offset = FILE_Pos();
+
+ if ( ALLOC ( gpos, sizeof( *gpos ) ) )
+ return error;
+
+ gpos->memory = memory;
+ gpos->gfunc = FT_Load_Glyph;
+ gpos->mmfunc = default_mmfunc;
+
+ /* skip version */
+
+ if ( FILE_Seek( base_offset + 4L ) ||
+ ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ScriptList( &gpos->ScriptList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_FeatureList( &gpos->FeatureList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_LookupList( &gpos->LookupList,
+ stream, HB_Type_GPOS ) ) != FT_Err_Ok )
+ goto Fail2;
+
+ gpos->gdef = gdef; /* can be NULL */
+
+ /* We now check the LookupFlags for values larger than 0xFF to find
+ out whether we need to load the `MarkAttachClassDef' field of the
+ GDEF table -- this hack is necessary for OpenType 1.2 tables since
+ the version field of the GDEF table hasn't been incremented.
+
+ For constructed GDEF tables, we only load it if
+ `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
+ a constructed mark attach table is not supported currently). */
+
+ if ( gdef &&
+ gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
+ {
+ lo = gpos->LookupList.Lookup;
+ num_lookups = gpos->LookupList.LookupCount;
+
+ for ( i = 0; i < num_lookups; i++ )
+ {
+ if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ {
+ if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,
+ 256, stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ break;
+ }
+ }
+ }
+
+ *retptr = gpos;
+
+ return FT_Err_Ok;
+
+Fail1:
+ _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS, memory );
+
+Fail2:
+ _HB_OPEN_Free_FeatureList( &gpos->FeatureList, memory );
+
+Fail3:
+ _HB_OPEN_Free_ScriptList( &gpos->ScriptList, memory );
+
+Fail4:
+ FREE( gpos );
+
+ return error;
+}
+
+
+FT_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos )
+{
+ FT_Memory memory = gpos->memory;
+
+ _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS, memory );
+ _HB_OPEN_Free_FeatureList( &gpos->FeatureList, memory );
+ _HB_OPEN_Free_ScriptList( &gpos->ScriptList, memory );
+
+ FREE( gpos );
+
+ return FT_Err_Ok;
+}
+
+
+/*****************************
+ * SubTable related functions
+ *****************************/
+
+/* shared tables */
+
+/* ValueRecord */
+
+/* There is a subtle difference in the specs between a `table' and a
+ `record' -- offsets for device tables in ValueRecords are taken from
+ the parent table and not the parent record. */
+
+static FT_Error Load_ValueRecord( HB_ValueRecord* vr,
+ FT_UShort format,
+ FT_ULong base_offset,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_ULong cur_offset, new_offset;
+
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ vr->XPlacement = GET_Short();
+
+ FORGET_Frame();
+ }
+ else
+ vr->XPlacement = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ vr->YPlacement = GET_Short();
+
+ FORGET_Frame();
+ }
+ else
+ vr->YPlacement = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ vr->XAdvance = GET_Short();
+
+ FORGET_Frame();
+ }
+ else
+ vr->XAdvance = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ vr->YAdvance = GET_Short();
+
+ FORGET_Frame();
+ }
+ else
+ vr->YAdvance = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &vr->XPlacementDevice,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ goto empty1;
+ }
+ else
+ {
+ empty1:
+ vr->XPlacementDevice.StartSize = 0;
+ vr->XPlacementDevice.EndSize = 0;
+ vr->XPlacementDevice.DeltaValue = NULL;
+ }
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &vr->YPlacementDevice,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ goto empty2;
+ }
+ else
+ {
+ empty2:
+ vr->YPlacementDevice.StartSize = 0;
+ vr->YPlacementDevice.EndSize = 0;
+ vr->YPlacementDevice.DeltaValue = NULL;
+ }
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &vr->XAdvanceDevice,
+ stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ goto empty3;
+ }
+ else
+ {
+ empty3:
+ vr->XAdvanceDevice.StartSize = 0;
+ vr->XAdvanceDevice.EndSize = 0;
+ vr->XAdvanceDevice.DeltaValue = NULL;
+ }
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &vr->YAdvanceDevice,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ goto empty4;
+ }
+ else
+ {
+ empty4:
+ vr->YAdvanceDevice.StartSize = 0;
+ vr->YAdvanceDevice.EndSize = 0;
+ vr->YAdvanceDevice.DeltaValue = NULL;
+ }
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ vr->XIdPlacement = GET_UShort();
+
+ FORGET_Frame();
+ }
+ else
+ vr->XIdPlacement = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ vr->YIdPlacement = GET_UShort();
+
+ FORGET_Frame();
+ }
+ else
+ vr->YIdPlacement = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ vr->XIdAdvance = GET_UShort();
+
+ FORGET_Frame();
+ }
+ else
+ vr->XIdAdvance = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ vr->YIdAdvance = GET_UShort();
+
+ FORGET_Frame();
+ }
+ else
+ vr->YIdAdvance = 0;
+
+ return FT_Err_Ok;
+
+Fail1:
+ _HB_OPEN_Free_Device( &vr->YAdvanceDevice, memory );
+
+Fail2:
+ _HB_OPEN_Free_Device( &vr->XAdvanceDevice, memory );
+
+Fail3:
+ _HB_OPEN_Free_Device( &vr->YPlacementDevice, memory );
+ return error;
+}
+
+
+static void Free_ValueRecord( HB_ValueRecord* vr,
+ FT_UShort format,
+ FT_Memory memory )
+{
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
+ _HB_OPEN_Free_Device( &vr->YAdvanceDevice, memory );
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
+ _HB_OPEN_Free_Device( &vr->XAdvanceDevice, memory );
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
+ _HB_OPEN_Free_Device( &vr->YPlacementDevice, memory );
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
+ _HB_OPEN_Free_Device( &vr->XPlacementDevice, memory );
+}
+
+
+static FT_Error Get_ValueRecord( GPOS_Instance* gpi,
+ HB_ValueRecord* vr,
+ FT_UShort format,
+ HB_Position gd )
+{
+ FT_Pos value;
+ FT_Short pixel_value;
+ FT_Error error = FT_Err_Ok;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ FT_UShort x_ppem, y_ppem;
+ FT_Fixed x_scale, y_scale;
+
+
+ if ( !format )
+ return FT_Err_Ok;
+
+ x_ppem = gpi->face->size->metrics.x_ppem;
+ y_ppem = gpi->face->size->metrics.y_ppem;
+ x_scale = gpi->face->size->metrics.x_scale;
+ y_scale = gpi->face->size->metrics.y_scale;
+
+ /* design units -> fractional pixel */
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
+ gd->x_pos += x_scale * vr->XPlacement / 0x10000;
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
+ gd->y_pos += y_scale * vr->YPlacement / 0x10000;
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
+ gd->x_advance += x_scale * vr->XAdvance / 0x10000;
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
+ gd->y_advance += y_scale * vr->YAdvance / 0x10000;
+
+ if ( !gpi->dvi )
+ {
+ /* pixel -> fractional pixel */
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
+ {
+ _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );
+ gd->x_pos += pixel_value << 6;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
+ {
+ _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );
+ gd->y_pos += pixel_value << 6;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
+ {
+ _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );
+ gd->x_advance += pixel_value << 6;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
+ {
+ _HB_OPEN_Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value );
+ gd->y_advance += pixel_value << 6;
+ }
+ }
+
+ /* values returned from mmfunc() are already in fractional pixels */
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
+ {
+ error = (gpos->mmfunc)( gpi->face, vr->XIdPlacement,
+ &value, gpos->data );
+ if ( error )
+ return error;
+ gd->x_pos += value;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
+ {
+ error = (gpos->mmfunc)( gpi->face, vr->YIdPlacement,
+ &value, gpos->data );
+ if ( error )
+ return error;
+ gd->y_pos += value;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
+ {
+ error = (gpos->mmfunc)( gpi->face, vr->XIdAdvance,
+ &value, gpos->data );
+ if ( error )
+ return error;
+ gd->x_advance += value;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
+ {
+ error = (gpos->mmfunc)( gpi->face, vr->YIdAdvance,
+ &value, gpos->data );
+ if ( error )
+ return error;
+ gd->y_advance += value;
+ }
+
+ return error;
+}
+
+
+/* AnchorFormat1 */
+/* AnchorFormat2 */
+/* AnchorFormat3 */
+/* AnchorFormat4 */
+
+static FT_Error Load_Anchor( HB_Anchor* an,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ an->PosFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( an->PosFormat )
+ {
+ case 1:
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ an->af.af1.XCoordinate = GET_Short();
+ an->af.af1.YCoordinate = GET_Short();
+
+ FORGET_Frame();
+ break;
+
+ case 2:
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ an->af.af2.XCoordinate = GET_Short();
+ an->af.af2.YCoordinate = GET_Short();
+ an->af.af2.AnchorPoint = GET_UShort();
+
+ FORGET_Frame();
+ break;
+
+ case 3:
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ an->af.af3.XCoordinate = GET_Short();
+ an->af.af3.YCoordinate = GET_Short();
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &an->af.af3.XDeviceTable,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ an->af.af3.XDeviceTable.StartSize = 0;
+ an->af.af3.XDeviceTable.EndSize = 0;
+ an->af.af3.XDeviceTable.DeltaValue = NULL;
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &an->af.af3.YDeviceTable,
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ an->af.af3.YDeviceTable.StartSize = 0;
+ an->af.af3.YDeviceTable.EndSize = 0;
+ an->af.af3.YDeviceTable.DeltaValue = NULL;
+ }
+ break;
+
+ case 4:
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ an->af.af4.XIdAnchor = GET_UShort();
+ an->af.af4.YIdAnchor = GET_UShort();
+
+ FORGET_Frame();
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable, memory );
+ return error;
+}
+
+
+static void Free_Anchor( HB_Anchor* an,
+ FT_Memory memory)
+{
+ if ( an->PosFormat == 3 )
+ {
+ _HB_OPEN_Free_Device( &an->af.af3.YDeviceTable, memory );
+ _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable, memory );
+ }
+}
+
+
+static FT_Error Get_Anchor( GPOS_Instance* gpi,
+ HB_Anchor* an,
+ FT_UShort glyph_index,
+ FT_Pos* x_value,
+ FT_Pos* y_value )
+{
+ FT_Error error = FT_Err_Ok;
+
+ FT_Outline outline;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ FT_UShort ap;
+
+ FT_Short pixel_value;
+ FT_UShort load_flags;
+
+ FT_UShort x_ppem, y_ppem;
+ FT_Fixed x_scale, y_scale;
+
+
+ x_ppem = gpi->face->size->metrics.x_ppem;
+ y_ppem = gpi->face->size->metrics.y_ppem;
+ x_scale = gpi->face->size->metrics.x_scale;
+ y_scale = gpi->face->size->metrics.y_scale;
+
+ switch ( an->PosFormat )
+ {
+ case 0:
+ /* The special case of an empty AnchorTable */
+
+ return HB_Err_Not_Covered;
+
+ case 1:
+ *x_value = x_scale * an->af.af1.XCoordinate / 0x10000;
+ *y_value = y_scale * an->af.af1.YCoordinate / 0x10000;
+ break;
+
+ case 2:
+ /* glyphs must be scaled */
+
+ load_flags = gpi->load_flags & ~FT_LOAD_NO_SCALE;
+
+ if ( !gpi->dvi )
+ {
+ error = (gpos->gfunc)( gpi->face, glyph_index, load_flags );
+ if ( error )
+ return error;
+
+ if ( gpi->face->glyph->format != ft_glyph_format_outline )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ ap = an->af.af2.AnchorPoint;
+
+ outline = gpi->face->glyph->outline;
+
+ /* if outline.n_points is set to zero by gfunc(), we use the
+ design coordinate value pair. This can happen e.g. for
+ sbit glyphs */
+
+ if ( !outline.n_points )
+ goto no_contour_point;
+
+ if ( ap >= outline.n_points )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ *x_value = outline.points[ap].x;
+ *y_value = outline.points[ap].y;
+ }
+ else
+ {
+ no_contour_point:
+ *x_value = x_scale * an->af.af3.XCoordinate / 0x10000;
+ *y_value = y_scale * an->af.af3.YCoordinate / 0x10000;
+ }
+ break;
+
+ case 3:
+ if ( !gpi->dvi )
+ {
+ _HB_OPEN_Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value );
+ *x_value = pixel_value << 6;
+ _HB_OPEN_Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value );
+ *y_value = pixel_value << 6;
+ }
+ else
+ *x_value = *y_value = 0;
+
+ *x_value += x_scale * an->af.af3.XCoordinate / 0x10000;
+ *y_value += y_scale * an->af.af3.YCoordinate / 0x10000;
+ break;
+
+ case 4:
+ error = (gpos->mmfunc)( gpi->face, an->af.af4.XIdAnchor,
+ x_value, gpos->data );
+ if ( error )
+ return error;
+
+ error = (gpos->mmfunc)( gpi->face, an->af.af4.YIdAnchor,
+ y_value, gpos->data );
+ if ( error )
+ return error;
+ break;
+ }
+
+ return error;
+}
+
+
+/* MarkArray */
+
+static FT_Error Load_MarkArray ( HB_MarkArray* ma,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_MarkRecord* mr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ma->MarkCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ma->MarkRecord = NULL;
+
+ if ( ALLOC_ARRAY( ma->MarkRecord, count, HB_MarkRecord ) )
+ return error;
+
+ mr = ma->MarkRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail;
+
+ mr[n].Class = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &mr[n].MarkAnchor, stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_Anchor( &mr[m].MarkAnchor, memory );
+
+ FREE( mr );
+ return error;
+}
+
+
+static void Free_MarkArray( HB_MarkArray* ma,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_MarkRecord* mr;
+
+
+ if ( ma->MarkRecord )
+ {
+ count = ma->MarkCount;
+ mr = ma->MarkRecord;
+
+ for ( n = 0; n < count; n++ )
+ Free_Anchor( &mr[n].MarkAnchor, memory );
+
+ FREE( mr );
+ }
+}
+
+
+/* LookupType 1 */
+
+/* SinglePosFormat1 */
+/* SinglePosFormat2 */
+
+static FT_Error Load_SinglePos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_SinglePos* sp = &st->single;
+
+ FT_UShort n, m, count, format;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ValueRecord* vr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ sp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ format = sp->ValueFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( !format )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &sp->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ switch ( sp->PosFormat )
+ {
+ case 1:
+ error = Load_ValueRecord( &sp->spf.spf1.Value, format,
+ base_offset, stream );
+ if ( error )
+ goto Fail2;
+ break;
+
+ case 2:
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = sp->spf.spf2.ValueCount = GET_UShort();
+
+ FORGET_Frame();
+
+ sp->spf.spf2.Value = NULL;
+
+ if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, HB_ValueRecord ) )
+ goto Fail2;
+
+ vr = sp->spf.spf2.Value;
+
+ for ( n = 0; n < count; n++ )
+ {
+ error = Load_ValueRecord( &vr[n], format, base_offset, stream );
+ if ( error )
+ goto Fail1;
+ }
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ValueRecord( &vr[m], format, memory );
+
+ FREE( vr );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &sp->Coverage, memory );
+ return error;
+}
+
+
+static void Free_SinglePos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count, format;
+ HB_SinglePos* sp = &st->single;
+
+ HB_ValueRecord* v;
+
+
+ format = sp->ValueFormat;
+
+ switch ( sp->PosFormat )
+ {
+ case 1:
+ Free_ValueRecord( &sp->spf.spf1.Value, format, memory );
+ break;
+
+ case 2:
+ if ( sp->spf.spf2.Value )
+ {
+ count = sp->spf.spf2.ValueCount;
+ v = sp->spf.spf2.Value;
+
+ for ( n = 0; n < count; n++ )
+ Free_ValueRecord( &v[n], format, memory );
+
+ FREE( v );
+ }
+ break;
+ }
+
+ _HB_OPEN_Free_Coverage( &sp->Coverage, memory );
+}
+
+static FT_Error Lookup_DefaultPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UNUSED(gpi);
+ FT_UNUSED(st);
+ FT_UNUSED(buffer);
+ FT_UNUSED(flags);
+ FT_UNUSED(context_length);
+ FT_UNUSED(nesting_level);
+ return HB_Err_Not_Covered;
+}
+
+static FT_Error Lookup_SinglePos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_SinglePos* sp = &st->single;
+
+ FT_UNUSED(nesting_level);
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ switch ( sp->PosFormat )
+ {
+ case 1:
+ error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
+ sp->ValueFormat, POSITION( buffer->in_pos ) );
+ if ( error )
+ return error;
+ break;
+
+ case 2:
+ if ( index >= sp->spf.spf2.ValueCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+ error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
+ sp->ValueFormat, POSITION( buffer->in_pos ) );
+ if ( error )
+ return error;
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable;
+ }
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 2 */
+
+/* PairSet */
+
+static FT_Error Load_PairSet ( HB_PairSet* ps,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong base_offset;
+
+ HB_PairValueRecord* pvr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ps->PairValueCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ps->PairValueRecord = NULL;
+
+ if ( ALLOC_ARRAY( ps->PairValueRecord, count, HB_PairValueRecord ) )
+ return error;
+
+ pvr = ps->PairValueRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ pvr[n].SecondGlyph = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( format1 )
+ {
+ error = Load_ValueRecord( &pvr[n].Value1, format1,
+ base_offset, stream );
+ if ( error )
+ goto Fail;
+ }
+ if ( format2 )
+ {
+ error = Load_ValueRecord( &pvr[n].Value2, format2,
+ base_offset, stream );
+ if ( error )
+ {
+ if ( format1 )
+ Free_ValueRecord( &pvr[n].Value1, format1, memory );
+ goto Fail;
+ }
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &pvr[m].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &pvr[m].Value2, format2, memory );
+ }
+
+ FREE( pvr );
+ return error;
+}
+
+
+static void Free_PairSet( HB_PairSet* ps,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PairValueRecord* pvr;
+
+
+ if ( ps->PairValueRecord )
+ {
+ count = ps->PairValueCount;
+ pvr = ps->PairValueRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &pvr[n].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &pvr[n].Value2, format2, memory );
+ }
+
+ FREE( pvr );
+ }
+}
+
+
+/* PairPosFormat1 */
+
+static FT_Error Load_PairPos1( HB_PairPosFormat1* ppf1,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PairSet* ps;
+
+
+ base_offset = FILE_Pos() - 8L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ppf1->PairSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ppf1->PairSet = NULL;
+
+ if ( ALLOC_ARRAY( ppf1->PairSet, count, HB_PairSet ) )
+ return error;
+
+ ps = ppf1->PairSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PairSet( &ps[n], format1,
+ format2, stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_PairSet( &ps[m], format1, format2, memory );
+
+ FREE( ps );
+ return error;
+}
+
+
+static void Free_PairPos1( HB_PairPosFormat1* ppf1,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PairSet* ps;
+
+
+ if ( ppf1->PairSet )
+ {
+ count = ppf1->PairSetCount;
+ ps = ppf1->PairSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_PairSet( &ps[n], format1, format2, memory );
+
+ FREE( ps );
+ }
+}
+
+
+/* PairPosFormat2 */
+
+static FT_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort m, n, k, count1, count2;
+ FT_ULong cur_offset, new_offset1, new_offset2, base_offset;
+
+ HB_Class1Record* c1r;
+ HB_Class2Record* c2r;
+
+
+ base_offset = FILE_Pos() - 8L;
+
+ if ( ACCESS_Frame( 8L ) )
+ return error;
+
+ new_offset1 = GET_UShort() + base_offset;
+ new_offset2 = GET_UShort() + base_offset;
+
+ /* `Class1Count' and `Class2Count' are the upper limits for class
+ values, thus we read it now to make additional safety checks. */
+
+ count1 = ppf2->Class1Count = GET_UShort();
+ count2 = ppf2->Class2Count = GET_UShort();
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset1 ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ if ( FILE_Seek( new_offset2 ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ ppf2->Class1Record = NULL;
+
+ if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) )
+ goto Fail2;
+
+ c1r = ppf2->Class1Record;
+
+ for ( m = 0; m < count1; m++ )
+ {
+ c1r[m].Class2Record = NULL;
+
+ if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )
+ goto Fail1;
+
+ c2r = c1r[m].Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ {
+ error = Load_ValueRecord( &c2r[n].Value1, format1,
+ base_offset, stream );
+ if ( error )
+ goto Fail0;
+ }
+ if ( format2 )
+ {
+ error = Load_ValueRecord( &c2r[n].Value2, format2,
+ base_offset, stream );
+ if ( error )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1, memory );
+ goto Fail0;
+ }
+ }
+ }
+
+ continue;
+
+ Fail0:
+ for ( k = 0; k < n; k++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[k].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &c2r[k].Value2, format2, memory );
+ }
+ goto Fail1;
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( k = 0; k < m; k++ )
+ {
+ c2r = c1r[k].Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &c2r[n].Value2, format2, memory );
+ }
+
+ FREE( c2r );
+ }
+
+ FREE( c1r );
+Fail2:
+
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2, memory );
+
+Fail3:
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1, memory );
+ return error;
+}
+
+
+static void Free_PairPos2( HB_PairPosFormat2* ppf2,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Memory memory )
+{
+ FT_UShort m, n, count1, count2;
+
+ HB_Class1Record* c1r;
+ HB_Class2Record* c2r;
+
+
+ if ( ppf2->Class1Record )
+ {
+ c1r = ppf2->Class1Record;
+ count1 = ppf2->Class1Count;
+ count2 = ppf2->Class2Count;
+
+ for ( m = 0; m < count1; m++ )
+ {
+ c2r = c1r[m].Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &c2r[n].Value2, format2, memory );
+ }
+
+ FREE( c2r );
+ }
+
+ FREE( c1r );
+
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2, memory );
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1, memory );
+ }
+}
+
+
+static FT_Error Load_PairPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_PairPos* pp = &st->pair;
+
+ FT_UShort format1, format2;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 8L ) )
+ return error;
+
+ pp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ format1 = pp->ValueFormat1 = GET_UShort();
+ format2 = pp->ValueFormat2 = GET_UShort();
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ switch ( pp->PosFormat )
+ {
+ case 1:
+ error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream );
+ if ( error )
+ goto Fail;
+ break;
+
+ case 2:
+ error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream );
+ if ( error )
+ goto Fail;
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ _HB_OPEN_Free_Coverage( &pp->Coverage, memory );
+ return error;
+}
+
+
+static void Free_PairPos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort format1, format2;
+ HB_PairPos* pp = &st->pair;
+
+
+ format1 = pp->ValueFormat1;
+ format2 = pp->ValueFormat2;
+
+ switch ( pp->PosFormat )
+ {
+ case 1:
+ Free_PairPos1( &pp->ppf.ppf1, format1, format2, memory );
+ break;
+
+ case 2:
+ Free_PairPos2( &pp->ppf.ppf2, format1, format2, memory );
+ break;
+ }
+
+ _HB_OPEN_Free_Coverage( &pp->Coverage, memory );
+}
+
+
+static FT_Error Lookup_PairPos1( GPOS_Instance* gpi,
+ HB_PairPosFormat1* ppf1,
+ HB_Buffer buffer,
+ FT_UShort first_pos,
+ FT_UShort index,
+ FT_UShort format1,
+ FT_UShort format2 )
+{
+ FT_Error error;
+ FT_UShort numpvr, glyph2;
+
+ HB_PairValueRecord* pvr;
+
+
+ if ( index >= ppf1->PairSetCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ pvr = ppf1->PairSet[index].PairValueRecord;
+ if ( !pvr )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ glyph2 = IN_CURGLYPH();
+
+ for ( numpvr = ppf1->PairSet[index].PairValueCount;
+ numpvr;
+ numpvr--, pvr++ )
+ {
+ if ( glyph2 == pvr->SecondGlyph )
+ {
+ error = Get_ValueRecord( gpi, &pvr->Value1, format1,
+ POSITION( first_pos ) );
+ if ( error )
+ return error;
+ return Get_ValueRecord( gpi, &pvr->Value2, format2,
+ POSITION( buffer->in_pos ) );
+ }
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_PairPos2( GPOS_Instance* gpi,
+ HB_PairPosFormat2* ppf2,
+ HB_Buffer buffer,
+ FT_UShort first_pos,
+ FT_UShort format1,
+ FT_UShort format2 )
+{
+ FT_Error error;
+ FT_UShort cl1, cl2;
+
+ HB_Class1Record* c1r;
+ HB_Class2Record* c2r;
+
+
+ error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
+ &cl1, NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(),
+ &cl2, NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ c1r = &ppf2->Class1Record[cl1];
+ if ( !c1r )
+ return HB_Err_Invalid_GPOS_SubTable;
+ c2r = &c1r->Class2Record[cl2];
+
+ error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
+ if ( error )
+ return error;
+ return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
+}
+
+
+static FT_Error Lookup_PairPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, property, first_pos;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_PairPos* pp = &st->pair;
+
+ FT_UNUSED(nesting_level);
+
+ if ( buffer->in_pos >= buffer->in_length - 1 )
+ return HB_Err_Not_Covered; /* Not enough glyphs in stream */
+
+ if ( context_length != 0xFFFF && context_length < 2 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ /* second glyph */
+
+ first_pos = buffer->in_pos;
+ (buffer->in_pos)++;
+
+ while ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( buffer->in_pos == buffer->in_length )
+ return HB_Err_Not_Covered;
+ (buffer->in_pos)++;
+ }
+
+ switch ( pp->PosFormat )
+ {
+ case 1:
+ error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
+ first_pos, index,
+ pp->ValueFormat1, pp->ValueFormat2 );
+ break;
+
+ case 2:
+ error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
+ pp->ValueFormat1, pp->ValueFormat2 );
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ /* if we don't have coverage for the second glyph don't skip it for
+ further lookups but reset in_pos back to the first_glyph and let
+ the caller in Do_String_Lookup increment in_pos */
+ if ( error == HB_Err_Not_Covered )
+ buffer->in_pos = first_pos;
+
+ /* adjusting the `next' glyph */
+
+ if ( pp->ValueFormat2 )
+ (buffer->in_pos)++;
+
+ return error;
+}
+
+
+/* LookupType 3 */
+
+/* CursivePosFormat1 */
+
+static FT_Error Load_CursivePos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_CursivePos* cp = &st->cursive;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_EntryExitRecord* eer;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ cp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &cp->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = cp->EntryExitCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cp->EntryExitRecord = NULL;
+
+ if ( ALLOC_ARRAY( cp->EntryExitRecord, count, HB_EntryExitRecord ) )
+ goto Fail2;
+
+ eer = cp->EntryExitRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ FT_ULong entry_offset;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ entry_offset = new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &eer[n].EntryAnchor,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ eer[n].EntryAnchor.PosFormat = 0;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &eer[n].ExitAnchor,
+ stream ) ) != FT_Err_Ok )
+ {
+ if ( entry_offset )
+ Free_Anchor( &eer[n].EntryAnchor, memory );
+ goto Fail1;
+ }
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ eer[n].ExitAnchor.PosFormat = 0;
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ {
+ Free_Anchor( &eer[m].EntryAnchor, memory );
+ Free_Anchor( &eer[m].ExitAnchor, memory );
+ }
+
+ FREE( eer );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &cp->Coverage, memory );
+ return error;
+}
+
+
+static void Free_CursivePos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_CursivePos* cp = &st->cursive;
+
+ HB_EntryExitRecord* eer;
+
+
+ if ( cp->EntryExitRecord )
+ {
+ count = cp->EntryExitCount;
+ eer = cp->EntryExitRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ Free_Anchor( &eer[n].EntryAnchor, memory );
+ Free_Anchor( &eer[n].ExitAnchor, memory );
+ }
+
+ FREE( eer );
+ }
+
+ _HB_OPEN_Free_Coverage( &cp->Coverage, memory );
+}
+
+
+static FT_Error Lookup_CursivePos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_CursivePos* cp = &st->cursive;
+
+ HB_EntryExitRecord* eer;
+ FT_Pos entry_x, entry_y;
+ FT_Pos exit_x, exit_y;
+
+ FT_UNUSED(nesting_level);
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ {
+ gpi->last = 0xFFFF;
+ return HB_Err_Not_Covered;
+ }
+
+ /* Glyphs not having the right GDEF properties will be ignored, i.e.,
+ gpi->last won't be reset (contrary to user defined properties). */
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* We don't handle mark glyphs here. According to Andrei, this isn't
+ possible, but who knows... */
+
+ if ( property == HB_GDEF_MARK )
+ {
+ gpi->last = 0xFFFF;
+ return HB_Err_Not_Covered;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ {
+ gpi->last = 0xFFFF;
+ return error;
+ }
+
+ if ( index >= cp->EntryExitCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ eer = &cp->EntryExitRecord[index];
+
+ /* Now comes the messiest part of the whole OpenType
+ specification. At first glance, cursive connections seem easy
+ to understand, but there are pitfalls! The reason is that
+ the specs don't mention how to compute the advance values
+ resp. glyph offsets. I was told it would be an omission, to
+ be fixed in the next OpenType version... Again many thanks to
+ Andrei Burago <andreib@microsoft.com> for clarifications.
+
+ Consider the following example:
+
+ | xadv1 |
+ +---------+
+ | |
+ +-----+--+ 1 |
+ | | .| |
+ | 0+--+------+
+ | 2 |
+ | |
+ 0+--------+
+ | xadv2 |
+
+ glyph1: advance width = 12
+ anchor point = (3,1)
+
+ glyph2: advance width = 11
+ anchor point = (9,4)
+
+ LSB is 1 for both glyphs (so the boxes drawn above are glyph
+ bboxes). Writing direction is R2L; `0' denotes the glyph's
+ coordinate origin.
+
+ Now the surprising part: The advance width of the *left* glyph
+ (resp. of the *bottom* glyph) will be modified, no matter
+ whether the writing direction is L2R or R2L (resp. T2B or
+ B2T)! This assymetry is caused by the fact that the glyph's
+ coordinate origin is always the lower left corner for all
+ writing directions.
+
+ Continuing the above example, we can compute the new
+ (horizontal) advance width of glyph2 as
+
+ 9 - 3 = 6 ,
+
+ and the new vertical offset of glyph2 as
+
+ 1 - 4 = -3 .
+
+
+ Vertical writing direction is far more complicated:
+
+ a) Assuming that we recompute the advance height of the lower glyph:
+
+ --
+ +---------+
+ -- | |
+ +-----+--+ 1 | yadv1
+ | | .| |
+ yadv2 | 0+--+------+ -- BSB1 --
+ | 2 | -- -- y_offset
+ | |
+ BSB2 -- 0+--------+ --
+ -- --
+
+ glyph1: advance height = 6
+ anchor point = (3,1)
+
+ glyph2: advance height = 7
+ anchor point = (9,4)
+
+ TSB is 1 for both glyphs; writing direction is T2B.
+
+
+ BSB1 = yadv1 - (TSB1 + ymax1)
+ BSB2 = yadv2 - (TSB2 + ymax2)
+ y_offset = y2 - y1
+
+ vertical advance width of glyph2
+ = y_offset + BSB2 - BSB1
+ = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))
+ = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)
+ = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1
+
+
+ b) Assuming that we recompute the advance height of the upper glyph:
+
+ -- --
+ +---------+ -- TSB1
+ -- -- | |
+ TSB2 -- +-----+--+ 1 | yadv1 ymax1
+ | | .| |
+ yadv2 | 0+--+------+ -- --
+ ymax2 | 2 | -- y_offset
+ | |
+ -- 0+--------+ --
+ --
+
+ glyph1: advance height = 6
+ anchor point = (3,1)
+
+ glyph2: advance height = 7
+ anchor point = (9,4)
+
+ TSB is 1 for both glyphs; writing direction is T2B.
+
+ y_offset = y2 - y1
+
+ vertical advance width of glyph2
+ = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)
+ = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2
+
+
+ Comparing a) with b) shows that b) is easier to compute. I'll wait
+ for a reply from Andrei to see what should really be implemented...
+
+ Since horizontal advance widths or vertical advance heights
+ can be used alone but not together, no ambiguity occurs. */
+
+ if ( gpi->last == 0xFFFF )
+ goto end;
+
+ /* Get_Anchor() returns HB_Err_Not_Covered if there is no anchor
+ table. */
+
+ error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),
+ &entry_x, &entry_y );
+ if ( error == HB_Err_Not_Covered )
+ goto end;
+ if ( error )
+ return error;
+
+ if ( gpi->r2l )
+ {
+ POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;
+ POSITION( buffer->in_pos )->new_advance = TRUE;
+ }
+ else
+ {
+ POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;
+ POSITION( gpi->last )->new_advance = TRUE;
+ }
+
+ if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT )
+ {
+ POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
+ POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
+ }
+ else
+ {
+ POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
+ POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
+ }
+
+end:
+ error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),
+ &exit_x, &exit_y );
+ if ( error == HB_Err_Not_Covered )
+ gpi->last = 0xFFFF;
+ else
+ {
+ gpi->last = buffer->in_pos;
+ gpi->anchor_x = exit_x;
+ gpi->anchor_y = exit_y;
+ }
+ if ( error )
+ return error;
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 4 */
+
+/* BaseArray */
+
+static FT_Error Load_BaseArray( HB_BaseArray* ba,
+ FT_UShort num_classes,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort m, n, k, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_BaseRecord* br;
+ HB_Anchor* ban;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ba->BaseCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ba->BaseRecord = NULL;
+
+ if ( ALLOC_ARRAY( ba->BaseRecord, count, HB_BaseRecord ) )
+ return error;
+
+ br = ba->BaseRecord;
+
+ for ( m = 0; m < count; m++ )
+ {
+ br[m].BaseAnchor = NULL;
+
+ if ( ALLOC_ARRAY( br[m].BaseAnchor, num_classes, HB_Anchor ) )
+ goto Fail;
+
+ ban = br[m].BaseAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail0;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if (new_offset == base_offset) {
+ /* Doulos SIL Regular is buggy and has zer offsets here. Skip */
+ ban[n].PosFormat = 0;
+ continue;
+ }
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &ban[n], stream ) ) != FT_Err_Ok )
+ goto Fail0;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ continue;
+ Fail0:
+ for ( k = 0; k < n; k++ )
+ Free_Anchor( &ban[k], memory );
+ goto Fail;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( k = 0; k < m; k++ )
+ {
+ ban = br[k].BaseAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &ban[n], memory );
+
+ FREE( ban );
+ }
+
+ FREE( br );
+ return error;
+}
+
+
+static void Free_BaseArray( HB_BaseArray* ba,
+ FT_UShort num_classes,
+ FT_Memory memory )
+{
+ FT_UShort m, n, count;
+
+ HB_BaseRecord* br;
+ HB_Anchor* ban;
+
+
+ if ( ba->BaseRecord )
+ {
+ count = ba->BaseCount;
+ br = ba->BaseRecord;
+
+ for ( m = 0; m < count; m++ )
+ {
+ ban = br[m].BaseAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &ban[n], memory );
+
+ FREE( ban );
+ }
+
+ FREE( br );
+ }
+}
+
+
+/* MarkBasePosFormat1 */
+
+static FT_Error Load_MarkBasePos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_MarkBasePos* mbp = &st->markbase;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ mbp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if (mbp->PosFormat != 1)
+ return HB_Err_Invalid_SubTable_Format;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mbp->BaseCoverage, stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail2;
+
+ mbp->ClassCount = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ return FT_Err_Ok;
+
+Fail1:
+ Free_MarkArray( &mbp->MarkArray, memory );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &mbp->BaseCoverage, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &mbp->MarkCoverage, memory );
+ return error;
+}
+
+
+static void Free_MarkBasePos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ HB_MarkBasePos* mbp = &st->markbase;
+
+ Free_BaseArray( &mbp->BaseArray, mbp->ClassCount, memory );
+ Free_MarkArray( &mbp->MarkArray, memory );
+ _HB_OPEN_Free_Coverage( &mbp->BaseCoverage, memory );
+ _HB_OPEN_Free_Coverage( &mbp->MarkCoverage, memory );
+}
+
+
+static FT_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort i, j, mark_index, base_index, property, class;
+ FT_Pos x_mark_value, y_mark_value, x_base_value, y_base_value;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_MarkBasePos* mbp = &st->markbase;
+
+ HB_MarkArray* ma;
+ HB_BaseArray* ba;
+ HB_BaseRecord* br;
+ HB_Anchor* mark_anchor;
+ HB_Anchor* base_anchor;
+
+ HB_Position o;
+
+ FT_UNUSED(nesting_level);
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),
+ &mark_index );
+ if ( error )
+ return error;
+
+ /* now we search backwards for a non-mark glyph */
+
+ i = 1;
+ j = buffer->in_pos - 1;
+
+ while ( i <= buffer->in_pos )
+ {
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
+ &property );
+ if ( error )
+ return error;
+
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
+ break;
+
+ i++;
+ j--;
+ }
+
+ /* The following assertion is too strong -- at least for mangal.ttf. */
+#if 0
+ if ( property != HB_GDEF_BASE_GLYPH )
+ return HB_Err_Not_Covered;
+#endif
+
+ if ( i > buffer->in_pos )
+ return HB_Err_Not_Covered;
+
+ error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
+ &base_index );
+ if ( error )
+ return error;
+
+ ma = &mbp->MarkArray;
+
+ if ( mark_index >= ma->MarkCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ class = ma->MarkRecord[mark_index].Class;
+ mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
+
+ if ( class >= mbp->ClassCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ ba = &mbp->BaseArray;
+
+ if ( base_index >= ba->BaseCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ br = &ba->BaseRecord[base_index];
+ base_anchor = &br->BaseAnchor[class];
+
+ error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
+ &x_mark_value, &y_mark_value );
+ if ( error )
+ return error;
+
+ error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
+ &x_base_value, &y_base_value );
+ if ( error )
+ return error;
+
+ /* anchor points are not cumulative */
+
+ o = POSITION( buffer->in_pos );
+
+ o->x_pos = x_base_value - x_mark_value;
+ o->y_pos = y_base_value - y_mark_value;
+ o->x_advance = 0;
+ o->y_advance = 0;
+ o->back = i;
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 5 */
+
+/* LigatureAttach */
+
+static FT_Error Load_LigatureAttach( HB_LigatureAttach* lat,
+ FT_UShort num_classes,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort m, n, k, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ComponentRecord* cr;
+ HB_Anchor* lan;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = lat->ComponentCount = GET_UShort();
+
+ FORGET_Frame();
+
+ lat->ComponentRecord = NULL;
+
+ if ( ALLOC_ARRAY( lat->ComponentRecord, count, HB_ComponentRecord ) )
+ return error;
+
+ cr = lat->ComponentRecord;
+
+ for ( m = 0; m < count; m++ )
+ {
+ cr[m].LigatureAnchor = NULL;
+
+ if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) )
+ goto Fail;
+
+ lan = cr[m].LigatureAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail0;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &lan[n], stream ) ) != FT_Err_Ok )
+ goto Fail0;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ lan[n].PosFormat = 0;
+ }
+
+ continue;
+ Fail0:
+ for ( k = 0; k < n; k++ )
+ Free_Anchor( &lan[k], memory );
+ goto Fail;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( k = 0; k < m; k++ )
+ {
+ lan = cr[k].LigatureAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &lan[n], memory );
+
+ FREE( lan );
+ }
+
+ FREE( cr );
+ return error;
+}
+
+
+static void Free_LigatureAttach( HB_LigatureAttach* lat,
+ FT_UShort num_classes,
+ FT_Memory memory )
+{
+ FT_UShort m, n, count;
+
+ HB_ComponentRecord* cr;
+ HB_Anchor* lan;
+
+
+ if ( lat->ComponentRecord )
+ {
+ count = lat->ComponentCount;
+ cr = lat->ComponentRecord;
+
+ for ( m = 0; m < count; m++ )
+ {
+ lan = cr[m].LigatureAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &lan[n], memory );
+
+ FREE( lan );
+ }
+
+ FREE( cr );
+ }
+}
+
+
+/* LigatureArray */
+
+static FT_Error Load_LigatureArray( HB_LigatureArray* la,
+ FT_UShort num_classes,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_LigatureAttach* lat;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = la->LigatureCount = GET_UShort();
+
+ FORGET_Frame();
+
+ la->LigatureAttach = NULL;
+
+ if ( ALLOC_ARRAY( la->LigatureAttach, count, HB_LigatureAttach ) )
+ return error;
+
+ lat = la->LigatureAttach;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigatureAttach( &lat[n], num_classes,
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_LigatureAttach( &lat[m], num_classes, memory );
+
+ FREE( lat );
+ return error;
+}
+
+
+static void Free_LigatureArray( HB_LigatureArray* la,
+ FT_UShort num_classes,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_LigatureAttach* lat;
+
+
+ if ( la->LigatureAttach )
+ {
+ count = la->LigatureCount;
+ lat = la->LigatureAttach;
+
+ for ( n = 0; n < count; n++ )
+ Free_LigatureAttach( &lat[n], num_classes, memory );
+
+ FREE( lat );
+ }
+}
+
+
+/* MarkLigPosFormat1 */
+
+static FT_Error Load_MarkLigPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_MarkLigPos* mlp = &st->marklig;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ mlp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mlp->LigatureCoverage,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail2;
+
+ mlp->ClassCount = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ return FT_Err_Ok;
+
+Fail1:
+ Free_MarkArray( &mlp->MarkArray, memory );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &mlp->MarkCoverage, memory );
+ return error;
+}
+
+
+static void Free_MarkLigPos( HB_GPOS_SubTable* st,
+ FT_Memory memory)
+{
+ HB_MarkLigPos* mlp = &st->marklig;
+
+ Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, memory );
+ Free_MarkArray( &mlp->MarkArray, memory );
+ _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage, memory );
+ _HB_OPEN_Free_Coverage( &mlp->MarkCoverage, memory );
+}
+
+
+static FT_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort i, j, mark_index, lig_index, property, class;
+ FT_UShort mark_glyph;
+ FT_Pos x_mark_value, y_mark_value, x_lig_value, y_lig_value;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_MarkLigPos* mlp = &st->marklig;
+
+ HB_MarkArray* ma;
+ HB_LigatureArray* la;
+ HB_LigatureAttach* lat;
+ HB_ComponentRecord* cr;
+ FT_UShort comp_index;
+ HB_Anchor* mark_anchor;
+ HB_Anchor* lig_anchor;
+
+ HB_Position o;
+
+ FT_UNUSED(nesting_level);
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES )
+ return HB_Err_Not_Covered;
+
+ mark_glyph = IN_CURGLYPH();
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
+ if ( error )
+ return error;
+
+ /* now we search backwards for a non-mark glyph */
+
+ i = 1;
+ j = buffer->in_pos - 1;
+
+ while ( i <= buffer->in_pos )
+ {
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
+ &property );
+ if ( error )
+ return error;
+
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
+ break;
+
+ i++;
+ j--;
+ }
+
+ /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
+ too strong, thus it is commented out. */
+#if 0
+ if ( property != HB_GDEF_LIGATURE )
+ return HB_Err_Not_Covered;
+#endif
+
+ if ( i > buffer->in_pos )
+ return HB_Err_Not_Covered;
+
+ error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
+ &lig_index );
+ if ( error )
+ return error;
+
+ ma = &mlp->MarkArray;
+
+ if ( mark_index >= ma->MarkCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ class = ma->MarkRecord[mark_index].Class;
+ mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
+
+ if ( class >= mlp->ClassCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ la = &mlp->LigatureArray;
+
+ if ( lig_index >= la->LigatureCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ lat = &la->LigatureAttach[lig_index];
+
+ /* We must now check whether the ligature ID of the current mark glyph
+ is identical to the ligature ID of the found ligature. If yes, we
+ can directly use the component index. If not, we attach the mark
+ glyph to the last component of the ligature. */
+
+ if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
+ {
+ comp_index = IN_COMPONENT( buffer->in_pos );
+ if ( comp_index >= lat->ComponentCount )
+ return HB_Err_Not_Covered;
+ }
+ else
+ comp_index = lat->ComponentCount - 1;
+
+ cr = &lat->ComponentRecord[comp_index];
+ lig_anchor = &cr->LigatureAnchor[class];
+
+ error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
+ &x_mark_value, &y_mark_value );
+ if ( error )
+ return error;
+ error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
+ &x_lig_value, &y_lig_value );
+ if ( error )
+ return error;
+
+ /* anchor points are not cumulative */
+
+ o = POSITION( buffer->in_pos );
+
+ o->x_pos = x_lig_value - x_mark_value;
+ o->y_pos = y_lig_value - y_mark_value;
+ o->x_advance = 0;
+ o->y_advance = 0;
+ o->back = i;
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 6 */
+
+/* Mark2Array */
+
+static FT_Error Load_Mark2Array( HB_Mark2Array* m2a,
+ FT_UShort num_classes,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort k, m, n, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Mark2Record* m2r;
+ HB_Anchor* m2an;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = m2a->Mark2Count = GET_UShort();
+
+ FORGET_Frame();
+
+ m2a->Mark2Record = NULL;
+
+ if ( ALLOC_ARRAY( m2a->Mark2Record, count, HB_Mark2Record ) )
+ return error;
+
+ m2r = m2a->Mark2Record;
+
+ for ( m = 0; m < count; m++ )
+ {
+ m2r[m].Mark2Anchor = NULL;
+
+ if ( ALLOC_ARRAY( m2r[m].Mark2Anchor, num_classes, HB_Anchor ) )
+ goto Fail;
+
+ m2an = m2r[m].Mark2Anchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail0;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &m2an[n], stream ) ) != FT_Err_Ok )
+ goto Fail0;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ continue;
+ Fail0:
+ for ( k = 0; k < n; k++ )
+ Free_Anchor( &m2an[k], memory );
+ goto Fail;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( k = 0; k < m; k++ )
+ {
+ m2an = m2r[k].Mark2Anchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &m2an[n], memory );
+
+ FREE( m2an );
+ }
+
+ FREE( m2r );
+ return error;
+}
+
+
+static void Free_Mark2Array( HB_Mark2Array* m2a,
+ FT_UShort num_classes,
+ FT_Memory memory )
+{
+ FT_UShort m, n, count;
+
+ HB_Mark2Record* m2r;
+ HB_Anchor* m2an;
+
+
+ if ( m2a->Mark2Record )
+ {
+ count = m2a->Mark2Count;
+ m2r = m2a->Mark2Record;
+
+ for ( m = 0; m < count; m++ )
+ {
+ m2an = m2r[m].Mark2Anchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &m2an[n], memory );
+
+ FREE( m2an );
+ }
+
+ FREE( m2r );
+ }
+}
+
+
+/* MarkMarkPosFormat1 */
+
+static FT_Error Load_MarkMarkPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_MarkMarkPos* mmp = &st->markmark;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ mmp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mmp->Mark2Coverage,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail2;
+
+ mmp->ClassCount = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ return FT_Err_Ok;
+
+Fail1:
+ Free_MarkArray( &mmp->Mark1Array, memory );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage, memory );
+ return error;
+}
+
+
+static void Free_MarkMarkPos( HB_GPOS_SubTable* st,
+ FT_Memory memory)
+{
+ HB_MarkMarkPos* mmp = &st->markmark;
+
+ Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount, memory );
+ Free_MarkArray( &mmp->Mark1Array, memory );
+ _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage, memory );
+ _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage, memory );
+}
+
+
+static FT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort i, j, mark1_index, mark2_index, property, class;
+ FT_Pos x_mark1_value, y_mark1_value,
+ x_mark2_value, y_mark2_value;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_MarkMarkPos* mmp = &st->markmark;
+
+ HB_MarkArray* ma1;
+ HB_Mark2Array* ma2;
+ HB_Mark2Record* m2r;
+ HB_Anchor* mark1_anchor;
+ HB_Anchor* mark2_anchor;
+
+ HB_Position o;
+
+ FT_UNUSED(nesting_level);
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(),
+ &mark1_index );
+ if ( error )
+ return error;
+
+ /* now we search backwards for a suitable mark glyph until a non-mark
+ glyph */
+
+ if ( buffer->in_pos == 0 )
+ return HB_Err_Not_Covered;
+
+ i = 1;
+ j = buffer->in_pos - 1;
+ while ( i <= buffer->in_pos )
+ {
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
+ &property );
+ if ( error )
+ return error;
+
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
+ return HB_Err_Not_Covered;
+
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ {
+ if ( property == (flags & 0xFF00) )
+ break;
+ }
+ else
+ break;
+
+ i++;
+ j--;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
+ &mark2_index );
+ if ( error )
+ return error;
+
+ ma1 = &mmp->Mark1Array;
+
+ if ( mark1_index >= ma1->MarkCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ class = ma1->MarkRecord[mark1_index].Class;
+ mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;
+
+ if ( class >= mmp->ClassCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ ma2 = &mmp->Mark2Array;
+
+ if ( mark2_index >= ma2->Mark2Count )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ m2r = &ma2->Mark2Record[mark2_index];
+ mark2_anchor = &m2r->Mark2Anchor[class];
+
+ error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(),
+ &x_mark1_value, &y_mark1_value );
+ if ( error )
+ return error;
+ error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
+ &x_mark2_value, &y_mark2_value );
+ if ( error )
+ return error;
+
+ /* anchor points are not cumulative */
+
+ o = POSITION( buffer->in_pos );
+
+ o->x_pos = x_mark2_value - x_mark1_value;
+ o->y_pos = y_mark2_value - y_mark1_value;
+ o->x_advance = 0;
+ o->y_advance = 0;
+ o->back = 1;
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* Do the actual positioning for a context positioning (either format
+ 7 or 8). This is only called after we've determined that the stream
+ matches the subrule. */
+
+static FT_Error Do_ContextPos( GPOS_Instance* gpi,
+ FT_UShort GlyphCount,
+ FT_UShort PosCount,
+ HB_PosLookupRecord* pos,
+ HB_Buffer buffer,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort i, old_pos;
+
+
+ i = 0;
+
+ while ( i < GlyphCount )
+ {
+ if ( PosCount && i == pos->SequenceIndex )
+ {
+ old_pos = buffer->in_pos;
+
+ /* Do a positioning */
+
+ error = GPOS_Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
+ GlyphCount, nesting_level );
+
+ if ( error )
+ return error;
+
+ pos++;
+ PosCount--;
+ i += buffer->in_pos - old_pos;
+ }
+ else
+ {
+ i++;
+ (buffer->in_pos)++;
+ }
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 7 */
+
+/* PosRule */
+
+static FT_Error Load_PosRule( HB_PosRule* pr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* i;
+
+ HB_PosLookupRecord* plr;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ pr->GlyphCount = GET_UShort();
+ pr->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ pr->Input = NULL;
+
+ count = pr->GlyphCount - 1; /* only GlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( pr->Input, count, FT_UShort ) )
+ return error;
+
+ i = pr->Input;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ i[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ pr->PosLookupRecord = NULL;
+
+ count = pr->PosCount;
+
+ if ( ALLOC_ARRAY( pr->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = pr->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ FREE( i );
+ return error;
+}
+
+
+static void Free_PosRule( HB_PosRule* pr,
+ FT_Memory memory )
+{
+ FREE( pr->PosLookupRecord );
+ FREE( pr->Input );
+}
+
+
+/* PosRuleSet */
+
+static FT_Error Load_PosRuleSet( HB_PosRuleSet* prs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PosRule* pr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = prs->PosRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ prs->PosRule = NULL;
+
+ if ( ALLOC_ARRAY( prs->PosRule, count, HB_PosRule ) )
+ return error;
+
+ pr = prs->PosRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PosRule( &pr[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_PosRule( &pr[m], memory );
+
+ FREE( pr );
+ return error;
+}
+
+
+static void Free_PosRuleSet( HB_PosRuleSet* prs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PosRule* pr;
+
+
+ if ( prs->PosRule )
+ {
+ count = prs->PosRuleCount;
+ pr = prs->PosRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_PosRule( &pr[n], memory );
+
+ FREE( pr );
+ }
+}
+
+
+/* ContextPosFormat1 */
+
+static FT_Error Load_ContextPos1( HB_ContextPosFormat1* cpf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PosRuleSet* prs;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &cpf1->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = cpf1->PosRuleSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpf1->PosRuleSet = NULL;
+
+ if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, HB_PosRuleSet ) )
+ goto Fail2;
+
+ prs = cpf1->PosRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PosRuleSet( &prs[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_PosRuleSet( &prs[m], memory );
+
+ FREE( prs );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &cpf1->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ContextPos1( HB_ContextPosFormat1* cpf1,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PosRuleSet* prs;
+
+
+ if ( cpf1->PosRuleSet )
+ {
+ count = cpf1->PosRuleSetCount;
+ prs = cpf1->PosRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_PosRuleSet( &prs[n], memory );
+
+ FREE( prs );
+ }
+
+ _HB_OPEN_Free_Coverage( &cpf1->Coverage, memory );
+}
+
+
+/* PosClassRule */
+
+static FT_Error Load_PosClassRule( HB_ContextPosFormat2* cpf2,
+ HB_PosClassRule* pcr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* c;
+ HB_PosLookupRecord* plr;
+ FT_Bool* d;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ pcr->GlyphCount = GET_UShort();
+ pcr->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( pcr->GlyphCount > cpf2->MaxContextLength )
+ cpf2->MaxContextLength = pcr->GlyphCount;
+
+ pcr->Class = NULL;
+
+ count = pcr->GlyphCount - 1; /* only GlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( pcr->Class, count, FT_UShort ) )
+ return error;
+
+ c = pcr->Class;
+ d = cpf2->ClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ {
+ c[n] = GET_UShort();
+
+ /* We check whether the specific class is used at all. If not,
+ class 0 is used instead. */
+
+ if ( !d[c[n]] )
+ c[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ pcr->PosLookupRecord = NULL;
+
+ count = pcr->PosCount;
+
+ if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = pcr->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ FREE( c );
+ return error;
+}
+
+
+static void Free_PosClassRule( HB_PosClassRule* pcr,
+ FT_Memory memory )
+{
+ FREE( pcr->PosLookupRecord );
+ FREE( pcr->Class );
+}
+
+
+/* PosClassSet */
+
+static FT_Error Load_PosClassSet( HB_ContextPosFormat2* cpf2,
+ HB_PosClassSet* pcs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PosClassRule* pcr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = pcs->PosClassRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ pcs->PosClassRule = NULL;
+
+ if ( ALLOC_ARRAY( pcs->PosClassRule, count, HB_PosClassRule ) )
+ return error;
+
+ pcr = pcs->PosClassRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PosClassRule( cpf2, &pcr[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_PosClassRule( &pcr[m], memory );
+
+ FREE( pcr );
+ return error;
+}
+
+
+static void Free_PosClassSet( HB_PosClassSet* pcs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PosClassRule* pcr;
+
+
+ if ( pcs->PosClassRule )
+ {
+ count = pcs->PosClassRuleCount;
+ pcr = pcs->PosClassRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_PosClassRule( &pcr[n], memory );
+
+ FREE( pcr );
+ }
+}
+
+
+/* ContextPosFormat2 */
+
+static FT_Error Load_ContextPos2( HB_ContextPosFormat2* cpf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PosClassSet* pcs;
+
+
+ base_offset = FILE_Pos() - 2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &cpf2->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ /* `PosClassSetCount' is the upper limit for class values, thus we
+ read it now to make an additional safety check. */
+
+ count = cpf2->PosClassSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &cpf2->ClassDef, count,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ cpf2->PosClassSet = NULL;
+ cpf2->MaxContextLength = 0;
+
+ if ( ALLOC_ARRAY( cpf2->PosClassSet, count, HB_PosClassSet ) )
+ goto Fail2;
+
+ pcs = cpf2->PosClassSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PosClassSet( cpf2, &pcs[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a PosClassSet table with no entries */
+
+ cpf2->PosClassSet[n].PosClassRuleCount = 0;
+ cpf2->PosClassSet[n].PosClassRule = NULL;
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; n++ )
+ Free_PosClassSet( &pcs[m], memory );
+
+ FREE( pcs );
+
+Fail2:
+ _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &cpf2->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ContextPos2( HB_ContextPosFormat2* cpf2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PosClassSet* pcs;
+
+
+ if ( cpf2->PosClassSet )
+ {
+ count = cpf2->PosClassSetCount;
+ pcs = cpf2->PosClassSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_PosClassSet( &pcs[n], memory );
+
+ FREE( pcs );
+ }
+
+ _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef, memory );
+ _HB_OPEN_Free_Coverage( &cpf2->Coverage, memory );
+}
+
+
+/* ContextPosFormat3 */
+
+static FT_Error Load_ContextPos3( HB_ContextPosFormat3* cpf3,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* c;
+ HB_PosLookupRecord* plr;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ cpf3->GlyphCount = GET_UShort();
+ cpf3->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpf3->Coverage = NULL;
+
+ count = cpf3->GlyphCount;
+
+ if ( ALLOC_ARRAY( cpf3->Coverage, count, HB_Coverage ) )
+ return error;
+
+ c = cpf3->Coverage;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ cpf3->PosLookupRecord = NULL;
+
+ count = cpf3->PosCount;
+
+ if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = cpf3->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ return error;
+}
+
+
+static void Free_ContextPos3( HB_ContextPosFormat3* cpf3,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Coverage* c;
+
+
+ FREE( cpf3->PosLookupRecord );
+
+ if ( cpf3->Coverage )
+ {
+ count = cpf3->GlyphCount;
+ c = cpf3->Coverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+}
+
+
+/* ContextPos */
+
+static FT_Error Load_ContextPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ HB_ContextPos* cp = &st->context;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cp->PosFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( cp->PosFormat )
+ {
+ case 1:
+ return Load_ContextPos1( &cp->cpf.cpf1, stream );
+
+ case 2:
+ return Load_ContextPos2( &cp->cpf.cpf2, stream );
+
+ case 3:
+ return Load_ContextPos3( &cp->cpf.cpf3, stream );
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static void Free_ContextPos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ HB_ContextPos* cp = &st->context;
+
+ switch ( cp->PosFormat )
+ {
+ case 1:
+ Free_ContextPos1( &cp->cpf.cpf1, memory );
+ break;
+
+ case 2:
+ Free_ContextPos2( &cp->cpf.cpf2, memory );
+ break;
+
+ case 3:
+ Free_ContextPos3( &cp->cpf.cpf3, memory );
+ break;
+ }
+}
+
+
+static FT_Error Lookup_ContextPos1( GPOS_Instance* gpi,
+ HB_ContextPosFormat1* cpf1,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_UShort i, j, k, numpr;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_PosRule* pr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ pr = cpf1->PosRuleSet[index].PosRule;
+ numpr = cpf1->PosRuleSet[index].PosRuleCount;
+
+ for ( k = 0; k < numpr; k++ )
+ {
+ if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
+ goto next_posrule;
+
+ if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
+ goto next_posrule; /* context is too long */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + pr[k].GlyphCount - i == (FT_Long)buffer->in_length )
+ goto next_posrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )
+ goto next_posrule;
+ }
+
+ return Do_ContextPos( gpi, pr[k].GlyphCount,
+ pr[k].PosCount, pr[k].PosLookupRecord,
+ buffer,
+ nesting_level );
+
+ next_posrule:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_ContextPos2( GPOS_Instance* gpi,
+ HB_ContextPosFormat2* cpf2,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ FT_Memory memory = gpi->face->memory;
+ FT_UShort i, j, k, known_classes;
+
+ FT_UShort* classes;
+ FT_UShort* cl;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_PosClassSet* pcs;
+ HB_PosClassRule* pr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* Note: The coverage table in format 2 doesn't give an index into
+ anything. It just lets us know whether or not we need to
+ do any lookup at all. */
+
+ error = _HB_OPEN_Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, FT_UShort ) )
+ return error;
+
+ error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_CURGLYPH(),
+ &classes[0], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+ known_classes = 0;
+
+ pcs = &cpf2->PosClassSet[classes[0]];
+ if ( !pcs )
+ {
+ error = HB_Err_Invalid_GPOS_SubTable;
+ goto End;
+ }
+
+ for ( k = 0; k < pcs->PosClassRuleCount; k++ )
+ {
+ pr = &pcs->PosClassRule[k];
+
+ if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
+ goto next_posclassrule;
+
+ if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
+ goto next_posclassrule; /* context is too long */
+
+ cl = pr->Class;
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+
+ if ( j + pr->GlyphCount - i == (FT_Long)buffer->in_length )
+ goto next_posclassrule;
+ j++;
+ }
+
+ if ( i > known_classes )
+ {
+ /* Keeps us from having to do this for each rule */
+
+ error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+ known_classes = i;
+ }
+
+ if ( cl[i - 1] != classes[i] )
+ goto next_posclassrule;
+ }
+
+ error = Do_ContextPos( gpi, pr->GlyphCount,
+ pr->PosCount, pr->PosLookupRecord,
+ buffer,
+ nesting_level );
+ goto End;
+
+ next_posclassrule:
+ ;
+ }
+
+ error = HB_Err_Not_Covered;
+
+End:
+ FREE( classes );
+ return error;
+}
+
+
+static FT_Error Lookup_ContextPos3( GPOS_Instance* gpi,
+ HB_ContextPosFormat3* cpf3,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, i, j, property;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_Coverage* c;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
+ return HB_Err_Not_Covered;
+
+ if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
+ return HB_Err_Not_Covered; /* context is too long */
+
+ c = cpf3->Coverage;
+
+ for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + cpf3->GlyphCount - i == (FT_Long)buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ return Do_ContextPos( gpi, cpf3->GlyphCount,
+ cpf3->PosCount, cpf3->PosLookupRecord,
+ buffer,
+ nesting_level );
+}
+
+
+static FT_Error Lookup_ContextPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ HB_ContextPos* cp = &st->context;
+
+ switch ( cp->PosFormat )
+ {
+ case 1:
+ return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
+ flags, context_length, nesting_level );
+
+ case 2:
+ return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
+ flags, context_length, nesting_level );
+
+ case 3:
+ return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
+ flags, context_length, nesting_level );
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+/* LookupType 8 */
+
+/* ChainPosRule */
+
+static FT_Error Load_ChainPosRule( HB_ChainPosRule* cpr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* b;
+ FT_UShort* i;
+ FT_UShort* l;
+
+ HB_PosLookupRecord* plr;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cpr->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpr->Backtrack = NULL;
+
+ count = cpr->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( cpr->Backtrack, count, FT_UShort ) )
+ return error;
+
+ b = cpr->Backtrack;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail4;
+
+ for ( n = 0; n < count; n++ )
+ b[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ cpr->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpr->Input = NULL;
+
+ count = cpr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( cpr->Input, count, FT_UShort ) )
+ goto Fail4;
+
+ i = cpr->Input;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail3;
+
+ for ( n = 0; n < count; n++ )
+ i[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ cpr->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpr->Lookahead = NULL;
+
+ count = cpr->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( cpr->Lookahead, count, FT_UShort ) )
+ goto Fail3;
+
+ l = cpr->Lookahead;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ l[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ cpr->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpr->PosLookupRecord = NULL;
+
+ count = cpr->PosCount;
+
+ if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = cpr->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ FREE( l );
+
+Fail3:
+ FREE( i );
+
+Fail4:
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainPosRule( HB_ChainPosRule* cpr,
+ FT_Memory memory )
+{
+ FREE( cpr->PosLookupRecord );
+ FREE( cpr->Lookahead );
+ FREE( cpr->Input );
+ FREE( cpr->Backtrack );
+}
+
+
+/* ChainPosRuleSet */
+
+static FT_Error Load_ChainPosRuleSet( HB_ChainPosRuleSet* cprs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainPosRule* cpr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cprs->ChainPosRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cprs->ChainPosRule = NULL;
+
+ if ( ALLOC_ARRAY( cprs->ChainPosRule, count, HB_ChainPosRule ) )
+ return error;
+
+ cpr = cprs->ChainPosRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainPosRule( &cpr[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_ChainPosRule( &cpr[m], memory );
+
+ FREE( cpr );
+ return error;
+}
+
+
+static void Free_ChainPosRuleSet( HB_ChainPosRuleSet* cprs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainPosRule* cpr;
+
+
+ if ( cprs->ChainPosRule )
+ {
+ count = cprs->ChainPosRuleCount;
+ cpr = cprs->ChainPosRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainPosRule( &cpr[n], memory );
+
+ FREE( cpr );
+ }
+}
+
+
+/* ChainContextPosFormat1 */
+
+static FT_Error Load_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainPosRuleSet* cprs;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ccpf1->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ccpf1->ChainPosRuleSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf1->ChainPosRuleSet = NULL;
+
+ if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, HB_ChainPosRuleSet ) )
+ goto Fail2;
+
+ cprs = ccpf1->ChainPosRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainPosRuleSet( &cprs[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ChainPosRuleSet( &cprs[m], memory );
+
+ FREE( cprs );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ccpf1->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainPosRuleSet* cprs;
+
+
+ if ( ccpf1->ChainPosRuleSet )
+ {
+ count = ccpf1->ChainPosRuleSetCount;
+ cprs = ccpf1->ChainPosRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainPosRuleSet( &cprs[n], memory );
+
+ FREE( cprs );
+ }
+
+ _HB_OPEN_Free_Coverage( &ccpf1->Coverage, memory );
+}
+
+
+/* ChainPosClassRule */
+
+static FT_Error Load_ChainPosClassRule(
+ HB_ChainContextPosFormat2* ccpf2,
+ HB_ChainPosClassRule* cpcr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* b;
+ FT_UShort* i;
+ FT_UShort* l;
+ HB_PosLookupRecord* plr;
+ FT_Bool* d;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cpcr->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength )
+ ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount;
+
+ cpcr->Backtrack = NULL;
+
+ count = cpcr->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( cpcr->Backtrack, count, FT_UShort ) )
+ return error;
+
+ b = cpcr->Backtrack;
+ d = ccpf2->BacktrackClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail4;
+
+ for ( n = 0; n < count; n++ )
+ {
+ b[n] = GET_UShort();
+
+ /* We check whether the specific class is used at all. If not,
+ class 0 is used instead. */
+
+ if ( !d[b[n]] )
+ b[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ cpcr->InputGlyphCount = GET_UShort();
+
+ if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength )
+ ccpf2->MaxInputLength = cpcr->InputGlyphCount;
+
+ FORGET_Frame();
+
+ cpcr->Input = NULL;
+
+ count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( cpcr->Input, count, FT_UShort ) )
+ goto Fail4;
+
+ i = cpcr->Input;
+ d = ccpf2->InputClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail3;
+
+ for ( n = 0; n < count; n++ )
+ {
+ i[n] = GET_UShort();
+
+ if ( !d[i[n]] )
+ i[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ cpcr->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength )
+ ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount;
+
+ cpcr->Lookahead = NULL;
+
+ count = cpcr->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( cpcr->Lookahead, count, FT_UShort ) )
+ goto Fail3;
+
+ l = cpcr->Lookahead;
+ d = ccpf2->LookaheadClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ {
+ l[n] = GET_UShort();
+
+ if ( !d[l[n]] )
+ l[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ cpcr->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpcr->PosLookupRecord = NULL;
+
+ count = cpcr->PosCount;
+
+ if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = cpcr->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ FREE( l );
+
+Fail3:
+ FREE( i );
+
+Fail4:
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainPosClassRule( HB_ChainPosClassRule* cpcr,
+ FT_Memory memory )
+{
+ FREE( cpcr->PosLookupRecord );
+ FREE( cpcr->Lookahead );
+ FREE( cpcr->Input );
+ FREE( cpcr->Backtrack );
+}
+
+
+/* PosClassSet */
+
+static FT_Error Load_ChainPosClassSet(
+ HB_ChainContextPosFormat2* ccpf2,
+ HB_ChainPosClassSet* cpcs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainPosClassRule* cpcr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cpcs->ChainPosClassRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpcs->ChainPosClassRule = NULL;
+
+ if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count,
+ HB_ChainPosClassRule ) )
+ return error;
+
+ cpcr = cpcs->ChainPosClassRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_ChainPosClassRule( &cpcr[m], memory );
+
+ FREE( cpcr );
+ return error;
+}
+
+
+static void Free_ChainPosClassSet( HB_ChainPosClassSet* cpcs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainPosClassRule* cpcr;
+
+
+ if ( cpcs->ChainPosClassRule )
+ {
+ count = cpcs->ChainPosClassRuleCount;
+ cpcr = cpcs->ChainPosClassRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainPosClassRule( &cpcr[n], memory );
+
+ FREE( cpcr );
+ }
+}
+
+
+static FT_Error GPOS_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_ULong class_offset,
+ FT_ULong base_offset,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_ULong cur_offset;
+
+ cur_offset = FILE_Pos();
+
+ if ( class_offset )
+ {
+ if ( !FILE_Seek( class_offset + base_offset ) )
+ error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
+ }
+ else
+ error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
+
+ if (error == FT_Err_Ok)
+ (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
+
+ return error;
+}
+
+/* ChainContextPosFormat2 */
+
+static FT_Error Load_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+ FT_ULong backtrack_offset, input_offset, lookahead_offset;
+
+ HB_ChainPosClassSet* cpcs;
+
+
+ base_offset = FILE_Pos() - 2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ccpf2->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 8L ) )
+ goto Fail5;
+
+ backtrack_offset = GET_UShort();
+ input_offset = GET_UShort();
+ lookahead_offset = GET_UShort();
+
+ /* `ChainPosClassSetCount' is the upper limit for input class values,
+ thus we read it now to make an additional safety check. No limit
+ is known or needed for the other two class definitions */
+
+ count = ccpf2->ChainPosClassSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
+ backtrack_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail5;
+ if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
+ input_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
+ lookahead_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+
+ ccpf2->ChainPosClassSet = NULL;
+ ccpf2->MaxBacktrackLength = 0;
+ ccpf2->MaxInputLength = 0;
+ ccpf2->MaxLookaheadLength = 0;
+
+ if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, HB_ChainPosClassSet ) )
+ goto Fail2;
+
+ cpcs = ccpf2->ChainPosClassSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a ChainPosClassSet table with no entries */
+
+ ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0;
+ ccpf2->ChainPosClassSet[n].ChainPosClassRule = NULL;
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ChainPosClassSet( &cpcs[m], memory );
+
+ FREE( cpcs );
+
+Fail2:
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef, memory );
+
+Fail3:
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef, memory );
+
+Fail4:
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef, memory );
+
+Fail5:
+ _HB_OPEN_Free_Coverage( &ccpf2->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainPosClassSet* cpcs;
+
+
+ if ( ccpf2->ChainPosClassSet )
+ {
+ count = ccpf2->ChainPosClassSetCount;
+ cpcs = ccpf2->ChainPosClassSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainPosClassSet( &cpcs[n], memory );
+
+ FREE( cpcs );
+ }
+
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef, memory );
+
+ _HB_OPEN_Free_Coverage( &ccpf2->Coverage, memory );
+}
+
+
+/* ChainContextPosFormat3 */
+
+static FT_Error Load_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, nb, ni, nl, m, count;
+ FT_UShort backtrack_count, input_count, lookahead_count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* b;
+ HB_Coverage* i;
+ HB_Coverage* l;
+ HB_PosLookupRecord* plr;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ ccpf3->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf3->BacktrackCoverage = NULL;
+
+ backtrack_count = ccpf3->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count,
+ HB_Coverage ) )
+ return error;
+
+ b = ccpf3->BacktrackCoverage;
+
+ for ( nb = 0; nb < backtrack_count; nb++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ ccpf3->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf3->InputCoverage = NULL;
+
+ input_count = ccpf3->InputGlyphCount;
+
+ if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, HB_Coverage ) )
+ goto Fail4;
+
+ i = ccpf3->InputCoverage;
+
+ for ( ni = 0; ni < input_count; ni++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ ccpf3->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf3->LookaheadCoverage = NULL;
+
+ lookahead_count = ccpf3->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count,
+ HB_Coverage ) )
+ goto Fail3;
+
+ l = ccpf3->LookaheadCoverage;
+
+ for ( nl = 0; nl < lookahead_count; nl++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ ccpf3->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf3->PosLookupRecord = NULL;
+
+ count = ccpf3->PosCount;
+
+ if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = ccpf3->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ for ( m = 0; m < nl; m++ )
+ _HB_OPEN_Free_Coverage( &l[m], memory );
+
+ FREE( l );
+
+Fail3:
+ for ( m = 0; m < ni; m++ )
+ _HB_OPEN_Free_Coverage( &i[m], memory );
+
+ FREE( i );
+
+Fail4:
+ for ( m = 0; m < nb; m++ )
+ _HB_OPEN_Free_Coverage( &b[m], memory );
+
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Coverage* c;
+
+
+ FREE( ccpf3->PosLookupRecord );
+
+ if ( ccpf3->LookaheadCoverage )
+ {
+ count = ccpf3->LookaheadGlyphCount;
+ c = ccpf3->LookaheadCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( ccpf3->InputCoverage )
+ {
+ count = ccpf3->InputGlyphCount;
+ c = ccpf3->InputCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( ccpf3->BacktrackCoverage )
+ {
+ count = ccpf3->BacktrackGlyphCount;
+ c = ccpf3->BacktrackCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+}
+
+
+/* ChainContextPos */
+
+static FT_Error Load_ChainContextPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ HB_ChainContextPos* ccp = &st->chain;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ ccp->PosFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( ccp->PosFormat )
+ {
+ case 1:
+ return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream );
+
+ case 2:
+ return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream );
+
+ case 3:
+ return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static void Free_ChainContextPos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ HB_ChainContextPos* ccp = &st->chain;
+
+ switch ( ccp->PosFormat )
+ {
+ case 1:
+ Free_ChainContextPos1( &ccp->ccpf.ccpf1, memory );
+ break;
+
+ case 2:
+ Free_ChainContextPos2( &ccp->ccpf.ccpf2, memory );
+ break;
+
+ case 3:
+ Free_ChainContextPos3( &ccp->ccpf.ccpf3, memory );
+ break;
+ }
+}
+
+
+static FT_Error Lookup_ChainContextPos1(
+ GPOS_Instance* gpi,
+ HB_ChainContextPosFormat1* ccpf1,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_UShort i, j, k, num_cpr;
+ FT_UShort bgc, igc, lgc;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_ChainPosRule* cpr;
+ HB_ChainPosRule curr_cpr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ cpr = ccpf1->ChainPosRuleSet[index].ChainPosRule;
+ num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount;
+
+ for ( k = 0; k < num_cpr; k++ )
+ {
+ curr_cpr = cpr[k];
+ bgc = curr_cpr.BacktrackGlyphCount;
+ igc = curr_cpr.InputGlyphCount;
+ lgc = curr_cpr.LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ goto next_chainposrule;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ goto next_chainposrule;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ goto next_chainposrule;
+ j--;
+ }
+
+ /* In OpenType 1.3, it is undefined whether the offsets of
+ backtrack glyphs is in logical order or not. Version 1.4
+ will clarify this:
+
+ Logical order - a b c d e f g h i j
+ i
+ Input offsets - 0 1
+ Backtrack offsets - 3 2 1 0
+ Lookahead offsets - 0 1 2 3 */
+
+ if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
+ goto next_chainposrule;
+ }
+ }
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
+ goto next_chainposrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )
+ goto next_chainposrule;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == (FT_Long)buffer->in_length )
+ goto next_chainposrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )
+ goto next_chainposrule;
+ }
+
+ return Do_ContextPos( gpi, igc,
+ curr_cpr.PosCount,
+ curr_cpr.PosLookupRecord,
+ buffer,
+ nesting_level );
+
+ next_chainposrule:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_ChainContextPos2(
+ GPOS_Instance* gpi,
+ HB_ChainContextPosFormat2* ccpf2,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Memory memory = gpi->face->memory;
+ FT_Error error;
+ FT_UShort i, j, k;
+ FT_UShort bgc, igc, lgc;
+ FT_UShort known_backtrack_classes,
+ known_input_classes,
+ known_lookahead_classes;
+
+ FT_UShort* backtrack_classes;
+ FT_UShort* input_classes;
+ FT_UShort* lookahead_classes;
+
+ FT_UShort* bc;
+ FT_UShort* ic;
+ FT_UShort* lc;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_ChainPosClassSet* cpcs;
+ HB_ChainPosClassRule cpcr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* Note: The coverage table in format 2 doesn't give an index into
+ anything. It just lets us know whether or not we need to
+ do any lookup at all. */
+
+ error = _HB_OPEN_Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, FT_UShort ) )
+ return error;
+ known_backtrack_classes = 0;
+
+ if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, FT_UShort ) )
+ goto End3;
+ known_input_classes = 1;
+
+ if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, FT_UShort ) )
+ goto End2;
+ known_lookahead_classes = 0;
+
+ error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(),
+ &input_classes[0], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];
+ if ( !cpcs )
+ {
+ error = HB_Err_Invalid_GPOS_SubTable;
+ goto End1;
+ }
+
+ for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ )
+ {
+ cpcr = cpcs->ChainPosClassRule[k];
+ bgc = cpcr.BacktrackGlyphCount;
+ igc = cpcr.InputGlyphCount;
+ lgc = cpcr.LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ goto next_chainposclassrule;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ goto next_chainposclassrule;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array.
+ Note that `known_backtrack_classes' starts at index 0. */
+
+ bc = cpcr.Backtrack;
+
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + 1 == bgc - i )
+ goto next_chainposclassrule;
+ j++;
+ }
+
+ if ( i >= known_backtrack_classes )
+ {
+ /* Keeps us from having to do this for each rule */
+
+ error = _HB_OPEN_Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
+ &backtrack_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_backtrack_classes = i;
+ }
+
+ if ( bc[i] != backtrack_classes[i] )
+ goto next_chainposclassrule;
+ }
+ }
+
+ ic = cpcr.Input;
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
+ goto next_chainposclassrule;
+ j++;
+ }
+
+ if ( i >= known_input_classes )
+ {
+ error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),
+ &input_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_input_classes = i;
+ }
+
+ if ( ic[i - 1] != input_classes[i] )
+ goto next_chainposclassrule;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ lc = cpcr.Lookahead;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + lgc - i == (FT_Long)buffer->in_length )
+ goto next_chainposclassrule;
+ j++;
+ }
+
+ if ( i >= known_lookahead_classes )
+ {
+ error = _HB_OPEN_Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),
+ &lookahead_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_lookahead_classes = i;
+ }
+
+ if ( lc[i] != lookahead_classes[i] )
+ goto next_chainposclassrule;
+ }
+
+ error = Do_ContextPos( gpi, igc,
+ cpcr.PosCount,
+ cpcr.PosLookupRecord,
+ buffer,
+ nesting_level );
+ goto End1;
+
+ next_chainposclassrule:
+ ;
+ }
+
+ error = HB_Err_Not_Covered;
+
+End1:
+ FREE( lookahead_classes );
+
+End2:
+ FREE( input_classes );
+
+End3:
+ FREE( backtrack_classes );
+ return error;
+}
+
+
+static FT_Error Lookup_ChainContextPos3(
+ GPOS_Instance* gpi,
+ HB_ChainContextPosFormat3* ccpf3,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, i, j, property;
+ FT_UShort bgc, igc, lgc;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_Coverage* bc;
+ HB_Coverage* ic;
+ HB_Coverage* lc;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ bgc = ccpf3->BacktrackGlyphCount;
+ igc = ccpf3->InputGlyphCount;
+ lgc = ccpf3->LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ return HB_Err_Not_Covered;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ return HB_Err_Not_Covered;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ bc = ccpf3->BacktrackCoverage;
+
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ return HB_Err_Not_Covered;
+ j--;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+ }
+
+ ic = ccpf3->InputCoverage;
+
+ for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
+ {
+ /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
+ while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ lc = ccpf3->LookaheadCoverage;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == (FT_Long)buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ return Do_ContextPos( gpi, igc,
+ ccpf3->PosCount,
+ ccpf3->PosLookupRecord,
+ buffer,
+ nesting_level );
+}
+
+
+static FT_Error Lookup_ChainContextPos(
+ GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ HB_ChainContextPos* ccp = &st->chain;
+
+ switch ( ccp->PosFormat )
+ {
+ case 1:
+ return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
+ flags, context_length,
+ nesting_level );
+
+ case 2:
+ return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
+ flags, context_length,
+ nesting_level );
+
+ case 3:
+ return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
+ flags, context_length,
+ nesting_level );
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+
+/***********
+ * GPOS API
+ ***********/
+
+
+
+FT_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,
+ FT_ULong script_tag,
+ FT_UShort* script_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+
+
+ if ( !gpos || !script_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ if ( script_tag == sr[n].ScriptTag )
+ {
+ *script_index = n;
+
+ return FT_Err_Ok;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+
+FT_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,
+ FT_ULong language_tag,
+ FT_UShort script_index,
+ FT_UShort* language_index,
+ FT_UShort* req_feature_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+
+
+ if ( !gpos || !language_index || !req_feature_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ for ( n = 0; n < s->LangSysCount; n++ )
+ if ( language_tag == lsr[n].LangSysTag )
+ {
+ *language_index = n;
+ *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
+
+ return FT_Err_Ok;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* selecting 0xFFFF for language_index asks for the values of the
+ default language (DefaultLangSys) */
+
+
+FT_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,
+ FT_ULong feature_tag,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_UShort* feature_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+ HB_LangSys* ls;
+ FT_UShort* fi;
+
+ HB_FeatureList* fl;
+ HB_FeatureRecord* fr;
+
+
+ if ( !gpos || !feature_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ fl = &gpos->FeatureList;
+ fr = fl->FeatureRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( language_index == 0xFFFF )
+ ls = &s->DefaultLangSys;
+ else
+ {
+ if ( language_index >= s->LangSysCount )
+ return FT_Err_Invalid_Argument;
+
+ ls = &lsr[language_index].LangSys;
+ }
+
+ fi = ls->FeatureIndex;
+
+ for ( n = 0; n < ls->FeatureCount; n++ )
+ {
+ if ( fi[n] >= fl->FeatureCount )
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+
+ if ( feature_tag == fr[fi[n]].FeatureTag )
+ {
+ *feature_index = fi[n];
+
+ return FT_Err_Ok;
+ }
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* The next three functions return a null-terminated list */
+
+
+FT_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,
+ FT_ULong** script_tag_list )
+{
+ FT_Error error;
+ FT_Memory memory;
+ FT_UShort n;
+ FT_ULong* stl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+
+
+ if ( !gpos || !script_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gpos->memory;
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ stl[n] = sr[n].ScriptTag;
+ stl[n] = 0;
+
+ *script_tag_list = stl;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,
+ FT_UShort script_index,
+ FT_ULong** language_tag_list )
+{
+ FT_Error error;
+ FT_Memory memory;
+ FT_UShort n;
+ FT_ULong* ltl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+
+
+ if ( !gpos || !language_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gpos->memory;
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < s->LangSysCount; n++ )
+ ltl[n] = lsr[n].LangSysTag;
+ ltl[n] = 0;
+
+ *language_tag_list = ltl;
+
+ return FT_Err_Ok;
+}
+
+
+/* selecting 0xFFFF for language_index asks for the values of the
+ default language (DefaultLangSys) */
+
+
+FT_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_ULong** feature_tag_list )
+{
+ FT_UShort n;
+ FT_Error error;
+ FT_Memory memory;
+ FT_ULong* ftl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+ HB_LangSys* ls;
+ FT_UShort* fi;
+
+ HB_FeatureList* fl;
+ HB_FeatureRecord* fr;
+
+
+ if ( !gpos || !feature_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gpos->memory;
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ fl = &gpos->FeatureList;
+ fr = fl->FeatureRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( language_index == 0xFFFF )
+ ls = &s->DefaultLangSys;
+ else
+ {
+ if ( language_index >= s->LangSysCount )
+ return FT_Err_Invalid_Argument;
+
+ ls = &lsr[language_index].LangSys;
+ }
+
+ fi = ls->FeatureIndex;
+
+ if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < ls->FeatureCount; n++ )
+ {
+ if ( fi[n] >= fl->FeatureCount )
+ {
+ FREE( ftl );
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+ ftl[n] = fr[fi[n]].FeatureTag;
+ }
+ ftl[n] = 0;
+
+ *feature_tag_list = ftl;
+
+ return FT_Err_Ok;
+}
+
+
+typedef FT_Error (*Lookup_Pos_Func_Type) ( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level );
+static const Lookup_Pos_Func_Type Lookup_Pos_Call_Table[] = {
+ Lookup_DefaultPos,
+ Lookup_SinglePos, /* HB_GPOS_LOOKUP_SINGLE 1 */
+ Lookup_PairPos, /* HB_GPOS_LOOKUP_PAIR 2 */
+ Lookup_CursivePos, /* HB_GPOS_LOOKUP_CURSIVE 3 */
+ Lookup_MarkBasePos, /* HB_GPOS_LOOKUP_MARKBASE 4 */
+ Lookup_MarkLigPos, /* HB_GPOS_LOOKUP_MARKLIG 5 */
+ Lookup_MarkMarkPos, /* HB_GPOS_LOOKUP_MARKMARK 6 */
+ Lookup_ContextPos, /* HB_GPOS_LOOKUP_CONTEXT 7 */
+ Lookup_ChainContextPos, /* HB_GPOS_LOOKUP_CHAIN 8 */
+ Lookup_DefaultPos, /* HB_GPOS_LOOKUP_EXTENSION 9 */
+};
+
+/* Do an individual subtable lookup. Returns FT_Err_Ok if positioning
+ has been done, or HB_Err_Not_Covered if not. */
+static FT_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,
+ FT_UShort lookup_index,
+ HB_Buffer buffer,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error = HB_Err_Not_Covered;
+ FT_UShort i, flags, lookup_count;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_Lookup* lo;
+ int lookup_type;
+ Lookup_Pos_Func_Type Func;
+
+
+ nesting_level++;
+
+ if ( nesting_level > HB_MAX_NESTING_LEVEL )
+ return HB_Err_Too_Many_Nested_Contexts;
+
+ lookup_count = gpos->LookupList.LookupCount;
+ if (lookup_index >= lookup_count)
+ return error;
+
+ lo = &gpos->LookupList.Lookup[lookup_index];
+ flags = lo->LookupFlag;
+ lookup_type = lo->LookupType;
+ if (lookup_type >= ARRAY_LEN (Lookup_Pos_Call_Table))
+ lookup_type = 0;
+ Func = Lookup_Pos_Call_Table[lookup_type];
+
+ for ( i = 0; i < lo->SubTableCount; i++ )
+ {
+ error = Func ( gpi,
+ &lo->SubTable[i].st.gpos,
+ buffer,
+ flags, context_length,
+ nesting_level );
+
+ /* Check whether we have a successful positioning or an error other
+ than HB_Err_Not_Covered */
+
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Load_DefaultPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_UNUSED(st);
+ FT_UNUSED(stream);
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+}
+
+typedef FT_Error (*Load_Pos_Func_Type)( HB_GPOS_SubTable* st,
+ FT_Stream stream );
+static const Load_Pos_Func_Type Load_Pos_Call_Table[] = {
+ Load_DefaultPos,
+ Load_SinglePos, /* HB_GPOS_LOOKUP_SINGLE 1 */
+ Load_PairPos, /* HB_GPOS_LOOKUP_PAIR 2 */
+ Load_CursivePos, /* HB_GPOS_LOOKUP_CURSIVE 3 */
+ Load_MarkBasePos, /* HB_GPOS_LOOKUP_MARKBASE 4 */
+ Load_MarkLigPos, /* HB_GPOS_LOOKUP_MARKLIG 5 */
+ Load_MarkMarkPos, /* HB_GPOS_LOOKUP_MARKMARK 6 */
+ Load_ContextPos, /* HB_GPOS_LOOKUP_CONTEXT 7 */
+ Load_ChainContextPos, /* HB_GPOS_LOOKUP_CHAIN 8 */
+ Load_DefaultPos, /* HB_GPOS_LOOKUP_EXTENSION 9 */
+};
+
+FT_Error _HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
+ FT_Stream stream,
+ FT_UShort lookup_type )
+{
+ Load_Pos_Func_Type Func;
+
+ if (lookup_type >= ARRAY_LEN (Load_Pos_Call_Table))
+ lookup_type = 0;
+
+ Func = Load_Pos_Call_Table[lookup_type];
+
+ return Func ( st, stream );
+}
+
+
+static void Free_DefaultPos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UNUSED(st);
+ FT_UNUSED(memory);
+}
+
+typedef void (*Free_Pos_Func_Type)( HB_GPOS_SubTable* st,
+ FT_Memory memory );
+static const Free_Pos_Func_Type Free_Pos_Call_Table[] = {
+ Free_DefaultPos,
+ Free_SinglePos, /* HB_GPOS_LOOKUP_SINGLE 1 */
+ Free_PairPos, /* HB_GPOS_LOOKUP_PAIR 2 */
+ Free_CursivePos, /* HB_GPOS_LOOKUP_CURSIVE 3 */
+ Free_MarkBasePos, /* HB_GPOS_LOOKUP_MARKBASE 4 */
+ Free_MarkLigPos, /* HB_GPOS_LOOKUP_MARKLIG 5 */
+ Free_MarkMarkPos, /* HB_GPOS_LOOKUP_MARKMARK 6 */
+ Free_ContextPos, /* HB_GPOS_LOOKUP_CONTEXT 7 */
+ Free_ChainContextPos, /* HB_GPOS_LOOKUP_CHAIN 8 */
+ Free_DefaultPos, /* HB_GPOS_LOOKUP_EXTENSION 9 */
+};
+
+void _HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
+ FT_Memory memory,
+ FT_UShort lookup_type )
+{
+ Free_Pos_Func_Type Func;
+
+ if (lookup_type >= ARRAY_LEN (Free_Pos_Call_Table))
+ lookup_type = 0;
+
+ Func = Free_Pos_Call_Table[lookup_type];
+
+ Func ( st, memory );
+}
+
+
+
+/* apply one lookup to the input string object */
+
+static FT_Error GPOS_Do_String_Lookup( GPOS_Instance* gpi,
+ FT_UShort lookup_index,
+ HB_Buffer buffer )
+{
+ FT_Error error, retError = HB_Err_Not_Covered;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ FT_UInt* properties = gpos->LookupList.Properties;
+
+ int nesting_level = 0;
+
+
+ gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */
+
+ buffer->in_pos = 0;
+
+ while ( buffer->in_pos < buffer->in_length )
+ {
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
+ {
+ /* 0xFFFF indicates that we don't have a context length yet. */
+
+ /* Note that the connection between mark and base glyphs hold
+ exactly one (string) lookup. For example, it would be possible
+ that in the first lookup, mark glyph X is attached to base
+ glyph A, and in the next lookup it is attached to base glyph B.
+ It is up to the font designer to provide meaningful lookups and
+ lookup order. */
+
+ error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer,
+ 0xFFFF, nesting_level );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+ else
+ {
+ /* Contrary to properties defined in GDEF, user-defined properties
+ will always stop a possible cursive positioning. */
+ gpi->last = 0xFFFF;
+
+ error = HB_Err_Not_Covered;
+ }
+
+ if ( error == HB_Err_Not_Covered )
+ (buffer->in_pos)++;
+ else
+ retError = error;
+ }
+
+ return retError;
+}
+
+
+static FT_Error Position_CursiveChain ( HB_Buffer buffer )
+{
+ FT_ULong i, j;
+ HB_Position positions = buffer->positions;
+
+ /* First handle all left-to-right connections */
+ for (j = 0; j < buffer->in_length; j--)
+ {
+ if (positions[j].cursive_chain > 0)
+ positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
+ }
+
+ /* Then handle all right-to-left connections */
+ for (i = buffer->in_length; i > 0; i--)
+ {
+ j = i - 1;
+
+ if (positions[j].cursive_chain < 0)
+ positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+FT_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,
+ FT_UShort feature_index,
+ FT_UInt property )
+{
+ FT_UShort i;
+
+ HB_Feature feature;
+ FT_UInt* properties;
+ FT_UShort* index;
+ FT_UShort lookup_count;
+
+ /* Each feature can only be added once */
+
+ if ( !gpos ||
+ feature_index >= gpos->FeatureList.FeatureCount ||
+ gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )
+ return FT_Err_Invalid_Argument;
+
+ gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;
+
+ properties = gpos->LookupList.Properties;
+
+ feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
+ index = feature.LookupListIndex;
+ lookup_count = gpos->LookupList.LookupCount;
+
+ for ( i = 0; i < feature.LookupListCount; i++ )
+ {
+ FT_UShort lookup_index = index[i];
+ if (lookup_index < lookup_count)
+ properties[lookup_index] |= property;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos )
+{
+ FT_UShort i;
+
+ FT_UInt* properties;
+
+
+ if ( !gpos )
+ return FT_Err_Invalid_Argument;
+
+ gpos->FeatureList.ApplyCount = 0;
+
+ properties = gpos->LookupList.Properties;
+
+ for ( i = 0; i < gpos->LookupList.LookupCount; i++ )
+ properties[i] = 0;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GPOS_Register_Glyph_Function( HB_GPOSHeader* gpos,
+ HB_GlyphFunction gfunc )
+{
+ if ( !gpos )
+ return FT_Err_Invalid_Argument;
+
+ gpos->gfunc = gfunc;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,
+ HB_MMFunction mmfunc,
+ void* data )
+{
+ if ( !gpos )
+ return FT_Err_Invalid_Argument;
+
+ gpos->mmfunc = mmfunc;
+ gpos->data = data;
+
+ return FT_Err_Ok;
+}
+
+/* If `dvi' is TRUE, glyph contour points for anchor points and device
+ tables are ignored -- you will get device independent values. */
+
+
+FT_Error HB_GPOS_Apply_String( FT_Face face,
+ HB_GPOSHeader* gpos,
+ FT_UShort load_flags,
+ HB_Buffer buffer,
+ FT_Bool dvi,
+ FT_Bool r2l )
+{
+ FT_Error error, retError = HB_Err_Not_Covered;
+ GPOS_Instance gpi;
+ FT_UShort i, j, feature_index, lookup_count;
+ HB_Feature feature;
+
+ if ( !face || !gpos ||
+ !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
+ return FT_Err_Invalid_Argument;
+
+ gpi.face = face;
+ gpi.gpos = gpos;
+ gpi.load_flags = load_flags;
+ gpi.r2l = r2l;
+ gpi.dvi = dvi;
+
+ lookup_count = gpos->LookupList.LookupCount;
+
+ for ( i = 0; i < gpos->FeatureList.ApplyCount; i++ )
+ {
+ /* index of i'th feature */
+ feature_index = gpos->FeatureList.ApplyOrder[i];
+ feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
+
+ for ( j = 0; j < feature.LookupListCount; j++ )
+ {
+ FT_UShort lookup_index = feature.LookupListIndex[j];
+
+ /* Skip nonexistant lookups */
+ if (lookup_index >= lookup_count)
+ continue;
+
+ error = GPOS_Do_String_Lookup( &gpi, lookup_index, buffer );
+ if ( error )
+ {
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+ else
+ retError = error;
+ }
+ }
+
+ error = Position_CursiveChain ( buffer );
+ if ( error )
+ return error;
+
+ return retError;
+}
+
+/* END */
diff --git a/trunk/pango/opentype/harfbuzz-gpos.h b/trunk/pango/opentype/harfbuzz-gpos.h
new file mode 100644
index 00000000..1c670279
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gpos.h
@@ -0,0 +1,168 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GPOS_H
+#define HARFBUZZ_GPOS_H
+
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-buffer.h"
+
+FT_BEGIN_HEADER
+
+#define HB_Err_Invalid_GPOS_SubTable_Format 0x1020
+#define HB_Err_Invalid_GPOS_SubTable 0x1021
+
+
+/* Lookup types for glyph positioning */
+
+#define HB_GPOS_LOOKUP_SINGLE 1
+#define HB_GPOS_LOOKUP_PAIR 2
+#define HB_GPOS_LOOKUP_CURSIVE 3
+#define HB_GPOS_LOOKUP_MARKBASE 4
+#define HB_GPOS_LOOKUP_MARKLIG 5
+#define HB_GPOS_LOOKUP_MARKMARK 6
+#define HB_GPOS_LOOKUP_CONTEXT 7
+#define HB_GPOS_LOOKUP_CHAIN 8
+#define HB_GPOS_LOOKUP_EXTENSION 9
+
+
+/* A pointer to a function which loads a glyph. Its parameters are
+ the same as in a call to Load_Glyph() -- if no glyph loading
+ function will be registered with HB_GPOS_Register_Glyph_Function(),
+ Load_Glyph() will be called indeed. The purpose of this function
+ pointer is to provide a hook for caching glyph outlines and sbits
+ (using the instance's generic pointer to hold the data).
+
+ If for some reason no outline data is available (e.g. for an
+ embedded bitmap glyph), _glyph->outline.n_points should be set to
+ zero. _glyph can be computed with
+
+ _glyph = HANDLE_Glyph( glyph ) */
+
+typedef FT_Error (*HB_GlyphFunction)(FT_Face face,
+ FT_UInt glyphIndex,
+ FT_Int loadFlags );
+
+
+/* A pointer to a function which accesses the PostScript interpreter.
+ Multiple Master fonts need this interface to convert a metric ID
+ (as stored in an OpenType font version 1.2 or higher) `metric_id'
+ into a metric value (returned in `metric_value').
+
+ `data' points to the user-defined structure specified during a
+ call to HB_GPOS_Register_MM_Function().
+
+ `metric_value' must be returned as a scaled value (but shouldn't
+ be rounded). */
+
+typedef FT_Error (*HB_MMFunction)(FT_Face face,
+ FT_UShort metric_id,
+ FT_Pos* metric_value,
+ void* data );
+
+
+struct HB_GPOSHeader_
+{
+ FT_Memory memory;
+
+ FT_Fixed Version;
+
+ HB_ScriptList ScriptList;
+ HB_FeatureList FeatureList;
+ HB_LookupList LookupList;
+
+ HB_GDEFHeader* gdef;
+
+ /* the next field is used for a callback function to get the
+ glyph outline. */
+
+ HB_GlyphFunction gfunc;
+
+ /* this is OpenType 1.2 -- Multiple Master fonts need this
+ callback function to get various metric values from the
+ PostScript interpreter. */
+
+ HB_MMFunction mmfunc;
+ void* data;
+};
+
+typedef struct HB_GPOSHeader_ HB_GPOSHeader;
+typedef HB_GPOSHeader* HB_GPOS;
+
+
+FT_Error HB_Load_GPOS_Table( FT_Face face,
+ HB_GPOSHeader** gpos,
+ HB_GDEFHeader* gdef );
+
+
+FT_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos );
+
+
+FT_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,
+ FT_ULong script_tag,
+ FT_UShort* script_index );
+
+FT_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,
+ FT_ULong language_tag,
+ FT_UShort script_index,
+ FT_UShort* language_index,
+ FT_UShort* req_feature_index );
+
+FT_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,
+ FT_ULong feature_tag,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_UShort* feature_index );
+
+
+FT_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,
+ FT_ULong** script_tag_list );
+
+FT_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,
+ FT_UShort script_index,
+ FT_ULong** language_tag_list );
+
+FT_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_ULong** feature_tag_list );
+
+
+FT_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,
+ FT_UShort feature_index,
+ FT_UInt property );
+
+FT_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos );
+
+
+FT_Error HB_GPOS_Register_Glyph_Function( HB_GPOSHeader* gpos,
+ HB_GlyphFunction gfunc );
+
+
+FT_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,
+ HB_MMFunction mmfunc,
+ void* data );
+
+/* If `dvi' is TRUE, glyph contour points for anchor points and device
+ tables are ignored -- you will get device independent values. */
+
+
+FT_Error HB_GPOS_Apply_String( FT_Face face,
+ HB_GPOSHeader* gpos,
+ FT_UShort load_flags,
+ HB_Buffer buffer,
+ FT_Bool dvi,
+ FT_Bool r2l );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GPOS_H */
diff --git a/trunk/pango/opentype/harfbuzz-gsub-private.h b/trunk/pango/opentype/harfbuzz-gsub-private.h
new file mode 100644
index 00000000..84c08df5
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gsub-private.h
@@ -0,0 +1,448 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GSUB_PRIVATE_H
+#define HARFBUZZ_GSUB_PRIVATE_H
+
+#include "harfbuzz-gsub.h"
+
+FT_BEGIN_HEADER
+
+
+typedef union HB_GSUB_SubTable_ HB_GSUB_SubTable;
+
+/* LookupType 1 */
+
+struct HB_SingleSubstFormat1_
+{
+ FT_Short DeltaGlyphID; /* constant added to get
+ substitution glyph index */
+};
+
+typedef struct HB_SingleSubstFormat1_ HB_SingleSubstFormat1;
+
+
+struct HB_SingleSubstFormat2_
+{
+ FT_UShort GlyphCount; /* number of glyph IDs in
+ Substitute array */
+ FT_UShort* Substitute; /* array of substitute glyph IDs */
+};
+
+typedef struct HB_SingleSubstFormat2_ HB_SingleSubstFormat2;
+
+
+struct HB_SingleSubst_
+{
+ FT_UShort SubstFormat; /* 1 or 2 */
+ HB_Coverage Coverage; /* Coverage table */
+
+ union
+ {
+ HB_SingleSubstFormat1 ssf1;
+ HB_SingleSubstFormat2 ssf2;
+ } ssf;
+};
+
+typedef struct HB_SingleSubst_ HB_SingleSubst;
+
+
+/* LookupType 2 */
+
+struct HB_Sequence_
+{
+ FT_UShort GlyphCount; /* number of glyph IDs in the
+ Substitute array */
+ FT_UShort* Substitute; /* string of glyph IDs to
+ substitute */
+};
+
+typedef struct HB_Sequence_ HB_Sequence;
+
+
+struct HB_MultipleSubst_
+{
+ FT_UShort SubstFormat; /* always 1 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort SequenceCount; /* number of Sequence tables */
+ HB_Sequence* Sequence; /* array of Sequence tables */
+};
+
+typedef struct HB_MultipleSubst_ HB_MultipleSubst;
+
+
+/* LookupType 3 */
+
+struct HB_AlternateSet_
+{
+ FT_UShort GlyphCount; /* number of glyph IDs in the
+ Alternate array */
+ FT_UShort* Alternate; /* array of alternate glyph IDs */
+};
+
+typedef struct HB_AlternateSet_ HB_AlternateSet;
+
+
+struct HB_AlternateSubst_
+{
+ FT_UShort SubstFormat; /* always 1 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort AlternateSetCount;
+ /* number of AlternateSet tables */
+ HB_AlternateSet* AlternateSet; /* array of AlternateSet tables */
+};
+
+typedef struct HB_AlternateSubst_ HB_AlternateSubst;
+
+
+/* LookupType 4 */
+
+struct HB_Ligature_
+{
+ FT_UShort LigGlyph; /* glyphID of ligature
+ to substitute */
+ FT_UShort ComponentCount; /* number of components in ligature */
+ FT_UShort* Component; /* array of component glyph IDs */
+};
+
+typedef struct HB_Ligature_ HB_Ligature;
+
+
+struct HB_LigatureSet_
+{
+ FT_UShort LigatureCount; /* number of Ligature tables */
+ HB_Ligature* Ligature; /* array of Ligature tables */
+};
+
+typedef struct HB_LigatureSet_ HB_LigatureSet;
+
+
+struct HB_LigatureSubst_
+{
+ FT_UShort SubstFormat; /* always 1 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort LigatureSetCount; /* number of LigatureSet tables */
+ HB_LigatureSet* LigatureSet; /* array of LigatureSet tables */
+};
+
+typedef struct HB_LigatureSubst_ HB_LigatureSubst;
+
+
+/* needed by both lookup type 5 and 6 */
+
+struct HB_SubstLookupRecord_
+{
+ FT_UShort SequenceIndex; /* index into current
+ glyph sequence */
+ FT_UShort LookupListIndex; /* Lookup to apply to that pos. */
+};
+
+typedef struct HB_SubstLookupRecord_ HB_SubstLookupRecord;
+
+
+/* LookupType 5 */
+
+struct HB_SubRule_
+{
+ FT_UShort GlyphCount; /* total number of input glyphs */
+ FT_UShort SubstCount; /* number of SubstLookupRecord
+ tables */
+ FT_UShort* Input; /* array of input glyph IDs */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of SubstLookupRecord
+ tables */
+};
+
+typedef struct HB_SubRule_ HB_SubRule;
+
+
+struct HB_SubRuleSet_
+{
+ FT_UShort SubRuleCount; /* number of SubRule tables */
+ HB_SubRule* SubRule; /* array of SubRule tables */
+};
+
+typedef struct HB_SubRuleSet_ HB_SubRuleSet;
+
+
+struct HB_ContextSubstFormat1_
+{
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort SubRuleSetCount; /* number of SubRuleSet tables */
+ HB_SubRuleSet* SubRuleSet; /* array of SubRuleSet tables */
+};
+
+typedef struct HB_ContextSubstFormat1_ HB_ContextSubstFormat1;
+
+
+struct HB_SubClassRule_
+{
+ FT_UShort GlyphCount; /* total number of context classes */
+ FT_UShort SubstCount; /* number of SubstLookupRecord
+ tables */
+ FT_UShort* Class; /* array of classes */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of SubstLookupRecord
+ tables */
+};
+
+typedef struct HB_SubClassRule_ HB_SubClassRule;
+
+
+struct HB_SubClassSet_
+{
+ FT_UShort SubClassRuleCount;
+ /* number of SubClassRule tables */
+ HB_SubClassRule* SubClassRule; /* array of SubClassRule tables */
+};
+
+typedef struct HB_SubClassSet_ HB_SubClassSet;
+
+
+/* The `MaxContextLength' field is not defined in the TTO specification
+ but simplifies the implementation of this format. It holds the
+ maximal context length used in the context rules. */
+
+struct HB_ContextSubstFormat2_
+{
+ FT_UShort MaxContextLength;
+ /* maximal context length */
+ HB_Coverage Coverage; /* Coverage table */
+ HB_ClassDefinition ClassDef; /* ClassDef table */
+ FT_UShort SubClassSetCount;
+ /* number of SubClassSet tables */
+ HB_SubClassSet* SubClassSet; /* array of SubClassSet tables */
+};
+
+typedef struct HB_ContextSubstFormat2_ HB_ContextSubstFormat2;
+
+
+struct HB_ContextSubstFormat3_
+{
+ FT_UShort GlyphCount; /* number of input glyphs */
+ FT_UShort SubstCount; /* number of SubstLookupRecords */
+ HB_Coverage* Coverage; /* array of Coverage tables */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ContextSubstFormat3_ HB_ContextSubstFormat3;
+
+
+struct HB_ContextSubst_
+{
+ FT_UShort SubstFormat; /* 1, 2, or 3 */
+
+ union
+ {
+ HB_ContextSubstFormat1 csf1;
+ HB_ContextSubstFormat2 csf2;
+ HB_ContextSubstFormat3 csf3;
+ } csf;
+};
+
+typedef struct HB_ContextSubst_ HB_ContextSubst;
+
+
+/* LookupType 6 */
+
+struct HB_ChainSubRule_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* total number of backtrack glyphs */
+ FT_UShort* Backtrack; /* array of backtrack glyph IDs */
+ FT_UShort InputGlyphCount;
+ /* total number of input glyphs */
+ FT_UShort* Input; /* array of input glyph IDs */
+ FT_UShort LookaheadGlyphCount;
+ /* total number of lookahead glyphs */
+ FT_UShort* Lookahead; /* array of lookahead glyph IDs */
+ FT_UShort SubstCount; /* number of SubstLookupRecords */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of SubstLookupRecords */
+};
+
+typedef struct HB_ChainSubRule_ HB_ChainSubRule;
+
+
+struct HB_ChainSubRuleSet_
+{
+ FT_UShort ChainSubRuleCount;
+ /* number of ChainSubRule tables */
+ HB_ChainSubRule* ChainSubRule; /* array of ChainSubRule tables */
+};
+
+typedef struct HB_ChainSubRuleSet_ HB_ChainSubRuleSet;
+
+
+struct HB_ChainContextSubstFormat1_
+{
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort ChainSubRuleSetCount;
+ /* number of ChainSubRuleSet tables */
+ HB_ChainSubRuleSet* ChainSubRuleSet;
+ /* array of ChainSubRuleSet tables */
+};
+
+typedef struct HB_ChainContextSubstFormat1_ HB_ChainContextSubstFormat1;
+
+
+struct HB_ChainSubClassRule_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* total number of backtrack
+ classes */
+ FT_UShort* Backtrack; /* array of backtrack classes */
+ FT_UShort InputGlyphCount;
+ /* total number of context classes */
+ FT_UShort* Input; /* array of context classes */
+ FT_UShort LookaheadGlyphCount;
+ /* total number of lookahead
+ classes */
+ FT_UShort* Lookahead; /* array of lookahead classes */
+ FT_UShort SubstCount; /* number of SubstLookupRecords */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ChainSubClassRule_ HB_ChainSubClassRule;
+
+
+struct HB_ChainSubClassSet_
+{
+ FT_UShort ChainSubClassRuleCount;
+ /* number of ChainSubClassRule
+ tables */
+ HB_ChainSubClassRule* ChainSubClassRule;
+ /* array of ChainSubClassRule
+ tables */
+};
+
+typedef struct HB_ChainSubClassSet_ HB_ChainSubClassSet;
+
+
+/* The `MaxXXXLength' fields are not defined in the TTO specification
+ but simplifies the implementation of this format. It holds the
+ maximal context length used in the specific context rules. */
+
+struct HB_ChainContextSubstFormat2_
+{
+ HB_Coverage Coverage; /* Coverage table */
+
+ FT_UShort MaxBacktrackLength;
+ /* maximal backtrack length */
+ HB_ClassDefinition BacktrackClassDef;
+ /* BacktrackClassDef table */
+ FT_UShort MaxInputLength;
+ /* maximal input length */
+ HB_ClassDefinition InputClassDef;
+ /* InputClassDef table */
+ FT_UShort MaxLookaheadLength;
+ /* maximal lookahead length */
+ HB_ClassDefinition LookaheadClassDef;
+ /* LookaheadClassDef table */
+
+ FT_UShort ChainSubClassSetCount;
+ /* number of ChainSubClassSet
+ tables */
+ HB_ChainSubClassSet* ChainSubClassSet;
+ /* array of ChainSubClassSet
+ tables */
+};
+
+typedef struct HB_ChainContextSubstFormat2_ HB_ChainContextSubstFormat2;
+
+
+struct HB_ChainContextSubstFormat3_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* number of backtrack glyphs */
+ HB_Coverage* BacktrackCoverage;
+ /* array of backtrack Coverage
+ tables */
+ FT_UShort InputGlyphCount;
+ /* number of input glyphs */
+ HB_Coverage* InputCoverage;
+ /* array of input coverage
+ tables */
+ FT_UShort LookaheadGlyphCount;
+ /* number of lookahead glyphs */
+ HB_Coverage* LookaheadCoverage;
+ /* array of lookahead coverage
+ tables */
+ FT_UShort SubstCount; /* number of SubstLookupRecords */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ChainContextSubstFormat3_ HB_ChainContextSubstFormat3;
+
+
+struct HB_ChainContextSubst_
+{
+ FT_UShort SubstFormat; /* 1, 2, or 3 */
+
+ union
+ {
+ HB_ChainContextSubstFormat1 ccsf1;
+ HB_ChainContextSubstFormat2 ccsf2;
+ HB_ChainContextSubstFormat3 ccsf3;
+ } ccsf;
+};
+
+typedef struct HB_ChainContextSubst_ HB_ChainContextSubst;
+
+
+/* LookupType 8 */
+struct HB_ReverseChainContextSubst_
+{
+ FT_UShort SubstFormat; /* always 1 */
+ HB_Coverage Coverage; /* coverage table for input glyphs */
+ FT_UShort BacktrackGlyphCount; /* number of backtrack glyphs */
+ HB_Coverage* BacktrackCoverage; /* array of backtrack Coverage
+ tables */
+ FT_UShort LookaheadGlyphCount; /* number of lookahead glyphs */
+ HB_Coverage* LookaheadCoverage; /* array of lookahead Coverage
+ tables */
+ FT_UShort GlyphCount; /* number of Glyph IDs */
+ FT_UShort* Substitute; /* array of substitute Glyph ID */
+};
+
+typedef struct HB_ReverseChainContextSubst_ HB_ReverseChainContextSubst;
+
+
+union HB_GSUB_SubTable_
+{
+ HB_SingleSubst single;
+ HB_MultipleSubst multiple;
+ HB_AlternateSubst alternate;
+ HB_LigatureSubst ligature;
+ HB_ContextSubst context;
+ HB_ChainContextSubst chain;
+ HB_ReverseChainContextSubst reverse;
+};
+
+
+
+
+
+FT_Error _HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
+ FT_Stream stream,
+ FT_UShort lookup_type );
+
+void _HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
+ FT_Memory memory,
+ FT_UShort lookup_type );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GSUB_PRIVATE_H */
diff --git a/trunk/pango/opentype/harfbuzz-gsub.c b/trunk/pango/opentype/harfbuzz-gsub.c
new file mode 100644
index 00000000..1d91a117
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gsub.c
@@ -0,0 +1,4592 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+#include "harfbuzz-gsub-private.h"
+#include "harfbuzz-open-private.h"
+#include "harfbuzz-gdef-private.h"
+
+static FT_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
+ FT_UShort lookup_index,
+ HB_Buffer buffer,
+ FT_UShort context_length,
+ int nesting_level );
+
+
+
+/**********************
+ * Auxiliary functions
+ **********************/
+
+
+
+FT_Error HB_Load_GSUB_Table( FT_Face face,
+ HB_GSUBHeader** retptr,
+ HB_GDEFHeader* gdef )
+{
+ FT_Stream stream = face->stream;
+ FT_Memory memory = face->memory;
+ FT_Error error;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ FT_UShort i, num_lookups;
+ HB_GSUBHeader* gsub;
+ HB_Lookup* lo;
+
+ if ( !retptr )
+ return FT_Err_Invalid_Argument;
+
+ if (( error = _hb_ftglue_face_goto_table( face, TTAG_GSUB, stream ) ))
+ return error;
+
+ base_offset = FILE_Pos();
+
+ if ( ALLOC ( gsub, sizeof( *gsub ) ) )
+ return error;
+
+ gsub->memory = memory;
+
+ /* skip version */
+
+ if ( FILE_Seek( base_offset + 4L ) ||
+ ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList,
+ stream, HB_Type_GSUB ) ) != FT_Err_Ok )
+ goto Fail2;
+
+ gsub->gdef = gdef; /* can be NULL */
+
+ /* We now check the LookupFlags for values larger than 0xFF to find
+ out whether we need to load the `MarkAttachClassDef' field of the
+ GDEF table -- this hack is necessary for OpenType 1.2 tables since
+ the version field of the GDEF table hasn't been incremented.
+
+ For constructed GDEF tables, we only load it if
+ `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
+ a constructed mark attach table is not supported currently). */
+
+ if ( gdef &&
+ gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
+ {
+ lo = gsub->LookupList.Lookup;
+ num_lookups = gsub->LookupList.LookupCount;
+
+ for ( i = 0; i < num_lookups; i++ )
+ {
+
+ if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ {
+ if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,
+ 256, stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ break;
+ }
+ }
+ }
+
+ *retptr = gsub;
+
+ return FT_Err_Ok;
+
+Fail1:
+ _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB, memory );
+
+Fail2:
+ _HB_OPEN_Free_FeatureList( &gsub->FeatureList, memory );
+
+Fail3:
+ _HB_OPEN_Free_ScriptList( &gsub->ScriptList, memory );
+
+Fail4:
+ FREE ( gsub );
+
+
+ return error;
+}
+
+
+FT_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub )
+{
+ FT_Memory memory = gsub->memory;
+
+ _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB, memory );
+ _HB_OPEN_Free_FeatureList( &gsub->FeatureList, memory );
+ _HB_OPEN_Free_ScriptList( &gsub->ScriptList, memory );
+
+ FREE( gsub );
+
+ return FT_Err_Ok;
+}
+
+/*****************************
+ * SubTable related functions
+ *****************************/
+
+static FT_Error Lookup_DefaultSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UNUSED(gsub);
+ FT_UNUSED(st);
+ FT_UNUSED(buffer);
+ FT_UNUSED(flags);
+ FT_UNUSED(context_length);
+ FT_UNUSED(nesting_level);
+ return HB_Err_Not_Covered;
+}
+
+
+/* LookupType 1 */
+
+/* SingleSubstFormat1 */
+/* SingleSubstFormat2 */
+
+static FT_Error Load_SingleSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_SingleSubst* ss = &st->single;
+
+ FT_UShort n, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ FT_UShort* s;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ ss->SubstFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ switch ( ss->SubstFormat )
+ {
+ case 1:
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ ss->ssf.ssf1.DeltaGlyphID = GET_UShort();
+
+ FORGET_Frame();
+
+ break;
+
+ case 2:
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ss->ssf.ssf2.GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ss->ssf.ssf2.Substitute = NULL;
+
+ if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, FT_UShort ) )
+ goto Fail2;
+
+ s = ss->ssf.ssf2.Substitute;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ s[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ break;
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( s );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ss->Coverage, memory );
+ return error;
+}
+
+
+static void Free_SingleSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ HB_SingleSubst* ss = &st->single;
+
+ switch ( ss->SubstFormat )
+ {
+ case 1:
+ break;
+
+ case 2:
+ FREE( ss->ssf.ssf2.Substitute );
+ break;
+ }
+
+ _HB_OPEN_Free_Coverage( &ss->Coverage, memory );
+}
+
+
+static FT_Error Lookup_SingleSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, value, property;
+ FT_Error error;
+ HB_SingleSubst* ss = &st->single;
+ HB_GDEFHeader* gdef = gsub->gdef;
+
+ FT_UNUSED(nesting_level);
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ switch ( ss->SubstFormat )
+ {
+ case 1:
+ value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
+ if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
+ return error;
+ break;
+
+ case 2:
+ if ( index >= ss->ssf.ssf2.GlyphCount )
+ return HB_Err_Invalid_GSUB_SubTable;
+ value = ss->ssf.ssf2.Substitute[index];
+ if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
+ return error;
+ break;
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable;
+ }
+
+ if ( gdef && gdef->NewGlyphClasses )
+ {
+ /* we inherit the old glyph class to the substituted glyph */
+
+ error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 2 */
+
+/* Sequence */
+
+static FT_Error Load_Sequence( HB_Sequence* s,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* sub;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = s->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ s->Substitute = NULL;
+
+ if ( count )
+ {
+ if ( ALLOC_ARRAY( s->Substitute, count, FT_UShort ) )
+ return error;
+
+ sub = s->Substitute;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( sub );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ sub[n] = GET_UShort();
+
+ FORGET_Frame();
+ }
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_Sequence( HB_Sequence* s,
+ FT_Memory memory )
+{
+ FREE( s->Substitute );
+}
+
+
+/* MultipleSubstFormat1 */
+
+static FT_Error Load_MultipleSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_MultipleSubst* ms = &st->multiple;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Sequence* s;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ ms->SubstFormat = GET_UShort(); /* should be 1 */
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ms->SequenceCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ms->Sequence = NULL;
+
+ if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) )
+ goto Fail2;
+
+ s = ms->Sequence;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Sequence( &s[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_Sequence( &s[m], memory );
+
+ FREE( s );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ms->Coverage, memory );
+ return error;
+}
+
+
+static void Free_MultipleSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_MultipleSubst* ms = &st->multiple;
+
+ HB_Sequence* s;
+
+
+ if ( ms->Sequence )
+ {
+ count = ms->SequenceCount;
+ s = ms->Sequence;
+
+ for ( n = 0; n < count; n++ )
+ Free_Sequence( &s[n], memory );
+
+ FREE( s );
+ }
+
+ _HB_OPEN_Free_Coverage( &ms->Coverage, memory );
+}
+
+
+static FT_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, property, n, count;
+ FT_UShort*s;
+ HB_MultipleSubst* ms = &st->multiple;
+ HB_GDEFHeader* gdef = gsub->gdef;
+
+ FT_UNUSED(nesting_level);
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( index >= ms->SequenceCount )
+ return HB_Err_Invalid_GSUB_SubTable;
+
+ count = ms->Sequence[index].GlyphCount;
+ s = ms->Sequence[index].Substitute;
+
+ if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
+ return error;
+
+ if ( gdef && gdef->NewGlyphClasses )
+ {
+ /* this is a guess only ... */
+
+ if ( property == HB_GDEF_LIGATURE )
+ property = HB_GDEF_BASE_GLYPH;
+
+ for ( n = 0; n < count; n++ )
+ {
+ error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 3 */
+
+/* AlternateSet */
+
+static FT_Error Load_AlternateSet( HB_AlternateSet* as,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* a;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = as->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ as->Alternate = NULL;
+
+ if ( ALLOC_ARRAY( as->Alternate, count, FT_UShort ) )
+ return error;
+
+ a = as->Alternate;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( a );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ a[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_AlternateSet( HB_AlternateSet* as,
+ FT_Memory memory )
+{
+ FREE( as->Alternate );
+}
+
+
+/* AlternateSubstFormat1 */
+
+static FT_Error Load_AlternateSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_AlternateSubst* as = &st->alternate;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_AlternateSet* aset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ as->SubstFormat = GET_UShort(); /* should be 1 */
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = as->AlternateSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ as->AlternateSet = NULL;
+
+ if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) )
+ goto Fail2;
+
+ aset = as->AlternateSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_AlternateSet( &aset[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_AlternateSet( &aset[m], memory );
+
+ FREE( aset );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &as->Coverage, memory );
+ return error;
+}
+
+
+static void Free_AlternateSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_AlternateSubst* as = &st->alternate;
+
+ HB_AlternateSet* aset;
+
+
+ if ( as->AlternateSet )
+ {
+ count = as->AlternateSetCount;
+ aset = as->AlternateSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_AlternateSet( &aset[n], memory );
+
+ FREE( aset );
+ }
+
+ _HB_OPEN_Free_Coverage( &as->Coverage, memory );
+}
+
+
+static FT_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, alt_index, property;
+ HB_AlternateSubst* as = &st->alternate;
+ HB_GDEFHeader* gdef = gsub->gdef;
+ HB_AlternateSet aset;
+
+ FT_UNUSED(nesting_level);
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ aset = as->AlternateSet[index];
+
+ /* we use a user-defined callback function to get the alternate index */
+
+ if ( gsub->altfunc )
+ alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(),
+ aset.GlyphCount, aset.Alternate,
+ gsub->data );
+ else
+ alt_index = 0;
+
+ if ( ADD_Glyph( buffer, aset.Alternate[alt_index],
+ 0xFFFF, 0xFFFF ) )
+ return error;
+
+ if ( gdef && gdef->NewGlyphClasses )
+ {
+ /* we inherit the old glyph class to the substituted glyph */
+
+ error = _HB_GDEF_Add_Glyph_Property( gdef, aset.Alternate[alt_index],
+ property );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 4 */
+
+/* Ligature */
+
+static FT_Error Load_Ligature( HB_Ligature* l,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* c;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ l->LigGlyph = GET_UShort();
+ l->ComponentCount = GET_UShort();
+
+ FORGET_Frame();
+
+ l->Component = NULL;
+
+ count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */
+
+ if ( ALLOC_ARRAY( l->Component, count, FT_UShort ) )
+ return error;
+
+ c = l->Component;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( c );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ c[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_Ligature( HB_Ligature* l,
+ FT_Memory memory )
+{
+ FREE( l->Component );
+}
+
+
+/* LigatureSet */
+
+static FT_Error Load_LigatureSet( HB_LigatureSet* ls,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Ligature* l;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ls->LigatureCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ls->Ligature = NULL;
+
+ if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) )
+ return error;
+
+ l = ls->Ligature;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Ligature( &l[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_Ligature( &l[m], memory );
+
+ FREE( l );
+ return error;
+}
+
+
+static void Free_LigatureSet( HB_LigatureSet* ls,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Ligature* l;
+
+
+ if ( ls->Ligature )
+ {
+ count = ls->LigatureCount;
+ l = ls->Ligature;
+
+ for ( n = 0; n < count; n++ )
+ Free_Ligature( &l[n], memory );
+
+ FREE( l );
+ }
+}
+
+
+/* LigatureSubstFormat1 */
+
+static FT_Error Load_LigatureSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_LigatureSubst* ls = &st->ligature;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_LigatureSet* lset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ ls->SubstFormat = GET_UShort(); /* should be 1 */
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ls->LigatureSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ls->LigatureSet = NULL;
+
+ if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) )
+ goto Fail2;
+
+ lset = ls->LigatureSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigatureSet( &lset[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_LigatureSet( &lset[m], memory );
+
+ FREE( lset );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ls->Coverage, memory );
+ return error;
+}
+
+
+static void Free_LigatureSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_LigatureSubst* ls = &st->ligature;
+
+ HB_LigatureSet* lset;
+
+
+ if ( ls->LigatureSet )
+ {
+ count = ls->LigatureSetCount;
+ lset = ls->LigatureSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_LigatureSet( &lset[n], memory );
+
+ FREE( lset );
+ }
+
+ _HB_OPEN_Free_Coverage( &ls->Coverage, memory );
+}
+
+
+static FT_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
+ FT_UShort* c;
+ HB_LigatureSubst* ls = &st->ligature;
+ HB_GDEFHeader* gdef = gsub->gdef;
+
+ HB_Ligature* lig;
+
+ FT_UNUSED(nesting_level);
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ first_is_mark = TRUE;
+
+ error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( index >= ls->LigatureSetCount )
+ return HB_Err_Invalid_GSUB_SubTable;
+
+ lig = ls->LigatureSet[index].Ligature;
+
+ for ( numlig = ls->LigatureSet[index].LigatureCount;
+ numlig;
+ numlig--, lig++ )
+ {
+ if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
+ goto next_ligature; /* Not enough glyphs in input */
+
+ c = lig->Component;
+
+ is_mark = first_is_mark;
+
+ if ( context_length != 0xFFFF && context_length < lig->ComponentCount )
+ break;
+
+ for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lig->ComponentCount - i == (FT_Long)buffer->in_length )
+ goto next_ligature;
+ j++;
+ }
+
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
+ is_mark = FALSE;
+
+ if ( IN_GLYPH( j ) != c[i - 1] )
+ goto next_ligature;
+ }
+
+ if ( gdef && gdef->NewGlyphClasses )
+ {
+ /* this is just a guess ... */
+
+ error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph,
+ is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
+ {
+ /* We don't use a new ligature ID if there are no skipped
+ glyphs and the ligature already has an ID. */
+
+ if ( IN_LIGID( buffer->in_pos ) )
+ {
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
+ 0xFFFF, 0xFFFF ) )
+ return error;
+ }
+ else
+ {
+ FT_UShort ligID = hb_buffer_allocate_ligid( buffer );
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
+ 0xFFFF, ligID ) )
+ return error;
+ }
+ }
+ else
+ {
+ FT_UShort ligID = hb_buffer_allocate_ligid( buffer );
+ if ( ADD_Glyph( buffer, lig->LigGlyph,
+ 0xFFFF, ligID ) )
+ return error;
+
+ /* Now we must do a second loop to copy the skipped glyphs to
+ `out' and assign component values to it. We start with the
+ glyph after the first component. Glyphs between component
+ i and i+1 belong to component i. Together with the ligID
+ value it is later possible to check whether a specific
+ component value really belongs to a given ligature. */
+
+ for ( i = 0; i < lig->ComponentCount - 1; i++ )
+ {
+ while ( CHECK_Property( gdef, IN_CURITEM(),
+ flags, &property ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH(),
+ i, ligID ) )
+ return error;
+
+ (buffer->in_pos)++;
+ }
+ }
+
+ return FT_Err_Ok;
+
+ next_ligature:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* Do the actual substitution for a context substitution (either format
+ 5 or 6). This is only called after we've determined that the input
+ matches the subrule. */
+
+static FT_Error Do_ContextSubst( HB_GSUBHeader* gsub,
+ FT_UShort GlyphCount,
+ FT_UShort SubstCount,
+ HB_SubstLookupRecord* subst,
+ HB_Buffer buffer,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort i, old_pos;
+
+
+ i = 0;
+
+ while ( i < GlyphCount )
+ {
+ if ( SubstCount && i == subst->SequenceIndex )
+ {
+ old_pos = buffer->in_pos;
+
+ /* Do a substitution */
+
+ error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
+ GlyphCount, nesting_level );
+
+ subst++;
+ SubstCount--;
+ i += buffer->in_pos - old_pos;
+
+ if ( error == HB_Err_Not_Covered )
+ {
+ /* XXX "can't happen" -- but don't count on it */
+
+ if ( ADD_Glyph( buffer, IN_CURGLYPH(),
+ 0xFFFF, 0xFFFF ) )
+ return error;
+ i++;
+ }
+ else if ( error )
+ return error;
+ }
+ else
+ {
+ /* No substitution for this index */
+
+ if ( ADD_Glyph( buffer, IN_CURGLYPH(),
+ 0xFFFF, 0xFFFF ) )
+ return error;
+ i++;
+ }
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 5 */
+
+/* SubRule */
+
+static FT_Error Load_SubRule( HB_SubRule* sr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* i;
+
+ HB_SubstLookupRecord* slr;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ sr->GlyphCount = GET_UShort();
+ sr->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ sr->Input = NULL;
+
+ count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( sr->Input, count, FT_UShort ) )
+ return error;
+
+ i = sr->Input;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ i[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ sr->SubstLookupRecord = NULL;
+
+ count = sr->SubstCount;
+
+ if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = sr->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ FREE( i );
+ return error;
+}
+
+
+static void Free_SubRule( HB_SubRule* sr,
+ FT_Memory memory )
+{
+ FREE( sr->SubstLookupRecord );
+ FREE( sr->Input );
+}
+
+
+/* SubRuleSet */
+
+static FT_Error Load_SubRuleSet( HB_SubRuleSet* srs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubRule* sr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = srs->SubRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ srs->SubRule = NULL;
+
+ if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) )
+ return error;
+
+ sr = srs->SubRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubRule( &sr[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_SubRule( &sr[m], memory );
+
+ FREE( sr );
+ return error;
+}
+
+
+static void Free_SubRuleSet( HB_SubRuleSet* srs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_SubRule* sr;
+
+
+ if ( srs->SubRule )
+ {
+ count = srs->SubRuleCount;
+ sr = srs->SubRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubRule( &sr[n], memory );
+
+ FREE( sr );
+ }
+}
+
+
+/* ContextSubstFormat1 */
+
+static FT_Error Load_ContextSubst1( HB_ContextSubstFormat1* csf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubRuleSet* srs;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &csf1->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = csf1->SubRuleSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csf1->SubRuleSet = NULL;
+
+ if ( ALLOC_ARRAY( csf1->SubRuleSet, count, HB_SubRuleSet ) )
+ goto Fail2;
+
+ srs = csf1->SubRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubRuleSet( &srs[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_SubRuleSet( &srs[m], memory );
+
+ FREE( srs );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &csf1->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ContextSubst1( HB_ContextSubstFormat1* csf1,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_SubRuleSet* srs;
+
+
+ if ( csf1->SubRuleSet )
+ {
+ count = csf1->SubRuleSetCount;
+ srs = csf1->SubRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubRuleSet( &srs[n], memory );
+
+ FREE( srs );
+ }
+
+ _HB_OPEN_Free_Coverage( &csf1->Coverage, memory );
+}
+
+
+/* SubClassRule */
+
+static FT_Error Load_SubClassRule( HB_ContextSubstFormat2* csf2,
+ HB_SubClassRule* scr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* c;
+ HB_SubstLookupRecord* slr;
+ FT_Bool* d;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ scr->GlyphCount = GET_UShort();
+ scr->SubstCount = GET_UShort();
+
+ if ( scr->GlyphCount > csf2->MaxContextLength )
+ csf2->MaxContextLength = scr->GlyphCount;
+
+ FORGET_Frame();
+
+ scr->Class = NULL;
+
+ count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( scr->Class, count, FT_UShort ) )
+ return error;
+
+ c = scr->Class;
+ d = csf2->ClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ {
+ c[n] = GET_UShort();
+
+ /* We check whether the specific class is used at all. If not,
+ class 0 is used instead. */
+ if ( !d[c[n]] )
+ c[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ scr->SubstLookupRecord = NULL;
+
+ count = scr->SubstCount;
+
+ if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = scr->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ FREE( c );
+ return error;
+}
+
+
+static void Free_SubClassRule( HB_SubClassRule* scr,
+ FT_Memory memory )
+{
+ FREE( scr->SubstLookupRecord );
+ FREE( scr->Class );
+}
+
+
+/* SubClassSet */
+
+static FT_Error Load_SubClassSet( HB_ContextSubstFormat2* csf2,
+ HB_SubClassSet* scs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubClassRule* scr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = scs->SubClassRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ scs->SubClassRule = NULL;
+
+ if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) )
+ return error;
+
+ scr = scs->SubClassRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubClassRule( csf2, &scr[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_SubClassRule( &scr[m], memory );
+
+ FREE( scr );
+ return error;
+}
+
+
+static void Free_SubClassSet( HB_SubClassSet* scs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_SubClassRule* scr;
+
+
+ if ( scs->SubClassRule )
+ {
+ count = scs->SubClassRuleCount;
+ scr = scs->SubClassRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubClassRule( &scr[n], memory );
+
+ FREE( scr );
+ }
+}
+
+
+/* ContextSubstFormat2 */
+
+static FT_Error Load_ContextSubst2( HB_ContextSubstFormat2* csf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubClassSet* scs;
+
+
+ base_offset = FILE_Pos() - 2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ /* `SubClassSetCount' is the upper limit for class values, thus we
+ read it now to make an additional safety check. */
+
+ count = csf2->SubClassSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ csf2->SubClassSet = NULL;
+ csf2->MaxContextLength = 0;
+
+ if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) )
+ goto Fail2;
+
+ scs = csf2->SubClassSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubClassSet( csf2, &scs[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a SubClassSet table with no entries */
+
+ csf2->SubClassSet[n].SubClassRuleCount = 0;
+ csf2->SubClassSet[n].SubClassRule = NULL;
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_SubClassSet( &scs[m], memory );
+
+ FREE( scs );
+
+Fail2:
+ _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &csf2->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ContextSubst2( HB_ContextSubstFormat2* csf2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_SubClassSet* scs;
+
+
+ if ( csf2->SubClassSet )
+ {
+ count = csf2->SubClassSetCount;
+ scs = csf2->SubClassSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubClassSet( &scs[n], memory );
+
+ FREE( scs );
+ }
+
+ _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef, memory );
+ _HB_OPEN_Free_Coverage( &csf2->Coverage, memory );
+}
+
+
+/* ContextSubstFormat3 */
+
+static FT_Error Load_ContextSubst3( HB_ContextSubstFormat3* csf3,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* c;
+ HB_SubstLookupRecord* slr;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ csf3->GlyphCount = GET_UShort();
+ csf3->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csf3->Coverage = NULL;
+
+ count = csf3->GlyphCount;
+
+ if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) )
+ return error;
+
+ c = csf3->Coverage;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ csf3->SubstLookupRecord = NULL;
+
+ count = csf3->SubstCount;
+
+ if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,
+ HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = csf3->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ for ( m = 0; m < n; m++ )
+ _HB_OPEN_Free_Coverage( &c[m], memory );
+
+ FREE( c );
+ return error;
+}
+
+
+static void Free_ContextSubst3( HB_ContextSubstFormat3* csf3,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Coverage* c;
+
+
+ FREE( csf3->SubstLookupRecord );
+
+ if ( csf3->Coverage )
+ {
+ count = csf3->GlyphCount;
+ c = csf3->Coverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+}
+
+
+/* ContextSubst */
+
+static FT_Error Load_ContextSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ HB_ContextSubst* cs = &st->context;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cs->SubstFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( cs->SubstFormat )
+ {
+ case 1:
+ return Load_ContextSubst1( &cs->csf.csf1, stream );
+
+ case 2:
+ return Load_ContextSubst2( &cs->csf.csf2, stream );
+
+ case 3:
+ return Load_ContextSubst3( &cs->csf.csf3, stream );
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static void Free_ContextSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ HB_ContextSubst* cs = &st->context;
+
+ switch ( cs->SubstFormat )
+ {
+ case 1:
+ Free_ContextSubst1( &cs->csf.csf1, memory );
+ break;
+
+ case 2:
+ Free_ContextSubst2( &cs->csf.csf2, memory );
+ break;
+
+ case 3:
+ Free_ContextSubst3( &cs->csf.csf3, memory );
+ break;
+ }
+}
+
+
+static FT_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub,
+ HB_ContextSubstFormat1* csf1,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_UShort i, j, k, numsr;
+ FT_Error error;
+
+ HB_SubRule* sr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ sr = csf1->SubRuleSet[index].SubRule;
+ numsr = csf1->SubRuleSet[index].SubRuleCount;
+
+ for ( k = 0; k < numsr; k++ )
+ {
+ if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
+ goto next_subrule;
+
+ if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
+ goto next_subrule; /* context is too long */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + sr[k].GlyphCount - i == (FT_Long)buffer->in_length )
+ goto next_subrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )
+ goto next_subrule;
+ }
+
+ return Do_ContextSubst( gsub, sr[k].GlyphCount,
+ sr[k].SubstCount, sr[k].SubstLookupRecord,
+ buffer,
+ nesting_level );
+ next_subrule:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub,
+ HB_ContextSubstFormat2* csf2,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ FT_Memory memory = gsub->memory;
+ FT_UShort i, j, k, known_classes;
+
+ FT_UShort* classes;
+ FT_UShort* cl;
+
+ HB_SubClassSet* scs;
+ HB_SubClassRule* sr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* Note: The coverage table in format 2 doesn't give an index into
+ anything. It just lets us know whether or not we need to
+ do any lookup at all. */
+
+ error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) )
+ return error;
+
+ error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(),
+ &classes[0], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+ known_classes = 0;
+
+ scs = &csf2->SubClassSet[classes[0]];
+ if ( !scs )
+ {
+ error = HB_Err_Invalid_GSUB_SubTable;
+ goto End;
+ }
+
+ for ( k = 0; k < scs->SubClassRuleCount; k++ )
+ {
+ sr = &scs->SubClassRule[k];
+
+ if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
+ goto next_subclassrule;
+
+ if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
+ goto next_subclassrule; /* context is too long */
+
+ cl = sr->Class;
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+
+ if ( j + sr->GlyphCount - i < (FT_Long)buffer->in_length )
+ goto next_subclassrule;
+ j++;
+ }
+
+ if ( i > known_classes )
+ {
+ /* Keeps us from having to do this for each rule */
+
+ error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+ known_classes = i;
+ }
+
+ if ( cl[i - 1] != classes[i] )
+ goto next_subclassrule;
+ }
+
+ error = Do_ContextSubst( gsub, sr->GlyphCount,
+ sr->SubstCount, sr->SubstLookupRecord,
+ buffer,
+ nesting_level );
+ goto End;
+
+ next_subclassrule:
+ ;
+ }
+
+ error = HB_Err_Not_Covered;
+
+End:
+ FREE( classes );
+ return error;
+}
+
+
+static FT_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub,
+ HB_ContextSubstFormat3* csf3,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, i, j, property;
+
+ HB_Coverage* c;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
+ return HB_Err_Not_Covered;
+
+ if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
+ return HB_Err_Not_Covered; /* context is too long */
+
+ c = csf3->Coverage;
+
+ for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + csf3->GlyphCount - i == (FT_Long)buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ return Do_ContextSubst( gsub, csf3->GlyphCount,
+ csf3->SubstCount, csf3->SubstLookupRecord,
+ buffer,
+ nesting_level );
+}
+
+
+static FT_Error Lookup_ContextSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ HB_ContextSubst* cs = &st->context;
+
+ switch ( cs->SubstFormat )
+ {
+ case 1:
+ return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer,
+ flags, context_length, nesting_level );
+
+ case 2:
+ return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer,
+ flags, context_length, nesting_level );
+
+ case 3:
+ return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer,
+ flags, context_length, nesting_level );
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+/* LookupType 6 */
+
+/* ChainSubRule */
+
+static FT_Error Load_ChainSubRule( HB_ChainSubRule* csr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* b;
+ FT_UShort* i;
+ FT_UShort* l;
+
+ HB_SubstLookupRecord* slr;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ csr->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csr->Backtrack = NULL;
+
+ count = csr->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( csr->Backtrack, count, FT_UShort ) )
+ return error;
+
+ b = csr->Backtrack;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail4;
+
+ for ( n = 0; n < count; n++ )
+ b[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ csr->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csr->Input = NULL;
+
+ count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( csr->Input, count, FT_UShort ) )
+ goto Fail4;
+
+ i = csr->Input;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail3;
+
+ for ( n = 0; n < count; n++ )
+ i[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ csr->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csr->Lookahead = NULL;
+
+ count = csr->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( csr->Lookahead, count, FT_UShort ) )
+ goto Fail3;
+
+ l = csr->Lookahead;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ l[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ csr->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csr->SubstLookupRecord = NULL;
+
+ count = csr->SubstCount;
+
+ if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = csr->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ FREE( l );
+
+Fail3:
+ FREE( i );
+
+Fail4:
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainSubRule( HB_ChainSubRule* csr,
+ FT_Memory memory )
+{
+ FREE( csr->SubstLookupRecord );
+ FREE( csr->Lookahead );
+ FREE( csr->Input );
+ FREE( csr->Backtrack );
+}
+
+
+/* ChainSubRuleSet */
+
+static FT_Error Load_ChainSubRuleSet( HB_ChainSubRuleSet* csrs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainSubRule* csr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = csrs->ChainSubRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csrs->ChainSubRule = NULL;
+
+ if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) )
+ return error;
+
+ csr = csrs->ChainSubRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainSubRule( &csr[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_ChainSubRule( &csr[m], memory );
+
+ FREE( csr );
+ return error;
+}
+
+
+static void Free_ChainSubRuleSet( HB_ChainSubRuleSet* csrs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainSubRule* csr;
+
+
+ if ( csrs->ChainSubRule )
+ {
+ count = csrs->ChainSubRuleCount;
+ csr = csrs->ChainSubRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainSubRule( &csr[n], memory );
+
+ FREE( csr );
+ }
+}
+
+
+/* ChainContextSubstFormat1 */
+
+static FT_Error Load_ChainContextSubst1(
+ HB_ChainContextSubstFormat1* ccsf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainSubRuleSet* csrs;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ccsf1->ChainSubRuleSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf1->ChainSubRuleSet = NULL;
+
+ if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) )
+ goto Fail2;
+
+ csrs = ccsf1->ChainSubRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ChainSubRuleSet( &csrs[m], memory );
+
+ FREE( csrs );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ccsf1->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainSubRuleSet* csrs;
+
+
+ if ( ccsf1->ChainSubRuleSet )
+ {
+ count = ccsf1->ChainSubRuleSetCount;
+ csrs = ccsf1->ChainSubRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainSubRuleSet( &csrs[n], memory );
+
+ FREE( csrs );
+ }
+
+ _HB_OPEN_Free_Coverage( &ccsf1->Coverage, memory );
+}
+
+
+/* ChainSubClassRule */
+
+static FT_Error Load_ChainSubClassRule(
+ HB_ChainContextSubstFormat2* ccsf2,
+ HB_ChainSubClassRule* cscr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* b;
+ FT_UShort* i;
+ FT_UShort* l;
+ HB_SubstLookupRecord* slr;
+ FT_Bool* d;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cscr->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )
+ ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;
+
+ cscr->Backtrack = NULL;
+
+ count = cscr->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( cscr->Backtrack, count, FT_UShort ) )
+ return error;
+
+ b = cscr->Backtrack;
+ d = ccsf2->BacktrackClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail4;
+
+ for ( n = 0; n < count; n++ )
+ {
+ b[n] = GET_UShort();
+
+ /* We check whether the specific class is used at all. If not,
+ class 0 is used instead. */
+
+ if ( !d[b[n]] )
+ b[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ cscr->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )
+ ccsf2->MaxInputLength = cscr->InputGlyphCount;
+
+ cscr->Input = NULL;
+
+ count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( cscr->Input, count, FT_UShort ) )
+ goto Fail4;
+
+ i = cscr->Input;
+ d = ccsf2->InputClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail3;
+
+ for ( n = 0; n < count; n++ )
+ {
+ i[n] = GET_UShort();
+
+ if ( !d[i[n]] )
+ i[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ cscr->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength )
+ ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount;
+
+ cscr->Lookahead = NULL;
+
+ count = cscr->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( cscr->Lookahead, count, FT_UShort ) )
+ goto Fail3;
+
+ l = cscr->Lookahead;
+ d = ccsf2->LookaheadClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ {
+ l[n] = GET_UShort();
+
+ if ( !d[l[n]] )
+ l[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ cscr->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cscr->SubstLookupRecord = NULL;
+
+ count = cscr->SubstCount;
+
+ if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count,
+ HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = cscr->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ FREE( l );
+
+Fail3:
+ FREE( i );
+
+Fail4:
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainSubClassRule( HB_ChainSubClassRule* cscr,
+ FT_Memory memory )
+{
+ FREE( cscr->SubstLookupRecord );
+ FREE( cscr->Lookahead );
+ FREE( cscr->Input );
+ FREE( cscr->Backtrack );
+}
+
+
+/* SubClassSet */
+
+static FT_Error Load_ChainSubClassSet(
+ HB_ChainContextSubstFormat2* ccsf2,
+ HB_ChainSubClassSet* cscs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainSubClassRule* cscr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cscs->ChainSubClassRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cscs->ChainSubClassRule = NULL;
+
+ if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count,
+ HB_ChainSubClassRule ) )
+ return error;
+
+ cscr = cscs->ChainSubClassRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainSubClassRule( ccsf2, &cscr[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_ChainSubClassRule( &cscr[m], memory );
+
+ FREE( cscr );
+ return error;
+}
+
+
+static void Free_ChainSubClassSet( HB_ChainSubClassSet* cscs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainSubClassRule* cscr;
+
+
+ if ( cscs->ChainSubClassRule )
+ {
+ count = cscs->ChainSubClassRuleCount;
+ cscr = cscs->ChainSubClassRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainSubClassRule( &cscr[n], memory );
+
+ FREE( cscr );
+ }
+}
+
+static FT_Error GSUB_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_ULong class_offset,
+ FT_ULong base_offset,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_ULong cur_offset;
+
+ cur_offset = FILE_Pos();
+
+ if ( class_offset )
+ {
+ if ( !FILE_Seek( class_offset + base_offset ) )
+ error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
+ }
+ else
+ error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
+
+ if (error == FT_Err_Ok)
+ (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
+
+ return error;
+}
+
+
+/* ChainContextSubstFormat2 */
+
+static FT_Error Load_ChainContextSubst2(
+ HB_ChainContextSubstFormat2* ccsf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+ FT_ULong backtrack_offset, input_offset, lookahead_offset;
+
+ HB_ChainSubClassSet* cscs;
+
+
+ base_offset = FILE_Pos() - 2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 8L ) )
+ goto Fail5;
+
+ backtrack_offset = GET_UShort();
+ input_offset = GET_UShort();
+ lookahead_offset = GET_UShort();
+
+ /* `ChainSubClassSetCount' is the upper limit for input class values,
+ thus we read it now to make an additional safety check. No limit
+ is known or needed for the other two class definitions */
+
+ count = ccsf2->ChainSubClassSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
+ backtrack_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail5;
+
+ if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
+ input_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
+ lookahead_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+
+ ccsf2->ChainSubClassSet = NULL;
+ ccsf2->MaxBacktrackLength = 0;
+ ccsf2->MaxInputLength = 0;
+ ccsf2->MaxLookaheadLength = 0;
+
+ if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) )
+ goto Fail2;
+
+ cscs = ccsf2->ChainSubClassSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainSubClassSet( ccsf2, &cscs[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a ChainSubClassSet table with no entries */
+
+ ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0;
+ ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL;
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ChainSubClassSet( &cscs[m], memory );
+
+ FREE( cscs );
+
+Fail2:
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef, memory );
+
+Fail3:
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef, memory );
+
+Fail4:
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef, memory );
+
+Fail5:
+ _HB_OPEN_Free_Coverage( &ccsf2->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainSubClassSet* cscs;
+
+
+ if ( ccsf2->ChainSubClassSet )
+ {
+ count = ccsf2->ChainSubClassSetCount;
+ cscs = ccsf2->ChainSubClassSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainSubClassSet( &cscs[n], memory );
+
+ FREE( cscs );
+ }
+
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef, memory );
+
+ _HB_OPEN_Free_Coverage( &ccsf2->Coverage, memory );
+}
+
+
+/* ChainContextSubstFormat3 */
+
+static FT_Error Load_ChainContextSubst3(
+ HB_ChainContextSubstFormat3* ccsf3,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, nb = 0, ni =0, nl = 0, m, count;
+ FT_UShort backtrack_count, input_count, lookahead_count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* b;
+ HB_Coverage* i;
+ HB_Coverage* l;
+ HB_SubstLookupRecord* slr;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ ccsf3->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf3->BacktrackCoverage = NULL;
+
+ backtrack_count = ccsf3->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count,
+ HB_Coverage ) )
+ return error;
+
+ b = ccsf3->BacktrackCoverage;
+
+ for ( nb = 0; nb < backtrack_count; nb++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ ccsf3->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf3->InputCoverage = NULL;
+
+ input_count = ccsf3->InputGlyphCount;
+
+ if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) )
+ goto Fail4;
+
+ i = ccsf3->InputCoverage;
+
+ for ( ni = 0; ni < input_count; ni++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ ccsf3->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf3->LookaheadCoverage = NULL;
+
+ lookahead_count = ccsf3->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count,
+ HB_Coverage ) )
+ goto Fail3;
+
+ l = ccsf3->LookaheadCoverage;
+
+ for ( nl = 0; nl < lookahead_count; nl++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ ccsf3->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf3->SubstLookupRecord = NULL;
+
+ count = ccsf3->SubstCount;
+
+ if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count,
+ HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = ccsf3->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ for ( m = 0; m < nl; m++ )
+ _HB_OPEN_Free_Coverage( &l[m], memory );
+
+ FREE( l );
+
+Fail3:
+ for ( m = 0; m < ni; m++ )
+ _HB_OPEN_Free_Coverage( &i[m], memory );
+
+ FREE( i );
+
+Fail4:
+ for ( m = 0; m < nb; m++ )
+ _HB_OPEN_Free_Coverage( &b[m], memory );
+
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Coverage* c;
+
+
+ FREE( ccsf3->SubstLookupRecord );
+
+ if ( ccsf3->LookaheadCoverage )
+ {
+ count = ccsf3->LookaheadGlyphCount;
+ c = ccsf3->LookaheadCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( ccsf3->InputCoverage )
+ {
+ count = ccsf3->InputGlyphCount;
+ c = ccsf3->InputCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( ccsf3->BacktrackCoverage )
+ {
+ count = ccsf3->BacktrackGlyphCount;
+ c = ccsf3->BacktrackCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+}
+
+
+/* ChainContextSubst */
+
+static FT_Error Load_ChainContextSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ HB_ChainContextSubst* ccs = &st->chain;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ ccs->SubstFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( ccs->SubstFormat )
+ {
+ case 1:
+ return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
+
+ case 2:
+ return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
+
+ case 3:
+ return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static void Free_ChainContextSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ HB_ChainContextSubst* ccs = &st->chain;
+
+ switch ( ccs->SubstFormat )
+ {
+ case 1:
+ Free_ChainContextSubst1( &ccs->ccsf.ccsf1, memory );
+ break;
+
+ case 2:
+ Free_ChainContextSubst2( &ccs->ccsf.ccsf2, memory );
+ break;
+
+ case 3:
+ Free_ChainContextSubst3( &ccs->ccsf.ccsf3, memory );
+ break;
+ }
+}
+
+
+static FT_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
+ HB_ChainContextSubstFormat1* ccsf1,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_UShort i, j, k, num_csr;
+ FT_UShort bgc, igc, lgc;
+ FT_Error error;
+
+ HB_ChainSubRule* csr;
+ HB_ChainSubRule curr_csr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ csr = ccsf1->ChainSubRuleSet[index].ChainSubRule;
+ num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount;
+
+ for ( k = 0; k < num_csr; k++ )
+ {
+ curr_csr = csr[k];
+ bgc = curr_csr.BacktrackGlyphCount;
+ igc = curr_csr.InputGlyphCount;
+ lgc = curr_csr.LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ goto next_chainsubrule;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ goto next_chainsubrule;
+
+ if ( bgc )
+ {
+ /* since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ goto next_chainsubrule;
+ j--;
+ }
+
+ /* In OpenType 1.3, it is undefined whether the offsets of
+ backtrack glyphs is in logical order or not. Version 1.4
+ will clarify this:
+
+ Logical order - a b c d e f g h i j
+ i
+ Input offsets - 0 1
+ Backtrack offsets - 3 2 1 0
+ Lookahead offsets - 0 1 2 3 */
+
+ if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] )
+ goto next_chainsubrule;
+ }
+ }
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
+ goto next_chainsubrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )
+ goto next_chainsubrule;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == (FT_Long)buffer->in_length )
+ goto next_chainsubrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )
+ goto next_chainsubrule;
+ }
+
+ return Do_ContextSubst( gsub, igc,
+ curr_csr.SubstCount,
+ curr_csr.SubstLookupRecord,
+ buffer,
+ nesting_level );
+
+ next_chainsubrule:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
+ HB_ChainContextSubstFormat2* ccsf2,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Memory memory;
+ FT_Error error;
+ FT_UShort i, j, k;
+ FT_UShort bgc, igc, lgc;
+ FT_UShort known_backtrack_classes,
+ known_input_classes,
+ known_lookahead_classes;
+
+ FT_UShort* backtrack_classes;
+ FT_UShort* input_classes;
+ FT_UShort* lookahead_classes;
+
+ FT_UShort* bc;
+ FT_UShort* ic;
+ FT_UShort* lc;
+
+ HB_ChainSubClassSet* cscs;
+ HB_ChainSubClassRule ccsr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+ memory = gsub->memory;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* Note: The coverage table in format 2 doesn't give an index into
+ anything. It just lets us know whether or not we need to
+ do any lookup at all. */
+
+ error = _HB_OPEN_Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, FT_UShort ) )
+ return error;
+ known_backtrack_classes = 0;
+
+ if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, FT_UShort ) )
+ goto End3;
+ known_input_classes = 1;
+
+ if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, FT_UShort ) )
+ goto End2;
+ known_lookahead_classes = 0;
+
+ error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(),
+ &input_classes[0], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ cscs = &ccsf2->ChainSubClassSet[input_classes[0]];
+ if ( !cscs )
+ {
+ error = HB_Err_Invalid_GSUB_SubTable;
+ goto End1;
+ }
+
+ for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ )
+ {
+ ccsr = cscs->ChainSubClassRule[k];
+ bgc = ccsr.BacktrackGlyphCount;
+ igc = ccsr.InputGlyphCount;
+ lgc = ccsr.LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ goto next_chainsubclassrule;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ goto next_chainsubclassrule;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array.
+ Note that `known_backtrack_classes' starts at index 0. */
+
+ bc = ccsr.Backtrack;
+
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + 1 == bgc - i )
+ goto next_chainsubclassrule;
+ j--;
+ }
+
+ if ( i >= known_backtrack_classes )
+ {
+ /* Keeps us from having to do this for each rule */
+
+ error = _HB_OPEN_Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ),
+ &backtrack_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_backtrack_classes = i;
+ }
+
+ if ( bc[i] != backtrack_classes[i] )
+ goto next_chainsubclassrule;
+ }
+ }
+
+ ic = ccsr.Input;
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
+ goto next_chainsubclassrule;
+ j++;
+ }
+
+ if ( i >= known_input_classes )
+ {
+ error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ),
+ &input_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_input_classes = i;
+ }
+
+ if ( ic[i - 1] != input_classes[i] )
+ goto next_chainsubclassrule;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ lc = ccsr.Lookahead;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + lgc - i == (FT_Long)buffer->in_length )
+ goto next_chainsubclassrule;
+ j++;
+ }
+
+ if ( i >= known_lookahead_classes )
+ {
+ error = _HB_OPEN_Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ),
+ &lookahead_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_lookahead_classes = i;
+ }
+
+ if ( lc[i] != lookahead_classes[i] )
+ goto next_chainsubclassrule;
+ }
+
+ error = Do_ContextSubst( gsub, igc,
+ ccsr.SubstCount,
+ ccsr.SubstLookupRecord,
+ buffer,
+ nesting_level );
+ goto End1;
+
+ next_chainsubclassrule:
+ ;
+ }
+
+ error = HB_Err_Not_Covered;
+
+End1:
+ FREE( lookahead_classes );
+
+End2:
+ FREE( input_classes );
+
+End3:
+ FREE( backtrack_classes );
+ return error;
+}
+
+
+static FT_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
+ HB_ChainContextSubstFormat3* ccsf3,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, i, j, property;
+ FT_UShort bgc, igc, lgc;
+ FT_Error error;
+
+ HB_Coverage* bc;
+ HB_Coverage* ic;
+ HB_Coverage* lc;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ bgc = ccsf3->BacktrackGlyphCount;
+ igc = ccsf3->InputGlyphCount;
+ lgc = ccsf3->LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ return HB_Err_Not_Covered;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ return HB_Err_Not_Covered;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ bc = ccsf3->BacktrackCoverage;
+
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ return HB_Err_Not_Covered;
+ j--;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &bc[i], OUT_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+ }
+
+ ic = ccsf3->InputCoverage;
+
+ for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
+ {
+ /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
+ while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ /* we are starting for lookahead glyphs right after the last context
+ glyph */
+
+ lc = ccsf3->LookaheadCoverage;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == (FT_Long)buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ return Do_ContextSubst( gsub, igc,
+ ccsf3->SubstCount,
+ ccsf3->SubstLookupRecord,
+ buffer,
+ nesting_level );
+}
+
+
+static FT_Error Lookup_ChainContextSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ HB_ChainContextSubst* ccs = &st->chain;
+
+ switch ( ccs->SubstFormat )
+ {
+ case 1:
+ return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer,
+ flags, context_length,
+ nesting_level );
+
+ case 2:
+ return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer,
+ flags, context_length,
+ nesting_level );
+
+ case 3:
+ return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer,
+ flags, context_length,
+ nesting_level );
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static FT_Error Load_ReverseChainContextSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_ReverseChainContextSubst* rccs = &st->reverse;
+
+ FT_UShort m, count;
+
+ FT_UShort nb = 0, nl = 0, n;
+ FT_UShort backtrack_count, lookahead_count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* b;
+ HB_Coverage* l;
+ FT_UShort* sub;
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ rccs->SubstFormat = GET_UShort();
+
+ if ( rccs->SubstFormat != 1 )
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &rccs->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ rccs->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ rccs->BacktrackCoverage = NULL;
+
+ backtrack_count = rccs->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count,
+ HB_Coverage ) )
+ goto Fail4;
+
+ b = rccs->BacktrackCoverage;
+
+ for ( nb = 0; nb < backtrack_count; nb++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+ }
+
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ rccs->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ rccs->LookaheadCoverage = NULL;
+
+ lookahead_count = rccs->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count,
+ HB_Coverage ) )
+ goto Fail3;
+
+ l = rccs->LookaheadCoverage;
+
+ for ( nl = 0; nl < lookahead_count; nl++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ rccs->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ rccs->Substitute = NULL;
+
+ count = rccs->GlyphCount;
+
+ if ( ALLOC_ARRAY( rccs->Substitute, count,
+ FT_UShort ) )
+ goto Fail2;
+
+ sub = rccs->Substitute;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ sub[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( sub );
+
+Fail2:
+ for ( m = 0; m < nl; m++ )
+ _HB_OPEN_Free_Coverage( &l[m], memory );
+
+ FREE( l );
+
+Fail3:
+ for ( m = 0; m < nb; m++ )
+ _HB_OPEN_Free_Coverage( &b[m], memory );
+
+ FREE( b );
+
+Fail4:
+ _HB_OPEN_Free_Coverage( &rccs->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ReverseChainContextSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_ReverseChainContextSubst* rccs = &st->reverse;
+
+ HB_Coverage* c;
+
+ _HB_OPEN_Free_Coverage( &rccs->Coverage, memory );
+
+ if ( rccs->LookaheadCoverage )
+ {
+ count = rccs->LookaheadGlyphCount;
+ c = rccs->LookaheadCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( rccs->BacktrackCoverage )
+ {
+ count = rccs->BacktrackGlyphCount;
+ c = rccs->BacktrackCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ FREE ( rccs->Substitute );
+}
+
+
+static FT_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ /* note different signature here: */ FT_ULong string_index )
+{
+ FT_UShort index, input_index, i, j, property;
+ FT_UShort bgc, lgc;
+ FT_Error error;
+
+ HB_ReverseChainContextSubst* rccs = &st->reverse;
+ HB_Coverage* bc;
+ HB_Coverage* lc;
+ HB_GDEFHeader* gdef;
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_ITEM( string_index ), flags, &property ) )
+ return error;
+
+ bgc = rccs->BacktrackGlyphCount;
+ lgc = rccs->LookaheadGlyphCount;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > string_index || string_index + 1 + lgc > buffer->in_length )
+ return HB_Err_Not_Covered;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ bc = rccs->BacktrackCoverage;
+
+ for ( i = 0, j = string_index - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ return HB_Err_Not_Covered;
+ j--;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+ }
+
+ j = string_index;
+
+ error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index );
+ if ( error )
+ return error;
+
+ /* we are starting for lookahead glyphs right after the last context
+ glyph */
+
+ j += 1;
+
+ lc = rccs->LookaheadCoverage;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == (FT_Long)buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ IN_GLYPH( string_index ) = rccs->Substitute[input_index];
+
+ return error;
+}
+
+
+
+/***********
+ * GSUB API
+ ***********/
+
+
+
+FT_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub,
+ FT_ULong script_tag,
+ FT_UShort* script_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+
+
+ if ( !gsub || !script_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ if ( script_tag == sr[n].ScriptTag )
+ {
+ *script_index = n;
+
+ return FT_Err_Ok;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+
+FT_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub,
+ FT_ULong language_tag,
+ FT_UShort script_index,
+ FT_UShort* language_index,
+ FT_UShort* req_feature_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+
+
+ if ( !gsub || !language_index || !req_feature_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ for ( n = 0; n < s->LangSysCount; n++ )
+ if ( language_tag == lsr[n].LangSysTag )
+ {
+ *language_index = n;
+ *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
+
+ return FT_Err_Ok;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* selecting 0xFFFF for language_index asks for the values of the
+ default language (DefaultLangSys) */
+
+
+FT_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub,
+ FT_ULong feature_tag,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_UShort* feature_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+ HB_LangSys* ls;
+ FT_UShort* fi;
+
+ HB_FeatureList* fl;
+ HB_FeatureRecord* fr;
+
+
+ if ( !gsub || !feature_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ fl = &gsub->FeatureList;
+ fr = fl->FeatureRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( language_index == 0xFFFF )
+ ls = &s->DefaultLangSys;
+ else
+ {
+ if ( language_index >= s->LangSysCount )
+ return FT_Err_Invalid_Argument;
+
+ ls = &lsr[language_index].LangSys;
+ }
+
+ fi = ls->FeatureIndex;
+
+ for ( n = 0; n < ls->FeatureCount; n++ )
+ {
+ if ( fi[n] >= fl->FeatureCount )
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+
+ if ( feature_tag == fr[fi[n]].FeatureTag )
+ {
+ *feature_index = fi[n];
+
+ return FT_Err_Ok;
+ }
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* The next three functions return a null-terminated list */
+
+
+FT_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub,
+ FT_ULong** script_tag_list )
+{
+ FT_UShort n;
+ FT_Error error;
+ FT_Memory memory;
+ FT_ULong* stl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+
+
+ if ( !gsub || !script_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gsub->memory;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ stl[n] = sr[n].ScriptTag;
+ stl[n] = 0;
+
+ *script_tag_list = stl;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub,
+ FT_UShort script_index,
+ FT_ULong** language_tag_list )
+{
+ FT_UShort n;
+ FT_Error error;
+ FT_Memory memory;
+ FT_ULong* ltl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+
+
+ if ( !gsub || !language_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gsub->memory;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < s->LangSysCount; n++ )
+ ltl[n] = lsr[n].LangSysTag;
+ ltl[n] = 0;
+
+ *language_tag_list = ltl;
+
+ return FT_Err_Ok;
+}
+
+
+/* selecting 0xFFFF for language_index asks for the values of the
+ default language (DefaultLangSys) */
+
+
+FT_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_ULong** feature_tag_list )
+{
+ FT_UShort n;
+ FT_Error error;
+ FT_Memory memory;
+ FT_ULong* ftl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+ HB_LangSys* ls;
+ FT_UShort* fi;
+
+ HB_FeatureList* fl;
+ HB_FeatureRecord* fr;
+
+
+ if ( !gsub || !feature_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gsub->memory;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ fl = &gsub->FeatureList;
+ fr = fl->FeatureRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( language_index == 0xFFFF )
+ ls = &s->DefaultLangSys;
+ else
+ {
+ if ( language_index >= s->LangSysCount )
+ return FT_Err_Invalid_Argument;
+
+ ls = &lsr[language_index].LangSys;
+ }
+
+ fi = ls->FeatureIndex;
+
+ if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < ls->FeatureCount; n++ )
+ {
+ if ( fi[n] >= fl->FeatureCount )
+ {
+ FREE( ftl );
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+ ftl[n] = fr[fi[n]].FeatureTag;
+ }
+ ftl[n] = 0;
+
+ *feature_tag_list = ftl;
+
+ return FT_Err_Ok;
+}
+
+
+typedef FT_Error (*Lookup_Subst_Func_Type)( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level );
+static const Lookup_Subst_Func_Type Lookup_Subst_Call_Table[] = {
+ Lookup_DefaultSubst,
+ Lookup_SingleSubst, /* HB_GSUB_LOOKUP_SINGLE 1 */
+ Lookup_MultipleSubst, /* HB_GSUB_LOOKUP_MULTIPLE 2 */
+ Lookup_AlternateSubst, /* HB_GSUB_LOOKUP_ALTERNATE 3 */
+ Lookup_LigatureSubst, /* HB_GSUB_LOOKUP_LIGATURE 4 */
+ Lookup_ContextSubst, /* HB_GSUB_LOOKUP_CONTEXT 5 */
+ Lookup_ChainContextSubst, /* HB_GSUB_LOOKUP_CHAIN 6 */
+ Lookup_DefaultSubst /* HB_GSUB_LOOKUP_EXTENSION 7 */
+};
+/* Note that the following lookup does not belong to the table above:
+ * Lookup_ReverseChainContextSubst, HB_GSUB_LOOKUP_REVERSE_CHAIN 8
+ * because it's invalid to happen where this table is used. It's
+ * signature is different too...
+ */
+
+/* Do an individual subtable lookup. Returns FT_Err_Ok if substitution
+ has been done, or HB_Err_Not_Covered if not. */
+static FT_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
+ FT_UShort lookup_index,
+ HB_Buffer buffer,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error = HB_Err_Not_Covered;
+ FT_UShort i, flags, lookup_count;
+ HB_Lookup* lo;
+ int lookup_type;
+ Lookup_Subst_Func_Type Func;
+
+
+ nesting_level++;
+
+ if ( nesting_level > HB_MAX_NESTING_LEVEL )
+ return HB_Err_Too_Many_Nested_Contexts;
+
+ lookup_count = gsub->LookupList.LookupCount;
+ if (lookup_index >= lookup_count)
+ return error;
+
+ lo = &gsub->LookupList.Lookup[lookup_index];
+ flags = lo->LookupFlag;
+ lookup_type = lo->LookupType;
+
+ if (lookup_type >= ARRAY_LEN (Lookup_Subst_Call_Table))
+ lookup_type = 0;
+ Func = Lookup_Subst_Call_Table[lookup_type];
+
+ for ( i = 0; i < lo->SubTableCount; i++ )
+ {
+ error = Func ( gsub,
+ &lo->SubTable[i].st.gsub,
+ buffer,
+ flags, context_length,
+ nesting_level );
+
+ /* Check whether we have a successful substitution or an error other
+ than HB_Err_Not_Covered */
+
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Load_DefaultSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_UNUSED(st);
+ FT_UNUSED(stream);
+
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+}
+
+typedef FT_Error (*Load_Subst_Func_Type)( HB_GSUB_SubTable* st,
+ FT_Stream stream );
+static const Load_Subst_Func_Type Load_Subst_Call_Table[] = {
+ Load_DefaultSubst,
+ Load_SingleSubst, /* HB_GSUB_LOOKUP_SINGLE 1 */
+ Load_MultipleSubst, /* HB_GSUB_LOOKUP_MULTIPLE 2 */
+ Load_AlternateSubst, /* HB_GSUB_LOOKUP_ALTERNATE 3 */
+ Load_LigatureSubst, /* HB_GSUB_LOOKUP_LIGATURE 4 */
+ Load_ContextSubst, /* HB_GSUB_LOOKUP_CONTEXT 5 */
+ Load_ChainContextSubst, /* HB_GSUB_LOOKUP_CHAIN 6 */
+ Load_DefaultSubst, /* HB_GSUB_LOOKUP_EXTENSION 7 */
+ Load_ReverseChainContextSubst /* HB_GSUB_LOOKUP_REVERSE_CHAIN 8 */
+};
+
+FT_Error _HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
+ FT_Stream stream,
+ FT_UShort lookup_type )
+{
+ Load_Subst_Func_Type Func;
+
+ if (lookup_type >= ARRAY_LEN (Load_Subst_Call_Table))
+ lookup_type = 0;
+
+ Func = Load_Subst_Call_Table[lookup_type];
+
+ return Func ( st, stream );
+}
+
+
+static void Free_DefaultSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UNUSED(st);
+ FT_UNUSED(memory);
+}
+
+typedef void (*Free_Subst_Func_Type)( HB_GSUB_SubTable* st,
+ FT_Memory memory );
+static const Free_Subst_Func_Type Free_Subst_Call_Table[] = {
+ Free_DefaultSubst,
+ Free_SingleSubst, /* HB_GSUB_LOOKUP_SINGLE 1 */
+ Free_MultipleSubst, /* HB_GSUB_LOOKUP_MULTIPLE 2 */
+ Free_AlternateSubst, /* HB_GSUB_LOOKUP_ALTERNATE 3 */
+ Free_LigatureSubst, /* HB_GSUB_LOOKUP_LIGATURE 4 */
+ Free_ContextSubst, /* HB_GSUB_LOOKUP_CONTEXT 5 */
+ Free_ChainContextSubst, /* HB_GSUB_LOOKUP_CHAIN 6 */
+ Free_DefaultSubst, /* HB_GSUB_LOOKUP_EXTENSION 7 */
+ Free_ReverseChainContextSubst /* HB_GSUB_LOOKUP_REVERSE_CHAIN 8 */
+};
+
+void _HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
+ FT_Memory memory,
+ FT_UShort lookup_type )
+{
+ Free_Subst_Func_Type Func;
+
+ if (lookup_type >= ARRAY_LEN (Free_Subst_Call_Table))
+ lookup_type = 0;
+
+ Func = Free_Subst_Call_Table[lookup_type];
+
+ Func ( st, memory );
+}
+
+
+
+/* apply one lookup to the input string object */
+
+static FT_Error GSUB_Do_String_Lookup( HB_GSUBHeader* gsub,
+ FT_UShort lookup_index,
+ HB_Buffer buffer )
+{
+ FT_Error error, retError = HB_Err_Not_Covered;
+
+ FT_UInt* properties = gsub->LookupList.Properties;
+
+ int nesting_level = 0;
+
+
+ while ( buffer->in_pos < buffer->in_length )
+ {
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
+ {
+ /* 0xFFFF indicates that we don't have a context length yet */
+ error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer,
+ 0xFFFF, nesting_level );
+ if ( error )
+ {
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+ else
+ retError = error;
+ }
+ else
+ error = HB_Err_Not_Covered;
+
+ if ( error == HB_Err_Not_Covered )
+ if ( hb_buffer_copy_output_glyph ( buffer ) )
+ return error;
+ }
+
+ return retError;
+}
+
+
+static FT_Error Apply_ReverseChainContextSubst( HB_GSUBHeader* gsub,
+ FT_UShort lookup_index,
+ HB_Buffer buffer )
+{
+ FT_UInt* properties = gsub->LookupList.Properties;
+ FT_Error error, retError = HB_Err_Not_Covered;
+ FT_ULong subtable_Count, string_index;
+ FT_UShort flags;
+ HB_Lookup* lo;
+
+ if ( buffer->in_length == 0 )
+ return HB_Err_Not_Covered;
+
+ lo = &gsub->LookupList.Lookup[lookup_index];
+ flags = lo->LookupFlag;
+
+ for ( subtable_Count = 0; subtable_Count < lo->SubTableCount; subtable_Count++ )
+ {
+ string_index = buffer->in_length - 1;
+ do
+ {
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
+ {
+ error = Lookup_ReverseChainContextSubst( gsub, &lo->SubTable[subtable_Count].st.gsub,
+ buffer, flags, string_index );
+ if ( error )
+ {
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+ else
+ retError = error;
+ }
+ }
+ while (string_index--);
+ }
+
+ return retError;
+}
+
+
+FT_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub,
+ FT_UShort feature_index,
+ FT_UInt property )
+{
+ FT_UShort i;
+
+ HB_Feature feature;
+ FT_UInt* properties;
+ FT_UShort* index;
+ FT_UShort lookup_count;
+
+ /* Each feature can only be added once */
+
+ if ( !gsub ||
+ feature_index >= gsub->FeatureList.FeatureCount ||
+ gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount )
+ return FT_Err_Invalid_Argument;
+
+ gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index;
+
+ properties = gsub->LookupList.Properties;
+
+ feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
+ index = feature.LookupListIndex;
+ lookup_count = gsub->LookupList.LookupCount;
+
+ for ( i = 0; i < feature.LookupListCount; i++ )
+ {
+ FT_UShort lookup_index = index[i];
+ if (lookup_index < lookup_count)
+ properties[lookup_index] |= property;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub )
+{
+ FT_UShort i;
+
+ FT_UInt* properties;
+
+
+ if ( !gsub )
+ return FT_Err_Invalid_Argument;
+
+ gsub->FeatureList.ApplyCount = 0;
+
+ properties = gsub->LookupList.Properties;
+
+ for ( i = 0; i < gsub->LookupList.LookupCount; i++ )
+ properties[i] = 0;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub,
+ HB_AltFunction altfunc,
+ void* data )
+{
+ if ( !gsub )
+ return FT_Err_Invalid_Argument;
+
+ gsub->altfunc = altfunc;
+ gsub->data = data;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub,
+ HB_Buffer buffer )
+{
+ FT_Error error, retError = HB_Err_Not_Covered;
+ FT_UShort i, j, lookup_count;
+
+ if ( !gsub ||
+ !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
+ return FT_Err_Invalid_Argument;
+
+ lookup_count = gsub->LookupList.LookupCount;
+
+ for ( i = 0; i < gsub->FeatureList.ApplyCount; i++)
+ {
+ FT_UShort feature_index;
+ HB_Feature feature;
+
+ feature_index = gsub->FeatureList.ApplyOrder[i];
+ feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
+
+ for ( j = 0; j < feature.LookupListCount; j++ )
+ {
+ FT_UShort lookup_index;
+ HB_Lookup* lookup;
+ FT_Bool need_swap;
+
+ lookup_index = feature.LookupListIndex[j];
+
+ /* Skip nonexistant lookups */
+ if (lookup_index >= lookup_count)
+ continue;
+
+ lookup = &gsub->LookupList.Lookup[lookup_index];
+
+ if ( lookup->LookupType == HB_GSUB_LOOKUP_REVERSE_CHAIN )
+ {
+ error = Apply_ReverseChainContextSubst( gsub, lookup_index, buffer);
+ need_swap = FALSE; /* We do ReverseChainContextSubst in-place */
+ }
+ else
+ {
+ error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer );
+ need_swap = TRUE;
+ }
+
+ if ( error )
+ {
+ if ( error != HB_Err_Not_Covered )
+ goto End;
+ }
+ else
+ retError = error;
+
+ if ( need_swap )
+ {
+ error = hb_buffer_swap( buffer );
+ if ( error )
+ goto End;
+ }
+ }
+ }
+
+ error = retError;
+
+End:
+ return error;
+}
+
+
+/* END */
diff --git a/trunk/pango/opentype/harfbuzz-gsub.h b/trunk/pango/opentype/harfbuzz-gsub.h
new file mode 100644
index 00000000..09145bad
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-gsub.h
@@ -0,0 +1,132 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GSUB_H
+#define HARFBUZZ_GSUB_H
+
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-buffer.h"
+
+FT_BEGIN_HEADER
+
+#define HB_Err_Invalid_GSUB_SubTable_Format 0x1010
+#define HB_Err_Invalid_GSUB_SubTable 0x1011
+
+
+/* Lookup types for glyph substitution */
+
+#define HB_GSUB_LOOKUP_SINGLE 1
+#define HB_GSUB_LOOKUP_MULTIPLE 2
+#define HB_GSUB_LOOKUP_ALTERNATE 3
+#define HB_GSUB_LOOKUP_LIGATURE 4
+#define HB_GSUB_LOOKUP_CONTEXT 5
+#define HB_GSUB_LOOKUP_CHAIN 6
+#define HB_GSUB_LOOKUP_EXTENSION 7
+#define HB_GSUB_LOOKUP_REVERSE_CHAIN 8
+
+
+/* A pointer to a function which selects the alternate glyph. `pos' is
+ the position of the glyph with index `glyphID', `num_alternates'
+ gives the number of alternates in the `alternates' array. `data'
+ points to the user-defined structure specified during a call to
+ HB_GSUB_Register_Alternate_Function(). The function must return an
+ index into the `alternates' array. */
+
+typedef FT_UShort (*HB_AltFunction)(FT_ULong pos,
+ FT_UShort glyphID,
+ FT_UShort num_alternates,
+ FT_UShort* alternates,
+ void* data );
+
+
+struct HB_GSUBHeader_
+{
+ FT_Memory memory;
+
+ FT_ULong offset;
+
+ FT_Fixed Version;
+
+ HB_ScriptList ScriptList;
+ HB_FeatureList FeatureList;
+ HB_LookupList LookupList;
+
+ HB_GDEFHeader* gdef;
+
+ /* the next two fields are used for an alternate substitution callback
+ function to select the proper alternate glyph. */
+
+ HB_AltFunction altfunc;
+ void* data;
+};
+
+typedef struct HB_GSUBHeader_ HB_GSUBHeader;
+typedef HB_GSUBHeader* HB_GSUB;
+
+
+FT_Error HB_Load_GSUB_Table( FT_Face face,
+ HB_GSUBHeader** gsub,
+ HB_GDEFHeader* gdef );
+
+
+FT_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub );
+
+
+FT_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub,
+ FT_ULong script_tag,
+ FT_UShort* script_index );
+
+FT_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub,
+ FT_ULong language_tag,
+ FT_UShort script_index,
+ FT_UShort* language_index,
+ FT_UShort* req_feature_index );
+
+FT_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub,
+ FT_ULong feature_tag,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_UShort* feature_index );
+
+
+FT_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub,
+ FT_ULong** script_tag_list );
+
+FT_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub,
+ FT_UShort script_index,
+ FT_ULong** language_tag_list );
+
+FT_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_ULong** feature_tag_list );
+
+
+FT_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub,
+ FT_UShort feature_index,
+ FT_UInt property );
+
+FT_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub );
+
+
+FT_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub,
+ HB_AltFunction altfunc,
+ void* data );
+
+
+FT_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub,
+ HB_Buffer buffer );
+
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GSUB_H */
diff --git a/trunk/pango/opentype/harfbuzz-impl.h b/trunk/pango/opentype/harfbuzz-impl.h
new file mode 100644
index 00000000..f31f5cde
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-impl.h
@@ -0,0 +1,83 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_IMPL_H
+#define HARFBUZZ_IMPL_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TAGS_H
+
+FT_BEGIN_HEADER
+
+#ifndef NULL
+# define NULL ((void *)0)
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef TTAG_GDEF
+# define TTAG_GDEF FT_MAKE_TAG( 'G', 'D', 'E', 'F' )
+#endif
+#ifndef TTAG_GPOS
+# define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
+#endif
+#ifndef TTAG_GSUB
+# define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
+#endif
+
+#ifndef FT_UNUSED
+# define FT_UNUSED(arg) ((arg) = (arg))
+#endif
+
+#include "ftglue.h"
+
+#define ARRAY_LEN(Array) ((int)(sizeof (Array) / sizeof (Array)[0]))
+
+
+
+
+#define IN_GLYPH( pos ) (buffer->in_string[(pos)].gindex)
+#define IN_ITEM( pos ) (&buffer->in_string[(pos)])
+#define IN_CURGLYPH() (buffer->in_string[buffer->in_pos].gindex)
+#define IN_CURITEM() (&buffer->in_string[buffer->in_pos])
+#define IN_PROPERTIES( pos ) (buffer->in_string[(pos)].properties)
+#define IN_LIGID( pos ) (buffer->in_string[(pos)].ligID)
+#define IN_COMPONENT( pos ) (buffer->in_string[(pos)].component)
+#define POSITION( pos ) (&buffer->positions[(pos)])
+#define OUT_GLYPH( pos ) (buffer->out_string[(pos)].gindex)
+#define OUT_ITEM( pos ) (&buffer->out_string[(pos)])
+
+#define CHECK_Property( gdef, index, flags, property ) \
+ ( ( error = _HB_GDEF_Check_Property( (gdef), (index), (flags), \
+ (property) ) ) != FT_Err_Ok )
+
+#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
+ ( ( error = hb_buffer_add_output_glyphs( (buffer), \
+ (num_in), (num_out), \
+ (glyph_data), (component), (ligID) \
+ ) ) != FT_Err_Ok )
+#define ADD_Glyph( buffer, glyph_index, component, ligID ) \
+ ( ( error = hb_buffer_add_output_glyph( (buffer), \
+ (glyph_index), (component), (ligID) \
+ ) ) != FT_Err_Ok )
+
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_IMPL_H */
diff --git a/trunk/pango/opentype/harfbuzz-open-private.h b/trunk/pango/opentype/harfbuzz-open-private.h
new file mode 100644
index 00000000..be265af2
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-open-private.h
@@ -0,0 +1,81 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_OPEN_PRIVATE_H
+#define HARFBUZZ_OPEN_PRIVATE_H
+
+#include "harfbuzz-open.h"
+#include "harfbuzz-gsub-private.h"
+#include "harfbuzz-gpos-private.h"
+
+FT_BEGIN_HEADER
+
+
+struct HB_SubTable_
+{
+ union
+ {
+ HB_GSUB_SubTable gsub;
+ HB_GPOS_SubTable gpos;
+ } st;
+};
+
+
+FT_Error _HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
+ FT_Stream stream );
+FT_Error _HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
+ FT_Stream input );
+FT_Error _HB_OPEN_Load_LookupList( HB_LookupList* ll,
+ FT_Stream input,
+ HB_Type type );
+
+FT_Error _HB_OPEN_Load_Coverage( HB_Coverage* c,
+ FT_Stream input );
+FT_Error _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_Stream input );
+FT_Error _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd,
+ FT_Stream input );
+FT_Error _HB_OPEN_Load_Device( HB_Device* d,
+ FT_Stream input );
+
+void _HB_OPEN_Free_ScriptList( HB_ScriptList* sl,
+ FT_Memory memory );
+void _HB_OPEN_Free_FeatureList( HB_FeatureList* fl,
+ FT_Memory memory );
+void _HB_OPEN_Free_LookupList( HB_LookupList* ll,
+ HB_Type type,
+ FT_Memory memory );
+
+void _HB_OPEN_Free_Coverage( HB_Coverage* c,
+ FT_Memory memory );
+void _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd,
+ FT_Memory memory );
+void _HB_OPEN_Free_Device( HB_Device* d,
+ FT_Memory memory );
+
+
+
+FT_Error _HB_OPEN_Coverage_Index( HB_Coverage* c,
+ FT_UShort glyphID,
+ FT_UShort* index );
+FT_Error _HB_OPEN_Get_Class( HB_ClassDefinition* cd,
+ FT_UShort glyphID,
+ FT_UShort* class,
+ FT_UShort* index );
+FT_Error _HB_OPEN_Get_Device( HB_Device* d,
+ FT_UShort size,
+ FT_Short* value );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_OPEN_PRIVATE_H */
diff --git a/trunk/pango/opentype/harfbuzz-open.c b/trunk/pango/opentype/harfbuzz-open.c
new file mode 100644
index 00000000..fa540401
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-open.c
@@ -0,0 +1,1431 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+#include "harfbuzz-open-private.h"
+
+
+/***************************
+ * Script related functions
+ ***************************/
+
+
+/* LangSys */
+
+static FT_Error Load_LangSys( HB_LangSys* ls,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_UShort n, count;
+ FT_UShort* fi;
+
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ ls->LookupOrderOffset = GET_UShort(); /* should be 0 */
+ ls->ReqFeatureIndex = GET_UShort();
+ count = ls->FeatureCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ls->FeatureIndex = NULL;
+
+ if ( ALLOC_ARRAY( ls->FeatureIndex, count, FT_UShort ) )
+ return error;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( ls->FeatureIndex );
+ return error;
+ }
+
+ fi = ls->FeatureIndex;
+
+ for ( n = 0; n < count; n++ )
+ fi[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_LangSys( HB_LangSys* ls,
+ FT_Memory memory )
+{
+ FREE( ls->FeatureIndex );
+}
+
+
+/* Script */
+
+static FT_Error Load_Script( HB_Script* s,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_LangSysRecord* lsr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LangSys( &s->DefaultLangSys,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a DefaultLangSys table with no entries */
+
+ s->DefaultLangSys.LookupOrderOffset = 0;
+ s->DefaultLangSys.ReqFeatureIndex = 0xFFFF;
+ s->DefaultLangSys.FeatureCount = 0;
+ s->DefaultLangSys.FeatureIndex = NULL;
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = s->LangSysCount = GET_UShort();
+
+ /* safety check; otherwise the official handling of TrueType Open
+ fonts won't work */
+
+ if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
+ {
+ error = HB_Err_Empty_Script;
+ goto Fail2;
+ }
+
+ FORGET_Frame();
+
+ s->LangSysRecord = NULL;
+
+ if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) )
+ goto Fail2;
+
+ lsr = s->LangSysRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 6L ) )
+ goto Fail1;
+
+ lsr[n].LangSysTag = GET_ULong();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_LangSys( &lsr[m].LangSys, memory );
+
+ FREE( s->LangSysRecord );
+
+Fail2:
+ Free_LangSys( &s->DefaultLangSys, memory );
+ return error;
+}
+
+
+static void Free_Script( HB_Script* s,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_LangSysRecord* lsr;
+
+
+ Free_LangSys( &s->DefaultLangSys, memory );
+
+ if ( s->LangSysRecord )
+ {
+ count = s->LangSysCount;
+ lsr = s->LangSysRecord;
+
+ for ( n = 0; n < count; n++ )
+ Free_LangSys( &lsr[n].LangSys, memory );
+
+ FREE( lsr );
+ }
+}
+
+
+/* ScriptList */
+
+FT_Error _HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, script_count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ScriptRecord* sr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ script_count = GET_UShort();
+
+ FORGET_Frame();
+
+ sl->ScriptRecord = NULL;
+
+ if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) )
+ return error;
+
+ sr = sl->ScriptRecord;
+
+ sl->ScriptCount= 0;
+ for ( n = 0; n < script_count; n++ )
+ {
+ if ( ACCESS_Frame( 6L ) )
+ goto Fail;
+
+ sr[sl->ScriptCount].ScriptTag = GET_ULong();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+
+ if ( FILE_Seek( new_offset ) )
+ goto Fail;
+
+ error = Load_Script( &sr[sl->ScriptCount].Script, stream );
+ if ( error == FT_Err_Ok )
+ sl->ScriptCount += 1;
+ else if ( error != HB_Err_Empty_Script )
+ goto Fail;
+
+ (void)FILE_Seek( cur_offset );
+ }
+
+ /* Empty tables are harmless and generated by fontforge.
+ * See http://bugzilla.gnome.org/show_bug.cgi?id=347073
+ */
+#if 0
+ if ( sl->ScriptCount == 0 )
+ {
+ error = HB_Err_Invalid_SubTable;
+ goto Fail;
+ }
+#endif
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ Free_Script( &sr[n].Script, memory );
+
+ FREE( sl->ScriptRecord );
+ return error;
+}
+
+
+void _HB_OPEN_Free_ScriptList( HB_ScriptList* sl,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ScriptRecord* sr;
+
+
+ if ( sl->ScriptRecord )
+ {
+ count = sl->ScriptCount;
+ sr = sl->ScriptRecord;
+
+ for ( n = 0; n < count; n++ )
+ Free_Script( &sr[n].Script, memory );
+
+ FREE( sr );
+ }
+}
+
+
+
+/*********************************
+ * Feature List related functions
+ *********************************/
+
+
+/* Feature */
+
+static FT_Error Load_Feature( HB_Feature* f,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* lli;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ f->FeatureParams = GET_UShort(); /* should be 0 */
+ count = f->LookupListCount = GET_UShort();
+
+ FORGET_Frame();
+
+ f->LookupListIndex = NULL;
+
+ if ( ALLOC_ARRAY( f->LookupListIndex, count, FT_UShort ) )
+ return error;
+
+ lli = f->LookupListIndex;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( f->LookupListIndex );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ lli[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_Feature( HB_Feature* f,
+ FT_Memory memory )
+{
+ FREE( f->LookupListIndex );
+}
+
+
+/* FeatureList */
+
+FT_Error _HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_FeatureRecord* fr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = fl->FeatureCount = GET_UShort();
+
+ FORGET_Frame();
+
+ fl->FeatureRecord = NULL;
+
+ if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) )
+ return error;
+ if ( ALLOC_ARRAY( fl->ApplyOrder, count, FT_UShort ) )
+ goto Fail2;
+
+ fl->ApplyCount = 0;
+
+ fr = fl->FeatureRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 6L ) )
+ goto Fail1;
+
+ fr[n].FeatureTag = GET_ULong();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Feature( &fr[n].Feature, stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_Feature( &fr[m].Feature, memory );
+
+ FREE( fl->ApplyOrder );
+
+Fail2:
+ FREE( fl->FeatureRecord );
+
+ return error;
+}
+
+
+void _HB_OPEN_Free_FeatureList( HB_FeatureList* fl,
+ FT_Memory memory)
+{
+ FT_UShort n, count;
+
+ HB_FeatureRecord* fr;
+
+
+ if ( fl->FeatureRecord )
+ {
+ count = fl->FeatureCount;
+ fr = fl->FeatureRecord;
+
+ for ( n = 0; n < count; n++ )
+ Free_Feature( &fr[n].Feature, memory );
+
+ FREE( fr );
+ }
+
+ FREE( fl->ApplyOrder );
+}
+
+
+
+/********************************
+ * Lookup List related functions
+ ********************************/
+
+/* the subroutines of the following two functions are defined in
+ ftxgsub.c and ftxgpos.c respectively */
+
+
+/* SubTable */
+
+static FT_Error Load_SubTable( HB_SubTable* st,
+ FT_Stream stream,
+ HB_Type table_type,
+ FT_UShort lookup_type )
+{
+ if ( table_type == HB_Type_GSUB )
+ return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type );
+ else
+ return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type );
+}
+
+
+static void Free_SubTable( HB_SubTable* st,
+ HB_Type table_type,
+ FT_UShort lookup_type,
+ FT_Memory memory )
+{
+ if ( table_type == HB_Type_GSUB )
+ _HB_GSUB_Free_SubTable ( &st->st.gsub, memory, lookup_type );
+ else
+ _HB_GPOS_Free_SubTable ( &st->st.gpos, memory, lookup_type );
+}
+
+
+/* Lookup */
+
+static FT_Error Load_Lookup( HB_Lookup* l,
+ FT_Stream stream,
+ HB_Type type )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubTable* st;
+
+ FT_Bool is_extension = FALSE;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ l->LookupType = GET_UShort();
+ l->LookupFlag = GET_UShort();
+ count = l->SubTableCount = GET_UShort();
+
+ FORGET_Frame();
+
+ l->SubTable = NULL;
+
+ if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) )
+ return error;
+
+ st = l->SubTable;
+
+ if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) ||
+ ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) )
+ is_extension = TRUE;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+
+ if ( is_extension )
+ {
+ if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) )
+ goto Fail;
+
+ if (GET_UShort() != 1) /* format should be 1 */
+ goto Fail;
+
+ l->LookupType = GET_UShort();
+ new_offset += GET_ULong();
+
+ FORGET_Frame();
+ }
+
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubTable( &st[n], stream,
+ type, l->LookupType ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_SubTable( &st[m], type, l->LookupType, memory );
+
+ FREE( l->SubTable );
+ return error;
+}
+
+
+static void Free_Lookup( HB_Lookup* l,
+ HB_Type type,
+ FT_Memory memory)
+{
+ FT_UShort n, count;
+
+ HB_SubTable* st;
+
+
+ if ( l->SubTable )
+ {
+ count = l->SubTableCount;
+ st = l->SubTable;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubTable( &st[n], type, l->LookupType, memory );
+
+ FREE( st );
+ }
+}
+
+
+/* LookupList */
+
+FT_Error _HB_OPEN_Load_LookupList( HB_LookupList* ll,
+ FT_Stream stream,
+ HB_Type type )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Lookup* l;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ll->LookupCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ll->Lookup = NULL;
+
+ if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) )
+ return error;
+ if ( ALLOC_ARRAY( ll->Properties, count, FT_UInt ) )
+ goto Fail2;
+
+ l = ll->Lookup;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Lookup( &l[n], stream, type ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( ll->Properties );
+
+ for ( m = 0; m < n; m++ )
+ Free_Lookup( &l[m], type, memory );
+
+Fail2:
+ FREE( ll->Lookup );
+ return error;
+}
+
+
+void _HB_OPEN_Free_LookupList( HB_LookupList* ll,
+ HB_Type type,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Lookup* l;
+
+
+ FREE( ll->Properties );
+
+ if ( ll->Lookup )
+ {
+ count = ll->LookupCount;
+ l = ll->Lookup;
+
+ for ( n = 0; n < count; n++ )
+ Free_Lookup( &l[n], type, memory );
+
+ FREE( l );
+ }
+}
+
+
+
+/*****************************
+ * Coverage related functions
+ *****************************/
+
+
+/* CoverageFormat1 */
+
+static FT_Error Load_Coverage1( HB_CoverageFormat1* cf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* ga;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cf1->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cf1->GlyphArray = NULL;
+
+ if ( ALLOC_ARRAY( cf1->GlyphArray, count, FT_UShort ) )
+ return error;
+
+ ga = cf1->GlyphArray;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( cf1->GlyphArray );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ ga[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_Coverage1( HB_CoverageFormat1* cf1,
+ FT_Memory memory)
+{
+ FREE( cf1->GlyphArray );
+}
+
+
+/* CoverageFormat2 */
+
+static FT_Error Load_Coverage2( HB_CoverageFormat2* cf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ HB_RangeRecord* rr;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cf2->RangeCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cf2->RangeRecord = NULL;
+
+ if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) )
+ return error;
+
+ rr = cf2->RangeRecord;
+
+ if ( ACCESS_Frame( count * 6L ) )
+ goto Fail;
+
+ for ( n = 0; n < count; n++ )
+ {
+ rr[n].Start = GET_UShort();
+ rr[n].End = GET_UShort();
+ rr[n].StartCoverageIndex = GET_UShort();
+
+ /* sanity check; we are limited to 16bit integers */
+ if ( rr[n].Start > rr[n].End ||
+ ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >=
+ 0x10000L )
+ {
+ error = HB_Err_Invalid_SubTable;
+ goto Fail;
+ }
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( cf2->RangeRecord );
+ return error;
+}
+
+
+static void Free_Coverage2( HB_CoverageFormat2* cf2,
+ FT_Memory memory )
+{
+ FREE( cf2->RangeRecord );
+}
+
+
+FT_Error _HB_OPEN_Load_Coverage( HB_Coverage* c,
+ FT_Stream stream )
+{
+ FT_Error error;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ c->CoverageFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( c->CoverageFormat )
+ {
+ case 1:
+ return Load_Coverage1( &c->cf.cf1, stream );
+
+ case 2:
+ return Load_Coverage2( &c->cf.cf2, stream );
+
+ default:
+ return HB_Err_Invalid_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+void _HB_OPEN_Free_Coverage( HB_Coverage* c,
+ FT_Memory memory )
+{
+ switch ( c->CoverageFormat )
+ {
+ case 1:
+ Free_Coverage1( &c->cf.cf1, memory );
+ break;
+
+ case 2:
+ Free_Coverage2( &c->cf.cf2, memory );
+ break;
+ }
+}
+
+
+static FT_Error Coverage_Index1( HB_CoverageFormat1* cf1,
+ FT_UShort glyphID,
+ FT_UShort* index )
+{
+ FT_UShort min, max, new_min, new_max, middle;
+
+ FT_UShort* array = cf1->GlyphArray;
+
+
+ /* binary search */
+
+ if ( cf1->GlyphCount == 0 )
+ return HB_Err_Not_Covered;
+
+ new_min = 0;
+ new_max = cf1->GlyphCount - 1;
+
+ do
+ {
+ min = new_min;
+ max = new_max;
+
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
+ overflow and rounding errors */
+
+ middle = max - ( ( max - min ) >> 1 );
+
+ if ( glyphID == array[middle] )
+ {
+ *index = middle;
+ return FT_Err_Ok;
+ }
+ else if ( glyphID < array[middle] )
+ {
+ if ( middle == min )
+ break;
+ new_max = middle - 1;
+ }
+ else
+ {
+ if ( middle == max )
+ break;
+ new_min = middle + 1;
+ }
+ } while ( min < max );
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Coverage_Index2( HB_CoverageFormat2* cf2,
+ FT_UShort glyphID,
+ FT_UShort* index )
+{
+ FT_UShort min, max, new_min, new_max, middle;
+
+ HB_RangeRecord* rr = cf2->RangeRecord;
+
+
+ /* binary search */
+
+ if ( cf2->RangeCount == 0 )
+ return HB_Err_Not_Covered;
+
+ new_min = 0;
+ new_max = cf2->RangeCount - 1;
+
+ do
+ {
+ min = new_min;
+ max = new_max;
+
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
+ overflow and rounding errors */
+
+ middle = max - ( ( max - min ) >> 1 );
+
+ if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End )
+ {
+ *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start;
+ return FT_Err_Ok;
+ }
+ else if ( glyphID < rr[middle].Start )
+ {
+ if ( middle == min )
+ break;
+ new_max = middle - 1;
+ }
+ else
+ {
+ if ( middle == max )
+ break;
+ new_min = middle + 1;
+ }
+ } while ( min < max );
+
+ return HB_Err_Not_Covered;
+}
+
+
+FT_Error _HB_OPEN_Coverage_Index( HB_Coverage* c,
+ FT_UShort glyphID,
+ FT_UShort* index )
+{
+ switch ( c->CoverageFormat )
+ {
+ case 1:
+ return Coverage_Index1( &c->cf.cf1, glyphID, index );
+
+ case 2:
+ return Coverage_Index2( &c->cf.cf2, glyphID, index );
+
+ default:
+ return HB_Err_Invalid_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+
+/*************************************
+ * Class Definition related functions
+ *************************************/
+
+
+/* ClassDefFormat1 */
+
+static FT_Error Load_ClassDef1( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* cva;
+ FT_Bool* d;
+
+ HB_ClassDefFormat1* cdf1;
+
+
+ cdf1 = &cd->cd.cd1;
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ cdf1->StartGlyph = GET_UShort();
+ count = cdf1->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ /* sanity check; we are limited to 16bit integers */
+
+ if ( cdf1->StartGlyph + (long)count >= 0x10000L )
+ return HB_Err_Invalid_SubTable;
+
+ cdf1->ClassValueArray = NULL;
+
+ if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, FT_UShort ) )
+ return error;
+
+ d = cd->Defined;
+ cva = cdf1->ClassValueArray;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail;
+
+ for ( n = 0; n < count; n++ )
+ {
+ cva[n] = GET_UShort();
+ if ( cva[n] >= limit )
+ {
+ error = HB_Err_Invalid_SubTable;
+ goto Fail;
+ }
+ d[cva[n]] = TRUE;
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( cva );
+
+ return error;
+}
+
+
+static void Free_ClassDef1( HB_ClassDefFormat1* cdf1,
+ FT_Memory memory )
+{
+ FREE( cdf1->ClassValueArray );
+}
+
+
+/* ClassDefFormat2 */
+
+static FT_Error Load_ClassDef2( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ HB_ClassRangeRecord* crr;
+ FT_Bool* d;
+
+ HB_ClassDefFormat2* cdf2;
+
+
+ cdf2 = &cd->cd.cd2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cdf2->ClassRangeCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cdf2->ClassRangeRecord = NULL;
+
+ if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) )
+ return error;
+
+ d = cd->Defined;
+ crr = cdf2->ClassRangeRecord;
+
+ if ( ACCESS_Frame( count * 6L ) )
+ goto Fail;
+
+ for ( n = 0; n < count; n++ )
+ {
+ crr[n].Start = GET_UShort();
+ crr[n].End = GET_UShort();
+ crr[n].Class = GET_UShort();
+
+ /* sanity check */
+
+ if ( crr[n].Start > crr[n].End ||
+ crr[n].Class >= limit )
+ {
+ error = HB_Err_Invalid_SubTable;
+ goto Fail;
+ }
+ d[crr[n].Class] = TRUE;
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( crr );
+
+ return error;
+}
+
+
+static void Free_ClassDef2( HB_ClassDefFormat2* cdf2,
+ FT_Memory memory )
+{
+ FREE( cdf2->ClassRangeRecord );
+}
+
+
+/* ClassDefinition */
+
+FT_Error _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+
+ if ( ALLOC_ARRAY( cd->Defined, limit, FT_Bool ) )
+ return error;
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ cd->ClassFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( cd->ClassFormat )
+ {
+ case 1:
+ error = Load_ClassDef1( cd, limit, stream );
+ break;
+
+ case 2:
+ error = Load_ClassDef2( cd, limit, stream );
+ break;
+
+ default:
+ error = HB_Err_Invalid_SubTable_Format;
+ break;
+ }
+
+ if ( error )
+ goto Fail;
+
+ cd->loaded = TRUE;
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( cd->Defined );
+ return error;
+}
+
+
+FT_Error _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+
+ if ( ALLOC_ARRAY( cd->Defined, 1, FT_Bool ) )
+ return error;
+
+ cd->ClassFormat = 1; /* Meaningless */
+ cd->Defined[0] = FALSE;
+
+ if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, FT_UShort ) )
+ goto Fail;
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( cd->Defined );
+ return error;
+}
+
+void _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd,
+ FT_Memory memory )
+{
+ if ( !cd->loaded )
+ return;
+
+ FREE( cd->Defined );
+
+ switch ( cd->ClassFormat )
+ {
+ case 1:
+ Free_ClassDef1( &cd->cd.cd1, memory );
+ break;
+
+ case 2:
+ Free_ClassDef2( &cd->cd.cd2, memory );
+ break;
+ }
+}
+
+
+static FT_Error Get_Class1( HB_ClassDefFormat1* cdf1,
+ FT_UShort glyphID,
+ FT_UShort* class,
+ FT_UShort* index )
+{
+ FT_UShort* cva = cdf1->ClassValueArray;
+
+
+ if ( index )
+ *index = 0;
+
+ if ( glyphID >= cdf1->StartGlyph &&
+ glyphID < cdf1->StartGlyph + cdf1->GlyphCount )
+ {
+ *class = cva[glyphID - cdf1->StartGlyph];
+ return FT_Err_Ok;
+ }
+ else
+ {
+ *class = 0;
+ return HB_Err_Not_Covered;
+ }
+}
+
+
+/* we need the index value of the last searched class range record
+ in case of failure for constructed GDEF tables */
+
+static FT_Error Get_Class2( HB_ClassDefFormat2* cdf2,
+ FT_UShort glyphID,
+ FT_UShort* class,
+ FT_UShort* index )
+{
+ FT_Error error = FT_Err_Ok;
+ FT_UShort min, max, new_min, new_max, middle;
+
+ HB_ClassRangeRecord* crr = cdf2->ClassRangeRecord;
+
+
+ /* binary search */
+
+ if ( cdf2->ClassRangeCount == 0 )
+ {
+ *class = 0;
+ if ( index )
+ *index = 0;
+
+ return HB_Err_Not_Covered;
+ }
+
+ new_min = 0;
+ new_max = cdf2->ClassRangeCount - 1;
+
+ do
+ {
+ min = new_min;
+ max = new_max;
+
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
+ overflow and rounding errors */
+
+ middle = max - ( ( max - min ) >> 1 );
+
+ if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End )
+ {
+ *class = crr[middle].Class;
+ error = FT_Err_Ok;
+ break;
+ }
+ else if ( glyphID < crr[middle].Start )
+ {
+ if ( middle == min )
+ {
+ *class = 0;
+ error = HB_Err_Not_Covered;
+ break;
+ }
+ new_max = middle - 1;
+ }
+ else
+ {
+ if ( middle == max )
+ {
+ *class = 0;
+ error = HB_Err_Not_Covered;
+ break;
+ }
+ new_min = middle + 1;
+ }
+ } while ( min < max );
+
+ if ( index )
+ *index = middle;
+
+ return error;
+}
+
+
+FT_Error _HB_OPEN_Get_Class( HB_ClassDefinition* cd,
+ FT_UShort glyphID,
+ FT_UShort* class,
+ FT_UShort* index )
+{
+ switch ( cd->ClassFormat )
+ {
+ case 1:
+ return Get_Class1( &cd->cd.cd1, glyphID, class, index );
+
+ case 2:
+ return Get_Class2( &cd->cd.cd2, glyphID, class, index );
+
+ default:
+ return HB_Err_Invalid_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+
+/***************************
+ * Device related functions
+ ***************************/
+
+
+FT_Error _HB_OPEN_Load_Device( HB_Device* d,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* dv;
+
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ d->StartSize = GET_UShort();
+ d->EndSize = GET_UShort();
+ d->DeltaFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( d->StartSize > d->EndSize ||
+ d->DeltaFormat == 0 || d->DeltaFormat > 3 )
+ return HB_Err_Invalid_SubTable;
+
+ d->DeltaValue = NULL;
+
+ count = ( ( d->EndSize - d->StartSize + 1 ) >>
+ ( 4 - d->DeltaFormat ) ) + 1;
+
+ if ( ALLOC_ARRAY( d->DeltaValue, count, FT_UShort ) )
+ return error;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( d->DeltaValue );
+ return error;
+ }
+
+ dv = d->DeltaValue;
+
+ for ( n = 0; n < count; n++ )
+ dv[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+void _HB_OPEN_Free_Device( HB_Device* d,
+ FT_Memory memory )
+{
+ FREE( d->DeltaValue );
+}
+
+
+/* Since we have the delta values stored in compressed form, we must
+ uncompress it now. To simplify the interface, the function always
+ returns a meaningful value in `value'; the error is just for
+ information.
+ | |
+ format = 1: 0011223344556677|8899101112131415|...
+ | |
+ byte 1 byte 2
+
+ 00: (byte >> 14) & mask
+ 11: (byte >> 12) & mask
+ ...
+
+ mask = 0x0003
+ | |
+ format = 2: 0000111122223333|4444555566667777|...
+ | |
+ byte 1 byte 2
+
+ 0000: (byte >> 12) & mask
+ 1111: (byte >> 8) & mask
+ ...
+
+ mask = 0x000F
+ | |
+ format = 3: 0000000011111111|2222222233333333|...
+ | |
+ byte 1 byte 2
+
+ 00000000: (byte >> 8) & mask
+ 11111111: (byte >> 0) & mask
+ ....
+
+ mask = 0x00FF */
+
+FT_Error _HB_OPEN_Get_Device( HB_Device* d,
+ FT_UShort size,
+ FT_Short* value )
+{
+ FT_UShort byte, bits, mask, f, s;
+
+
+ f = d->DeltaFormat;
+
+ if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize )
+ {
+ s = size - d->StartSize;
+ byte = d->DeltaValue[s >> ( 4 - f )];
+ bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) );
+ mask = 0xFFFF >> ( 16 - ( 1 << f ) );
+
+ *value = (FT_Short)( bits & mask );
+
+ /* conversion to a signed value */
+
+ if ( *value >= ( ( mask + 1 ) >> 1 ) )
+ *value -= mask + 1;
+
+ return FT_Err_Ok;
+ }
+ else
+ {
+ *value = 0;
+ return HB_Err_Not_Covered;
+ }
+}
+
+
+/* END */
diff --git a/trunk/pango/opentype/harfbuzz-open.h b/trunk/pango/opentype/harfbuzz-open.h
new file mode 100644
index 00000000..17e1f29b
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz-open.h
@@ -0,0 +1,285 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_OPEN_H
+#define HARFBUZZ_OPEN_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+FT_BEGIN_HEADER
+
+/* Use this if a feature applies to all glyphs */
+#define HB_ALL_GLYPHS 0xFFFF
+
+#define HB_DEFAULT_LANGUAGE 0xFFFF
+
+#define HB_MAX_NESTING_LEVEL 100
+
+#define HB_Err_Invalid_SubTable_Format 0x1000
+#define HB_Err_Invalid_SubTable 0x1001
+#define HB_Err_Not_Covered 0x1002
+#define HB_Err_Too_Many_Nested_Contexts 0x1003
+#define HB_Err_No_MM_Interpreter 0x1004
+#define HB_Err_Empty_Script 0x1005
+
+
+/* Script list related structures */
+
+struct HB_LangSys_
+{
+ FT_UShort LookupOrderOffset; /* always 0 for TT Open 1.0 */
+ FT_UShort ReqFeatureIndex; /* required FeatureIndex */
+ FT_UShort FeatureCount; /* number of Feature indices */
+ FT_UShort* FeatureIndex; /* array of Feature indices */
+};
+
+typedef struct HB_LangSys_ HB_LangSys;
+
+
+struct HB_LangSysRecord_
+{
+ FT_ULong LangSysTag; /* LangSysTag identifier */
+ HB_LangSys LangSys; /* LangSys table */
+};
+
+typedef struct HB_LangSysRecord_ HB_LangSysRecord;
+
+
+struct HB_Script_
+{
+ HB_LangSys DefaultLangSys; /* DefaultLangSys table */
+ FT_UShort LangSysCount; /* number of LangSysRecords */
+ HB_LangSysRecord* LangSysRecord; /* array of LangSysRecords */
+};
+
+typedef struct HB_Script_ HB_Script;
+
+
+struct HB_ScriptRecord_
+{
+ FT_ULong ScriptTag; /* ScriptTag identifier */
+ HB_Script Script; /* Script table */
+};
+
+typedef struct HB_ScriptRecord_ HB_ScriptRecord;
+
+
+struct HB_ScriptList_
+{
+ FT_UShort ScriptCount; /* number of ScriptRecords */
+ HB_ScriptRecord* ScriptRecord; /* array of ScriptRecords */
+};
+
+typedef struct HB_ScriptList_ HB_ScriptList;
+
+
+/* Feature list related structures */
+
+struct HB_Feature_
+{
+ FT_UShort FeatureParams; /* always 0 for TT Open 1.0 */
+ FT_UShort LookupListCount; /* number of LookupList indices */
+ FT_UShort* LookupListIndex; /* array of LookupList indices */
+};
+
+typedef struct HB_Feature_ HB_Feature;
+
+
+struct HB_FeatureRecord_
+{
+ FT_ULong FeatureTag; /* FeatureTag identifier */
+ HB_Feature Feature; /* Feature table */
+};
+
+typedef struct HB_FeatureRecord_ HB_FeatureRecord;
+
+
+struct HB_FeatureList_
+{
+ FT_UShort FeatureCount; /* number of FeatureRecords */
+ HB_FeatureRecord* FeatureRecord; /* array of FeatureRecords */
+ FT_UShort* ApplyOrder; /* order to apply features */
+ FT_UShort ApplyCount; /* number of elements in ApplyOrder */
+};
+
+typedef struct HB_FeatureList_ HB_FeatureList;
+
+
+/* Lookup list related structures */
+
+typedef struct HB_SubTable_ HB_SubTable;
+
+
+struct HB_Lookup_
+{
+ FT_UShort LookupType; /* Lookup type */
+ FT_UShort LookupFlag; /* Lookup qualifiers */
+ FT_UShort SubTableCount; /* number of SubTables */
+ HB_SubTable* SubTable; /* array of SubTables */
+};
+
+typedef struct HB_Lookup_ HB_Lookup;
+
+
+/* The `Properties' field is not defined in the OpenType specification but
+ is needed for processing lookups. If properties[n] is > 0, the
+ functions HB_GSUB_Apply_String() resp. HB_GPOS_Apply_String() will
+ process Lookup[n] for glyphs which have the specific bit not set in
+ the `properties' field of the input string object. */
+
+struct HB_LookupList_
+{
+ FT_UShort LookupCount; /* number of Lookups */
+ HB_Lookup* Lookup; /* array of Lookup records */
+ FT_UInt* Properties; /* array of flags */
+};
+
+typedef struct HB_LookupList_ HB_LookupList;
+
+
+/* Possible LookupFlag bit masks. `HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS' comes from the
+ OpenType 1.2 specification; HB_LOOKUP_FLAG_RIGHT_TO_LEFT has been (re)introduced in
+ OpenType 1.3 -- if set, the last glyph in a cursive attachment
+ sequence has to be positioned on the baseline -- regardless of the
+ writing direction. */
+
+#define HB_LOOKUP_FLAG_RIGHT_TO_LEFT 0x0001
+#define HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS 0x0002
+#define HB_LOOKUP_FLAG_IGNORE_LIGATURES 0x0004
+#define HB_LOOKUP_FLAG_IGNORE_MARKS 0x0008
+#define HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS 0xFF00
+
+
+struct HB_CoverageFormat1_
+{
+ FT_UShort GlyphCount; /* number of glyphs in GlyphArray */
+ FT_UShort* GlyphArray; /* array of glyph IDs */
+};
+
+typedef struct HB_CoverageFormat1_ HB_CoverageFormat1;
+
+
+struct HB_RangeRecord_
+{
+ FT_UShort Start; /* first glyph ID in the range */
+ FT_UShort End; /* last glyph ID in the range */
+ FT_UShort StartCoverageIndex; /* coverage index of first
+ glyph ID in the range */
+};
+
+typedef struct HB_RangeRecord_ HB_RangeRecord;
+
+
+struct HB_CoverageFormat2_
+{
+ FT_UShort RangeCount; /* number of RangeRecords */
+ HB_RangeRecord* RangeRecord; /* array of RangeRecords */
+};
+
+typedef struct HB_CoverageFormat2_ HB_CoverageFormat2;
+
+
+struct HB_Coverage_
+{
+ FT_UShort CoverageFormat; /* 1 or 2 */
+
+ union
+ {
+ HB_CoverageFormat1 cf1;
+ HB_CoverageFormat2 cf2;
+ } cf;
+};
+
+typedef struct HB_Coverage_ HB_Coverage;
+
+
+struct HB_ClassDefFormat1_
+{
+ FT_UShort StartGlyph; /* first glyph ID of the
+ ClassValueArray */
+ FT_UShort GlyphCount; /* size of the ClassValueArray */
+ FT_UShort* ClassValueArray; /* array of class values */
+};
+
+typedef struct HB_ClassDefFormat1_ HB_ClassDefFormat1;
+
+
+struct HB_ClassRangeRecord_
+{
+ FT_UShort Start; /* first glyph ID in the range */
+ FT_UShort End; /* last glyph ID in the range */
+ FT_UShort Class; /* applied to all glyphs in range */
+};
+
+typedef struct HB_ClassRangeRecord_ HB_ClassRangeRecord;
+
+
+struct HB_ClassDefFormat2_
+{
+ FT_UShort ClassRangeCount;
+ /* number of ClassRangeRecords */
+ HB_ClassRangeRecord* ClassRangeRecord;
+ /* array of ClassRangeRecords */
+};
+
+typedef struct HB_ClassDefFormat2_ HB_ClassDefFormat2;
+
+
+/* The `Defined' field is not defined in the OpenType specification but
+ apparently needed for processing fonts like trado.ttf: This font
+ refers to a class which contains not a single element. We map such
+ classes to class 0. */
+
+struct HB_ClassDefinition_
+{
+ FT_Bool loaded;
+
+ FT_Bool* Defined; /* array of Booleans.
+ If Defined[n] is FALSE,
+ class n contains no glyphs. */
+ FT_UShort ClassFormat; /* 1 or 2 */
+
+ union
+ {
+ HB_ClassDefFormat1 cd1;
+ HB_ClassDefFormat2 cd2;
+ } cd;
+};
+
+typedef struct HB_ClassDefinition_ HB_ClassDefinition;
+
+
+struct HB_Device_
+{
+ FT_UShort StartSize; /* smallest size to correct */
+ FT_UShort EndSize; /* largest size to correct */
+ FT_UShort DeltaFormat; /* DeltaValue array data format:
+ 1, 2, or 3 */
+ FT_UShort* DeltaValue; /* array of compressed data */
+};
+
+typedef struct HB_Device_ HB_Device;
+
+
+enum HB_Type_
+{
+ HB_Type_GSUB,
+ HB_Type_GPOS
+};
+
+typedef enum HB_Type_ HB_Type;
+
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_OPEN_H */
diff --git a/trunk/pango/opentype/harfbuzz.c b/trunk/pango/opentype/harfbuzz.c
new file mode 100644
index 00000000..4fd8bf9f
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz.c
@@ -0,0 +1,19 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "ftglue.c"
+#include "harfbuzz-open.c"
+#include "harfbuzz-buffer.c"
+#include "harfbuzz-gdef.c"
+#include "harfbuzz-gsub.c"
+#include "harfbuzz-gpos.c"
+#include "harfbuzz-dump.c"
diff --git a/trunk/pango/opentype/harfbuzz.h b/trunk/pango/opentype/harfbuzz.h
new file mode 100644
index 00000000..e8e08a2a
--- /dev/null
+++ b/trunk/pango/opentype/harfbuzz.h
@@ -0,0 +1,23 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_H
+#define HARFBUZZ_H
+
+#include "harfbuzz-open.h"
+#include "harfbuzz-buffer.h"
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-gsub.h"
+#include "harfbuzz-gpos.h"
+#include "harfbuzz-dump.h"
+
+#endif /* HARFBUZZ_OPEN_H */
diff --git a/trunk/pango/opentype/makefile.msc b/trunk/pango/opentype/makefile.msc
new file mode 100644
index 00000000..29438833
--- /dev/null
+++ b/trunk/pango/opentype/makefile.msc
@@ -0,0 +1,19 @@
+TOP = ..\..\..
+!INCLUDE $(TOP)\glib\build\win32\make.msc
+
+INCLUDES = -I . -I ..\.. $(FREETYPE2_CFLAGS) $(GLIB_CFLAGS)
+DEFINES = -DPANGO_ENABLE_ENGINE
+
+OBJECTS = \
+ ftglue.obj \
+ harfbuzz-buffer.obj \
+ harfbuzz-gdef.obj \
+ harfbuzz-gpos.obj \
+ harfbuzz-gsub.obj \
+ harfbuzz-open.obj \
+
+all : \
+ pango-ot.lib
+
+pango-ot.lib : $(OBJECTS)
+ lib /out:$@ $(OBJECTS) \ No newline at end of file
diff --git a/trunk/pango/pango-attributes.c b/trunk/pango/pango-attributes.c
new file mode 100644
index 00000000..e054b14d
--- /dev/null
+++ b/trunk/pango/pango-attributes.c
@@ -0,0 +1,1986 @@
+/* Pango
+ * pango-attributes.c: Attributed text
+ *
+ * Copyright (C) 2000-2002 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "pango-attributes.h"
+#include "pango-impl-utils.h"
+
+struct _PangoAttrList
+{
+ guint ref_count;
+ GSList *attributes;
+ GSList *attributes_tail;
+};
+
+struct _PangoAttrIterator
+{
+ GSList *next_attribute;
+ GList *attribute_stack;
+ guint start_index;
+ guint end_index;
+};
+
+static PangoAttribute *pango_attr_color_new (const PangoAttrClass *klass,
+ guint16 red,
+ guint16 green,
+ guint16 blue);
+static PangoAttribute *pango_attr_string_new (const PangoAttrClass *klass,
+ const char *str);
+static PangoAttribute *pango_attr_int_new (const PangoAttrClass *klass,
+ int value);
+static PangoAttribute *pango_attr_float_new (const PangoAttrClass *klass,
+ double value);
+static PangoAttribute *pango_attr_size_new_internal (int size,
+ gboolean absolute);
+
+
+/**
+ * pango_attr_type_register:
+ * @name: an identifier for the type (currently unused.)
+ *
+ * Allocate a new attribute type ID.
+ *
+ * Return value: the new type ID.
+ **/
+PangoAttrType
+pango_attr_type_register (const gchar *name)
+{
+ static guint current_type = 0x1000000;
+
+ return current_type++;
+}
+
+/**
+ * pango_attribute_copy:
+ * @attr: a #PangoAttribute
+ *
+ * Make a copy of an attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attribute_copy (const PangoAttribute *attr)
+{
+ PangoAttribute *result;
+
+ g_return_val_if_fail (attr != NULL, NULL);
+
+ result = attr->klass->copy (attr);
+ result->start_index = attr->start_index;
+ result->end_index = attr->end_index;
+
+ return result;
+}
+
+/**
+ * pango_attribute_destroy:
+ * @attr: a #PangoAttribute.
+ *
+ * Destroy a #PangoAttribute and free all associated memory.
+ **/
+void
+pango_attribute_destroy (PangoAttribute *attr)
+{
+ g_return_if_fail (attr != NULL);
+
+ attr->klass->destroy (attr);
+}
+
+/**
+ * pango_attribute_equal:
+ * @attr1: a #PangoAttribute
+ * @attr2: another #PangoAttribute
+ *
+ * Compare two attributes for equality. This compares only the
+ * actual value of the two attributes and not the ranges that the
+ * attributes apply to.
+ *
+ * Return value: %TRUE if the two attributes have the same value.
+ **/
+gboolean
+pango_attribute_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ g_return_val_if_fail (attr1 != NULL, FALSE);
+ g_return_val_if_fail (attr2 != NULL, FALSE);
+
+ if (attr1->klass->type != attr2->klass->type)
+ return FALSE;
+
+ return attr1->klass->equal (attr1, attr2);
+}
+
+static PangoAttribute *
+pango_attr_string_copy (const PangoAttribute *attr)
+{
+ return pango_attr_string_new (attr->klass, ((PangoAttrString *)attr)->value);
+}
+
+static void
+pango_attr_string_destroy (PangoAttribute *attr)
+{
+ PangoAttrString *sattr = (PangoAttrString *)attr;
+
+ g_free (sattr->value);
+ g_slice_free (PangoAttrString, sattr);
+}
+
+static gboolean
+pango_attr_string_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ return strcmp (((PangoAttrString *)attr1)->value, ((PangoAttrString *)attr2)->value) == 0;
+}
+
+static PangoAttribute *
+pango_attr_string_new (const PangoAttrClass *klass,
+ const char *str)
+{
+ PangoAttrString *result = g_slice_new (PangoAttrString);
+
+ result->attr.klass = klass;
+ result->value = g_strdup (str);
+
+ return (PangoAttribute *)result;
+}
+
+/**
+ * pango_attr_family_new:
+ * @family: the family or comma separated list of families
+ *
+ * Create a new font family attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_family_new (const char *family)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_FAMILY,
+ pango_attr_string_copy,
+ pango_attr_string_destroy,
+ pango_attr_string_equal
+ };
+
+ g_return_val_if_fail (family != NULL, NULL);
+
+ return pango_attr_string_new (&klass, family);
+}
+
+static PangoAttribute *
+pango_attr_language_copy (const PangoAttribute *attr)
+{
+ return pango_attr_language_new (((PangoAttrLanguage *)attr)->value);
+}
+
+static void
+pango_attr_language_destroy (PangoAttribute *attr)
+{
+ PangoAttrLanguage *lattr = (PangoAttrLanguage *)attr;
+
+ g_slice_free (PangoAttrLanguage, lattr);
+}
+
+static gboolean
+pango_attr_language_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ return ((PangoAttrLanguage *)attr1)->value == ((PangoAttrLanguage *)attr2)->value;
+}
+
+/**
+ * pango_attr_language_new:
+ * @language: language tag
+ *
+ * Create a new language tag attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_language_new (PangoLanguage *language)
+{
+ PangoAttrLanguage *result;
+
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_LANGUAGE,
+ pango_attr_language_copy,
+ pango_attr_language_destroy,
+ pango_attr_language_equal
+ };
+
+ g_return_val_if_fail (language != NULL, NULL);
+
+ result = g_slice_new (PangoAttrLanguage);
+
+ result->attr.klass = &klass;
+ result->value = language;
+
+ return (PangoAttribute *)result;
+}
+
+static PangoAttribute *
+pango_attr_color_copy (const PangoAttribute *attr)
+{
+ const PangoAttrColor *color_attr = (PangoAttrColor *)attr;
+
+ return pango_attr_color_new (attr->klass,
+ color_attr->color.red,
+ color_attr->color.green,
+ color_attr->color.blue);
+}
+
+static void
+pango_attr_color_destroy (PangoAttribute *attr)
+{
+ PangoAttrColor *cattr = (PangoAttrColor *)attr;
+
+ g_slice_free (PangoAttrColor, cattr);
+}
+
+static gboolean
+pango_attr_color_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ const PangoAttrColor *color_attr1 = (const PangoAttrColor *)attr1;
+ const PangoAttrColor *color_attr2 = (const PangoAttrColor *)attr2;
+
+ return (color_attr1->color.red == color_attr2->color.red &&
+ color_attr1->color.blue == color_attr2->color.blue &&
+ color_attr1->color.green == color_attr2->color.green);
+}
+
+static PangoAttribute *
+pango_attr_color_new (const PangoAttrClass *klass,
+ guint16 red,
+ guint16 green,
+ guint16 blue)
+{
+ PangoAttrColor *result = g_slice_new (PangoAttrColor);
+ result->attr.klass = klass;
+ result->color.red = red;
+ result->color.green = green;
+ result->color.blue = blue;
+
+ return (PangoAttribute *)result;
+}
+
+/**
+ * pango_attr_foreground_new:
+ * @red: the red value (ranging from 0 to 65535)
+ * @green: the green value
+ * @blue: the blue value
+ *
+ * Create a new foreground color attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_foreground_new (guint16 red,
+ guint16 green,
+ guint16 blue)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_FOREGROUND,
+ pango_attr_color_copy,
+ pango_attr_color_destroy,
+ pango_attr_color_equal
+ };
+
+ return pango_attr_color_new (&klass, red, green, blue);
+}
+
+/**
+ * pango_attr_background_new:
+ * @red: the red value (ranging from 0 to 65535)
+ * @green: the green value
+ * @blue: the blue value
+ *
+ * Create a new background color attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_background_new (guint16 red,
+ guint16 green,
+ guint16 blue)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_BACKGROUND,
+ pango_attr_color_copy,
+ pango_attr_color_destroy,
+ pango_attr_color_equal
+ };
+
+ return pango_attr_color_new (&klass, red, green, blue);
+}
+
+static PangoAttribute *
+pango_attr_int_copy (const PangoAttribute *attr)
+{
+ const PangoAttrInt *int_attr = (PangoAttrInt *)attr;
+
+ return pango_attr_int_new (attr->klass, int_attr->value);
+}
+
+static void
+pango_attr_int_destroy (PangoAttribute *attr)
+{
+ PangoAttrInt *iattr = (PangoAttrInt *)attr;
+
+ g_slice_free (PangoAttrInt, iattr);
+}
+
+static gboolean
+pango_attr_int_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ const PangoAttrInt *int_attr1 = (const PangoAttrInt *)attr1;
+ const PangoAttrInt *int_attr2 = (const PangoAttrInt *)attr2;
+
+ return (int_attr1->value == int_attr2->value);
+}
+
+static PangoAttribute *
+pango_attr_int_new (const PangoAttrClass *klass,
+ int value)
+{
+ PangoAttrInt *result = g_slice_new (PangoAttrInt);
+ result->attr.klass = klass;
+ result->value = value;
+
+ return (PangoAttribute *)result;
+}
+
+static PangoAttribute *
+pango_attr_float_copy (const PangoAttribute *attr)
+{
+ const PangoAttrFloat *float_attr = (PangoAttrFloat *)attr;
+
+ return pango_attr_float_new (attr->klass, float_attr->value);
+}
+
+static void
+pango_attr_float_destroy (PangoAttribute *attr)
+{
+ PangoAttrFloat *fattr = (PangoAttrFloat *)attr;
+
+ g_slice_free (PangoAttrFloat, fattr);
+}
+
+static gboolean
+pango_attr_float_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ const PangoAttrFloat *float_attr1 = (const PangoAttrFloat *)attr1;
+ const PangoAttrFloat *float_attr2 = (const PangoAttrFloat *)attr2;
+
+ return (float_attr1->value == float_attr2->value);
+}
+
+static PangoAttribute*
+pango_attr_float_new (const PangoAttrClass *klass,
+ double value)
+{
+ PangoAttrFloat *result = g_slice_new (PangoAttrFloat);
+ result->attr.klass = klass;
+ result->value = value;
+
+ return (PangoAttribute *)result;
+}
+
+static PangoAttribute *
+pango_attr_size_copy (const PangoAttribute *attr)
+{
+ const PangoAttrSize *size_attr = (PangoAttrSize *)attr;
+
+ if (attr->klass->type == PANGO_ATTR_ABSOLUTE_SIZE)
+ return pango_attr_size_new_absolute (size_attr->size);
+ else
+ return pango_attr_size_new (size_attr->size);
+}
+
+static void
+pango_attr_size_destroy (PangoAttribute *attr)
+{
+ PangoAttrSize *sattr = (PangoAttrSize *)attr;
+
+ g_slice_free (PangoAttrSize, sattr);
+}
+
+static gboolean
+pango_attr_size_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ const PangoAttrSize *size_attr1 = (const PangoAttrSize *)attr1;
+ const PangoAttrSize *size_attr2 = (const PangoAttrSize *)attr2;
+
+ return size_attr1->size == size_attr2->size;
+}
+
+static PangoAttribute *
+pango_attr_size_new_internal (int size,
+ gboolean absolute)
+{
+ PangoAttrSize *result;
+
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_SIZE,
+ pango_attr_size_copy,
+ pango_attr_size_destroy,
+ pango_attr_size_equal
+ };
+ static const PangoAttrClass absolute_klass = {
+ PANGO_ATTR_ABSOLUTE_SIZE,
+ pango_attr_size_copy,
+ pango_attr_size_destroy,
+ pango_attr_size_equal
+ };
+
+ result = g_slice_new (PangoAttrSize);
+ result->attr.klass = absolute ? &absolute_klass : &klass;
+ result->size = size;
+ result->absolute = absolute;
+
+ return (PangoAttribute *)result;
+}
+
+/**
+ * pango_attr_size_new:
+ * @size: the font size, in %PANGO_SCALE<!-- -->ths of a point.
+ *
+ * Create a new font-size attribute in fractional points.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_size_new (int size)
+{
+ return pango_attr_size_new_internal (size, FALSE);
+}
+
+/**
+ * pango_attr_size_new_absolute:
+ * @size: the font size, in %PANGO_SCALE<!-- -->ths of a device unit.
+ *
+ * Create a new font-size attribute in device units.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.8
+ **/
+PangoAttribute *
+pango_attr_size_new_absolute (int size)
+{
+ return pango_attr_size_new_internal (size, TRUE);
+}
+
+/**
+ * pango_attr_style_new:
+ * @style: the slant style
+ *
+ * Create a new font slant style attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_style_new (PangoStyle style)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_STYLE,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)style);
+}
+
+/**
+ * pango_attr_weight_new:
+ * @weight: the weight
+ *
+ * Create a new font weight attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_weight_new (PangoWeight weight)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_WEIGHT,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)weight);
+}
+
+/**
+ * pango_attr_variant_new:
+ * @variant: the variant
+ *
+ * Create a new font variant attribute (normal or small caps)
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_variant_new (PangoVariant variant)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_VARIANT,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)variant);
+}
+
+/**
+ * pango_attr_stretch_new:
+ * @stretch: the stretch
+ *
+ * Create a new font stretch attribute
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_stretch_new (PangoStretch stretch)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_STRETCH,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)stretch);
+}
+
+static PangoAttribute *
+pango_attr_font_desc_copy (const PangoAttribute *attr)
+{
+ const PangoAttrFontDesc *desc_attr = (const PangoAttrFontDesc *)attr;
+
+ return pango_attr_font_desc_new (desc_attr->desc);
+}
+
+static void
+pango_attr_font_desc_destroy (PangoAttribute *attr)
+{
+ PangoAttrFontDesc *desc_attr = (PangoAttrFontDesc *)attr;
+
+ pango_font_description_free (desc_attr->desc);
+ g_slice_free (PangoAttrFontDesc, desc_attr);
+}
+
+static gboolean
+pango_attr_font_desc_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ const PangoAttrFontDesc *desc_attr1 = (const PangoAttrFontDesc *)attr1;
+ const PangoAttrFontDesc *desc_attr2 = (const PangoAttrFontDesc *)attr2;
+
+ return pango_font_description_get_set_fields (desc_attr1->desc) ==
+ pango_font_description_get_set_fields (desc_attr2->desc) &&
+ pango_font_description_equal (desc_attr1->desc, desc_attr2->desc);
+}
+
+/**
+ * pango_attr_font_desc_new:
+ * @desc: the font description
+ *
+ * Create a new font description attribute. This attribute
+ * allows setting family, style, weight, variant, stretch,
+ * and size simultaneously.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_font_desc_new (const PangoFontDescription *desc)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_FONT_DESC,
+ pango_attr_font_desc_copy,
+ pango_attr_font_desc_destroy,
+ pango_attr_font_desc_equal
+ };
+
+ PangoAttrFontDesc *result = g_slice_new (PangoAttrFontDesc);
+ result->attr.klass = &klass;
+ result->desc = pango_font_description_copy (desc);
+
+ return (PangoAttribute *)result;
+}
+
+
+/**
+ * pango_attr_underline_new:
+ * @underline: the underline style.
+ *
+ * Create a new underline-style attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_underline_new (PangoUnderline underline)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_UNDERLINE,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)underline);
+}
+
+/**
+ * pango_attr_underline_color_new:
+ * @red: the red value (ranging from 0 to 65535)
+ * @green: the green value
+ * @blue: the blue value
+ *
+ * Create a new underline color attribute. This attribute
+ * modifies the color of underlines. If not set, underlines
+ * will use the foreground color.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.8
+ **/
+PangoAttribute *
+pango_attr_underline_color_new (guint16 red,
+ guint16 green,
+ guint16 blue)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_UNDERLINE_COLOR,
+ pango_attr_color_copy,
+ pango_attr_color_destroy,
+ pango_attr_color_equal
+ };
+
+ return pango_attr_color_new (&klass, red, green, blue);
+}
+
+/**
+ * pango_attr_strikethrough_new:
+ * @strikethrough: %TRUE if the text should be struck-through.
+ *
+ * Create a new strike-through attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_strikethrough_new (gboolean strikethrough)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_STRIKETHROUGH,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)strikethrough);
+}
+
+/**
+ * pango_attr_strikethrough_color_new:
+ * @red: the red value (ranging from 0 to 65535)
+ * @green: the green value
+ * @blue: the blue value
+ *
+ * Create a new strikethrough color attribute. This attribute
+ * modifies the color of strikethrough lines. If not set, strikethrough
+ * lines will use the foreground color.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.8
+ **/
+PangoAttribute *
+pango_attr_strikethrough_color_new (guint16 red,
+ guint16 green,
+ guint16 blue)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_STRIKETHROUGH_COLOR,
+ pango_attr_color_copy,
+ pango_attr_color_destroy,
+ pango_attr_color_equal
+ };
+
+ return pango_attr_color_new (&klass, red, green, blue);
+}
+
+/**
+ * pango_attr_rise_new:
+ * @rise: the amount that the text should be displaced vertically,
+ * in Pango units. Positive values displace the text upwards.
+ *
+ * Create a new baseline displacement attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_rise_new (int rise)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_RISE,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)rise);
+}
+
+/**
+ * pango_attr_scale_new:
+ * @scale_factor: factor to scale the font
+ *
+ * Create a new font size scale attribute. The base font for the
+ * affected text will have its size multiplied by @scale_factor.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute*
+pango_attr_scale_new (double scale_factor)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_SCALE,
+ pango_attr_float_copy,
+ pango_attr_float_destroy,
+ pango_attr_float_equal
+ };
+
+ return pango_attr_float_new (&klass, scale_factor);
+}
+
+/**
+ * pango_attr_fallback_new:
+ * @enable_fallback: %TRUE if we should fall back on other fonts
+ * for characters the active font is missing.
+ *
+ * Create a new font fallback attribute.
+ *
+ * If fallback is disabled, characters will only be used from the
+ * closest matching font on the system. No fallback will be done to
+ * other fonts on the system that might contain the characters in the
+ * text.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.4
+ **/
+PangoAttribute *
+pango_attr_fallback_new (gboolean enable_fallback)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_FALLBACK,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal,
+ };
+
+ return pango_attr_int_new (&klass, (int)enable_fallback);
+}
+
+/**
+ * pango_attr_letter_spacing_new:
+ * @letter_spacing: amount of extra space to add between graphemes
+ * of the text, in Pango units.
+ *
+ * Create a new letter-spacing attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.6
+ **/
+PangoAttribute *
+pango_attr_letter_spacing_new (int letter_spacing)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_LETTER_SPACING,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, letter_spacing);
+}
+
+static PangoAttribute *
+pango_attr_shape_copy (const PangoAttribute *attr)
+{
+ const PangoAttrShape *shape_attr = (PangoAttrShape *)attr;
+ gpointer data;
+
+ if (shape_attr->copy_func)
+ data = shape_attr->copy_func (shape_attr->data);
+ else
+ data = shape_attr->data;
+
+ return pango_attr_shape_new_with_data (&shape_attr->ink_rect, &shape_attr->logical_rect,
+ data, shape_attr->copy_func, shape_attr->destroy_func);
+}
+
+static void
+pango_attr_shape_destroy (PangoAttribute *attr)
+{
+ PangoAttrShape *shape_attr = (PangoAttrShape *)attr;
+
+ if (shape_attr->destroy_func)
+ shape_attr->destroy_func (shape_attr->data);
+
+ g_slice_free (PangoAttrShape, shape_attr);
+}
+
+static gboolean
+pango_attr_shape_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ const PangoAttrShape *shape_attr1 = (const PangoAttrShape *)attr1;
+ const PangoAttrShape *shape_attr2 = (const PangoAttrShape *)attr2;
+
+ return (shape_attr1->logical_rect.x == shape_attr2->logical_rect.x &&
+ shape_attr1->logical_rect.y == shape_attr2->logical_rect.y &&
+ shape_attr1->logical_rect.width == shape_attr2->logical_rect.width &&
+ shape_attr1->logical_rect.height == shape_attr2->logical_rect.height &&
+ shape_attr1->ink_rect.x == shape_attr2->ink_rect.x &&
+ shape_attr1->ink_rect.y == shape_attr2->ink_rect.y &&
+ shape_attr1->ink_rect.width == shape_attr2->ink_rect.width &&
+ shape_attr1->ink_rect.height == shape_attr2->ink_rect.height &&
+ shape_attr1->data == shape_attr2->data);
+}
+
+/**
+ * pango_attr_shape_new_with_data:
+ * @ink_rect: ink rectangle to assign to each character
+ * @logical_rect: logical rectangle to assign to each character
+ * @data: user data pointer
+ * @copy_func: function to copy @data when the attribute
+ * is copied. If %NULL, @data is simply copied
+ * as a pointer.
+ * @destroy_func: function to free @data when the attribute
+ * is freed, or %NULL
+ *
+ * Like pango_attr_shape_new(), but a user data pointer is also
+ * provided; this pointer can be accessed when later
+ * rendering the glyph.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.8
+ **/
+PangoAttribute *
+pango_attr_shape_new_with_data (const PangoRectangle *ink_rect,
+ const PangoRectangle *logical_rect,
+ gpointer data,
+ PangoAttrDataCopyFunc copy_func,
+ GDestroyNotify destroy_func)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_SHAPE,
+ pango_attr_shape_copy,
+ pango_attr_shape_destroy,
+ pango_attr_shape_equal
+ };
+
+ PangoAttrShape *result;
+
+ g_return_val_if_fail (ink_rect != NULL, NULL);
+ g_return_val_if_fail (logical_rect != NULL, NULL);
+
+ result = g_slice_new (PangoAttrShape);
+ result->attr.klass = &klass;
+ result->ink_rect = *ink_rect;
+ result->logical_rect = *logical_rect;
+ result->data = data;
+ result->copy_func = copy_func;
+ result->destroy_func = destroy_func;
+
+ return (PangoAttribute *)result;
+}
+
+/**
+ * pango_attr_shape_new:
+ * @ink_rect: ink rectangle to assign to each character
+ * @logical_rect: logical rectangle to assign to each character
+ *
+ * Create a new shape attribute. A shape is used to impose a
+ * particular ink and logical rectangle on the result of shaping a
+ * particular glyph. This might be used, for instance, for
+ * embedding a picture or a widget inside a #PangoLayout.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ **/
+PangoAttribute *
+pango_attr_shape_new (const PangoRectangle *ink_rect,
+ const PangoRectangle *logical_rect)
+{
+ g_return_val_if_fail (ink_rect != NULL, NULL);
+ g_return_val_if_fail (logical_rect != NULL, NULL);
+
+ return pango_attr_shape_new_with_data (ink_rect, logical_rect,
+ NULL, NULL, NULL);
+}
+
+/**
+ * pango_attr_gravity_new:
+ * @gravity: the gravity value; should not be %PANGO_GRAVITY_AUTO.
+ *
+ * Create a new gravity attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.16
+ **/
+PangoAttribute *
+pango_attr_gravity_new (PangoGravity gravity)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_GRAVITY,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ g_return_val_if_fail (gravity != PANGO_GRAVITY_AUTO, NULL);
+
+ return pango_attr_int_new (&klass, (int)gravity);
+}
+
+/**
+ * pango_attr_gravity_hint_new:
+ * @hint: the gravity hint value.
+ *
+ * Create a new gravity hint attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.16
+ **/
+PangoAttribute *
+pango_attr_gravity_hint_new (PangoGravityHint hint)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_GRAVITY_HINT,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)hint);
+}
+
+
+/*
+ * Attribute List
+ */
+
+GType
+pango_attr_list_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoAttrList"),
+ (GBoxedCopyFunc) pango_attr_list_copy,
+ (GBoxedFreeFunc) pango_attr_list_unref);
+
+ return our_type;
+}
+
+/**
+ * pango_attr_list_new:
+ *
+ * Create a new empty attribute list with a reference count of one.
+ *
+ * Return value: the newly allocated #PangoAttrList, which should
+ * be freed with pango_attr_list_unref().
+ **/
+PangoAttrList *
+pango_attr_list_new (void)
+{
+ PangoAttrList *list = g_slice_new (PangoAttrList);
+
+ list->ref_count = 1;
+ list->attributes = NULL;
+ list->attributes_tail = NULL;
+
+ return list;
+}
+
+/**
+ * pango_attr_list_ref:
+ * @list: a #PangoAttrList
+ *
+ * Increase the reference count of the given attribute list by one.
+ *
+ * Return value: The attribute list passed in
+ *
+ * Since: 1.10
+ **/
+PangoAttrList *
+pango_attr_list_ref (PangoAttrList *list)
+{
+ g_return_val_if_fail (list != NULL, NULL);
+
+ list->ref_count++;
+
+ return list;
+}
+
+/**
+ * pango_attr_list_unref:
+ * @list: a #PangoAttrList
+ *
+ * Decrease the reference count of the given attribute list by one.
+ * If the result is zero, free the attribute list and the attributes
+ * it contains.
+ **/
+void
+pango_attr_list_unref (PangoAttrList *list)
+{
+ GSList *tmp_list;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (list->ref_count > 0);
+
+ list->ref_count--;
+ if (list->ref_count == 0)
+ {
+ tmp_list = list->attributes;
+ while (tmp_list)
+ {
+ PangoAttribute *attr = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ attr->klass->destroy (attr);
+ }
+
+ g_slist_free (list->attributes);
+
+ g_slice_free (PangoAttrList, list);
+ }
+}
+
+/**
+ * pango_attr_list_copy:
+ * @list: a #PangoAttrList
+ *
+ * Copy @list and return an identical new list.
+ *
+ * Return value: the newly allocated #PangoAttrList, with a
+ * reference count of one, which should
+ * be freed with pango_attr_list_unref().
+ **/
+PangoAttrList *
+pango_attr_list_copy (PangoAttrList *list)
+{
+ PangoAttrList *new;
+ GSList *iter;
+ GSList *new_attrs;
+
+ g_return_val_if_fail (list != NULL, NULL);
+
+ new = pango_attr_list_new ();
+
+ iter = list->attributes;
+ new_attrs = NULL;
+ while (iter != NULL)
+ {
+ new_attrs = g_slist_prepend (new_attrs,
+ pango_attribute_copy (iter->data));
+
+ iter = g_slist_next (iter);
+ }
+
+ /* we're going to reverse the nodes, so head becomes tail */
+ new->attributes_tail = new_attrs;
+ new->attributes = g_slist_reverse (new_attrs);
+
+ return new;
+}
+
+static void
+pango_attr_list_insert_internal (PangoAttrList *list,
+ PangoAttribute *attr,
+ gboolean before)
+{
+ GSList *tmp_list, *prev, *link;
+ guint start_index = attr->start_index;
+
+ if (!list->attributes)
+ {
+ list->attributes = g_slist_prepend (NULL, attr);
+ list->attributes_tail = list->attributes;
+ }
+ else if (((PangoAttribute *)list->attributes_tail->data)->start_index < start_index ||
+ (!before && ((PangoAttribute *)list->attributes_tail->data)->start_index == start_index))
+ {
+ g_slist_append (list->attributes_tail, attr);
+ list->attributes_tail = list->attributes_tail->next;
+ g_assert (list->attributes_tail);
+ }
+ else
+ {
+ prev = NULL;
+ tmp_list = list->attributes;
+ while (1)
+ {
+ PangoAttribute *tmp_attr = tmp_list->data;
+
+ if (tmp_attr->start_index > start_index ||
+ (before && tmp_attr->start_index == start_index))
+ {
+ link = g_slist_alloc ();
+ link->next = tmp_list;
+ link->data = attr;
+
+ if (prev)
+ prev->next = link;
+ else
+ list->attributes = link;
+
+ if (!tmp_list)
+ list->attributes_tail = link;
+
+ break;
+ }
+
+ prev = tmp_list;
+ tmp_list = tmp_list->next;
+ }
+ }
+}
+
+/**
+ * pango_attr_list_insert:
+ * @list: a #PangoAttrList
+ * @attr: the attribute to insert. Ownership of this value is
+ * assumed by the list.
+ *
+ * Insert the given attribute into the #PangoAttrList. It will
+ * be inserted after all other attributes with a matching
+ * @start_index.
+ **/
+void
+pango_attr_list_insert (PangoAttrList *list,
+ PangoAttribute *attr)
+{
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (attr != NULL);
+
+ pango_attr_list_insert_internal (list, attr, FALSE);
+}
+
+/**
+ * pango_attr_list_insert_before:
+ * @list: a #PangoAttrList
+ * @attr: the attribute to insert. Ownership of this value is
+ * assumed by the list.
+ *
+ * Insert the given attribute into the #PangoAttrList. It will
+ * be inserted before all other attributes with a matching
+ * @start_index.
+ **/
+void
+pango_attr_list_insert_before (PangoAttrList *list,
+ PangoAttribute *attr)
+{
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (attr != NULL);
+
+ pango_attr_list_insert_internal (list, attr, TRUE);
+}
+
+/**
+ * pango_attr_list_change:
+ * @list: a #PangoAttrList
+ * @attr: the attribute to insert. Ownership of this value is
+ * assumed by the list.
+ *
+ * Insert the given attribute into the #PangoAttrList. It will
+ * replace any attributes of the same type on that segment
+ * and be merged with any adjoining attributes that are identical.
+ *
+ * This function is slower than pango_attr_list_insert() for
+ * creating a attribute list in order (potentially much slower
+ * for large lists). However, pango_attr_list_insert() is not
+ * suitable for continually changing a set of attributes
+ * since it never removes or combines existing attributes.
+ **/
+void
+pango_attr_list_change (PangoAttrList *list,
+ PangoAttribute *attr)
+{
+ GSList *tmp_list, *prev, *link;
+ guint start_index = attr->start_index;
+ guint end_index = attr->end_index;
+
+ g_return_if_fail (list != NULL);
+
+ if (start_index == end_index) /* empty, nothing to do */
+ {
+ pango_attribute_destroy (attr);
+ return;
+ }
+
+ tmp_list = list->attributes;
+ prev = NULL;
+ while (1)
+ {
+ PangoAttribute *tmp_attr;
+
+ if (!tmp_list ||
+ ((PangoAttribute *)tmp_list->data)->start_index > start_index)
+ {
+ /* We need to insert a new attribute
+ */
+ link = g_slist_alloc ();
+ link->next = tmp_list;
+ link->data = attr;
+
+ if (prev)
+ prev->next = link;
+ else
+ list->attributes = link;
+
+ if (!tmp_list)
+ list->attributes_tail = link;
+
+ prev = link;
+ tmp_list = prev->next;
+ break;
+ }
+
+ tmp_attr = tmp_list->data;
+
+ if (tmp_attr->klass->type == attr->klass->type &&
+ tmp_attr->end_index >= start_index)
+ {
+ /* We overlap with an existing attribute */
+ if (pango_attribute_equal (tmp_attr, attr))
+ {
+ /* We can merge the new attribute with this attribute
+ */
+ if (tmp_attr->end_index >= end_index)
+ {
+ /* We are totally overlapping the previous attribute.
+ * No action is needed.
+ */
+ pango_attribute_destroy (attr);
+ return;
+ }
+ tmp_attr->end_index = end_index;
+ pango_attribute_destroy (attr);
+
+ attr = tmp_attr;
+
+ prev = tmp_list;
+ tmp_list = tmp_list->next;
+
+ break;
+ }
+ else
+ {
+ /* Split, truncate, or remove the old attribute
+ */
+ if (tmp_attr->end_index > attr->end_index)
+ {
+ PangoAttribute *end_attr = pango_attribute_copy (tmp_attr);
+
+ end_attr->start_index = attr->end_index;
+ pango_attr_list_insert (list, end_attr);
+ }
+
+ if (tmp_attr->start_index == attr->start_index)
+ {
+ pango_attribute_destroy (tmp_attr);
+ tmp_list->data = attr;
+
+ prev = tmp_list;
+ tmp_list = tmp_list->next;
+ break;
+ }
+ else
+ {
+ tmp_attr->end_index = attr->start_index;
+ }
+ }
+ }
+ prev = tmp_list;
+ tmp_list = tmp_list->next;
+ }
+ /* At this point, prev points to the list node with attr in it,
+ * tmp_list points to prev->next.
+ */
+
+ g_assert (prev->data == attr);
+ g_assert (prev->next == tmp_list);
+
+ /* We now have the range inserted into the list one way or the
+ * other. Fix up the remainder
+ */
+ while (tmp_list)
+ {
+ PangoAttribute *tmp_attr = tmp_list->data;
+
+ if (tmp_attr->start_index > end_index)
+ break;
+ else if (tmp_attr->klass->type == attr->klass->type)
+ {
+ if (tmp_attr->end_index <= attr->end_index ||
+ pango_attribute_equal (tmp_attr, attr))
+ {
+ /* We can merge the new attribute with this attribute.
+ */
+ attr->end_index = MAX (end_index, tmp_attr->end_index);
+
+ pango_attribute_destroy (tmp_attr);
+ prev->next = tmp_list->next;
+
+ if (!prev->next)
+ list->attributes_tail = prev;
+
+ g_slist_free_1 (tmp_list);
+ tmp_list = prev->next;
+
+ continue;
+ }
+ else
+ {
+ /* Trim the start of this attribute that it begins at the end
+ * of the new attribute. This may involve moving
+ * it in the list to maintain the required non-decreasing
+ * order of start indices
+ */
+ GSList *tmp_list2;
+ GSList *prev2;
+
+ tmp_attr->start_index = attr->end_index;
+
+ tmp_list2 = tmp_list->next;
+ prev2 = tmp_list;
+
+ while (tmp_list2)
+ {
+ PangoAttribute *tmp_attr2 = tmp_list2->data;
+
+ if (tmp_attr2->start_index >= tmp_attr->start_index)
+ break;
+
+ prev2 = tmp_list2;
+ tmp_list2 = tmp_list2->next;
+ }
+
+ /* Now remove and insert before tmp_list2. We'll
+ * hit this attribute again later, but that's harmless.
+ */
+ if (prev2 != tmp_list)
+ {
+ GSList *old_next = tmp_list->next;
+
+ prev->next = old_next;
+ prev2->next = tmp_list;
+ tmp_list->next = tmp_list2;
+
+ if (!tmp_list->next)
+ list->attributes_tail = tmp_list;
+
+ tmp_list = old_next;
+
+ continue;
+ }
+ }
+ }
+
+ prev = tmp_list;
+ tmp_list = tmp_list->next;
+ }
+}
+
+/**
+ * pango_attr_list_splice:
+ * @list: a #PangoAttrList
+ * @other: another #PangoAttrList
+ * @pos: the position in @list at which to insert @other
+ * @len: the length of the spliced segment. (Note that this
+ * must be specified since the attributes in @other
+ * may only be present at some subsection of this range)
+ *
+ * This function opens up a hole in @list, fills it in with attributes from
+ * the left, and then merges @other on top of the hole.
+ *
+ * This operation is equivalent to stretching every attribute
+ * that applies at position @pos in @list by an amount @len,
+ * and then calling pango_attr_list_change() with a copy
+ * of each attribute in @other in sequence (offset in position by @pos).
+ *
+ * This operation proves useful for, for instance, inserting
+ * a pre-edit string in the middle of an edit buffer.
+ **/
+void
+pango_attr_list_splice (PangoAttrList *list,
+ PangoAttrList *other,
+ gint pos,
+ gint len)
+{
+ GSList *tmp_list;
+ guint upos, ulen;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (other != NULL);
+ g_return_if_fail (pos >= 0);
+ g_return_if_fail (len >= 0);
+
+ upos = (guint)pos;
+ ulen = (guint)len;
+
+/* This definition only works when a and b are unsigned; overflow
+ * isn't defined in the C standard for signed integers
+ */
+#define CLAMP_ADD(a,b) (((a) + (b) < (a)) ? G_MAXUINT : (a) + (b))
+
+ tmp_list = list->attributes;
+ while (tmp_list)
+ {
+ PangoAttribute *attr = tmp_list->data;
+
+ if (attr->start_index <= upos)
+ {
+ if (attr->end_index > upos)
+ attr->end_index = CLAMP_ADD (attr->end_index, ulen);
+ }
+ else
+ {
+ /* This could result in a zero length attribute if it
+ * gets squashed up against G_MAXUINT, but deleting such
+ * an element could (in theory) suprise the caller, so
+ * we don't delete it.
+ */
+ attr->start_index = CLAMP_ADD (attr->start_index, ulen);
+ attr->end_index = CLAMP_ADD (attr->end_index, ulen);
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ tmp_list = other->attributes;
+ while (tmp_list)
+ {
+ PangoAttribute *attr = pango_attribute_copy (tmp_list->data);
+ attr->start_index = CLAMP_ADD (attr->start_index, upos);
+ attr->end_index = CLAMP_ADD (attr->end_index, upos);
+
+ /* Same as above, the attribute could be squashed to zero-length; here
+ * pango_attr_list_change() will take care of deleting it.
+ */
+ pango_attr_list_change (list, attr);
+
+ tmp_list = tmp_list->next;
+ }
+#undef CLAMP_ADD
+}
+
+/**
+ * pango_attr_list_get_iterator:
+ * @list: a #PangoAttrList
+ *
+ * Create a iterator initialized to the beginning of the list.
+ * @list must not be modified until this iterator is freed.
+ *
+ * Return value: the newly allocated #PangoAttrIterator, which should
+ * be freed with pango_attr_iterator_destroy().
+ **/
+PangoAttrIterator *
+pango_attr_list_get_iterator (PangoAttrList *list)
+{
+ PangoAttrIterator *iterator;
+
+ g_return_val_if_fail (list != NULL, NULL);
+
+ iterator = g_slice_new (PangoAttrIterator);
+ iterator->next_attribute = list->attributes;
+ iterator->attribute_stack = NULL;
+
+ iterator->start_index = 0;
+ iterator->end_index = 0;
+
+ if (!pango_attr_iterator_next (iterator))
+ iterator->end_index = G_MAXUINT;
+
+ return iterator;
+}
+
+/**
+ * pango_attr_iterator_range:
+ * @iterator: a #PangoAttrIterator
+ * @start: location to store the start of the range
+ * @end: location to store the end of the range
+ *
+ * Get the range of the current segment. Note that the
+ * stored return values are signed, not unsigned like
+ * the values in #PangoAttribute. To deal with this API
+ * oversight, stored return values that wouldn't fit into
+ * a signed integer are clamped to %G_MAXINT.
+ **/
+void
+pango_attr_iterator_range (PangoAttrIterator *iterator,
+ gint *start,
+ gint *end)
+{
+ g_return_if_fail (iterator != NULL);
+
+ if (start)
+ *start = MIN (iterator->start_index, G_MAXINT);
+ if (end)
+ *end = MIN (iterator->end_index, G_MAXINT);
+}
+
+/**
+ * pango_attr_iterator_next:
+ * @iterator: a #PangoAttrIterator
+ *
+ * Advance the iterator until the next change of style.
+ *
+ * Return value: %FALSE if the iterator is at the end of the list, otherwise %TRUE
+ **/
+gboolean
+pango_attr_iterator_next (PangoAttrIterator *iterator)
+{
+ GList *tmp_list;
+
+ g_return_val_if_fail (iterator != NULL, FALSE);
+
+ if (!iterator->next_attribute && !iterator->attribute_stack)
+ return FALSE;
+
+ iterator->start_index = iterator->end_index;
+ iterator->end_index = G_MAXUINT;
+
+ tmp_list = iterator->attribute_stack;
+ while (tmp_list)
+ {
+ GList *next = tmp_list->next;
+ PangoAttribute *attr = tmp_list->data;
+
+ if (attr->end_index == iterator->start_index)
+ {
+ iterator->attribute_stack = g_list_remove_link (iterator->attribute_stack, tmp_list);
+ g_list_free_1 (tmp_list);
+ }
+ else
+ {
+ iterator->end_index = MIN (iterator->end_index, attr->end_index);
+ }
+
+ tmp_list = next;
+ }
+
+ while (iterator->next_attribute &&
+ ((PangoAttribute *)iterator->next_attribute->data)->start_index == iterator->start_index)
+ {
+ if (((PangoAttribute *)iterator->next_attribute->data)->end_index > iterator->start_index)
+ {
+ iterator->attribute_stack = g_list_prepend (iterator->attribute_stack, iterator->next_attribute->data);
+ iterator->end_index = MIN (iterator->end_index, ((PangoAttribute *)iterator->next_attribute->data)->end_index);
+ }
+ iterator->next_attribute = iterator->next_attribute->next;
+ }
+
+ if (iterator->next_attribute)
+ iterator->end_index = MIN (iterator->end_index, ((PangoAttribute *)iterator->next_attribute->data)->start_index);
+
+ return TRUE;
+}
+
+/**
+ * pango_attr_iterator_copy:
+ * @iterator: a #PangoAttrIterator.
+ *
+ * Copy a #PangoAttrIterator
+ *
+ * Return value: the newly allocated #PangoAttrIterator, which should
+ * be freed with pango_attr_iterator_destroy().
+ **/
+PangoAttrIterator *
+pango_attr_iterator_copy (PangoAttrIterator *iterator)
+{
+ PangoAttrIterator *copy;
+
+ g_return_val_if_fail (iterator != NULL, NULL);
+
+ copy = g_slice_new (PangoAttrIterator);
+
+ *copy = *iterator;
+
+ copy->attribute_stack = g_list_copy (iterator->attribute_stack);
+
+ return copy;
+}
+
+/**
+ * pango_attr_iterator_destroy:
+ * @iterator: a #PangoAttrIterator.
+ *
+ * Destroy a #PangoAttrIterator and free all associated memory.
+ **/
+void
+pango_attr_iterator_destroy (PangoAttrIterator *iterator)
+{
+ g_return_if_fail (iterator != NULL);
+
+ g_list_free (iterator->attribute_stack);
+ g_slice_free (PangoAttrIterator, iterator);
+}
+
+/**
+ * pango_attr_iterator_get:
+ * @iterator: a #PangoAttrIterator
+ * @type: the type of attribute to find.
+ *
+ * Find the current attribute of a particular type at the iterator
+ * location. When multiple attributes of the same type overlap,
+ * the attribute whose range starts closest to the current location
+ * is used.
+ *
+ * Return value: the current attribute of the given type, or %NULL
+ * if no attribute of that type applies to the current
+ * location.
+ **/
+PangoAttribute *
+pango_attr_iterator_get (PangoAttrIterator *iterator,
+ PangoAttrType type)
+{
+ GList *tmp_list;
+
+ g_return_val_if_fail (iterator != NULL, NULL);
+
+ tmp_list = iterator->attribute_stack;
+ while (tmp_list)
+ {
+ PangoAttribute *attr = tmp_list->data;
+
+ if (attr->klass->type == type)
+ return attr;
+
+ tmp_list = tmp_list->next;
+ }
+
+ return NULL;
+}
+
+/**
+ * pango_attr_iterator_get_font:
+ * @iterator: a #PangoAttrIterator
+ * @desc: a #PangoFontDescription to fill in with the current values.
+ * The family name in this structure will be set using
+ * pango_font_description_set_family_static() using values from
+ * an attribute in the #PangoAttrList associated with the iterator,
+ * so if you plan to keep it around, you must call:
+ * <literal>pango_font_description_set_family (desc, pango_font_description_get_family (desc))</literal>.
+ * @language: if non-%NULL, location to store language tag for item, or %NULL
+ * if none is found.
+ * @extra_attrs: if non-%NULL, location in which to store a list of non-font
+ * attributes at the the current position; only the highest priority
+ * value of each attribute will be added to this list. In order
+ * to free this value, you must call pango_attribute_destroy() on
+ * each member.
+ *
+ * Get the font and other attributes at the current iterator position.
+ **/
+void
+pango_attr_iterator_get_font (PangoAttrIterator *iterator,
+ PangoFontDescription *desc,
+ PangoLanguage **language,
+ GSList **extra_attrs)
+{
+ GList *tmp_list1;
+ GSList *tmp_list2;
+
+ PangoFontMask mask = 0;
+ gboolean have_language = FALSE;
+ gdouble scale = 0;
+ gboolean have_scale = FALSE;
+
+ g_return_if_fail (iterator != NULL);
+ g_return_if_fail (desc != NULL);
+
+ if (language)
+ *language = NULL;
+
+ if (extra_attrs)
+ *extra_attrs = NULL;
+
+ tmp_list1 = iterator->attribute_stack;
+ while (tmp_list1)
+ {
+ PangoAttribute *attr = tmp_list1->data;
+ tmp_list1 = tmp_list1->next;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_FONT_DESC:
+ {
+ PangoFontMask new_mask = pango_font_description_get_set_fields (((PangoAttrFontDesc *)attr)->desc) & ~mask;
+ mask |= new_mask;
+ pango_font_description_unset_fields (desc, new_mask);
+ pango_font_description_merge_static (desc, ((PangoAttrFontDesc *)attr)->desc, FALSE);
+
+ break;
+ }
+ case PANGO_ATTR_FAMILY:
+ if (!(mask & PANGO_FONT_MASK_FAMILY))
+ {
+ mask |= PANGO_FONT_MASK_FAMILY;
+ pango_font_description_set_family (desc, ((PangoAttrString *)attr)->value);
+ }
+ break;
+ case PANGO_ATTR_STYLE:
+ if (!(mask & PANGO_FONT_MASK_STYLE))
+ {
+ mask |= PANGO_FONT_MASK_STYLE;
+ pango_font_description_set_style (desc, ((PangoAttrInt *)attr)->value);
+ }
+ break;
+ case PANGO_ATTR_VARIANT:
+ if (!(mask & PANGO_FONT_MASK_VARIANT))
+ {
+ mask |= PANGO_FONT_MASK_VARIANT;
+ pango_font_description_set_variant (desc, ((PangoAttrInt *)attr)->value);
+ }
+ break;
+ case PANGO_ATTR_WEIGHT:
+ if (!(mask & PANGO_FONT_MASK_WEIGHT))
+ {
+ mask |= PANGO_FONT_MASK_WEIGHT;
+ pango_font_description_set_weight (desc, ((PangoAttrInt *)attr)->value);
+ }
+ break;
+ case PANGO_ATTR_STRETCH:
+ if (!(mask & PANGO_FONT_MASK_STRETCH))
+ {
+ mask |= PANGO_FONT_MASK_STRETCH;
+ pango_font_description_set_stretch (desc, ((PangoAttrInt *)attr)->value);
+ }
+ break;
+ case PANGO_ATTR_SIZE:
+ if (!(mask & PANGO_FONT_MASK_SIZE))
+ {
+ mask |= PANGO_FONT_MASK_SIZE;
+ pango_font_description_set_size (desc, ((PangoAttrSize *)attr)->size);
+ }
+ break;
+ case PANGO_ATTR_ABSOLUTE_SIZE:
+ if (!(mask & PANGO_FONT_MASK_SIZE))
+ {
+ mask |= PANGO_FONT_MASK_SIZE;
+ pango_font_description_set_absolute_size (desc, ((PangoAttrSize *)attr)->size);
+ }
+ break;
+ case PANGO_ATTR_SCALE:
+ if (!have_scale)
+ {
+ have_scale = TRUE;
+ scale = ((PangoAttrFloat *)attr)->value;
+ }
+ break;
+ case PANGO_ATTR_LANGUAGE:
+ if (language)
+ {
+ if (!have_language)
+ {
+ have_language = TRUE;
+ *language = ((PangoAttrLanguage *)attr)->value;
+ }
+ }
+ break;
+ default:
+ if (extra_attrs)
+ {
+ gboolean found = FALSE;
+
+ tmp_list2 = *extra_attrs;
+ while (tmp_list2)
+ {
+ PangoAttribute *old_attr = tmp_list2->data;
+ if (attr->klass->type == old_attr->klass->type)
+ {
+ found = TRUE;
+ break;
+ }
+
+ tmp_list2 = tmp_list2->next;
+ }
+
+ if (!found)
+ *extra_attrs = g_slist_prepend (*extra_attrs, pango_attribute_copy (attr));
+ }
+ }
+ }
+
+ if (have_scale)
+ pango_font_description_set_size (desc, scale * pango_font_description_get_size (desc));
+
+}
+
+/**
+ * pango_attr_list_filter:
+ * @list: a #PangoAttrList
+ * @func: callback function; returns %TRUE if an attribute
+ * should be filtered out.
+ * @data: Data to be passed to @func
+ *
+ * Given a #PangoAttrList and callback function, removes any elements
+ * of @list for which @func returns %TRUE and inserts them into
+ * a new list.
+ *
+ * Return value: the new #PangoAttrList or %NULL if
+ * no attributes of the given types were found.
+ *
+ * Since: 1.2
+ **/
+PangoAttrList *
+pango_attr_list_filter (PangoAttrList *list,
+ PangoAttrFilterFunc func,
+ gpointer data)
+
+{
+ PangoAttrList *new = NULL;
+ GSList *tmp_list;
+ GSList *prev;
+
+ g_return_val_if_fail (list != NULL, NULL);
+
+ tmp_list = list->attributes;
+ prev = NULL;
+ while (tmp_list)
+ {
+ GSList *next = tmp_list->next;
+ PangoAttribute *tmp_attr = tmp_list->data;
+
+ if ((*func) (tmp_attr, data))
+ {
+ if (!tmp_list->next)
+ list->attributes_tail = prev;
+
+ if (prev)
+ prev->next = tmp_list->next;
+ else
+ list->attributes = tmp_list->next;
+
+ tmp_list->next = NULL;
+
+ if (!new)
+ {
+ new = pango_attr_list_new ();
+ new->attributes = new->attributes_tail = tmp_list;
+ }
+ else
+ {
+ new->attributes_tail->next = tmp_list;
+ new->attributes_tail = tmp_list;
+ }
+
+ goto next_attr;
+ }
+
+ prev = tmp_list;
+
+ next_attr:
+ tmp_list = next;
+ }
+
+ return new;
+}
+
+/**
+ * pango_attr_iterator_get_attrs:
+ * @iterator: a #PangoAttrIterator
+ *
+ * Gets a list of all attributes at the current position of the
+ * iterator.
+ *
+ * Return value: a list of all attributes for the current range.
+ * To free this value, call pango_attribute_destroy() on
+ * each value and g_slist_free() on the list.
+ *
+ * Since: 1.2
+ **/
+GSList *
+pango_attr_iterator_get_attrs (PangoAttrIterator *iterator)
+{
+ GSList *attrs = NULL;
+ GList *tmp_list;
+
+ for (tmp_list = iterator->attribute_stack; tmp_list; tmp_list = tmp_list->next)
+ {
+ PangoAttribute *attr = tmp_list->data;
+ GSList *tmp_list2;
+ gboolean found = FALSE;
+
+ for (tmp_list2 = attrs; tmp_list2; tmp_list2 = tmp_list2->next)
+ {
+ PangoAttribute *old_attr = tmp_list2->data;
+ if (attr->klass->type == old_attr->klass->type)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ attrs = g_slist_prepend (attrs, pango_attribute_copy (attr));
+ }
+
+ return attrs;
+}
diff --git a/trunk/pango/pango-attributes.h b/trunk/pango/pango-attributes.h
new file mode 100644
index 00000000..98ee9868
--- /dev/null
+++ b/trunk/pango/pango-attributes.h
@@ -0,0 +1,274 @@
+/* Pango
+ * pango-attributes.h: Attributed text
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_ATTRIBUTES_H__
+#define __PANGO_ATTRIBUTES_H__
+
+#include <pango/pango-font.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* PangoColor */
+
+typedef struct _PangoColor PangoColor;
+
+struct _PangoColor
+{
+ guint16 red;
+ guint16 green;
+ guint16 blue;
+};
+
+#define PANGO_TYPE_COLOR pango_color_get_type ()
+GType pango_color_get_type (void) G_GNUC_CONST;
+
+PangoColor *pango_color_copy (const PangoColor *src);
+void pango_color_free (PangoColor *color);
+gboolean pango_color_parse (PangoColor *color,
+ const char *spec);
+gchar *pango_color_to_string(const PangoColor *color);
+
+
+/* Attributes */
+
+typedef struct _PangoAttribute PangoAttribute;
+typedef struct _PangoAttrClass PangoAttrClass;
+
+typedef struct _PangoAttrString PangoAttrString;
+typedef struct _PangoAttrLanguage PangoAttrLanguage;
+typedef struct _PangoAttrInt PangoAttrInt;
+typedef struct _PangoAttrSize PangoAttrSize;
+typedef struct _PangoAttrFloat PangoAttrFloat;
+typedef struct _PangoAttrColor PangoAttrColor;
+typedef struct _PangoAttrFontDesc PangoAttrFontDesc;
+typedef struct _PangoAttrShape PangoAttrShape;
+
+#define PANGO_TYPE_ATTR_LIST pango_attr_list_get_type ()
+typedef struct _PangoAttrList PangoAttrList;
+typedef struct _PangoAttrIterator PangoAttrIterator;
+
+typedef enum
+{
+ PANGO_ATTR_INVALID, /* 0 is an invalid attribute type */
+ PANGO_ATTR_LANGUAGE, /* PangoAttrLanguage */
+ PANGO_ATTR_FAMILY, /* PangoAttrString */
+ PANGO_ATTR_STYLE, /* PangoAttrInt */
+ PANGO_ATTR_WEIGHT, /* PangoAttrInt */
+ PANGO_ATTR_VARIANT, /* PangoAttrInt */
+ PANGO_ATTR_STRETCH, /* PangoAttrInt */
+ PANGO_ATTR_SIZE, /* PangoAttrSize */
+ PANGO_ATTR_FONT_DESC, /* PangoAttrFontDesc */
+ PANGO_ATTR_FOREGROUND, /* PangoAttrColor */
+ PANGO_ATTR_BACKGROUND, /* PangoAttrColor */
+ PANGO_ATTR_UNDERLINE, /* PangoAttrInt */
+ PANGO_ATTR_STRIKETHROUGH, /* PangoAttrInt */
+ PANGO_ATTR_RISE, /* PangoAttrInt */
+ PANGO_ATTR_SHAPE, /* PangoAttrShape */
+ PANGO_ATTR_SCALE, /* PangoAttrFloat */
+ PANGO_ATTR_FALLBACK, /* PangoAttrInt */
+ PANGO_ATTR_LETTER_SPACING, /* PangoAttrInt */
+ PANGO_ATTR_UNDERLINE_COLOR, /* PangoAttrColor */
+ PANGO_ATTR_STRIKETHROUGH_COLOR,/* PangoAttrColor */
+ PANGO_ATTR_ABSOLUTE_SIZE, /* PangoAttrSize */
+ PANGO_ATTR_GRAVITY, /* PangoAttrInt */
+ PANGO_ATTR_GRAVITY_HINT /* PangoAttrInt */
+} PangoAttrType;
+
+typedef enum {
+ PANGO_UNDERLINE_NONE,
+ PANGO_UNDERLINE_SINGLE,
+ PANGO_UNDERLINE_DOUBLE,
+ PANGO_UNDERLINE_LOW,
+ PANGO_UNDERLINE_ERROR
+} PangoUnderline;
+
+struct _PangoAttribute
+{
+ const PangoAttrClass *klass;
+ guint start_index; /* in bytes */
+ guint end_index; /* in bytes. The character at this index is not included */
+};
+
+typedef gboolean (*PangoAttrFilterFunc) (PangoAttribute *attribute,
+ gpointer data);
+
+typedef gpointer (*PangoAttrDataCopyFunc) (gconstpointer data);
+
+struct _PangoAttrClass
+{
+ /*< public >*/
+ PangoAttrType type;
+ PangoAttribute * (*copy) (const PangoAttribute *attr);
+ void (*destroy) (PangoAttribute *attr);
+ gboolean (*equal) (const PangoAttribute *attr1, const PangoAttribute *attr2);
+};
+
+struct _PangoAttrString
+{
+ PangoAttribute attr;
+ char *value;
+};
+
+struct _PangoAttrLanguage
+{
+ PangoAttribute attr;
+ PangoLanguage *value;
+};
+
+struct _PangoAttrInt
+{
+ PangoAttribute attr;
+ int value;
+};
+
+struct _PangoAttrFloat
+{
+ PangoAttribute attr;
+ double value;
+};
+
+struct _PangoAttrColor
+{
+ PangoAttribute attr;
+ PangoColor color;
+};
+
+struct _PangoAttrSize
+{
+ PangoAttribute attr;
+ int size;
+ guint absolute : 1;
+};
+
+struct _PangoAttrShape
+{
+ PangoAttribute attr;
+ PangoRectangle ink_rect;
+ PangoRectangle logical_rect;
+
+ gpointer data;
+ PangoAttrDataCopyFunc copy_func;
+ GDestroyNotify destroy_func;
+};
+
+struct _PangoAttrFontDesc
+{
+ PangoAttribute attr;
+ PangoFontDescription *desc;
+};
+
+PangoAttrType pango_attr_type_register (const gchar *name);
+
+PangoAttribute * pango_attribute_copy (const PangoAttribute *attr);
+void pango_attribute_destroy (PangoAttribute *attr);
+gboolean pango_attribute_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2) G_GNUC_PURE;
+
+PangoAttribute *pango_attr_language_new (PangoLanguage *language);
+PangoAttribute *pango_attr_family_new (const char *family);
+PangoAttribute *pango_attr_foreground_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+PangoAttribute *pango_attr_background_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+PangoAttribute *pango_attr_size_new (int size);
+PangoAttribute *pango_attr_size_new_absolute (int size);
+PangoAttribute *pango_attr_style_new (PangoStyle style);
+PangoAttribute *pango_attr_weight_new (PangoWeight weight);
+PangoAttribute *pango_attr_variant_new (PangoVariant variant);
+PangoAttribute *pango_attr_stretch_new (PangoStretch stretch);
+PangoAttribute *pango_attr_font_desc_new (const PangoFontDescription *desc);
+
+PangoAttribute *pango_attr_underline_new (PangoUnderline underline);
+PangoAttribute *pango_attr_underline_color_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+PangoAttribute *pango_attr_strikethrough_new (gboolean strikethrough);
+PangoAttribute *pango_attr_strikethrough_color_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+
+PangoAttribute *pango_attr_rise_new (int rise);
+PangoAttribute *pango_attr_scale_new (double scale_factor);
+PangoAttribute *pango_attr_fallback_new (gboolean enable_fallback);
+PangoAttribute *pango_attr_letter_spacing_new (int letter_spacing);
+
+PangoAttribute *pango_attr_shape_new (const PangoRectangle *ink_rect,
+ const PangoRectangle *logical_rect);
+PangoAttribute *pango_attr_shape_new_with_data (const PangoRectangle *ink_rect,
+ const PangoRectangle *logical_rect,
+ gpointer data,
+ PangoAttrDataCopyFunc copy_func,
+ GDestroyNotify destroy_func);
+
+PangoAttribute *pango_attr_gravity_new (PangoGravity gravity);
+PangoAttribute *pango_attr_gravity_hint_new (PangoGravityHint hint);
+
+GType pango_attr_list_get_type (void) G_GNUC_CONST;
+PangoAttrList * pango_attr_list_new (void);
+PangoAttrList * pango_attr_list_ref (PangoAttrList *list);
+void pango_attr_list_unref (PangoAttrList *list);
+PangoAttrList * pango_attr_list_copy (PangoAttrList *list);
+void pango_attr_list_insert (PangoAttrList *list,
+ PangoAttribute *attr);
+void pango_attr_list_insert_before (PangoAttrList *list,
+ PangoAttribute *attr);
+void pango_attr_list_change (PangoAttrList *list,
+ PangoAttribute *attr);
+void pango_attr_list_splice (PangoAttrList *list,
+ PangoAttrList *other,
+ gint pos,
+ gint len);
+
+PangoAttrList *pango_attr_list_filter (PangoAttrList *list,
+ PangoAttrFilterFunc func,
+ gpointer data);
+
+PangoAttrIterator *pango_attr_list_get_iterator (PangoAttrList *list);
+
+void pango_attr_iterator_range (PangoAttrIterator *iterator,
+ gint *start,
+ gint *end);
+gboolean pango_attr_iterator_next (PangoAttrIterator *iterator);
+PangoAttrIterator *pango_attr_iterator_copy (PangoAttrIterator *iterator);
+void pango_attr_iterator_destroy (PangoAttrIterator *iterator);
+PangoAttribute * pango_attr_iterator_get (PangoAttrIterator *iterator,
+ PangoAttrType type);
+void pango_attr_iterator_get_font (PangoAttrIterator *iterator,
+ PangoFontDescription *desc,
+ PangoLanguage **language,
+ GSList **extra_attrs);
+GSList * pango_attr_iterator_get_attrs (PangoAttrIterator *iterator);
+
+
+gboolean pango_parse_markup (const char *markup_text,
+ int length,
+ gunichar accel_marker,
+ PangoAttrList **attr_list,
+ char **text,
+ gunichar *accel_char,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __PANGO_ATTRIBUTES_H__ */
diff --git a/trunk/pango/pango-break.h b/trunk/pango/pango-break.h
new file mode 100644
index 00000000..fe22acec
--- /dev/null
+++ b/trunk/pango/pango-break.h
@@ -0,0 +1,117 @@
+/* Pango
+ * pango-break.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_BREAK_H__
+#define __PANGO_BREAK_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#include <pango/pango-item.h>
+
+/* Logical attributes of a character.
+ */
+struct _PangoLogAttr
+{
+ guint is_line_break : 1; /* Can break line in front of character */
+
+ guint is_mandatory_break : 1; /* Must break line in front of character */
+
+ guint is_char_break : 1; /* Can break here when doing char wrap */
+
+ guint is_white : 1; /* Whitespace character */
+
+ /* Cursor can appear in front of character (i.e. this is a grapheme
+ * boundary, or the first character in the text).
+ */
+ guint is_cursor_position : 1;
+
+ /* Note that in degenerate cases, you could have both start/end set on
+ * some text, most likely for sentences (e.g. no space after a period, so
+ * the next sentence starts right away).
+ */
+
+ guint is_word_start : 1; /* first character in a word */
+ guint is_word_end : 1; /* is first non-word char after a word */
+
+ /* There are two ways to divide sentences. The first assigns all
+ * intersentence whitespace/control/format chars to some sentence,
+ * so all chars are in some sentence; is_sentence_boundary denotes
+ * the boundaries there. The second way doesn't assign
+ * between-sentence spaces, etc. to any sentence, so
+ * is_sentence_start/is_sentence_end mark the boundaries of those
+ * sentences.
+ */
+ guint is_sentence_boundary : 1;
+ guint is_sentence_start : 1; /* first character in a sentence */
+ guint is_sentence_end : 1; /* first non-sentence char after a sentence */
+
+ /* If set, backspace deletes one character rather than
+ * the entire grapheme cluster.
+ */
+ guint backspace_deletes_character : 1;
+
+ /* Only few space variants (U+0020 and U+00A0) have variable
+ * width during justification.
+ */
+ guint is_expandable_space : 1;
+};
+
+/* Determine information about cluster/word/line breaks in a string
+ * of Unicode text.
+ */
+void pango_break (const gchar *text,
+ int length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len);
+
+void pango_find_paragraph_boundary (const gchar *text,
+ gint length,
+ gint *paragraph_delimiter_index,
+ gint *next_paragraph_start);
+
+void pango_get_log_attrs (const char *text,
+ int length,
+ int level,
+ PangoLanguage *language,
+ PangoLogAttr *log_attrs,
+ int attrs_len);
+
+#ifdef PANGO_ENABLE_ENGINE
+
+/* This is the default break algorithm, used if no language
+ * engine overrides it. Normally you should use pango_break()
+ * instead; this function is mostly useful for chaining up
+ * from a language engine override.
+ */
+void pango_default_break (const gchar *text,
+ int length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len);
+
+#endif /* PANGO_ENABLE_ENGINE */
+
+G_END_DECLS
+
+#endif /* __PANGO_BREAK_H__ */
diff --git a/trunk/pango/pango-color-table.h b/trunk/pango/pango-color-table.h
new file mode 100644
index 00000000..ce93d94e
--- /dev/null
+++ b/trunk/pango/pango-color-table.h
@@ -0,0 +1,1521 @@
+/* pango-color-table.h: Generated by gen-color-table.pl from rgb.txt
+ *
+ * Date: Fri Mar 4 23:40:25 2005
+ *
+ * Do not edit.
+ */
+static const char color_names[] =
+ "alice blue\0"
+ "AliceBlue\0"
+ "antique white\0"
+ "AntiqueWhite\0"
+ "AntiqueWhite1\0"
+ "AntiqueWhite2\0"
+ "AntiqueWhite3\0"
+ "AntiqueWhite4\0"
+ "aquamarine\0"
+ "aquamarine1\0"
+ "aquamarine2\0"
+ "aquamarine3\0"
+ "aquamarine4\0"
+ "azure\0"
+ "azure1\0"
+ "azure2\0"
+ "azure3\0"
+ "azure4\0"
+ "beige\0"
+ "bisque\0"
+ "bisque1\0"
+ "bisque2\0"
+ "bisque3\0"
+ "bisque4\0"
+ "black\0"
+ "blanched almond\0"
+ "BlanchedAlmond\0"
+ "blue\0"
+ "blue violet\0"
+ "blue1\0"
+ "blue2\0"
+ "blue3\0"
+ "blue4\0"
+ "BlueViolet\0"
+ "brown\0"
+ "brown1\0"
+ "brown2\0"
+ "brown3\0"
+ "brown4\0"
+ "burlywood\0"
+ "burlywood1\0"
+ "burlywood2\0"
+ "burlywood3\0"
+ "burlywood4\0"
+ "cadet blue\0"
+ "CadetBlue\0"
+ "CadetBlue1\0"
+ "CadetBlue2\0"
+ "CadetBlue3\0"
+ "CadetBlue4\0"
+ "chartreuse\0"
+ "chartreuse1\0"
+ "chartreuse2\0"
+ "chartreuse3\0"
+ "chartreuse4\0"
+ "chocolate\0"
+ "chocolate1\0"
+ "chocolate2\0"
+ "chocolate3\0"
+ "chocolate4\0"
+ "coral\0"
+ "coral1\0"
+ "coral2\0"
+ "coral3\0"
+ "coral4\0"
+ "cornflower blue\0"
+ "CornflowerBlue\0"
+ "cornsilk\0"
+ "cornsilk1\0"
+ "cornsilk2\0"
+ "cornsilk3\0"
+ "cornsilk4\0"
+ "cyan\0"
+ "cyan1\0"
+ "cyan2\0"
+ "cyan3\0"
+ "cyan4\0"
+ "dark blue\0"
+ "dark cyan\0"
+ "dark goldenrod\0"
+ "dark gray\0"
+ "dark green\0"
+ "dark grey\0"
+ "dark khaki\0"
+ "dark magenta\0"
+ "dark olive green\0"
+ "dark orange\0"
+ "dark orchid\0"
+ "dark red\0"
+ "dark salmon\0"
+ "dark sea green\0"
+ "dark slate blue\0"
+ "dark slate gray\0"
+ "dark slate grey\0"
+ "dark turquoise\0"
+ "dark violet\0"
+ "DarkBlue\0"
+ "DarkCyan\0"
+ "DarkGoldenrod\0"
+ "DarkGoldenrod1\0"
+ "DarkGoldenrod2\0"
+ "DarkGoldenrod3\0"
+ "DarkGoldenrod4\0"
+ "DarkGray\0"
+ "DarkGreen\0"
+ "DarkGrey\0"
+ "DarkKhaki\0"
+ "DarkMagenta\0"
+ "DarkOliveGreen\0"
+ "DarkOliveGreen1\0"
+ "DarkOliveGreen2\0"
+ "DarkOliveGreen3\0"
+ "DarkOliveGreen4\0"
+ "DarkOrange\0"
+ "DarkOrange1\0"
+ "DarkOrange2\0"
+ "DarkOrange3\0"
+ "DarkOrange4\0"
+ "DarkOrchid\0"
+ "DarkOrchid1\0"
+ "DarkOrchid2\0"
+ "DarkOrchid3\0"
+ "DarkOrchid4\0"
+ "DarkRed\0"
+ "DarkSalmon\0"
+ "DarkSeaGreen\0"
+ "DarkSeaGreen1\0"
+ "DarkSeaGreen2\0"
+ "DarkSeaGreen3\0"
+ "DarkSeaGreen4\0"
+ "DarkSlateBlue\0"
+ "DarkSlateGray\0"
+ "DarkSlateGray1\0"
+ "DarkSlateGray2\0"
+ "DarkSlateGray3\0"
+ "DarkSlateGray4\0"
+ "DarkSlateGrey\0"
+ "DarkTurquoise\0"
+ "DarkViolet\0"
+ "deep pink\0"
+ "deep sky blue\0"
+ "DeepPink\0"
+ "DeepPink1\0"
+ "DeepPink2\0"
+ "DeepPink3\0"
+ "DeepPink4\0"
+ "DeepSkyBlue\0"
+ "DeepSkyBlue1\0"
+ "DeepSkyBlue2\0"
+ "DeepSkyBlue3\0"
+ "DeepSkyBlue4\0"
+ "dim gray\0"
+ "dim grey\0"
+ "DimGray\0"
+ "DimGrey\0"
+ "dodger blue\0"
+ "DodgerBlue\0"
+ "DodgerBlue1\0"
+ "DodgerBlue2\0"
+ "DodgerBlue3\0"
+ "DodgerBlue4\0"
+ "firebrick\0"
+ "firebrick1\0"
+ "firebrick2\0"
+ "firebrick3\0"
+ "firebrick4\0"
+ "floral white\0"
+ "FloralWhite\0"
+ "forest green\0"
+ "ForestGreen\0"
+ "gainsboro\0"
+ "ghost white\0"
+ "GhostWhite\0"
+ "gold\0"
+ "gold1\0"
+ "gold2\0"
+ "gold3\0"
+ "gold4\0"
+ "goldenrod\0"
+ "goldenrod1\0"
+ "goldenrod2\0"
+ "goldenrod3\0"
+ "goldenrod4\0"
+ "gray\0"
+ "gray0\0"
+ "gray1\0"
+ "gray10\0"
+ "gray100\0"
+ "gray11\0"
+ "gray12\0"
+ "gray13\0"
+ "gray14\0"
+ "gray15\0"
+ "gray16\0"
+ "gray17\0"
+ "gray18\0"
+ "gray19\0"
+ "gray2\0"
+ "gray20\0"
+ "gray21\0"
+ "gray22\0"
+ "gray23\0"
+ "gray24\0"
+ "gray25\0"
+ "gray26\0"
+ "gray27\0"
+ "gray28\0"
+ "gray29\0"
+ "gray3\0"
+ "gray30\0"
+ "gray31\0"
+ "gray32\0"
+ "gray33\0"
+ "gray34\0"
+ "gray35\0"
+ "gray36\0"
+ "gray37\0"
+ "gray38\0"
+ "gray39\0"
+ "gray4\0"
+ "gray40\0"
+ "gray41\0"
+ "gray42\0"
+ "gray43\0"
+ "gray44\0"
+ "gray45\0"
+ "gray46\0"
+ "gray47\0"
+ "gray48\0"
+ "gray49\0"
+ "gray5\0"
+ "gray50\0"
+ "gray51\0"
+ "gray52\0"
+ "gray53\0"
+ "gray54\0"
+ "gray55\0"
+ "gray56\0"
+ "gray57\0"
+ "gray58\0"
+ "gray59\0"
+ "gray6\0"
+ "gray60\0"
+ "gray61\0"
+ "gray62\0"
+ "gray63\0"
+ "gray64\0"
+ "gray65\0"
+ "gray66\0"
+ "gray67\0"
+ "gray68\0"
+ "gray69\0"
+ "gray7\0"
+ "gray70\0"
+ "gray71\0"
+ "gray72\0"
+ "gray73\0"
+ "gray74\0"
+ "gray75\0"
+ "gray76\0"
+ "gray77\0"
+ "gray78\0"
+ "gray79\0"
+ "gray8\0"
+ "gray80\0"
+ "gray81\0"
+ "gray82\0"
+ "gray83\0"
+ "gray84\0"
+ "gray85\0"
+ "gray86\0"
+ "gray87\0"
+ "gray88\0"
+ "gray89\0"
+ "gray9\0"
+ "gray90\0"
+ "gray91\0"
+ "gray92\0"
+ "gray93\0"
+ "gray94\0"
+ "gray95\0"
+ "gray96\0"
+ "gray97\0"
+ "gray98\0"
+ "gray99\0"
+ "green\0"
+ "green yellow\0"
+ "green1\0"
+ "green2\0"
+ "green3\0"
+ "green4\0"
+ "GreenYellow\0"
+ "grey\0"
+ "grey0\0"
+ "grey1\0"
+ "grey10\0"
+ "grey100\0"
+ "grey11\0"
+ "grey12\0"
+ "grey13\0"
+ "grey14\0"
+ "grey15\0"
+ "grey16\0"
+ "grey17\0"
+ "grey18\0"
+ "grey19\0"
+ "grey2\0"
+ "grey20\0"
+ "grey21\0"
+ "grey22\0"
+ "grey23\0"
+ "grey24\0"
+ "grey25\0"
+ "grey26\0"
+ "grey27\0"
+ "grey28\0"
+ "grey29\0"
+ "grey3\0"
+ "grey30\0"
+ "grey31\0"
+ "grey32\0"
+ "grey33\0"
+ "grey34\0"
+ "grey35\0"
+ "grey36\0"
+ "grey37\0"
+ "grey38\0"
+ "grey39\0"
+ "grey4\0"
+ "grey40\0"
+ "grey41\0"
+ "grey42\0"
+ "grey43\0"
+ "grey44\0"
+ "grey45\0"
+ "grey46\0"
+ "grey47\0"
+ "grey48\0"
+ "grey49\0"
+ "grey5\0"
+ "grey50\0"
+ "grey51\0"
+ "grey52\0"
+ "grey53\0"
+ "grey54\0"
+ "grey55\0"
+ "grey56\0"
+ "grey57\0"
+ "grey58\0"
+ "grey59\0"
+ "grey6\0"
+ "grey60\0"
+ "grey61\0"
+ "grey62\0"
+ "grey63\0"
+ "grey64\0"
+ "grey65\0"
+ "grey66\0"
+ "grey67\0"
+ "grey68\0"
+ "grey69\0"
+ "grey7\0"
+ "grey70\0"
+ "grey71\0"
+ "grey72\0"
+ "grey73\0"
+ "grey74\0"
+ "grey75\0"
+ "grey76\0"
+ "grey77\0"
+ "grey78\0"
+ "grey79\0"
+ "grey8\0"
+ "grey80\0"
+ "grey81\0"
+ "grey82\0"
+ "grey83\0"
+ "grey84\0"
+ "grey85\0"
+ "grey86\0"
+ "grey87\0"
+ "grey88\0"
+ "grey89\0"
+ "grey9\0"
+ "grey90\0"
+ "grey91\0"
+ "grey92\0"
+ "grey93\0"
+ "grey94\0"
+ "grey95\0"
+ "grey96\0"
+ "grey97\0"
+ "grey98\0"
+ "grey99\0"
+ "honeydew\0"
+ "honeydew1\0"
+ "honeydew2\0"
+ "honeydew3\0"
+ "honeydew4\0"
+ "hot pink\0"
+ "HotPink\0"
+ "HotPink1\0"
+ "HotPink2\0"
+ "HotPink3\0"
+ "HotPink4\0"
+ "indian red\0"
+ "IndianRed\0"
+ "IndianRed1\0"
+ "IndianRed2\0"
+ "IndianRed3\0"
+ "IndianRed4\0"
+ "ivory\0"
+ "ivory1\0"
+ "ivory2\0"
+ "ivory3\0"
+ "ivory4\0"
+ "khaki\0"
+ "khaki1\0"
+ "khaki2\0"
+ "khaki3\0"
+ "khaki4\0"
+ "lavender\0"
+ "lavender blush\0"
+ "LavenderBlush\0"
+ "LavenderBlush1\0"
+ "LavenderBlush2\0"
+ "LavenderBlush3\0"
+ "LavenderBlush4\0"
+ "lawn green\0"
+ "LawnGreen\0"
+ "lemon chiffon\0"
+ "LemonChiffon\0"
+ "LemonChiffon1\0"
+ "LemonChiffon2\0"
+ "LemonChiffon3\0"
+ "LemonChiffon4\0"
+ "light blue\0"
+ "light coral\0"
+ "light cyan\0"
+ "light goldenrod\0"
+ "light goldenrod yellow\0"
+ "light gray\0"
+ "light green\0"
+ "light grey\0"
+ "light pink\0"
+ "light salmon\0"
+ "light sea green\0"
+ "light sky blue\0"
+ "light slate blue\0"
+ "light slate gray\0"
+ "light slate grey\0"
+ "light steel blue\0"
+ "light yellow\0"
+ "LightBlue\0"
+ "LightBlue1\0"
+ "LightBlue2\0"
+ "LightBlue3\0"
+ "LightBlue4\0"
+ "LightCoral\0"
+ "LightCyan\0"
+ "LightCyan1\0"
+ "LightCyan2\0"
+ "LightCyan3\0"
+ "LightCyan4\0"
+ "LightGoldenrod\0"
+ "LightGoldenrod1\0"
+ "LightGoldenrod2\0"
+ "LightGoldenrod3\0"
+ "LightGoldenrod4\0"
+ "LightGoldenrodYellow\0"
+ "LightGray\0"
+ "LightGreen\0"
+ "LightGrey\0"
+ "LightPink\0"
+ "LightPink1\0"
+ "LightPink2\0"
+ "LightPink3\0"
+ "LightPink4\0"
+ "LightSalmon\0"
+ "LightSalmon1\0"
+ "LightSalmon2\0"
+ "LightSalmon3\0"
+ "LightSalmon4\0"
+ "LightSeaGreen\0"
+ "LightSkyBlue\0"
+ "LightSkyBlue1\0"
+ "LightSkyBlue2\0"
+ "LightSkyBlue3\0"
+ "LightSkyBlue4\0"
+ "LightSlateBlue\0"
+ "LightSlateGray\0"
+ "LightSlateGrey\0"
+ "LightSteelBlue\0"
+ "LightSteelBlue1\0"
+ "LightSteelBlue2\0"
+ "LightSteelBlue3\0"
+ "LightSteelBlue4\0"
+ "LightYellow\0"
+ "LightYellow1\0"
+ "LightYellow2\0"
+ "LightYellow3\0"
+ "LightYellow4\0"
+ "lime green\0"
+ "LimeGreen\0"
+ "linen\0"
+ "magenta\0"
+ "magenta1\0"
+ "magenta2\0"
+ "magenta3\0"
+ "magenta4\0"
+ "maroon\0"
+ "maroon1\0"
+ "maroon2\0"
+ "maroon3\0"
+ "maroon4\0"
+ "medium aquamarine\0"
+ "medium blue\0"
+ "medium orchid\0"
+ "medium purple\0"
+ "medium sea green\0"
+ "medium slate blue\0"
+ "medium spring green\0"
+ "medium turquoise\0"
+ "medium violet red\0"
+ "MediumAquamarine\0"
+ "MediumBlue\0"
+ "MediumOrchid\0"
+ "MediumOrchid1\0"
+ "MediumOrchid2\0"
+ "MediumOrchid3\0"
+ "MediumOrchid4\0"
+ "MediumPurple\0"
+ "MediumPurple1\0"
+ "MediumPurple2\0"
+ "MediumPurple3\0"
+ "MediumPurple4\0"
+ "MediumSeaGreen\0"
+ "MediumSlateBlue\0"
+ "MediumSpringGreen\0"
+ "MediumTurquoise\0"
+ "MediumVioletRed\0"
+ "midnight blue\0"
+ "MidnightBlue\0"
+ "mint cream\0"
+ "MintCream\0"
+ "misty rose\0"
+ "MistyRose\0"
+ "MistyRose1\0"
+ "MistyRose2\0"
+ "MistyRose3\0"
+ "MistyRose4\0"
+ "moccasin\0"
+ "navajo white\0"
+ "NavajoWhite\0"
+ "NavajoWhite1\0"
+ "NavajoWhite2\0"
+ "NavajoWhite3\0"
+ "NavajoWhite4\0"
+ "navy\0"
+ "navy blue\0"
+ "NavyBlue\0"
+ "old lace\0"
+ "OldLace\0"
+ "olive drab\0"
+ "OliveDrab\0"
+ "OliveDrab1\0"
+ "OliveDrab2\0"
+ "OliveDrab3\0"
+ "OliveDrab4\0"
+ "orange\0"
+ "orange red\0"
+ "orange1\0"
+ "orange2\0"
+ "orange3\0"
+ "orange4\0"
+ "OrangeRed\0"
+ "OrangeRed1\0"
+ "OrangeRed2\0"
+ "OrangeRed3\0"
+ "OrangeRed4\0"
+ "orchid\0"
+ "orchid1\0"
+ "orchid2\0"
+ "orchid3\0"
+ "orchid4\0"
+ "pale goldenrod\0"
+ "pale green\0"
+ "pale turquoise\0"
+ "pale violet red\0"
+ "PaleGoldenrod\0"
+ "PaleGreen\0"
+ "PaleGreen1\0"
+ "PaleGreen2\0"
+ "PaleGreen3\0"
+ "PaleGreen4\0"
+ "PaleTurquoise\0"
+ "PaleTurquoise1\0"
+ "PaleTurquoise2\0"
+ "PaleTurquoise3\0"
+ "PaleTurquoise4\0"
+ "PaleVioletRed\0"
+ "PaleVioletRed1\0"
+ "PaleVioletRed2\0"
+ "PaleVioletRed3\0"
+ "PaleVioletRed4\0"
+ "papaya whip\0"
+ "PapayaWhip\0"
+ "peach puff\0"
+ "PeachPuff\0"
+ "PeachPuff1\0"
+ "PeachPuff2\0"
+ "PeachPuff3\0"
+ "PeachPuff4\0"
+ "peru\0"
+ "pink\0"
+ "pink1\0"
+ "pink2\0"
+ "pink3\0"
+ "pink4\0"
+ "plum\0"
+ "plum1\0"
+ "plum2\0"
+ "plum3\0"
+ "plum4\0"
+ "powder blue\0"
+ "PowderBlue\0"
+ "purple\0"
+ "purple1\0"
+ "purple2\0"
+ "purple3\0"
+ "purple4\0"
+ "red\0"
+ "red1\0"
+ "red2\0"
+ "red3\0"
+ "red4\0"
+ "rosy brown\0"
+ "RosyBrown\0"
+ "RosyBrown1\0"
+ "RosyBrown2\0"
+ "RosyBrown3\0"
+ "RosyBrown4\0"
+ "royal blue\0"
+ "RoyalBlue\0"
+ "RoyalBlue1\0"
+ "RoyalBlue2\0"
+ "RoyalBlue3\0"
+ "RoyalBlue4\0"
+ "saddle brown\0"
+ "SaddleBrown\0"
+ "salmon\0"
+ "salmon1\0"
+ "salmon2\0"
+ "salmon3\0"
+ "salmon4\0"
+ "sandy brown\0"
+ "SandyBrown\0"
+ "sea green\0"
+ "SeaGreen\0"
+ "SeaGreen1\0"
+ "SeaGreen2\0"
+ "SeaGreen3\0"
+ "SeaGreen4\0"
+ "seashell\0"
+ "seashell1\0"
+ "seashell2\0"
+ "seashell3\0"
+ "seashell4\0"
+ "sienna\0"
+ "sienna1\0"
+ "sienna2\0"
+ "sienna3\0"
+ "sienna4\0"
+ "sky blue\0"
+ "SkyBlue\0"
+ "SkyBlue1\0"
+ "SkyBlue2\0"
+ "SkyBlue3\0"
+ "SkyBlue4\0"
+ "slate blue\0"
+ "slate gray\0"
+ "slate grey\0"
+ "SlateBlue\0"
+ "SlateBlue1\0"
+ "SlateBlue2\0"
+ "SlateBlue3\0"
+ "SlateBlue4\0"
+ "SlateGray\0"
+ "SlateGray1\0"
+ "SlateGray2\0"
+ "SlateGray3\0"
+ "SlateGray4\0"
+ "SlateGrey\0"
+ "snow\0"
+ "snow1\0"
+ "snow2\0"
+ "snow3\0"
+ "snow4\0"
+ "spring green\0"
+ "SpringGreen\0"
+ "SpringGreen1\0"
+ "SpringGreen2\0"
+ "SpringGreen3\0"
+ "SpringGreen4\0"
+ "steel blue\0"
+ "SteelBlue\0"
+ "SteelBlue1\0"
+ "SteelBlue2\0"
+ "SteelBlue3\0"
+ "SteelBlue4\0"
+ "tan\0"
+ "tan1\0"
+ "tan2\0"
+ "tan3\0"
+ "tan4\0"
+ "thistle\0"
+ "thistle1\0"
+ "thistle2\0"
+ "thistle3\0"
+ "thistle4\0"
+ "tomato\0"
+ "tomato1\0"
+ "tomato2\0"
+ "tomato3\0"
+ "tomato4\0"
+ "turquoise\0"
+ "turquoise1\0"
+ "turquoise2\0"
+ "turquoise3\0"
+ "turquoise4\0"
+ "violet\0"
+ "violet red\0"
+ "VioletRed\0"
+ "VioletRed1\0"
+ "VioletRed2\0"
+ "VioletRed3\0"
+ "VioletRed4\0"
+ "wheat\0"
+ "wheat1\0"
+ "wheat2\0"
+ "wheat3\0"
+ "wheat4\0"
+ "white\0"
+ "white smoke\0"
+ "WhiteSmoke\0"
+ "yellow\0"
+ "yellow green\0"
+ "yellow1\0"
+ "yellow2\0"
+ "yellow3\0"
+ "yellow4\0"
+ "YellowGreen\0";
+
+typedef struct {
+ guint16 name_offset;
+ guchar red;
+ guchar green;
+ guchar blue;
+} ColorEntry;
+
+static const ColorEntry color_entries[] = {
+ { 0, 240, 248, 255 },
+ { 11, 240, 248, 255 },
+ { 21, 250, 235, 215 },
+ { 35, 250, 235, 215 },
+ { 48, 255, 239, 219 },
+ { 62, 238, 223, 204 },
+ { 76, 205, 192, 176 },
+ { 90, 139, 131, 120 },
+ { 104, 127, 255, 212 },
+ { 115, 127, 255, 212 },
+ { 127, 118, 238, 198 },
+ { 139, 102, 205, 170 },
+ { 151, 69, 139, 116 },
+ { 163, 240, 255, 255 },
+ { 169, 240, 255, 255 },
+ { 176, 224, 238, 238 },
+ { 183, 193, 205, 205 },
+ { 190, 131, 139, 139 },
+ { 197, 245, 245, 220 },
+ { 203, 255, 228, 196 },
+ { 210, 255, 228, 196 },
+ { 218, 238, 213, 183 },
+ { 226, 205, 183, 158 },
+ { 234, 139, 125, 107 },
+ { 242, 0, 0, 0 },
+ { 248, 255, 235, 205 },
+ { 264, 255, 235, 205 },
+ { 279, 0, 0, 255 },
+ { 284, 138, 43, 226 },
+ { 296, 0, 0, 255 },
+ { 302, 0, 0, 238 },
+ { 308, 0, 0, 205 },
+ { 314, 0, 0, 139 },
+ { 320, 138, 43, 226 },
+ { 331, 165, 42, 42 },
+ { 337, 255, 64, 64 },
+ { 344, 238, 59, 59 },
+ { 351, 205, 51, 51 },
+ { 358, 139, 35, 35 },
+ { 365, 222, 184, 135 },
+ { 375, 255, 211, 155 },
+ { 386, 238, 197, 145 },
+ { 397, 205, 170, 125 },
+ { 408, 139, 115, 85 },
+ { 419, 95, 158, 160 },
+ { 430, 95, 158, 160 },
+ { 440, 152, 245, 255 },
+ { 451, 142, 229, 238 },
+ { 462, 122, 197, 205 },
+ { 473, 83, 134, 139 },
+ { 484, 127, 255, 0 },
+ { 495, 127, 255, 0 },
+ { 507, 118, 238, 0 },
+ { 519, 102, 205, 0 },
+ { 531, 69, 139, 0 },
+ { 543, 210, 105, 30 },
+ { 553, 255, 127, 36 },
+ { 564, 238, 118, 33 },
+ { 575, 205, 102, 29 },
+ { 586, 139, 69, 19 },
+ { 597, 255, 127, 80 },
+ { 603, 255, 114, 86 },
+ { 610, 238, 106, 80 },
+ { 617, 205, 91, 69 },
+ { 624, 139, 62, 47 },
+ { 631, 100, 149, 237 },
+ { 647, 100, 149, 237 },
+ { 662, 255, 248, 220 },
+ { 671, 255, 248, 220 },
+ { 681, 238, 232, 205 },
+ { 691, 205, 200, 177 },
+ { 701, 139, 136, 120 },
+ { 711, 0, 255, 255 },
+ { 716, 0, 255, 255 },
+ { 722, 0, 238, 238 },
+ { 728, 0, 205, 205 },
+ { 734, 0, 139, 139 },
+ { 740, 0, 0, 139 },
+ { 750, 0, 139, 139 },
+ { 760, 184, 134, 11 },
+ { 775, 169, 169, 169 },
+ { 785, 0, 100, 0 },
+ { 796, 169, 169, 169 },
+ { 806, 189, 183, 107 },
+ { 817, 139, 0, 139 },
+ { 830, 85, 107, 47 },
+ { 847, 255, 140, 0 },
+ { 859, 153, 50, 204 },
+ { 871, 139, 0, 0 },
+ { 880, 233, 150, 122 },
+ { 892, 143, 188, 143 },
+ { 907, 72, 61, 139 },
+ { 923, 47, 79, 79 },
+ { 939, 47, 79, 79 },
+ { 955, 0, 206, 209 },
+ { 970, 148, 0, 211 },
+ { 982, 0, 0, 139 },
+ { 991, 0, 139, 139 },
+ { 1000, 184, 134, 11 },
+ { 1014, 255, 185, 15 },
+ { 1029, 238, 173, 14 },
+ { 1044, 205, 149, 12 },
+ { 1059, 139, 101, 8 },
+ { 1074, 169, 169, 169 },
+ { 1083, 0, 100, 0 },
+ { 1093, 169, 169, 169 },
+ { 1102, 189, 183, 107 },
+ { 1112, 139, 0, 139 },
+ { 1124, 85, 107, 47 },
+ { 1139, 202, 255, 112 },
+ { 1155, 188, 238, 104 },
+ { 1171, 162, 205, 90 },
+ { 1187, 110, 139, 61 },
+ { 1203, 255, 140, 0 },
+ { 1214, 255, 127, 0 },
+ { 1226, 238, 118, 0 },
+ { 1238, 205, 102, 0 },
+ { 1250, 139, 69, 0 },
+ { 1262, 153, 50, 204 },
+ { 1273, 191, 62, 255 },
+ { 1285, 178, 58, 238 },
+ { 1297, 154, 50, 205 },
+ { 1309, 104, 34, 139 },
+ { 1321, 139, 0, 0 },
+ { 1329, 233, 150, 122 },
+ { 1340, 143, 188, 143 },
+ { 1353, 193, 255, 193 },
+ { 1367, 180, 238, 180 },
+ { 1381, 155, 205, 155 },
+ { 1395, 105, 139, 105 },
+ { 1409, 72, 61, 139 },
+ { 1423, 47, 79, 79 },
+ { 1437, 151, 255, 255 },
+ { 1452, 141, 238, 238 },
+ { 1467, 121, 205, 205 },
+ { 1482, 82, 139, 139 },
+ { 1497, 47, 79, 79 },
+ { 1511, 0, 206, 209 },
+ { 1525, 148, 0, 211 },
+ { 1536, 255, 20, 147 },
+ { 1546, 0, 191, 255 },
+ { 1560, 255, 20, 147 },
+ { 1569, 255, 20, 147 },
+ { 1579, 238, 18, 137 },
+ { 1589, 205, 16, 118 },
+ { 1599, 139, 10, 80 },
+ { 1609, 0, 191, 255 },
+ { 1621, 0, 191, 255 },
+ { 1634, 0, 178, 238 },
+ { 1647, 0, 154, 205 },
+ { 1660, 0, 104, 139 },
+ { 1673, 105, 105, 105 },
+ { 1682, 105, 105, 105 },
+ { 1691, 105, 105, 105 },
+ { 1699, 105, 105, 105 },
+ { 1707, 30, 144, 255 },
+ { 1719, 30, 144, 255 },
+ { 1730, 30, 144, 255 },
+ { 1742, 28, 134, 238 },
+ { 1754, 24, 116, 205 },
+ { 1766, 16, 78, 139 },
+ { 1778, 178, 34, 34 },
+ { 1788, 255, 48, 48 },
+ { 1799, 238, 44, 44 },
+ { 1810, 205, 38, 38 },
+ { 1821, 139, 26, 26 },
+ { 1832, 255, 250, 240 },
+ { 1845, 255, 250, 240 },
+ { 1857, 34, 139, 34 },
+ { 1870, 34, 139, 34 },
+ { 1882, 220, 220, 220 },
+ { 1892, 248, 248, 255 },
+ { 1904, 248, 248, 255 },
+ { 1915, 255, 215, 0 },
+ { 1920, 255, 215, 0 },
+ { 1926, 238, 201, 0 },
+ { 1932, 205, 173, 0 },
+ { 1938, 139, 117, 0 },
+ { 1944, 218, 165, 32 },
+ { 1954, 255, 193, 37 },
+ { 1965, 238, 180, 34 },
+ { 1976, 205, 155, 29 },
+ { 1987, 139, 105, 20 },
+ { 1998, 190, 190, 190 },
+ { 2003, 0, 0, 0 },
+ { 2009, 3, 3, 3 },
+ { 2015, 26, 26, 26 },
+ { 2022, 255, 255, 255 },
+ { 2030, 28, 28, 28 },
+ { 2037, 31, 31, 31 },
+ { 2044, 33, 33, 33 },
+ { 2051, 36, 36, 36 },
+ { 2058, 38, 38, 38 },
+ { 2065, 41, 41, 41 },
+ { 2072, 43, 43, 43 },
+ { 2079, 46, 46, 46 },
+ { 2086, 48, 48, 48 },
+ { 2093, 5, 5, 5 },
+ { 2099, 51, 51, 51 },
+ { 2106, 54, 54, 54 },
+ { 2113, 56, 56, 56 },
+ { 2120, 59, 59, 59 },
+ { 2127, 61, 61, 61 },
+ { 2134, 64, 64, 64 },
+ { 2141, 66, 66, 66 },
+ { 2148, 69, 69, 69 },
+ { 2155, 71, 71, 71 },
+ { 2162, 74, 74, 74 },
+ { 2169, 8, 8, 8 },
+ { 2175, 77, 77, 77 },
+ { 2182, 79, 79, 79 },
+ { 2189, 82, 82, 82 },
+ { 2196, 84, 84, 84 },
+ { 2203, 87, 87, 87 },
+ { 2210, 89, 89, 89 },
+ { 2217, 92, 92, 92 },
+ { 2224, 94, 94, 94 },
+ { 2231, 97, 97, 97 },
+ { 2238, 99, 99, 99 },
+ { 2245, 10, 10, 10 },
+ { 2251, 102, 102, 102 },
+ { 2258, 105, 105, 105 },
+ { 2265, 107, 107, 107 },
+ { 2272, 110, 110, 110 },
+ { 2279, 112, 112, 112 },
+ { 2286, 115, 115, 115 },
+ { 2293, 117, 117, 117 },
+ { 2300, 120, 120, 120 },
+ { 2307, 122, 122, 122 },
+ { 2314, 125, 125, 125 },
+ { 2321, 13, 13, 13 },
+ { 2327, 127, 127, 127 },
+ { 2334, 130, 130, 130 },
+ { 2341, 133, 133, 133 },
+ { 2348, 135, 135, 135 },
+ { 2355, 138, 138, 138 },
+ { 2362, 140, 140, 140 },
+ { 2369, 143, 143, 143 },
+ { 2376, 145, 145, 145 },
+ { 2383, 148, 148, 148 },
+ { 2390, 150, 150, 150 },
+ { 2397, 15, 15, 15 },
+ { 2403, 153, 153, 153 },
+ { 2410, 156, 156, 156 },
+ { 2417, 158, 158, 158 },
+ { 2424, 161, 161, 161 },
+ { 2431, 163, 163, 163 },
+ { 2438, 166, 166, 166 },
+ { 2445, 168, 168, 168 },
+ { 2452, 171, 171, 171 },
+ { 2459, 173, 173, 173 },
+ { 2466, 176, 176, 176 },
+ { 2473, 18, 18, 18 },
+ { 2479, 179, 179, 179 },
+ { 2486, 181, 181, 181 },
+ { 2493, 184, 184, 184 },
+ { 2500, 186, 186, 186 },
+ { 2507, 189, 189, 189 },
+ { 2514, 191, 191, 191 },
+ { 2521, 194, 194, 194 },
+ { 2528, 196, 196, 196 },
+ { 2535, 199, 199, 199 },
+ { 2542, 201, 201, 201 },
+ { 2549, 20, 20, 20 },
+ { 2555, 204, 204, 204 },
+ { 2562, 207, 207, 207 },
+ { 2569, 209, 209, 209 },
+ { 2576, 212, 212, 212 },
+ { 2583, 214, 214, 214 },
+ { 2590, 217, 217, 217 },
+ { 2597, 219, 219, 219 },
+ { 2604, 222, 222, 222 },
+ { 2611, 224, 224, 224 },
+ { 2618, 227, 227, 227 },
+ { 2625, 23, 23, 23 },
+ { 2631, 229, 229, 229 },
+ { 2638, 232, 232, 232 },
+ { 2645, 235, 235, 235 },
+ { 2652, 237, 237, 237 },
+ { 2659, 240, 240, 240 },
+ { 2666, 242, 242, 242 },
+ { 2673, 245, 245, 245 },
+ { 2680, 247, 247, 247 },
+ { 2687, 250, 250, 250 },
+ { 2694, 252, 252, 252 },
+ { 2701, 0, 255, 0 },
+ { 2707, 173, 255, 47 },
+ { 2720, 0, 255, 0 },
+ { 2727, 0, 238, 0 },
+ { 2734, 0, 205, 0 },
+ { 2741, 0, 139, 0 },
+ { 2748, 173, 255, 47 },
+ { 2760, 190, 190, 190 },
+ { 2765, 0, 0, 0 },
+ { 2771, 3, 3, 3 },
+ { 2777, 26, 26, 26 },
+ { 2784, 255, 255, 255 },
+ { 2792, 28, 28, 28 },
+ { 2799, 31, 31, 31 },
+ { 2806, 33, 33, 33 },
+ { 2813, 36, 36, 36 },
+ { 2820, 38, 38, 38 },
+ { 2827, 41, 41, 41 },
+ { 2834, 43, 43, 43 },
+ { 2841, 46, 46, 46 },
+ { 2848, 48, 48, 48 },
+ { 2855, 5, 5, 5 },
+ { 2861, 51, 51, 51 },
+ { 2868, 54, 54, 54 },
+ { 2875, 56, 56, 56 },
+ { 2882, 59, 59, 59 },
+ { 2889, 61, 61, 61 },
+ { 2896, 64, 64, 64 },
+ { 2903, 66, 66, 66 },
+ { 2910, 69, 69, 69 },
+ { 2917, 71, 71, 71 },
+ { 2924, 74, 74, 74 },
+ { 2931, 8, 8, 8 },
+ { 2937, 77, 77, 77 },
+ { 2944, 79, 79, 79 },
+ { 2951, 82, 82, 82 },
+ { 2958, 84, 84, 84 },
+ { 2965, 87, 87, 87 },
+ { 2972, 89, 89, 89 },
+ { 2979, 92, 92, 92 },
+ { 2986, 94, 94, 94 },
+ { 2993, 97, 97, 97 },
+ { 3000, 99, 99, 99 },
+ { 3007, 10, 10, 10 },
+ { 3013, 102, 102, 102 },
+ { 3020, 105, 105, 105 },
+ { 3027, 107, 107, 107 },
+ { 3034, 110, 110, 110 },
+ { 3041, 112, 112, 112 },
+ { 3048, 115, 115, 115 },
+ { 3055, 117, 117, 117 },
+ { 3062, 120, 120, 120 },
+ { 3069, 122, 122, 122 },
+ { 3076, 125, 125, 125 },
+ { 3083, 13, 13, 13 },
+ { 3089, 127, 127, 127 },
+ { 3096, 130, 130, 130 },
+ { 3103, 133, 133, 133 },
+ { 3110, 135, 135, 135 },
+ { 3117, 138, 138, 138 },
+ { 3124, 140, 140, 140 },
+ { 3131, 143, 143, 143 },
+ { 3138, 145, 145, 145 },
+ { 3145, 148, 148, 148 },
+ { 3152, 150, 150, 150 },
+ { 3159, 15, 15, 15 },
+ { 3165, 153, 153, 153 },
+ { 3172, 156, 156, 156 },
+ { 3179, 158, 158, 158 },
+ { 3186, 161, 161, 161 },
+ { 3193, 163, 163, 163 },
+ { 3200, 166, 166, 166 },
+ { 3207, 168, 168, 168 },
+ { 3214, 171, 171, 171 },
+ { 3221, 173, 173, 173 },
+ { 3228, 176, 176, 176 },
+ { 3235, 18, 18, 18 },
+ { 3241, 179, 179, 179 },
+ { 3248, 181, 181, 181 },
+ { 3255, 184, 184, 184 },
+ { 3262, 186, 186, 186 },
+ { 3269, 189, 189, 189 },
+ { 3276, 191, 191, 191 },
+ { 3283, 194, 194, 194 },
+ { 3290, 196, 196, 196 },
+ { 3297, 199, 199, 199 },
+ { 3304, 201, 201, 201 },
+ { 3311, 20, 20, 20 },
+ { 3317, 204, 204, 204 },
+ { 3324, 207, 207, 207 },
+ { 3331, 209, 209, 209 },
+ { 3338, 212, 212, 212 },
+ { 3345, 214, 214, 214 },
+ { 3352, 217, 217, 217 },
+ { 3359, 219, 219, 219 },
+ { 3366, 222, 222, 222 },
+ { 3373, 224, 224, 224 },
+ { 3380, 227, 227, 227 },
+ { 3387, 23, 23, 23 },
+ { 3393, 229, 229, 229 },
+ { 3400, 232, 232, 232 },
+ { 3407, 235, 235, 235 },
+ { 3414, 237, 237, 237 },
+ { 3421, 240, 240, 240 },
+ { 3428, 242, 242, 242 },
+ { 3435, 245, 245, 245 },
+ { 3442, 247, 247, 247 },
+ { 3449, 250, 250, 250 },
+ { 3456, 252, 252, 252 },
+ { 3463, 240, 255, 240 },
+ { 3472, 240, 255, 240 },
+ { 3482, 224, 238, 224 },
+ { 3492, 193, 205, 193 },
+ { 3502, 131, 139, 131 },
+ { 3512, 255, 105, 180 },
+ { 3521, 255, 105, 180 },
+ { 3529, 255, 110, 180 },
+ { 3538, 238, 106, 167 },
+ { 3547, 205, 96, 144 },
+ { 3556, 139, 58, 98 },
+ { 3565, 205, 92, 92 },
+ { 3576, 205, 92, 92 },
+ { 3586, 255, 106, 106 },
+ { 3597, 238, 99, 99 },
+ { 3608, 205, 85, 85 },
+ { 3619, 139, 58, 58 },
+ { 3630, 255, 255, 240 },
+ { 3636, 255, 255, 240 },
+ { 3643, 238, 238, 224 },
+ { 3650, 205, 205, 193 },
+ { 3657, 139, 139, 131 },
+ { 3664, 240, 230, 140 },
+ { 3670, 255, 246, 143 },
+ { 3677, 238, 230, 133 },
+ { 3684, 205, 198, 115 },
+ { 3691, 139, 134, 78 },
+ { 3698, 230, 230, 250 },
+ { 3707, 255, 240, 245 },
+ { 3722, 255, 240, 245 },
+ { 3736, 255, 240, 245 },
+ { 3751, 238, 224, 229 },
+ { 3766, 205, 193, 197 },
+ { 3781, 139, 131, 134 },
+ { 3796, 124, 252, 0 },
+ { 3807, 124, 252, 0 },
+ { 3817, 255, 250, 205 },
+ { 3831, 255, 250, 205 },
+ { 3844, 255, 250, 205 },
+ { 3858, 238, 233, 191 },
+ { 3872, 205, 201, 165 },
+ { 3886, 139, 137, 112 },
+ { 3900, 173, 216, 230 },
+ { 3911, 240, 128, 128 },
+ { 3923, 224, 255, 255 },
+ { 3934, 238, 221, 130 },
+ { 3950, 250, 250, 210 },
+ { 3973, 211, 211, 211 },
+ { 3984, 144, 238, 144 },
+ { 3996, 211, 211, 211 },
+ { 4007, 255, 182, 193 },
+ { 4018, 255, 160, 122 },
+ { 4031, 32, 178, 170 },
+ { 4047, 135, 206, 250 },
+ { 4062, 132, 112, 255 },
+ { 4079, 119, 136, 153 },
+ { 4096, 119, 136, 153 },
+ { 4113, 176, 196, 222 },
+ { 4130, 255, 255, 224 },
+ { 4143, 173, 216, 230 },
+ { 4153, 191, 239, 255 },
+ { 4164, 178, 223, 238 },
+ { 4175, 154, 192, 205 },
+ { 4186, 104, 131, 139 },
+ { 4197, 240, 128, 128 },
+ { 4208, 224, 255, 255 },
+ { 4218, 224, 255, 255 },
+ { 4229, 209, 238, 238 },
+ { 4240, 180, 205, 205 },
+ { 4251, 122, 139, 139 },
+ { 4262, 238, 221, 130 },
+ { 4277, 255, 236, 139 },
+ { 4293, 238, 220, 130 },
+ { 4309, 205, 190, 112 },
+ { 4325, 139, 129, 76 },
+ { 4341, 250, 250, 210 },
+ { 4362, 211, 211, 211 },
+ { 4372, 144, 238, 144 },
+ { 4383, 211, 211, 211 },
+ { 4393, 255, 182, 193 },
+ { 4403, 255, 174, 185 },
+ { 4414, 238, 162, 173 },
+ { 4425, 205, 140, 149 },
+ { 4436, 139, 95, 101 },
+ { 4447, 255, 160, 122 },
+ { 4459, 255, 160, 122 },
+ { 4472, 238, 149, 114 },
+ { 4485, 205, 129, 98 },
+ { 4498, 139, 87, 66 },
+ { 4511, 32, 178, 170 },
+ { 4525, 135, 206, 250 },
+ { 4538, 176, 226, 255 },
+ { 4552, 164, 211, 238 },
+ { 4566, 141, 182, 205 },
+ { 4580, 96, 123, 139 },
+ { 4594, 132, 112, 255 },
+ { 4609, 119, 136, 153 },
+ { 4624, 119, 136, 153 },
+ { 4639, 176, 196, 222 },
+ { 4654, 202, 225, 255 },
+ { 4670, 188, 210, 238 },
+ { 4686, 162, 181, 205 },
+ { 4702, 110, 123, 139 },
+ { 4718, 255, 255, 224 },
+ { 4730, 255, 255, 224 },
+ { 4743, 238, 238, 209 },
+ { 4756, 205, 205, 180 },
+ { 4769, 139, 139, 122 },
+ { 4782, 50, 205, 50 },
+ { 4793, 50, 205, 50 },
+ { 4803, 250, 240, 230 },
+ { 4809, 255, 0, 255 },
+ { 4817, 255, 0, 255 },
+ { 4826, 238, 0, 238 },
+ { 4835, 205, 0, 205 },
+ { 4844, 139, 0, 139 },
+ { 4853, 176, 48, 96 },
+ { 4860, 255, 52, 179 },
+ { 4868, 238, 48, 167 },
+ { 4876, 205, 41, 144 },
+ { 4884, 139, 28, 98 },
+ { 4892, 102, 205, 170 },
+ { 4910, 0, 0, 205 },
+ { 4922, 186, 85, 211 },
+ { 4936, 147, 112, 219 },
+ { 4950, 60, 179, 113 },
+ { 4967, 123, 104, 238 },
+ { 4985, 0, 250, 154 },
+ { 5005, 72, 209, 204 },
+ { 5022, 199, 21, 133 },
+ { 5040, 102, 205, 170 },
+ { 5057, 0, 0, 205 },
+ { 5068, 186, 85, 211 },
+ { 5081, 224, 102, 255 },
+ { 5095, 209, 95, 238 },
+ { 5109, 180, 82, 205 },
+ { 5123, 122, 55, 139 },
+ { 5137, 147, 112, 219 },
+ { 5150, 171, 130, 255 },
+ { 5164, 159, 121, 238 },
+ { 5178, 137, 104, 205 },
+ { 5192, 93, 71, 139 },
+ { 5206, 60, 179, 113 },
+ { 5221, 123, 104, 238 },
+ { 5237, 0, 250, 154 },
+ { 5255, 72, 209, 204 },
+ { 5271, 199, 21, 133 },
+ { 5287, 25, 25, 112 },
+ { 5301, 25, 25, 112 },
+ { 5314, 245, 255, 250 },
+ { 5325, 245, 255, 250 },
+ { 5335, 255, 228, 225 },
+ { 5346, 255, 228, 225 },
+ { 5356, 255, 228, 225 },
+ { 5367, 238, 213, 210 },
+ { 5378, 205, 183, 181 },
+ { 5389, 139, 125, 123 },
+ { 5400, 255, 228, 181 },
+ { 5409, 255, 222, 173 },
+ { 5422, 255, 222, 173 },
+ { 5434, 255, 222, 173 },
+ { 5447, 238, 207, 161 },
+ { 5460, 205, 179, 139 },
+ { 5473, 139, 121, 94 },
+ { 5486, 0, 0, 128 },
+ { 5491, 0, 0, 128 },
+ { 5501, 0, 0, 128 },
+ { 5510, 253, 245, 230 },
+ { 5519, 253, 245, 230 },
+ { 5527, 107, 142, 35 },
+ { 5538, 107, 142, 35 },
+ { 5548, 192, 255, 62 },
+ { 5559, 179, 238, 58 },
+ { 5570, 154, 205, 50 },
+ { 5581, 105, 139, 34 },
+ { 5592, 255, 165, 0 },
+ { 5599, 255, 69, 0 },
+ { 5610, 255, 165, 0 },
+ { 5618, 238, 154, 0 },
+ { 5626, 205, 133, 0 },
+ { 5634, 139, 90, 0 },
+ { 5642, 255, 69, 0 },
+ { 5652, 255, 69, 0 },
+ { 5663, 238, 64, 0 },
+ { 5674, 205, 55, 0 },
+ { 5685, 139, 37, 0 },
+ { 5696, 218, 112, 214 },
+ { 5703, 255, 131, 250 },
+ { 5711, 238, 122, 233 },
+ { 5719, 205, 105, 201 },
+ { 5727, 139, 71, 137 },
+ { 5735, 238, 232, 170 },
+ { 5750, 152, 251, 152 },
+ { 5761, 175, 238, 238 },
+ { 5776, 219, 112, 147 },
+ { 5792, 238, 232, 170 },
+ { 5806, 152, 251, 152 },
+ { 5816, 154, 255, 154 },
+ { 5827, 144, 238, 144 },
+ { 5838, 124, 205, 124 },
+ { 5849, 84, 139, 84 },
+ { 5860, 175, 238, 238 },
+ { 5874, 187, 255, 255 },
+ { 5889, 174, 238, 238 },
+ { 5904, 150, 205, 205 },
+ { 5919, 102, 139, 139 },
+ { 5934, 219, 112, 147 },
+ { 5948, 255, 130, 171 },
+ { 5963, 238, 121, 159 },
+ { 5978, 205, 104, 137 },
+ { 5993, 139, 71, 93 },
+ { 6008, 255, 239, 213 },
+ { 6020, 255, 239, 213 },
+ { 6031, 255, 218, 185 },
+ { 6042, 255, 218, 185 },
+ { 6052, 255, 218, 185 },
+ { 6063, 238, 203, 173 },
+ { 6074, 205, 175, 149 },
+ { 6085, 139, 119, 101 },
+ { 6096, 205, 133, 63 },
+ { 6101, 255, 192, 203 },
+ { 6106, 255, 181, 197 },
+ { 6112, 238, 169, 184 },
+ { 6118, 205, 145, 158 },
+ { 6124, 139, 99, 108 },
+ { 6130, 221, 160, 221 },
+ { 6135, 255, 187, 255 },
+ { 6141, 238, 174, 238 },
+ { 6147, 205, 150, 205 },
+ { 6153, 139, 102, 139 },
+ { 6159, 176, 224, 230 },
+ { 6171, 176, 224, 230 },
+ { 6182, 160, 32, 240 },
+ { 6189, 155, 48, 255 },
+ { 6197, 145, 44, 238 },
+ { 6205, 125, 38, 205 },
+ { 6213, 85, 26, 139 },
+ { 6221, 255, 0, 0 },
+ { 6225, 255, 0, 0 },
+ { 6230, 238, 0, 0 },
+ { 6235, 205, 0, 0 },
+ { 6240, 139, 0, 0 },
+ { 6245, 188, 143, 143 },
+ { 6256, 188, 143, 143 },
+ { 6266, 255, 193, 193 },
+ { 6277, 238, 180, 180 },
+ { 6288, 205, 155, 155 },
+ { 6299, 139, 105, 105 },
+ { 6310, 65, 105, 225 },
+ { 6321, 65, 105, 225 },
+ { 6331, 72, 118, 255 },
+ { 6342, 67, 110, 238 },
+ { 6353, 58, 95, 205 },
+ { 6364, 39, 64, 139 },
+ { 6375, 139, 69, 19 },
+ { 6388, 139, 69, 19 },
+ { 6400, 250, 128, 114 },
+ { 6407, 255, 140, 105 },
+ { 6415, 238, 130, 98 },
+ { 6423, 205, 112, 84 },
+ { 6431, 139, 76, 57 },
+ { 6439, 244, 164, 96 },
+ { 6451, 244, 164, 96 },
+ { 6462, 46, 139, 87 },
+ { 6472, 46, 139, 87 },
+ { 6481, 84, 255, 159 },
+ { 6491, 78, 238, 148 },
+ { 6501, 67, 205, 128 },
+ { 6511, 46, 139, 87 },
+ { 6521, 255, 245, 238 },
+ { 6530, 255, 245, 238 },
+ { 6540, 238, 229, 222 },
+ { 6550, 205, 197, 191 },
+ { 6560, 139, 134, 130 },
+ { 6570, 160, 82, 45 },
+ { 6577, 255, 130, 71 },
+ { 6585, 238, 121, 66 },
+ { 6593, 205, 104, 57 },
+ { 6601, 139, 71, 38 },
+ { 6609, 135, 206, 235 },
+ { 6618, 135, 206, 235 },
+ { 6626, 135, 206, 255 },
+ { 6635, 126, 192, 238 },
+ { 6644, 108, 166, 205 },
+ { 6653, 74, 112, 139 },
+ { 6662, 106, 90, 205 },
+ { 6673, 112, 128, 144 },
+ { 6684, 112, 128, 144 },
+ { 6695, 106, 90, 205 },
+ { 6705, 131, 111, 255 },
+ { 6716, 122, 103, 238 },
+ { 6727, 105, 89, 205 },
+ { 6738, 71, 60, 139 },
+ { 6749, 112, 128, 144 },
+ { 6759, 198, 226, 255 },
+ { 6770, 185, 211, 238 },
+ { 6781, 159, 182, 205 },
+ { 6792, 108, 123, 139 },
+ { 6803, 112, 128, 144 },
+ { 6813, 255, 250, 250 },
+ { 6818, 255, 250, 250 },
+ { 6824, 238, 233, 233 },
+ { 6830, 205, 201, 201 },
+ { 6836, 139, 137, 137 },
+ { 6842, 0, 255, 127 },
+ { 6855, 0, 255, 127 },
+ { 6867, 0, 255, 127 },
+ { 6880, 0, 238, 118 },
+ { 6893, 0, 205, 102 },
+ { 6906, 0, 139, 69 },
+ { 6919, 70, 130, 180 },
+ { 6930, 70, 130, 180 },
+ { 6940, 99, 184, 255 },
+ { 6951, 92, 172, 238 },
+ { 6962, 79, 148, 205 },
+ { 6973, 54, 100, 139 },
+ { 6984, 210, 180, 140 },
+ { 6988, 255, 165, 79 },
+ { 6993, 238, 154, 73 },
+ { 6998, 205, 133, 63 },
+ { 7003, 139, 90, 43 },
+ { 7008, 216, 191, 216 },
+ { 7016, 255, 225, 255 },
+ { 7025, 238, 210, 238 },
+ { 7034, 205, 181, 205 },
+ { 7043, 139, 123, 139 },
+ { 7052, 255, 99, 71 },
+ { 7059, 255, 99, 71 },
+ { 7067, 238, 92, 66 },
+ { 7075, 205, 79, 57 },
+ { 7083, 139, 54, 38 },
+ { 7091, 64, 224, 208 },
+ { 7101, 0, 245, 255 },
+ { 7112, 0, 229, 238 },
+ { 7123, 0, 197, 205 },
+ { 7134, 0, 134, 139 },
+ { 7145, 238, 130, 238 },
+ { 7152, 208, 32, 144 },
+ { 7163, 208, 32, 144 },
+ { 7173, 255, 62, 150 },
+ { 7184, 238, 58, 140 },
+ { 7195, 205, 50, 120 },
+ { 7206, 139, 34, 82 },
+ { 7217, 245, 222, 179 },
+ { 7223, 255, 231, 186 },
+ { 7230, 238, 216, 174 },
+ { 7237, 205, 186, 150 },
+ { 7244, 139, 126, 102 },
+ { 7251, 255, 255, 255 },
+ { 7257, 245, 245, 245 },
+ { 7269, 245, 245, 245 },
+ { 7280, 255, 255, 0 },
+ { 7287, 154, 205, 50 },
+ { 7300, 255, 255, 0 },
+ { 7308, 238, 238, 0 },
+ { 7316, 205, 205, 0 },
+ { 7324, 139, 139, 0 },
+ { 7332, 154, 205, 50 }
+};
diff --git a/trunk/pango/pango-color.c b/trunk/pango/pango-color.c
new file mode 100644
index 00000000..beae87fa
--- /dev/null
+++ b/trunk/pango/pango-color.c
@@ -0,0 +1,259 @@
+/* pango
+ * pango-color.c: Color handling
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pango-attributes.h"
+#include "pango-impl-utils.h"
+
+GType
+pango_color_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoColor"),
+ (GBoxedCopyFunc) pango_color_copy,
+ (GBoxedFreeFunc) pango_color_free);
+
+ return our_type;
+}
+
+/**
+ * pango_color_copy:
+ * @src: color to copy
+ *
+ * Creates a copy of @src, which should be freed with
+ * pango_color_free(). Primarily used by language bindings,
+ * not that useful otherwise (since colors can just be copied
+ * by assignment in C).
+ *
+ * Return value: the newly allocated #PangoColor, which should
+ * be freed with pango_color_free().
+ **/
+PangoColor*
+pango_color_copy (const PangoColor *src)
+{
+ PangoColor *ret;
+
+ g_return_val_if_fail (src != NULL, NULL);
+
+ ret = g_slice_new (PangoColor);
+
+ *ret = *src;
+
+ return ret;
+}
+
+/**
+ * pango_color_free:
+ * @color: an allocated #PangoColor
+ *
+ * Frees a color allocated by pango_color_copy().
+ **/
+void
+pango_color_free (PangoColor *color)
+{
+ g_return_if_fail (color != NULL);
+
+ g_slice_free (PangoColor, color);
+}
+
+/**
+ * pango_color_to_string:
+ * @color: a #PangoColor
+ *
+ * Returns a textual specification of @color in the hexadecimal form
+ * <literal>&num;rrrrggggbbbb</literal>, where <literal>r</literal>,
+ * <literal>g</literal> and <literal>b</literal> are hex digits representing
+ * the red, green, and blue components respectively.
+ *
+ * Return value: a newly-allocated text string that must be freed with g_free().
+ *
+ * Since: 1.16
+ **/
+gchar *
+pango_color_to_string (const PangoColor *color)
+{
+ g_return_val_if_fail (color != NULL, NULL);
+
+ return g_strdup_printf ("#%04x%04x%04x", color->red, color->green, color->blue);
+}
+
+/* Color parsing
+ */
+
+/* The following 2 routines (parse_color, find_color) come from Tk, via the Win32
+ * port of GDK. The licensing terms on these (longer than the functions) is:
+ *
+ * This software is copyrighted by the Regents of the University of
+ * California, Sun Microsystems, Inc., and other parties. The following
+ * terms apply to all files associated with the software unless explicitly
+ * disclaimed in individual files.
+ *
+ * The authors hereby grant permission to use, copy, modify, distribute,
+ * and license this software and its documentation for any purpose, provided
+ * that existing copyright notices are retained in all copies and that this
+ * notice is included verbatim in any distributions. No written agreement,
+ * license, or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their authors
+ * and need not follow the licensing terms described here, provided that
+ * the new terms are clearly indicated on the first page of each file where
+ * they apply.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+ * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+ * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+ * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ *
+ * GOVERNMENT USE: If you are acquiring this software on behalf of the
+ * U.S. government, the Government shall have only "Restricted Rights"
+ * in the software and related documentation as defined in the Federal
+ * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+ * are acquiring the software on behalf of the Department of Defense, the
+ * software shall be classified as "Commercial Computer Software" and the
+ * Government shall have only "Restricted Rights" as defined in Clause
+ * 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+ * authors grant the U.S. Government and others acting in its behalf
+ * permission to use and distribute the software in accordance with the
+ * terms specified in this license.
+ */
+
+#include "pango-color-table.h"
+
+static int
+compare_xcolor_entries (const void *a, const void *b)
+{
+ return g_ascii_strcasecmp ((const char *) a, color_names + ((const ColorEntry *) b)->name_offset);
+}
+
+static gboolean
+find_color(const char *name,
+ PangoColor *color)
+{
+ ColorEntry *found;
+
+ found = bsearch (name, color_entries, G_N_ELEMENTS (color_entries),
+ sizeof (ColorEntry),
+ compare_xcolor_entries);
+ if (found == NULL)
+ return FALSE;
+
+ if (color)
+ {
+ color->red = (found->red * 65535) / 255;
+ color->green = (found->green * 65535) / 255;
+ color->blue = (found->blue * 65535) / 255;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+hex (const char *spec,
+ int len,
+ unsigned int *c)
+{
+ const char *end;
+ *c = 0;
+ for (end = spec + len; spec != end; spec++)
+ if (g_ascii_isxdigit (*spec))
+ *c = (*c << 4) | g_ascii_xdigit_value (*spec);
+ else
+ return FALSE;
+ return TRUE;
+}
+
+/**
+ * pango_color_parse:
+ * @color: a #PangoColor structure in which to store the result
+ * @spec: a string specifying the new color
+ *
+ * Fill in the fields of a color from a string specification. The
+ * string can either one of a large set of standard names. (Taken
+ * from the X11 <filename>rgb.txt</filename> file), or it can be a hex value in the
+ * form '&num;rgb' '&num;rrggbb' '&num;rrrgggbbb' or '&num;rrrrggggbbbb' where
+ * 'r', 'g' and 'b' are hex digits of the red, green, and blue
+ * components of the color, respectively. (White in the four
+ * forms is '&num;fff' '&num;ffffff' '&num;fffffffff' and '&num;ffffffffffff')
+ *
+ * Return value: %TRUE if parsing of the specifier succeeded,
+ * otherwise false.
+ **/
+gboolean
+pango_color_parse (PangoColor *color,
+ const char *spec)
+{
+ g_return_val_if_fail (spec != NULL, FALSE);
+
+ if (spec[0] == '#')
+ {
+ size_t len;
+ unsigned int r, g, b;
+
+ spec++;
+ len = strlen (spec);
+ if (len % 3 || len < 3 || len > 12)
+ return FALSE;
+
+ len /= 3;
+
+ if (!hex (spec, len, &r) ||
+ !hex (spec + len, len, &g) ||
+ !hex (spec + len * 2, len, &b))
+ return FALSE;
+
+ if (color)
+ {
+ int bits = len * 4;
+ r <<= 16 - bits;
+ g <<= 16 - bits;
+ b <<= 16 - bits;
+ while (bits < 16)
+ {
+ r |= (r >> bits);
+ g |= (g >> bits);
+ b |= (b >> bits);
+ bits *= 2;
+ }
+ color->red = r;
+ color->green = g;
+ color->blue = b;
+ }
+ }
+ else
+ {
+ if (!find_color (spec, color))
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/trunk/pango/pango-context.c b/trunk/pango/pango-context.c
new file mode 100644
index 00000000..6f588191
--- /dev/null
+++ b/trunk/pango/pango-context.c
@@ -0,0 +1,1640 @@
+/* Pango
+ * pango-context.c: Contexts for itemization and shaping
+ *
+ * Copyright (C) 2000, 2006 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "pango-context.h"
+#include "pango-impl-utils.h"
+
+#include "pango-engine.h"
+#include "pango-engine-private.h"
+#include "pango-modules.h"
+
+struct _PangoContext
+{
+ GObject parent_instance;
+
+ PangoLanguage *set_language;
+ PangoLanguage *language;
+ PangoDirection base_dir;
+ PangoGravity base_gravity;
+ PangoGravity resolved_gravity;
+ PangoGravityHint gravity_hint;
+
+ PangoFontDescription *font_desc;
+
+ PangoMatrix *matrix;
+
+ PangoFontMap *font_map;
+};
+
+struct _PangoContextClass
+{
+ GObjectClass parent_class;
+
+};
+
+static void pango_context_finalize (GObject *object);
+
+G_DEFINE_TYPE (PangoContext, pango_context, G_TYPE_OBJECT)
+
+static void
+pango_context_init (PangoContext *context)
+{
+ context->base_dir = PANGO_DIRECTION_WEAK_LTR;
+ context->resolved_gravity = context->base_gravity = PANGO_GRAVITY_SOUTH;
+ context->gravity_hint = PANGO_GRAVITY_HINT_NATURAL;
+
+ context->set_language = NULL;
+ context->language = pango_language_get_default ();
+ context->font_map = NULL;
+
+ context->font_desc = pango_font_description_new ();
+ pango_font_description_set_family_static (context->font_desc, "serif");
+ pango_font_description_set_style (context->font_desc, PANGO_STYLE_NORMAL);
+ pango_font_description_set_variant (context->font_desc, PANGO_VARIANT_NORMAL);
+ pango_font_description_set_weight (context->font_desc, PANGO_WEIGHT_NORMAL);
+ pango_font_description_set_stretch (context->font_desc, PANGO_STRETCH_NORMAL);
+ pango_font_description_set_size (context->font_desc, 12 * PANGO_SCALE);
+}
+
+static void
+pango_context_class_init (PangoContextClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = pango_context_finalize;
+}
+
+static void
+pango_context_finalize (GObject *object)
+{
+ PangoContext *context;
+
+ context = PANGO_CONTEXT (object);
+
+ if (context->font_map)
+ g_object_unref (context->font_map);
+
+ pango_font_description_free (context->font_desc);
+ if (context->matrix)
+ pango_matrix_free (context->matrix);
+
+ G_OBJECT_CLASS (pango_context_parent_class)->finalize (object);
+}
+
+
+/**
+ * pango_context_new:
+ *
+ * Creates a new #PangoContext initialized to default value.
+ *
+ * This function is only useful when implementing a new backend
+ * for Pango, something applications won't do. You should use
+ * the context creation function for the backend you are using,
+ * for example, pango_cairo_font_map_create_context(), pango_xft_get_context(),
+ * pango_win32_get_context() or, pango_ft2_font_map_create_context().
+ *
+ * If you are using Pango as part of a higher-level system,
+ * that system may have it's own ways of create a #PangoContext.
+ * For instance, the GTK+ toolkit has, among others,
+ * gdk_pango_context_get_for_screen(), and
+ * gtk_widget_get_pango_context().
+ *
+ * Return value: the newly allocated #PangoContext, which should
+ * be freed with g_object_unref().
+ **/
+PangoContext *
+pango_context_new (void)
+{
+ PangoContext *context;
+
+ context = g_object_new (PANGO_TYPE_CONTEXT, NULL);
+
+ return context;
+}
+
+static void
+update_resolved_gravity (PangoContext *context)
+{
+ if (context->base_gravity == PANGO_GRAVITY_AUTO)
+ context->resolved_gravity = pango_gravity_get_for_matrix (context->matrix);
+ else
+ context->resolved_gravity = context->base_gravity;
+}
+
+/**
+ * pango_context_set_matrix:
+ * @context: a #PangoContext
+ * @matrix: a #PangoMatrix, or %NULL to unset any existing matrix.
+ * (No matrix set is the same as setting the identity matrix.)
+ *
+ * Sets the transformation matrix that will be applied when rendering
+ * with this context. Note that reported metrics are in the user space
+ * coordinates before the application of the matrix, not device-space
+ * coordinates after the application of the matrix. So, they don't scale
+ * with the matrix, though they may change slightly for different
+ * matrices, depending on how the text is fit to the pixel grid.
+ *
+ * Since: 1.6
+ **/
+void
+pango_context_set_matrix (PangoContext *context,
+ const PangoMatrix *matrix)
+{
+ g_return_if_fail (PANGO_IS_CONTEXT (context));
+
+ if (context->matrix)
+ pango_matrix_free (context->matrix);
+ if (matrix)
+ context->matrix = pango_matrix_copy (matrix);
+ else
+ context->matrix = NULL;
+
+ update_resolved_gravity (context);
+}
+
+/**
+ * pango_context_get_matrix:
+ * @context: a #PangoContext
+ *
+ * Gets the transformation matrix that will be applied when
+ * rendering with this context. See pango_context_set_matrix().
+ *
+ * Return value: the matrix, or %NULL if no matrix has been set
+ * (which is the same as the identity matrix). The returned
+ * matrix is owned by Pango and must not be modified or
+ * freed.
+ *
+ * Since: 1.6
+ **/
+G_CONST_RETURN PangoMatrix *
+pango_context_get_matrix (PangoContext *context)
+{
+ g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
+
+ return context->matrix;
+}
+
+/**
+ * pango_context_set_font_map:
+ * @context: a #PangoContext
+ * @font_map: the #PangoFontMap to set.
+ *
+ * Sets the font map to be searched when fonts are looked-up in this context.
+ * This is only for internal use by Pango backends, a #PangoContext obtained
+ * via one of the recommended methods should already have a suitable font map.
+ **/
+void
+pango_context_set_font_map (PangoContext *context,
+ PangoFontMap *font_map)
+{
+ g_return_if_fail (PANGO_IS_CONTEXT (context));
+ g_return_if_fail (!font_map || PANGO_IS_FONT_MAP (font_map));
+
+ if (font_map)
+ g_object_ref (font_map);
+
+ if (context->font_map)
+ g_object_unref (context->font_map);
+
+ context->font_map = font_map;
+}
+
+/**
+ * pango_context_get_font_map:
+ * @context: a #PangoContext
+ *
+ * Gets the #PangoFontmap used to look up fonts for this context.
+ *
+ * Return value: the font map for the #PangoContext. This value
+ * is owned by Pango and should not be unreferenced.
+ *
+ * Since: 1.6
+ **/
+PangoFontMap *
+pango_context_get_font_map (PangoContext *context)
+{
+ g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
+
+ return context->font_map;
+}
+
+/**
+ * pango_context_list_families:
+ * @context: a #PangoContext
+ * @families: location to store a pointer to an array of #PangoFontFamily *.
+ * This array should be freed with g_free().
+ * @n_families: location to store the number of elements in @descs
+ *
+ * List all families for a context.
+ **/
+void
+pango_context_list_families (PangoContext *context,
+ PangoFontFamily ***families,
+ int *n_families)
+{
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (families == NULL || n_families != NULL);
+
+ if (n_families == NULL)
+ return;
+
+ if (context->font_map == NULL)
+ {
+ *n_families = 0;
+ if (families)
+ *families = NULL;
+
+ return;
+ }
+ else
+ pango_font_map_list_families (context->font_map, families, n_families);
+}
+
+/**
+ * pango_context_load_font:
+ * @context: a #PangoContext
+ * @desc: a #PangoFontDescription describing the font to load
+ *
+ * Loads the font in one of the fontmaps in the context
+ * that is the closest match for @desc.
+ *
+ * Returns the font loaded, or %NULL if no font matched.
+ **/
+PangoFont *
+pango_context_load_font (PangoContext *context,
+ const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (pango_font_description_get_family (desc) != NULL, NULL);
+
+ return pango_font_map_load_font (context->font_map, context, desc);
+}
+
+/**
+ * pango_context_load_fontset:
+ * @context: a #PangoContext
+ * @desc: a #PangoFontDescription describing the fonts to load
+ * @language: a #PangoLanguage the fonts will be used for
+ *
+ * Load a set of fonts in the context that can be used to render
+ * a font matching @desc.
+ *
+ * Returns the fontset, or %NULL if no font matched.
+ **/
+PangoFontset *
+pango_context_load_fontset (PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (pango_font_description_get_family (desc) != NULL, NULL);
+ g_return_val_if_fail (pango_font_description_get_size (desc) != 0, NULL);
+
+ return pango_font_map_load_fontset (context->font_map, context, desc, language);
+}
+
+/**
+ * pango_context_set_font_description:
+ * @context: a #PangoContext
+ * @desc: the new pango font description
+ *
+ * Set the default font description for the context
+ **/
+void
+pango_context_set_font_description (PangoContext *context,
+ const PangoFontDescription *desc)
+{
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (desc != NULL);
+
+ pango_font_description_free (context->font_desc);
+ context->font_desc = pango_font_description_copy (desc);
+}
+
+/**
+ * pango_context_get_font_description:
+ * @context: a #PangoContext
+ *
+ * Retrieve the default font description for the context.
+ *
+ * Return value: a pointer to the context's default font description.
+ * This value must not be modified or freed.
+ **/
+PangoFontDescription *
+pango_context_get_font_description (PangoContext *context)
+{
+ g_return_val_if_fail (context != NULL, NULL);
+
+ return context->font_desc;
+}
+
+/**
+ * pango_context_set_language:
+ * @context: a #PangoContext
+ * @language: the new language tag.
+ *
+ * Sets the global language tag for the context. The default language
+ * for the locale of the running process can be found using
+ * pango_language_get_default().
+ **/
+void
+pango_context_set_language (PangoContext *context,
+ PangoLanguage *language)
+{
+ g_return_if_fail (context != NULL);
+
+ context->set_language = language;
+ if (language)
+ context->language = language;
+ else
+ context->language = pango_language_get_default ();
+}
+
+/**
+ * pango_context_get_language:
+ * @context: a #PangoContext
+ *
+ * Retrieves the global language tag for the context.
+ *
+ * Return value: the global language tag.
+ **/
+PangoLanguage *
+pango_context_get_language (PangoContext *context)
+{
+ g_return_val_if_fail (context != NULL, NULL);
+
+ return context->set_language;
+}
+
+/**
+ * pango_context_set_base_dir:
+ * @context: a #PangoContext
+ * @direction: the new base direction
+ *
+ * Sets the base direction for the context.
+ *
+ * The base direction is used in applying the Unicode bidirectional
+ * algorithm; if the @direction is %PANGO_DIRECTION_LTR or
+ * %PANGO_DIRECTION_RTL, then the value will be used as the paragraph
+ * direction in the Unicode bidirectional algorithm. A value of
+ * %PANGO_DIRECTION_WEAK_LTR or %PANGO_DIRECTION_WEAK_RTL is used only
+ * for paragraphs that do not contain any strong characters themselves.
+ **/
+void
+pango_context_set_base_dir (PangoContext *context,
+ PangoDirection direction)
+{
+ g_return_if_fail (context != NULL);
+
+ context->base_dir = direction;
+}
+
+/**
+ * pango_context_get_base_dir:
+ * @context: a #PangoContext
+ *
+ * Retrieves the base direction for the context. See
+ * pango_context_set_base_dir().
+ *
+ * Return value: the base direction for the context.
+ **/
+PangoDirection
+pango_context_get_base_dir (PangoContext *context)
+{
+ g_return_val_if_fail (context != NULL, PANGO_DIRECTION_LTR);
+
+ return context->base_dir;
+}
+
+/**
+ * pango_context_set_base_gravity:
+ * @context: a #PangoContext
+ * @gravity: the new base gravity
+ *
+ * Sets the base gravity for the context.
+ *
+ * The base gravity is used in laying vertical text out.
+ *
+ * Since: 1.16
+ **/
+void
+pango_context_set_base_gravity (PangoContext *context,
+ PangoGravity gravity)
+{
+ g_return_if_fail (context != NULL);
+
+ context->base_gravity = gravity;
+
+ update_resolved_gravity (context);
+}
+
+/**
+ * pango_context_get_base_gravity:
+ * @context: a #PangoContext
+ *
+ * Retrieves the base gravity for the context. See
+ * pango_context_set_base_gravity().
+ *
+ * Return value: the base gravity for the context.
+ *
+ * Since: 1.16
+ **/
+PangoGravity
+pango_context_get_base_gravity (PangoContext *context)
+{
+ g_return_val_if_fail (context != NULL, PANGO_GRAVITY_SOUTH);
+
+ return context->base_gravity;
+}
+
+/**
+ * pango_context_get_gravity:
+ * @context: a #PangoContext
+ *
+ * Retrieves the gravity for the context. This is similar to
+ * pango_context_get_base_gravity(), except for when the base gravity
+ * is %PANGO_GRAVITY_AUTO for which pango_gravity_get_for_matrix() is used
+ * to return the gravity from the current context matrix.
+ *
+ * Return value: the resolved gravity for the context.
+ *
+ * Since: 1.16
+ **/
+PangoGravity
+pango_context_get_gravity (PangoContext *context)
+{
+ g_return_val_if_fail (context != NULL, PANGO_GRAVITY_SOUTH);
+
+ return context->resolved_gravity;
+}
+
+/**
+ * pango_context_set_gravity_hint:
+ * @context: a #PangoContext
+ * @hint: the new gravity hint
+ *
+ * Sets the gravity hint for the context.
+ *
+ * The gravity hint is used in laying vertical text out, and is only relevant
+ * if gravity of the context as returned by pango_context_get_gravity()
+ * is set %PANGO_GRAVITY_EAST or %PANGO_GRAVITY_WEST.
+ *
+ * Since: 1.16
+ **/
+void
+pango_context_set_gravity_hint (PangoContext *context,
+ PangoGravityHint hint)
+{
+ g_return_if_fail (context != NULL);
+
+ context->gravity_hint = hint;
+}
+
+/**
+ * pango_context_get_gravity_hint:
+ * @context: a #PangoContext
+ *
+ * Retrieves the gravity hint for the context. See
+ * pango_context_set_gravity_hint() for details.
+ *
+ * Return value: the gravity hint for the context.
+ *
+ * Since: 1.16
+ **/
+PangoGravityHint
+pango_context_get_gravity_hint (PangoContext *context)
+{
+ g_return_val_if_fail (context != NULL, PANGO_GRAVITY_HINT_NATURAL);
+
+ return context->gravity_hint;
+}
+
+/**********************************************************************/
+
+static gboolean
+advance_attr_iterator_to (PangoAttrIterator *iterator,
+ int start_index)
+{
+ int start_range, end_range;
+
+ pango_attr_iterator_range (iterator, &start_range, &end_range);
+
+ while (start_index >= end_range)
+ {
+ if (!pango_attr_iterator_next (iterator))
+ return FALSE;
+ pango_attr_iterator_range (iterator, &start_range, &end_range);
+ }
+
+ if (start_range > start_index)
+ g_warning ("In pango_itemize(), the cached iterator passed in "
+ "had already moved beyond the start_index");
+
+ return TRUE;
+}
+
+/***************************************************************************
+ * We cache the results of character,fontset => font,shaper in a hash table
+ ***************************************************************************/
+
+typedef struct {
+ GHashTable *hash;
+} ShaperFontCache;
+
+typedef struct {
+ PangoEngineShape *shape_engine;
+ PangoFont *font;
+} ShaperFontElement;
+
+static void
+shaper_font_cache_destroy (ShaperFontCache *cache)
+{
+ g_hash_table_destroy (cache->hash);
+ g_slice_free (ShaperFontCache, cache);
+}
+
+static void
+shaper_font_element_destroy (ShaperFontElement *element)
+{
+ if (element->font)
+ g_object_unref (element->font);
+ g_slice_free (ShaperFontElement, element);
+}
+
+static ShaperFontCache *
+get_shaper_font_cache (PangoFontset *fontset)
+{
+ ShaperFontCache *cache;
+
+ static GQuark cache_quark = 0;
+ if (!cache_quark)
+ cache_quark = g_quark_from_static_string ("pango-shaper-font-cache");
+
+ cache = g_object_get_qdata (G_OBJECT (fontset), cache_quark);
+ if (!cache)
+ {
+ cache = g_slice_new (ShaperFontCache);
+ cache->hash = g_hash_table_new_full (g_direct_hash, NULL,
+ NULL, (GDestroyNotify)shaper_font_element_destroy);
+
+ g_object_set_qdata_full (G_OBJECT (fontset), cache_quark,
+ cache, (GDestroyNotify)shaper_font_cache_destroy);
+ }
+
+ return cache;
+}
+
+static gboolean
+shaper_font_cache_get (ShaperFontCache *cache,
+ gunichar wc,
+ PangoEngineShape **shape_engine,
+ PangoFont **font)
+{
+ ShaperFontElement *element;
+
+ element = g_hash_table_lookup (cache->hash, GUINT_TO_POINTER (wc));
+ if (element)
+ {
+ *shape_engine = element->shape_engine;
+ *font = element->font;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void
+shaper_font_cache_insert (ShaperFontCache *cache,
+ gunichar wc,
+ PangoEngineShape *shape_engine,
+ PangoFont *font)
+{
+ ShaperFontElement *element = g_slice_new (ShaperFontElement);
+ element->shape_engine = shape_engine;
+ element->font = font;
+
+ g_hash_table_insert (cache->hash, GUINT_TO_POINTER (wc), element);
+}
+
+/**********************************************************************/
+
+typedef enum {
+ EMBEDDING_CHANGED = 1 << 0,
+ SCRIPT_CHANGED = 1 << 1,
+ LANG_CHANGED = 1 << 2,
+ FONT_CHANGED = 1 << 3,
+ DERIVED_LANG_CHANGED = 1 << 4
+} ChangedFlags;
+
+typedef struct _ItemizeState ItemizeState;
+
+struct _ItemizeState
+{
+ PangoContext *context;
+ const char *text;
+ const char *end;
+
+ const char *run_start;
+ const char *run_end;
+
+ GList *result;
+ PangoItem *item;
+
+ guint8 *embedding_levels;
+ int embedding_end_offset;
+ const char *embedding_end;
+ guint8 embedding;
+
+ PangoGravity gravity;
+ PangoGravityHint gravity_hint;
+ PangoGravity resolved_gravity;
+ PangoGravity font_desc_gravity;
+ gboolean centered_baseline;
+
+ PangoAttrIterator *attr_iter;
+ gboolean free_attr_iter;
+ const char *attr_end;
+ PangoFontDescription *font_desc;
+ PangoLanguage *lang;
+ GSList *extra_attrs;
+ gboolean copy_extra_attrs;
+
+ ChangedFlags changed;
+
+ PangoScriptIter *script_iter;
+ const char *script_end;
+ PangoScript script;
+
+ PangoLanguage *derived_lang;
+ PangoEngineLang *lang_engine;
+
+ PangoFontset *current_fonts;
+ ShaperFontCache *cache;
+ PangoFont *base_font;
+ gboolean enable_fallback;
+
+ GSList *exact_engines;
+ GSList *fallback_engines;
+};
+
+static void
+update_embedding_end (ItemizeState *state)
+{
+ state->embedding = state->embedding_levels[state->embedding_end_offset];
+ while (state->embedding_end < state->end &&
+ state->embedding_levels[state->embedding_end_offset] == state->embedding)
+ {
+ state->embedding_end_offset++;
+ state->embedding_end = g_utf8_next_char (state->embedding_end);
+ }
+
+ state->changed |= EMBEDDING_CHANGED;
+}
+
+static PangoAttribute *
+find_attribute (GSList *attr_list,
+ PangoAttrType type)
+{
+ GSList *node;
+
+ for (node = attr_list; node; node = node->next)
+ if (((PangoAttribute *) node->data)->klass->type == type)
+ return (PangoAttribute *) node->data;
+
+ return NULL;
+}
+
+static void
+update_attr_iterator (ItemizeState *state)
+{
+ PangoLanguage *old_lang;
+ PangoAttribute *attr;
+ int end_index;
+
+ pango_attr_iterator_range (state->attr_iter, NULL, &end_index);
+ if (end_index < state->end - state->text)
+ state->attr_end = state->text + end_index;
+ else
+ state->attr_end = state->end;
+
+ old_lang = state->lang;
+ if (state->font_desc)
+ pango_font_description_free (state->font_desc);
+ state->font_desc = pango_font_description_copy_static (state->context->font_desc);
+ pango_attr_iterator_get_font (state->attr_iter, state->font_desc,
+ &state->lang, &state->extra_attrs);
+ if (pango_font_description_get_set_fields (state->font_desc) & PANGO_FONT_MASK_GRAVITY)
+ state->font_desc_gravity = pango_font_description_get_gravity (state->font_desc);
+ else
+ state->font_desc_gravity = PANGO_GRAVITY_AUTO;
+
+ state->copy_extra_attrs = FALSE;
+
+ if (!state->lang)
+ state->lang = state->context->language;
+
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_FALLBACK);
+ state->enable_fallback = (attr == NULL || ((PangoAttrInt *)attr)->value);
+
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY);
+ state->gravity = attr == NULL ? PANGO_GRAVITY_AUTO : ((PangoAttrInt *)attr)->value;
+
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY_HINT);
+ state->gravity_hint = attr == NULL ? state->context->gravity_hint : ((PangoAttrInt *)attr)->value;
+
+ state->changed |= FONT_CHANGED;
+ if (state->lang != old_lang)
+ state->changed |= LANG_CHANGED;
+}
+
+static void
+update_end (ItemizeState *state)
+{
+ state->run_end = state->embedding_end;
+ if (state->attr_end < state->run_end)
+ state->run_end = state->attr_end;
+ if (state->script_end < state->run_end)
+ state->run_end = state->script_end;
+}
+
+static void
+itemize_state_init (ItemizeState *state,
+ PangoContext *context,
+ const char *text,
+ PangoDirection base_dir,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter,
+ const PangoFontDescription *desc)
+{
+
+ state->context = context;
+ state->text = text;
+ state->end = text + start_index + length;
+
+ state->result = NULL;
+ state->item = NULL;
+
+ state->run_start = text + start_index;
+
+ /* First, apply the bidirectional algorithm to break
+ * the text into directional runs.
+ */
+ state->embedding_levels = pango_log2vis_get_embedding_levels (text + start_index, length, &base_dir);
+
+ state->embedding_end_offset = 0;
+ state->embedding_end = text + start_index;
+ update_embedding_end (state);
+
+ /* Initialize the attribute iterator
+ */
+ if (cached_iter)
+ {
+ state->attr_iter = cached_iter;
+ state->free_attr_iter = FALSE;
+ }
+ else if (attrs)
+ {
+ state->attr_iter = pango_attr_list_get_iterator (attrs);
+ state->free_attr_iter = TRUE;
+ }
+ else
+ {
+ state->attr_iter = NULL;
+ state->free_attr_iter = FALSE;
+ }
+
+ if (state->attr_iter)
+ {
+ state->font_desc = NULL;
+ state->lang = NULL;
+
+ advance_attr_iterator_to (state->attr_iter, start_index);
+ update_attr_iterator (state);
+ }
+ else
+ {
+ state->font_desc = pango_font_description_copy_static (desc ? desc : state->context->font_desc);
+ state->lang = state->context->language;
+ state->extra_attrs = NULL;
+ state->copy_extra_attrs = FALSE;
+
+ state->attr_end = state->end;
+ state->enable_fallback = TRUE;
+ }
+
+ /* Initialize the script iterator
+ */
+ state->script_iter = pango_script_iter_new (text + start_index, length);
+ pango_script_iter_get_range (state->script_iter, NULL,
+ &state->script_end, &state->script);
+
+ update_end (state);
+
+ if (pango_font_description_get_set_fields (state->font_desc) & PANGO_FONT_MASK_GRAVITY)
+ state->font_desc_gravity = pango_font_description_get_gravity (state->font_desc);
+ else
+ state->font_desc_gravity = PANGO_GRAVITY_AUTO;
+
+ state->gravity = PANGO_GRAVITY_AUTO;
+ state->centered_baseline = PANGO_GRAVITY_IS_VERTICAL (state->context->resolved_gravity);
+ state->gravity_hint = state->context->gravity_hint;
+ state->resolved_gravity = PANGO_GRAVITY_AUTO;
+ state->derived_lang = NULL;
+ state->lang_engine = NULL;
+ state->current_fonts = NULL;
+ state->cache = NULL;
+ state->exact_engines = NULL;
+ state->fallback_engines = NULL;
+ state->base_font = NULL;
+
+ state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED | FONT_CHANGED;
+}
+
+static gboolean
+itemize_state_next (ItemizeState *state)
+{
+ if (state->run_end == state->end)
+ return FALSE;
+
+ state->changed = 0;
+
+ state->run_start = state->run_end;
+
+ if (state->run_end == state->embedding_end)
+ {
+ update_embedding_end (state);
+ }
+
+ if (state->run_end == state->attr_end)
+ {
+ pango_attr_iterator_next (state->attr_iter);
+ update_attr_iterator (state);
+ }
+
+ if (state->run_end == state->script_end)
+ {
+ pango_script_iter_next (state->script_iter);
+ pango_script_iter_get_range (state->script_iter, NULL,
+ &state->script_end, &state->script);
+ state->changed |= SCRIPT_CHANGED;
+ }
+
+ update_end (state);
+
+ return TRUE;
+}
+
+static GSList *
+copy_attr_slist (GSList *attr_slist)
+{
+ GSList *new_list = NULL;
+ GSList *l;
+
+ for (l = attr_slist; l; l = l->next)
+ new_list = g_slist_prepend (new_list, pango_attribute_copy (l->data));
+
+ return g_slist_reverse (new_list);
+}
+
+static void
+itemize_state_fill_shaper (ItemizeState *state,
+ PangoEngineShape *shape_engine,
+ PangoFont *font)
+{
+ GList *l;
+
+ for (l = state->result; l; l = l->next)
+ {
+ PangoItem *item = l->data;
+ if (item->analysis.shape_engine)
+ break;
+ if (font)
+ item->analysis.font = g_object_ref (font);
+ else
+ item->analysis.font = NULL;
+ item->analysis.shape_engine = shape_engine;
+ }
+}
+
+static void
+itemize_state_add_character (ItemizeState *state,
+ PangoEngineShape *shape_engine,
+ PangoFont *font,
+ gboolean force_break,
+ const char *pos)
+{
+ if (state->item)
+ {
+ if (!state->item->analysis.shape_engine && shape_engine)
+ {
+ itemize_state_fill_shaper (state, shape_engine, font);
+ }
+ else if (state->item->analysis.shape_engine && !shape_engine)
+ {
+ font = state->item->analysis.font;
+ shape_engine = state->item->analysis.shape_engine;
+ }
+
+ if (!force_break &&
+ state->item->analysis.lang_engine == state->lang_engine &&
+ state->item->analysis.shape_engine == shape_engine &&
+ state->item->analysis.font == font)
+ {
+ state->item->num_chars++;
+ return;
+ }
+
+ state->item->length = (pos - state->text) - state->item->offset;
+ }
+
+ state->item = pango_item_new ();
+ state->item->offset = pos - state->text;
+ state->item->length = 0;
+ state->item->num_chars = 1;
+ state->item->analysis.shape_engine = shape_engine;
+ state->item->analysis.lang_engine = state->lang_engine;
+
+ if (font)
+ g_object_ref (font);
+ state->item->analysis.font = font;
+
+ state->item->analysis.level = state->embedding;
+ state->item->analysis.gravity = state->resolved_gravity;
+
+ /* The level vs. gravity dance:
+ * - If gravity is SOUTH, leave level untouched.
+ * - If gravity is NORTH, step level one up, to
+ * not get mirrored upside-down text.
+ * - If gravity is EAST, step up to an even level, as
+ * it's a clockwise-rotated layout, so the rotated
+ * top is unrotated left.
+ * - If gravity is WEST, step up to an odd level, as
+ * it's a counter-clockwise-rotated layout, so the rotated
+ * top is unrotated right.
+ *
+ * A similar dance is performed in pango-layout.c:
+ * line_set_resolved_dir(). Keep in synch.
+ */
+ switch (state->item->analysis.gravity)
+ {
+ case PANGO_GRAVITY_SOUTH:
+ default:
+ break;
+ case PANGO_GRAVITY_NORTH:
+ state->item->analysis.level++;
+ break;
+ case PANGO_GRAVITY_EAST:
+ state->item->analysis.level += 1;
+ state->item->analysis.level &= ~1;
+ break;
+ case PANGO_GRAVITY_WEST:
+ state->item->analysis.level |= 1;
+ break;
+ }
+
+ state->item->analysis.flags = state->centered_baseline ? PANGO_ANALYSIS_FLAG_CENTERED_BASELINE : 0;
+
+ state->item->analysis.script = state->script;
+ state->item->analysis.language = state->derived_lang;
+
+ if (state->copy_extra_attrs)
+ {
+ state->item->analysis.extra_attrs = copy_attr_slist (state->extra_attrs);
+ }
+ else
+ {
+ state->item->analysis.extra_attrs = state->extra_attrs;
+ state->copy_extra_attrs = TRUE;
+ }
+
+ state->result = g_list_prepend (state->result, state->item);
+}
+
+static void
+get_engines (PangoContext *context,
+ PangoLanguage *lang,
+ PangoScript script,
+ GSList **exact_engines,
+ GSList **fallback_engines)
+{
+ const char *engine_type = pango_font_map_get_shape_engine_type (context->font_map);
+ PangoMap *shaper_map = pango_find_map (lang,
+ g_quark_from_string (PANGO_ENGINE_TYPE_SHAPE),
+ g_quark_from_string (engine_type));
+ pango_map_get_engines (shaper_map, script,
+ exact_engines, fallback_engines);
+}
+
+typedef struct {
+ PangoLanguage *lang;
+ gunichar wc;
+ GSList *engines;
+ PangoEngineShape *shape_engine;
+ PangoFont *font;
+} GetShaperFontInfo;
+
+static gboolean
+get_shaper_and_font_foreach (PangoFontset *fontset,
+ PangoFont *font,
+ gpointer data)
+{
+ GetShaperFontInfo *info = data;
+ GSList *l;
+
+ for (l = info->engines; l; l = l->next)
+ {
+ PangoEngineShape *engine = l->data;
+ PangoCoverageLevel level;
+
+ level = _pango_engine_shape_covers (engine, font,
+ info->lang, info->wc);
+ if (level != PANGO_COVERAGE_NONE)
+ {
+ info->shape_engine = engine;
+ info->font = g_object_ref (font);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static PangoFont *
+get_base_font (ItemizeState *state)
+{
+ if (!state->base_font)
+ state->base_font = pango_font_map_load_font (state->context->font_map,
+ state->context,
+ state->font_desc);
+ return state->base_font;
+}
+
+static gboolean
+get_shaper_and_font (ItemizeState *state,
+ gunichar wc,
+ PangoEngineShape **shape_engine,
+ PangoFont **font)
+{
+ GetShaperFontInfo info;
+
+ /* We'd need a separate cache when fallback is disabled, but since lookup
+ * with fallback disabled is faster anyways, we just skip caching */
+ if (state->enable_fallback && shaper_font_cache_get (state->cache, wc, shape_engine, font))
+ return *shape_engine != NULL;
+
+ if (!state->exact_engines && !state->fallback_engines)
+ {
+ /* Always use a basic shaper for vertical layout (ie, east/west gravity)
+ * as we do not support vertical shaping as of now.
+ */
+ PangoScript script;
+
+ if (PANGO_GRAVITY_IS_VERTICAL (state->resolved_gravity))
+ script = PANGO_SCRIPT_COMMON;
+ else
+ script = state->script;
+
+ get_engines (state->context, state->derived_lang, script,
+ &state->exact_engines, &state->fallback_engines);
+ }
+
+ info.lang = state->derived_lang;
+ info.wc = wc;
+ info.shape_engine = NULL;
+ info.font = NULL;
+
+ info.engines = state->exact_engines;
+ if (state->enable_fallback)
+ pango_fontset_foreach (state->current_fonts, get_shaper_and_font_foreach, &info);
+ else
+ get_shaper_and_font_foreach (NULL, get_base_font (state), &info);
+
+ if (info.shape_engine)
+ {
+ *shape_engine = info.shape_engine;
+ *font = info.font;
+
+ /* skip caching if fallback disabled (see above) */
+ if (state->enable_fallback)
+ shaper_font_cache_insert (state->cache, wc, *shape_engine, *font);
+
+ return TRUE;
+ }
+
+ info.engines = state->fallback_engines;
+ if (state->enable_fallback)
+ pango_fontset_foreach (state->current_fonts, get_shaper_and_font_foreach, &info);
+ else
+ get_shaper_and_font_foreach (NULL, get_base_font (state), &info);
+
+ *shape_engine = info.shape_engine;
+ *font = info.font;
+
+ /* skip caching if fallback disabled (see above) */
+ if (state->enable_fallback)
+ shaper_font_cache_insert (state->cache, wc, *shape_engine, *font);
+
+ return *shape_engine != NULL;
+}
+
+static void
+itemize_state_reset_shape_engines (ItemizeState *state)
+{
+ g_slist_free (state->exact_engines);
+ state->exact_engines = NULL;
+ g_slist_free (state->fallback_engines);
+ state->fallback_engines = NULL;
+}
+
+static PangoLanguage *
+compute_derived_language (PangoLanguage *lang,
+ PangoScript script)
+{
+ PangoLanguage *derived_lang;
+
+ /* Make sure the language tag is consistent with the derived
+ * script. There is no point in marking up a section of
+ * Arabic text with the "en" language tag.
+ */
+ if (lang && pango_language_includes_script (lang, script))
+ derived_lang = lang;
+ else
+ {
+ derived_lang = pango_script_get_sample_language (script);
+ /* If we don't find a sample language for the script, we
+ * use a language tag that shouldn't actually be used
+ * anywhere. This keeps fontconfig (for the PangoFc*
+ * backend) from using the language tag to affect the
+ * sort order. I don't have a reference for 'xx' being
+ * safe here, though Keith Packard claims it is.
+ */
+ if (!derived_lang)
+ derived_lang = pango_language_from_string ("xx");
+ }
+
+ return derived_lang;
+}
+
+static PangoMap *
+get_lang_map (PangoLanguage *lang)
+{
+ static guint engine_type_id = 0;
+ static guint render_type_id = 0;
+
+ if (engine_type_id == 0)
+ {
+ engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_LANG);
+ render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_NONE);
+ }
+
+ return pango_find_map (lang, engine_type_id, render_type_id);
+}
+
+static void
+itemize_state_update_for_new_run (ItemizeState *state)
+{
+ /* This block should be moved to update_attr_iterator, but I'm too lazy to
+ * do it right now */
+ if (state->changed & (FONT_CHANGED | SCRIPT_CHANGED))
+ {
+ PangoGravity old_gravity = state->resolved_gravity;
+
+ if (state->font_desc_gravity != PANGO_GRAVITY_AUTO)
+ {
+ state->resolved_gravity = state->font_desc_gravity;
+ }
+ else
+ {
+ PangoGravity gravity = state->gravity;
+ PangoGravityHint gravity_hint = state->gravity_hint;
+
+ if (G_LIKELY (gravity == PANGO_GRAVITY_AUTO))
+ gravity = state->context->resolved_gravity;
+
+ state->resolved_gravity = pango_gravity_get_for_script (state->script,
+ gravity,
+ gravity_hint);
+ }
+
+ if (old_gravity != state->resolved_gravity)
+ {
+ pango_font_description_set_gravity (state->font_desc, state->resolved_gravity);
+ state->changed |= FONT_CHANGED;
+ }
+ }
+
+ if (state->changed & (SCRIPT_CHANGED | LANG_CHANGED))
+ {
+ PangoLanguage *old_derived_lang = state->derived_lang;
+ state->derived_lang = compute_derived_language (state->lang, state->script);
+ if (old_derived_lang != state->derived_lang)
+ state->changed |= DERIVED_LANG_CHANGED;
+ }
+
+ if ((state->changed & DERIVED_LANG_CHANGED) || !state->lang_engine)
+ {
+ PangoMap *lang_map = get_lang_map (state->derived_lang);
+ state->lang_engine = (PangoEngineLang *)pango_map_get_engine (lang_map, state->script);
+ }
+
+ if (state->changed & (SCRIPT_CHANGED | DERIVED_LANG_CHANGED))
+ itemize_state_reset_shape_engines (state);
+
+ if (state->changed & (FONT_CHANGED | DERIVED_LANG_CHANGED) &&
+ state->current_fonts)
+ {
+ g_object_unref (state->current_fonts);
+ state->current_fonts = NULL;
+ state->cache = NULL;
+ }
+
+ if (!state->current_fonts)
+ {
+ state->current_fonts = pango_font_map_load_fontset (state->context->font_map,
+ state->context,
+ state->font_desc,
+ state->derived_lang);
+ state->cache = get_shaper_font_cache (state->current_fonts);
+ }
+
+ if ((state->changed & FONT_CHANGED) && state->base_font)
+ {
+ g_object_unref (state->base_font);
+ state->base_font = NULL;
+ }
+}
+
+static void
+itemize_state_process_run (ItemizeState *state)
+{
+ const char *p;
+ gboolean last_was_forced_break = FALSE;
+
+ /* Only one character has type G_UNICODE_LINE_SEPARATOR in Unicode 4.0;
+ * update this if that changes. */
+#define LINE_SEPARATOR 0x2028
+
+ itemize_state_update_for_new_run (state);
+
+ /* We should never get an empty run */
+ g_assert (state->run_end != state->run_start);
+
+ for (p = state->run_start;
+ p < state->run_end;
+ p = g_utf8_next_char (p))
+ {
+ gunichar wc = g_utf8_get_char (p);
+ gboolean is_forced_break = (wc == '\t' || wc == LINE_SEPARATOR);
+ PangoEngineShape *shape_engine;
+ PangoFont *font;
+
+ /* We don't want space characters to affect font selection; in general,
+ * it's always wrong to select a font just to render a space. But until
+ * we have a better solution, choosing a font for spaces seems to work
+ * better. However, all fonts are assumed to cover ASCII space, so that
+ * one is an exception. See bug #355987.
+ *
+ * The exception of PrivateUse and Unassigned characters is necessary
+ * to be able to render any of them. (for private or being encoded
+ * scripts, etc.)
+ */
+ if (wc == 0x0020 ||
+ G_UNLIKELY (!g_unichar_isprint (wc) &&
+ g_unichar_type (wc) != G_UNICODE_PRIVATE_USE &&
+ g_unichar_type (wc) != G_UNICODE_UNASSIGNED))
+ {
+ shape_engine = NULL;
+ font = NULL;
+ }
+ else
+ {
+ get_shaper_and_font (state, wc, &shape_engine, &font);
+ }
+
+ itemize_state_add_character (state,
+ shape_engine, font,
+ is_forced_break || last_was_forced_break,
+ p);
+
+ last_was_forced_break = is_forced_break;
+ }
+
+ /* Finish the final item from the current segment */
+ state->item->length = (p - state->text) - state->item->offset;
+ if (!state->item->analysis.shape_engine)
+ {
+ PangoEngineShape *shape_engine;
+ PangoFont *font;
+
+ if (!get_shaper_and_font (state, ' ', &shape_engine, &font))
+ {
+ shape_engine = _pango_get_fallback_shaper ();
+ font = NULL;
+ }
+
+ itemize_state_fill_shaper (state, shape_engine, font);
+ }
+ state->item = NULL;
+}
+
+static void
+itemize_state_finish (ItemizeState *state)
+{
+ g_free (state->embedding_levels);
+ if (state->free_attr_iter)
+ pango_attr_iterator_destroy (state->attr_iter);
+ pango_script_iter_free (state->script_iter);
+ pango_font_description_free (state->font_desc);
+
+ itemize_state_reset_shape_engines (state);
+ if (state->current_fonts)
+ g_object_unref (state->current_fonts);
+ if (state->base_font)
+ g_object_unref (state->base_font);
+}
+
+/**
+ * pango_itemize_with_base_dir:
+ * @context: a structure holding information that affects
+ the itemization process.
+ * @text: the text to itemize.
+ * @start_index: first byte in @text to process
+ * @length: the number of bytes (not characters) to process
+ * after @start_index.
+ * This must be >= 0.
+ * @base_dir: base direction to use for bidirectional processing
+ * @attrs: the set of attributes that apply to @text.
+ * @cached_iter: Cached attribute iterator, or %NULL
+ *
+ * Like pango_itemize(), but the base direction to use when
+ * computing bidirectional levels (see pango_context_set_base_dir ()),
+ * is specified explicitly rather than gotten from the #PangoContext.
+ *
+ * Return value: a #GList of #PangoItem structures. The items should be
+ * freed using pango_item_free() probably in combination with g_list_foreach(),
+ * and the list itself using g_list_free().
+ *
+ * Since: 1.4
+ */
+GList *
+pango_itemize_with_base_dir (PangoContext *context,
+ PangoDirection base_dir,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter)
+{
+ ItemizeState state;
+
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (start_index >= 0, NULL);
+ g_return_val_if_fail (length >= 0, NULL);
+ g_return_val_if_fail (length == 0 || text != NULL, NULL);
+
+ if (length == 0)
+ return NULL;
+
+ itemize_state_init (&state, context, text, base_dir, start_index, length,
+ attrs, cached_iter, NULL);
+
+ do
+ itemize_state_process_run (&state);
+ while (itemize_state_next (&state));
+
+ itemize_state_finish (&state);
+
+ return g_list_reverse (state.result);
+}
+
+static GList *
+itemize_with_font (PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ const PangoFontDescription *desc)
+{
+ ItemizeState state;
+
+ if (length == 0)
+ return NULL;
+
+ itemize_state_init (&state, context, text, context->base_dir, start_index, length,
+ NULL, NULL, desc);
+
+ do
+ itemize_state_process_run (&state);
+ while (itemize_state_next (&state));
+
+ itemize_state_finish (&state);
+
+ return g_list_reverse (state.result);
+}
+
+/**
+ * pango_itemize:
+ * @context: a structure holding information that affects
+ the itemization process.
+ * @text: the text to itemize.
+ * @start_index: first byte in @text to process
+ * @length: the number of bytes (not characters) to process
+ * after @start_index.
+ * This must be >= 0.
+ * @attrs: the set of attributes that apply to @text.
+ * @cached_iter: Cached attribute iterator, or %NULL
+ *
+ * Breaks a piece of text into segments with consistent
+ * directional level and shaping engine. Each byte of @text will
+ * be contained in exactly one of the items in the returned list;
+ * the generated list of items will be in logical order (the start
+ * offsets of the items are ascending).
+ *
+ * @cached_iter should be an iterator over @attrs currently positioned at a
+ * range before or containing @start_index; @cached_iter will be advanced to
+ * the range covering the position just after @start_index + @length.
+ * (i.e. if itemizing in a loop, just keep passing in the same @cached_iter).
+ *
+ * Return value: a #GList of #PangoItem structures.
+ */
+GList *
+pango_itemize (PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter)
+{
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (start_index >= 0, NULL);
+ g_return_val_if_fail (length >= 0, NULL);
+ g_return_val_if_fail (length == 0 || text != NULL, NULL);
+
+ return pango_itemize_with_base_dir (context, context->base_dir,
+ text, start_index, length, attrs, cached_iter);
+}
+
+static gboolean
+get_first_metrics_foreach (PangoFontset *fontset,
+ PangoFont *font,
+ gpointer data)
+{
+ PangoFontMetrics *fontset_metrics = data;
+ PangoLanguage *language = PANGO_FONTSET_GET_CLASS (fontset)->get_language (fontset);
+ PangoFontMetrics *font_metrics = pango_font_get_metrics (font, language);
+ guint save_ref_count;
+
+ /* Initialize the fontset metrics to metrics of the first font in the
+ * fontset; saving the refcount and restoring it is a bit of hack but avoids
+ * having to update this code for each metrics addition.
+ */
+ save_ref_count = fontset_metrics->ref_count;
+ *fontset_metrics = *font_metrics;
+ fontset_metrics->ref_count = save_ref_count;
+
+ pango_font_metrics_unref (font_metrics);
+
+ return TRUE; /* Stops iteration */
+}
+
+static PangoFontMetrics *
+get_base_metrics (PangoFontset *fontset)
+{
+ PangoFontMetrics *metrics = pango_font_metrics_new ();
+
+ /* Initialize the metrics from the first font in the fontset */
+ pango_fontset_foreach (fontset, get_first_metrics_foreach, metrics);
+
+ return metrics;
+}
+
+static void
+update_metrics_from_items (PangoFontMetrics *metrics,
+ PangoLanguage *language,
+ GList *items)
+
+{
+ GHashTable *fonts_seen = g_hash_table_new (NULL, NULL);
+ int count = 0;
+ GList *l;
+
+ for (l = items; l; l = l->next)
+ {
+ PangoItem *item = l->data;
+ PangoFont *font = item->analysis.font;
+
+ if (font != NULL && g_hash_table_lookup (fonts_seen, font) == NULL)
+ {
+ PangoFontMetrics *raw_metrics = pango_font_get_metrics (font, language);
+ g_hash_table_insert (fonts_seen, font, font);
+
+ /* metrics will already be initialized from the first font in the fontset */
+ metrics->ascent = MAX (metrics->ascent, raw_metrics->ascent);
+ metrics->descent = MAX (metrics->descent, raw_metrics->descent);
+
+ if (count == 0)
+ {
+ metrics->approximate_char_width = raw_metrics->approximate_char_width;
+ metrics->approximate_digit_width = raw_metrics->approximate_digit_width;
+ }
+ else
+ {
+ metrics->approximate_char_width += raw_metrics->approximate_char_width;
+ metrics->approximate_digit_width += raw_metrics->approximate_digit_width;
+ }
+ count++;
+ pango_font_metrics_unref (raw_metrics);
+ }
+ }
+
+ g_hash_table_destroy (fonts_seen);
+
+ if (count)
+ {
+ metrics->approximate_char_width /= count;
+ metrics->approximate_digit_width /= count;
+ }
+}
+
+/**
+ * pango_context_get_metrics:
+ * @context: a #PangoContext
+ * @desc: a #PangoFontDescription structure
+ * @language: language tag used to determine which script to get the metrics
+ * for. %NULL means that the language tag from the context will
+ * be used. If no language tag is set on the context, metrics
+ * large enough to cover a range of languages will be returned.
+ * The process of determining such metrics is slow, so it is best
+ * to always make sure some real language tag will be used.
+ *
+ * Get overall metric information for a particular font
+ * description. Since the metrics may be substantially different for
+ * different scripts, a language tag can be provided to indicate that
+ * the metrics should be retrieved that correspond to the script(s)
+ * used by that language.
+ *
+ * The #PangoFontDescription is interpreted in the same way as
+ * by pango_itemize(), and the family name may be a comma separated
+ * list of figures. If characters from multiple of these families
+ * would be used to render the string, then the returned fonts would
+ * be a composite of the metrics for the fonts loaded for the
+ * individual families.
+ *
+ * Return value: a #PangoFontMetrics object. The caller must call pango_font_metrics_unref()
+ * when finished using the object.
+ **/
+PangoFontMetrics *
+pango_context_get_metrics (PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ PangoFontset *current_fonts = NULL;
+ PangoFontMetrics *metrics;
+ const char *sample_str;
+ GList *items;
+
+ g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ if (!language)
+ language = context->language;
+
+ current_fonts = pango_font_map_load_fontset (context->font_map, context, desc, language);
+ metrics = get_base_metrics (current_fonts);
+
+ sample_str = pango_language_get_sample_string (language);
+ items = itemize_with_font (context, sample_str, 0, strlen (sample_str), desc);
+
+ update_metrics_from_items (metrics, language, items);
+
+ g_list_foreach (items, (GFunc)pango_item_free, NULL);
+ g_list_free (items);
+
+ g_object_unref (current_fonts);
+
+ return metrics;
+}
diff --git a/trunk/pango/pango-context.h b/trunk/pango/pango-context.h
new file mode 100644
index 00000000..5cd88404
--- /dev/null
+++ b/trunk/pango/pango-context.h
@@ -0,0 +1,113 @@
+/* Pango
+ * pango-context.h: Rendering contexts
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_CONTEXT_H__
+#define __PANGO_CONTEXT_H__
+
+#include <pango/pango-font.h>
+#include <pango/pango-fontmap.h>
+#include <pango/pango-attributes.h>
+
+G_BEGIN_DECLS
+
+/* Sort of like a GC - application set information about how
+ * to handle scripts
+ */
+
+/* PangoContext typedefed in pango-fontmap.h */
+typedef struct _PangoContextClass PangoContextClass;
+
+#define PANGO_TYPE_CONTEXT (pango_context_get_type ())
+#define PANGO_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CONTEXT, PangoContext))
+#define PANGO_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CONTEXT, PangoContextClass))
+#define PANGO_IS_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CONTEXT))
+#define PANGO_IS_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CONTEXT))
+#define PANGO_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CONTEXT, PangoContextClass))
+
+
+/* The PangoContext and PangoContextClass structs are private; if you
+ * need to create a subclass of these, file a bug.
+ */
+
+GType pango_context_get_type (void) G_GNUC_CONST;
+
+#ifdef PANGO_ENABLE_BACKEND
+PangoContext *pango_context_new (void);
+void pango_context_set_font_map (PangoContext *context,
+ PangoFontMap *font_map);
+#endif /* PANGO_ENABLE_BACKEND */
+PangoFontMap *pango_context_get_font_map (PangoContext *context);
+
+void pango_context_list_families (PangoContext *context,
+ PangoFontFamily ***families,
+ int *n_families);
+PangoFont * pango_context_load_font (PangoContext *context,
+ const PangoFontDescription *desc);
+PangoFontset *pango_context_load_fontset (PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
+
+PangoFontMetrics *pango_context_get_metrics (PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
+
+void pango_context_set_font_description (PangoContext *context,
+ const PangoFontDescription *desc);
+PangoFontDescription * pango_context_get_font_description (PangoContext *context);
+PangoLanguage *pango_context_get_language (PangoContext *context);
+void pango_context_set_language (PangoContext *context,
+ PangoLanguage *language);
+void pango_context_set_base_dir (PangoContext *context,
+ PangoDirection direction);
+PangoDirection pango_context_get_base_dir (PangoContext *context);
+void pango_context_set_base_gravity (PangoContext *context,
+ PangoGravity gravity);
+PangoGravity pango_context_get_base_gravity (PangoContext *context);
+PangoGravity pango_context_get_gravity (PangoContext *context);
+void pango_context_set_gravity_hint (PangoContext *context,
+ PangoGravityHint hint);
+PangoGravityHint pango_context_get_gravity_hint (PangoContext *context);
+
+void pango_context_set_matrix (PangoContext *context,
+ const PangoMatrix *matrix);
+G_CONST_RETURN PangoMatrix *pango_context_get_matrix (PangoContext *context);
+
+/* Break a string of Unicode characters into segments with
+ * consistent shaping/language engine and bidrectional level.
+ * Returns a #GList of #PangoItem's
+ */
+GList *pango_itemize (PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter);
+GList *pango_itemize_with_base_dir (PangoContext *context,
+ PangoDirection base_dir,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter);
+
+G_END_DECLS
+
+#endif /* __PANGO_CONTEXT_H__ */
diff --git a/trunk/pango/pango-coverage.c b/trunk/pango/pango-coverage.c
new file mode 100644
index 00000000..340ccf7c
--- /dev/null
+++ b/trunk/pango/pango-coverage.c
@@ -0,0 +1,494 @@
+/* Pango
+ * pango-coverage.c: Coverage maps for fonts
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "pango-coverage.h"
+
+typedef struct _PangoBlockInfo PangoBlockInfo;
+
+#define N_BLOCKS_INCREMENT 256
+
+/* The structure of a PangoCoverage object is a two-level table, with blocks of size 256.
+ * each block is stored as a packed array of 2 bit values for each index, in LSB order.
+ */
+
+struct _PangoBlockInfo
+{
+ guchar *data;
+ PangoCoverageLevel level; /* Used if data == NULL */
+};
+
+struct _PangoCoverage
+{
+ guint ref_count;
+ int n_blocks;
+ int data_size;
+
+ PangoBlockInfo *blocks;
+};
+
+/**
+ * pango_coverage_new:
+ *
+ * Create a new #PangoCoverage
+ *
+ * Return value: the newly allocated #PangoCoverage,
+ * initialized to %PANGO_COVERAGE_NONE
+ * with a reference count of one, which
+ * should be freed with pango_coverage_unref().
+ **/
+PangoCoverage *
+pango_coverage_new (void)
+{
+ PangoCoverage *coverage = g_slice_new (PangoCoverage);
+
+ coverage->n_blocks = N_BLOCKS_INCREMENT;
+ coverage->blocks = g_new0 (PangoBlockInfo, coverage->n_blocks);
+ coverage->ref_count = 1;
+
+ return coverage;
+}
+
+/**
+ * pango_coverage_copy:
+ * @coverage: a #PangoCoverage
+ *
+ * Copy an existing #PangoCoverage. (This function may now be unnecessary
+ * since we refcount the structure. File a bug if you use it.)
+ *
+ * Return value: the newly allocated #PangoCoverage,
+ * with a reference count of one, which
+ * should be freed with pango_coverage_unref().
+ **/
+PangoCoverage *
+pango_coverage_copy (PangoCoverage *coverage)
+{
+ int i;
+ PangoCoverage *result;
+
+ g_return_val_if_fail (coverage != NULL, NULL);
+
+ result = g_slice_new (PangoCoverage);
+ result->n_blocks = coverage->n_blocks;
+ result->blocks = g_new (PangoBlockInfo, coverage->n_blocks);
+ result->ref_count = 1;
+
+ for (i=0; i<coverage->n_blocks; i++)
+ {
+ if (coverage->blocks[i].data)
+ {
+ result->blocks[i].data = g_new (guchar, 64);
+ memcpy (result->blocks[i].data, coverage->blocks[i].data, 64);
+ }
+ else
+ result->blocks[i].data = NULL;
+
+ result->blocks[i].level = coverage->blocks[i].level;
+ }
+
+ return result;
+}
+
+/**
+ * pango_coverage_ref:
+ * @coverage: a #PangoCoverage
+ *
+ * Increase the reference count on the #PangoCoverage by one
+ *
+ * Return value: @coverage
+ **/
+PangoCoverage *
+pango_coverage_ref (PangoCoverage *coverage)
+{
+ g_return_val_if_fail (coverage != NULL, NULL);
+
+ coverage->ref_count++;
+
+ return coverage;
+}
+
+/**
+ * pango_coverage_unref:
+ * @coverage: a #PangoCoverage
+ *
+ * Increase the reference count on the #PangoCoverage by one.
+ * if the result is zero, free the coverage and all associated memory.
+ **/
+void
+pango_coverage_unref (PangoCoverage *coverage)
+{
+ int i;
+
+ g_return_if_fail (coverage != NULL);
+ g_return_if_fail (coverage->ref_count > 0);
+
+ coverage->ref_count--;
+
+ if (coverage->ref_count == 0)
+ {
+ for (i=0; i<coverage->n_blocks; i++)
+ g_free (coverage->blocks[i].data);
+
+ g_free (coverage->blocks);
+ g_slice_free (PangoCoverage, coverage);
+ }
+}
+
+/**
+ * pango_coverage_get:
+ * @coverage: a #PangoCoverage
+ * @index_: the index to check
+ *
+ * Determine whether a particular index is covered by @coverage
+ *
+ * Return value: the coverage level of @coverage for character @index_.
+ **/
+PangoCoverageLevel
+pango_coverage_get (PangoCoverage *coverage,
+ int index)
+{
+ int block_index;
+
+ g_return_val_if_fail (coverage != NULL, PANGO_COVERAGE_NONE);
+ g_return_val_if_fail (index >= 0, PANGO_COVERAGE_NONE);
+
+ block_index = index / 256;
+
+ if (block_index >= coverage->n_blocks)
+ return PANGO_COVERAGE_NONE;
+ else
+ {
+ guchar *data = coverage->blocks[block_index].data;
+ if (data)
+ {
+ int i = index % 256;
+ int shift = (i % 4) * 2;
+
+ return (data[i/4] >> shift) & 0x3;
+ }
+ else
+ return coverage->blocks[block_index].level;
+ }
+}
+
+/**
+ * pango_coverage_set:
+ * @coverage: a #PangoCoverage
+ * @index_: the index to modify
+ * @level: the new level for @index_
+ *
+ * Modify a particular index within @coverage
+ **/
+void
+pango_coverage_set (PangoCoverage *coverage,
+ int index,
+ PangoCoverageLevel level)
+{
+ int block_index, i;
+ guchar *data;
+
+ g_return_if_fail (coverage != NULL);
+ g_return_if_fail (index >= 0);
+ g_return_if_fail (level >= 0 && level <= 3);
+
+ block_index = index / 256;
+
+ if (block_index >= coverage->n_blocks)
+ {
+ int old_n_blocks = coverage->n_blocks;
+
+ coverage->n_blocks =
+ N_BLOCKS_INCREMENT * ((block_index + N_BLOCKS_INCREMENT) / N_BLOCKS_INCREMENT);
+
+ coverage->blocks = g_renew (PangoBlockInfo, coverage->blocks, coverage->n_blocks);
+ memset (coverage->blocks + old_n_blocks, 0,
+ sizeof (PangoBlockInfo) * (coverage->n_blocks - old_n_blocks));
+ }
+
+ data = coverage->blocks[block_index].data;
+ if (!data)
+ {
+ guchar byte;
+
+ if (level == coverage->blocks[block_index].level)
+ return;
+
+ data = g_new (guchar, 64);
+ coverage->blocks[block_index].data = data;
+
+ byte = coverage->blocks[block_index].level |
+ (coverage->blocks[block_index].level << 2) |
+ (coverage->blocks[block_index].level << 4) |
+ (coverage->blocks[block_index].level << 6);
+
+ memset (data, byte, 64);
+ }
+
+ i = index % 256;
+ data[i/4] |= level << ((i % 4) * 2);
+}
+
+/**
+ * pango_coverage_max:
+ * @coverage: a #PangoCoverage
+ * @other: another #PangoCoverage
+ *
+ * Set the coverage for each index in @coverage to be the max (better)
+ * value of the current coverage for the index and the coverage for
+ * the corresponding index in @other.
+ **/
+void
+pango_coverage_max (PangoCoverage *coverage,
+ PangoCoverage *other)
+{
+ int block_index, i;
+ int old_blocks;
+
+ g_return_if_fail (coverage != NULL);
+
+ old_blocks = MIN (coverage->n_blocks, other->n_blocks);
+
+ if (other->n_blocks > coverage->n_blocks)
+ {
+ coverage->n_blocks = other->n_blocks;
+ coverage->blocks = g_renew (PangoBlockInfo, coverage->blocks, coverage->n_blocks);
+
+ for (block_index = old_blocks; block_index < coverage->n_blocks; block_index++)
+ {
+ if (other->blocks[block_index].data)
+ {
+ coverage->blocks[block_index].data = g_new (guchar, 64);
+ memcpy (coverage->blocks[block_index].data, other->blocks[block_index].data, 64);
+ }
+ else
+ coverage->blocks[block_index].data = NULL;
+
+ coverage->blocks[block_index].level = other->blocks[block_index].level;
+ }
+ }
+
+ for (block_index = 0; block_index < old_blocks; block_index++)
+ {
+ if (!coverage->blocks[block_index].data && !other->blocks[block_index].data)
+ {
+ coverage->blocks[block_index].level = MAX (coverage->blocks[block_index].level, other->blocks[block_index].level);
+ }
+ else if (coverage->blocks[block_index].data && other->blocks[block_index].data)
+ {
+ guchar *data = coverage->blocks[block_index].data;
+
+ for (i=0; i<64; i++)
+ {
+ int byte1 = data[i];
+ int byte2 = other->blocks[block_index].data[i];
+
+ /* There are almost certainly some clever logical ops to do this */
+ data[i] =
+ MAX (byte1 & 0x3, byte2 & 0x3) |
+ MAX (byte1 & 0xc, byte2 & 0xc) |
+ MAX (byte1 & 0x30, byte2 & 0x30) |
+ MAX (byte1 & 0xc0, byte2 & 0xc0);
+ }
+ }
+ else
+ {
+ guchar *src, *dest;
+ int level, byte2;
+
+ if (coverage->blocks[block_index].data)
+ {
+ src = dest = coverage->blocks[block_index].data;
+ level = other->blocks[block_index].level;
+ }
+ else
+ {
+ src = other->blocks[block_index].data;
+ dest = g_new (guchar, 64);
+ coverage->blocks[block_index].data = dest;
+ level = coverage->blocks[block_index].level;
+ }
+
+ byte2 = level | (level << 2) | (level << 4) | (level << 6);
+
+ for (i=0; i<64; i++)
+ {
+ int byte1 = src[i];
+
+ /* There are almost certainly some clever logical ops to do this */
+ dest[i] =
+ MAX (byte1 & 0x3, byte2 & 0x3) |
+ MAX (byte1 & 0xc, byte2 & 0xc) |
+ MAX (byte1 & 0x30, byte2 & 0x30) |
+ MAX (byte1 & 0xc0, byte2 & 0xc0);
+ }
+ }
+ }
+}
+
+#define PANGO_COVERAGE_MAGIC 0xc89dbd5e
+
+/**
+ * pango_coverage_to_bytes:
+ * @coverage: a #PangoCoverage
+ * @bytes: location to store result (must be freed with g_free())
+ * @n_bytes: location to store size of result
+ *
+ * Convert a #PangoCoverage structure into a flat binary format
+ **/
+void
+pango_coverage_to_bytes (PangoCoverage *coverage,
+ guchar **bytes,
+ int *n_bytes)
+{
+ int i, j;
+ int size = 8 + 4 * coverage->n_blocks;
+ guchar *data;
+ int offset;
+
+ for (i=0; i<coverage->n_blocks; i++)
+ {
+ if (coverage->blocks[i].data)
+ size += 64;
+ }
+
+ data = g_malloc (size);
+
+ *(guint32 *)&data[0] = g_htonl (PANGO_COVERAGE_MAGIC); /* Magic */
+ *(guint32 *)&data[4] = g_htonl (coverage->n_blocks);
+ offset = 8;
+
+ for (i=0; i<coverage->n_blocks; i++)
+ {
+ guint32 header_val;
+
+ /* Check for solid blocks. This is a sort of random place
+ * to do the optimization, but we care most about getting
+ * it right when storing it somewhere persistant.
+ */
+ if (coverage->blocks[i].data != NULL)
+ {
+ guchar *data = coverage->blocks[i].data;
+ guchar first_val = data[0];
+
+ for (j = 1 ; j < 64; j++)
+ if (data[j] != first_val)
+ break;
+
+ if (j == 64)
+ {
+ g_free (data);
+ coverage->blocks[i].data = NULL;
+ coverage->blocks[i].level = first_val & 0x3;
+ }
+ }
+
+ if (coverage->blocks[i].data != NULL)
+ header_val = (guint32)-1;
+ else
+ header_val = coverage->blocks[i].level;
+
+ *(guint32 *)&data[offset] = g_htonl (header_val);
+ offset += 4;
+
+ if (coverage->blocks[i].data)
+ {
+ memcpy (data + offset, coverage->blocks[i].data, 64);
+ offset += 64;
+ }
+ }
+
+ *bytes = data;
+ *n_bytes = size;
+}
+
+static guint32
+pango_coverage_get_uint32 (guchar **ptr)
+{
+ guint32 val;
+
+ memcpy (&val, *ptr, 4);
+ *ptr += 4;
+
+ return g_ntohl (val);
+}
+
+/**
+ * pango_coverage_from_bytes:
+ * @bytes: binary data representing a #PangoCoverage
+ * @n_bytes: the size of @bytes in bytes
+ *
+ * Convert data generated from pango_converage_to_bytes() back
+ * to a #PangoCoverage
+ *
+ * Return value: a newly allocated #PangoCoverage, or %NULL if
+ * the data was invalid.
+ **/
+PangoCoverage *
+pango_coverage_from_bytes (guchar *bytes,
+ int n_bytes)
+{
+ PangoCoverage *coverage = g_slice_new0 (PangoCoverage);
+ guchar *ptr = bytes;
+ int i;
+
+ coverage->ref_count = 1;
+
+ if (n_bytes < 8)
+ goto error;
+
+ if (pango_coverage_get_uint32 (&ptr) != PANGO_COVERAGE_MAGIC)
+ goto error;
+
+ coverage->n_blocks = pango_coverage_get_uint32 (&ptr);
+ coverage->blocks = g_new0 (PangoBlockInfo, coverage->n_blocks);
+
+ for (i = 0; i < coverage->n_blocks; i++)
+ {
+ guint val;
+
+ if (ptr + 4 > bytes + n_bytes)
+ goto error;
+
+ val = pango_coverage_get_uint32 (&ptr);
+ if (val == (guint32)-1)
+ {
+ if (ptr + 64 > bytes + n_bytes)
+ goto error;
+
+ coverage->blocks[i].data = g_new (guchar, 64);
+ memcpy (coverage->blocks[i].data, ptr, 64);
+ ptr += 64;
+ }
+ else
+ coverage->blocks[i].level = val;
+ }
+
+ return coverage;
+
+ error:
+
+ pango_coverage_unref (coverage);
+ return NULL;
+}
+
+
diff --git a/trunk/pango/pango-coverage.h b/trunk/pango/pango-coverage.h
new file mode 100644
index 00000000..e1e8d133
--- /dev/null
+++ b/trunk/pango/pango-coverage.h
@@ -0,0 +1,58 @@
+/* Pango
+ * pango-coverage.h: Coverage sets for fonts
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_COVERAGE_H__
+#define __PANGO_COVERAGE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoCoverage PangoCoverage;
+
+typedef enum {
+ PANGO_COVERAGE_NONE,
+ PANGO_COVERAGE_FALLBACK,
+ PANGO_COVERAGE_APPROXIMATE,
+ PANGO_COVERAGE_EXACT
+} PangoCoverageLevel;
+
+PangoCoverage * pango_coverage_new (void);
+PangoCoverage * pango_coverage_ref (PangoCoverage *coverage);
+void pango_coverage_unref (PangoCoverage *coverage);
+PangoCoverage * pango_coverage_copy (PangoCoverage *coverage);
+PangoCoverageLevel pango_coverage_get (PangoCoverage *coverage,
+ int index_);
+void pango_coverage_set (PangoCoverage *coverage,
+ int index_,
+ PangoCoverageLevel level);
+void pango_coverage_max (PangoCoverage *coverage,
+ PangoCoverage *other);
+
+void pango_coverage_to_bytes (PangoCoverage *coverage,
+ guchar **bytes,
+ int *n_bytes);
+PangoCoverage *pango_coverage_from_bytes (guchar *bytes,
+ int n_bytes);
+
+G_END_DECLS
+
+#endif /* __PANGO_COVERAGE_H__ */
diff --git a/trunk/pango/pango-engine-private.h b/trunk/pango/pango-engine-private.h
new file mode 100644
index 00000000..5c88a4b1
--- /dev/null
+++ b/trunk/pango/pango-engine-private.h
@@ -0,0 +1,46 @@
+/* Pango
+ * pango-engine-private.h: Private routines related to engines for
+ * script and language specific processing
+ *
+ * Copyright (C) 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_ENGINE_PRIVATE_H__
+#define __PANGO_ENGINE_PRIVATE_H__
+
+#include <pango-engine.h>
+
+G_BEGIN_DECLS
+
+void _pango_engine_shape_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs);
+PangoCoverageLevel _pango_engine_shape_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *language,
+ gunichar wc);
+
+PangoEngineShape *_pango_get_fallback_shaper (void);
+
+G_END_DECLS
+
+#endif /* __PANGO_ENGINE_PRIVATE_H__ */
+
diff --git a/trunk/pango/pango-engine.c b/trunk/pango/pango-engine.c
new file mode 100644
index 00000000..a21e5d84
--- /dev/null
+++ b/trunk/pango/pango-engine.c
@@ -0,0 +1,174 @@
+/* Pango
+ * pango-engine.c: Engines for script and language specific processing
+ *
+ * Copyright (C) 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-engine.h"
+#include "pango-engine-private.h"
+#include "pango-impl-utils.h"
+
+PANGO_DEFINE_TYPE_ABSTRACT (PangoEngine, pango_engine,
+ NULL, NULL,
+ G_TYPE_OBJECT)
+
+PANGO_DEFINE_TYPE_ABSTRACT (PangoEngineLang, pango_engine_lang,
+ NULL, NULL,
+ PANGO_TYPE_ENGINE)
+
+static PangoCoverageLevel
+pango_engine_shape_real_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *language,
+ gunichar wc)
+{
+
+ PangoCoverage *coverage = pango_font_get_coverage (font, language);
+ PangoCoverageLevel result = pango_coverage_get (coverage, wc);
+
+ pango_coverage_unref (coverage);
+
+ return result;
+}
+
+static void
+pango_engine_shape_class_init (PangoEngineShapeClass *class)
+{
+ class->covers = pango_engine_shape_real_covers;
+}
+
+PANGO_DEFINE_TYPE_ABSTRACT (PangoEngineShape, pango_engine_shape,
+ pango_engine_shape_class_init, NULL,
+ PANGO_TYPE_ENGINE)
+
+void
+_pango_engine_shape_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ glyphs->num_glyphs = 0;
+
+ PANGO_ENGINE_SHAPE_GET_CLASS (engine)->script_shape (engine,
+ font,
+ text, length,
+ analysis,
+ glyphs);
+}
+
+PangoCoverageLevel
+_pango_engine_shape_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *language,
+ gunichar wc)
+{
+ g_return_val_if_fail (PANGO_IS_ENGINE_SHAPE (engine), PANGO_COVERAGE_NONE);
+ g_return_val_if_fail (PANGO_IS_FONT (font), PANGO_COVERAGE_NONE);
+
+ return PANGO_ENGINE_SHAPE_GET_CLASS (engine)->covers (engine,
+ font,
+ language,
+ wc);
+}
+
+/* No extra fields needed */
+typedef PangoEngineShape PangoFallbackEngine;
+typedef PangoEngineShapeClass PangoFallbackEngineClass;
+
+static void
+fallback_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ int n_chars;
+ const char *p;
+ int cluster = 0;
+ int i;
+
+ n_chars = text ? g_utf8_strlen (text, length) : 0;
+
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ p = text;
+ for (i = 0; i < n_chars; i++)
+ {
+ gunichar wc;
+ PangoGlyph glyph;
+ PangoRectangle logical_rect;
+
+ wc = g_utf8_get_char (p);
+
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
+
+ if (pango_is_zero_width (wc))
+ glyph = PANGO_GLYPH_EMPTY;
+ else
+ glyph = PANGO_GET_UNKNOWN_GLYPH (wc);
+
+ pango_font_get_glyph_extents (analysis->font, glyph, NULL, &logical_rect);
+
+ glyphs->glyphs[i].glyph = glyph;
+
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+
+ glyphs->log_clusters[i] = cluster;
+
+ p = g_utf8_next_char (p);
+ }
+}
+
+static PangoCoverageLevel
+fallback_engine_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *lang,
+ gunichar wc)
+{
+ return PANGO_COVERAGE_NONE;
+}
+
+static void
+fallback_engine_class_init (PangoEngineShapeClass *class)
+{
+ class->covers = fallback_engine_covers;
+ class->script_shape = fallback_engine_shape;
+}
+
+static PANGO_DEFINE_TYPE (PangoFallbackEngine, pango_fallback_engine,
+ fallback_engine_class_init, NULL,
+ PANGO_TYPE_ENGINE_SHAPE)
+
+PangoEngineShape *
+_pango_get_fallback_shaper (void)
+{
+ static PangoEngineShape *fallback_shaper = NULL;
+ if (!fallback_shaper)
+ fallback_shaper = g_object_new (pango_fallback_engine_get_type (), NULL);
+
+ return fallback_shaper;
+}
+
diff --git a/trunk/pango/pango-engine.h b/trunk/pango/pango-engine.h
new file mode 100644
index 00000000..ddc9ab16
--- /dev/null
+++ b/trunk/pango/pango-engine.h
@@ -0,0 +1,379 @@
+/* Pango
+ * pango-engine.h: Engines for script and language specific processing
+ *
+ * Copyright (C) 2000,2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_ENGINE_H__
+#define __PANGO_ENGINE_H__
+
+#include <pango/pango-types.h>
+#include <pango/pango-item.h>
+#include <pango/pango-font.h>
+#include <pango/pango-glyph.h>
+#include <pango/pango-script.h>
+
+G_BEGIN_DECLS
+
+#ifdef PANGO_ENABLE_ENGINE
+
+/* Module API */
+
+#define PANGO_RENDER_TYPE_NONE "PangoRenderNone"
+
+#define PANGO_TYPE_ENGINE (pango_engine_get_type ())
+#define PANGO_ENGINE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_ENGINE, PangoEngine))
+#define PANGO_IS_ENGINE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_ENGINE))
+#define PANGO_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_ENGINE, PangoEngineClass))
+#define PANGO_IS_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_ENGINE))
+#define PANGO_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_ENGINE, PangoEngineClass))
+
+typedef struct _PangoEngine PangoEngine;
+typedef struct _PangoEngineClass PangoEngineClass;
+
+/**
+ * PangoEngine:
+ *
+ * #PangoEngine is the base class for all types of language and
+ * script specific engines. It has no functionality by itself.
+ **/
+struct _PangoEngine
+{
+ /*< private >*/
+ GObject parent_instance;
+};
+
+/**
+ * PangoEngineClass:
+ *
+ * Class structure for #PangoEngine
+ **/
+struct _PangoEngineClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+};
+
+GType pango_engine_get_type (void) G_GNUC_CONST;
+
+#define PANGO_ENGINE_TYPE_LANG "PangoEngineLang"
+
+#define PANGO_TYPE_ENGINE_LANG (pango_engine_lang_get_type ())
+#define PANGO_ENGINE_LANG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_ENGINE_LANG, PangoEngineLang))
+#define PANGO_IS_ENGINE_LANG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_ENGINE_LANG))
+#define PANGO_ENGINE_LANG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_ENGINE_LANG, PangoEngineLangClass))
+#define PANGO_IS_ENGINE_LANG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_ENGINE_LANG))
+#define PANGO_ENGINE_LANG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_ENGINE_LANG, PangoEngineLangClass))
+
+typedef struct _PangoEngineLangClass PangoEngineLangClass;
+
+/**
+ * PangoEngineLang:
+ *
+ * The #PangoEngineLang class is implemented by engines that
+ * customize the rendering-system independent part of the
+ * Pango pipeline for a particular script or language. For
+ * instance, a custom #PangoEngineLang could be provided for
+ * Thai to implement the dictionary-based word boundary
+ * lookups needed for that language.
+ **/
+struct _PangoEngineLang
+{
+ /*< private >*/
+ PangoEngine parent_instance;
+};
+
+/**
+ * PangoEngineLangClass:
+ * @script_break: Provides a custom implementation of pango_break().
+ * If %NULL, pango_default_break() is used instead. If not %NULL, for
+ * Pango versions before 1.16 (module interface version before 1.6.0),
+ * this was called instead of pango_default_break(), but in newer versions,
+ * pango_default_break() is always called and this is called after that to
+ * allow tailoring the breaking results.
+ *
+ * Class structure for #PangoEngineLang
+ **/
+struct _PangoEngineLangClass
+{
+ /*< private >*/
+ PangoEngineClass parent_class;
+
+ /*< public >*/
+ void (*script_break) (PangoEngineLang *engine,
+ const char *text,
+ int len,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len);
+};
+
+GType pango_engine_lang_get_type (void) G_GNUC_CONST;
+
+#define PANGO_ENGINE_TYPE_SHAPE "PangoEngineShape"
+
+#define PANGO_TYPE_ENGINE_SHAPE (pango_engine_shape_get_type ())
+#define PANGO_ENGINE_SHAPE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_ENGINE_SHAPE, PangoEngineShape))
+#define PANGO_IS_ENGINE_SHAPE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_ENGINE_SHAPE))
+#define PANGO_ENGINE_SHAPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_ENGINE_SHAPE, PangoEngine_ShapeClass))
+#define PANGO_IS_ENGINE_SHAPE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_ENGINE_SHAPE))
+#define PANGO_ENGINE_SHAPE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_ENGINE_SHAPE, PangoEngineShapeClass))
+
+typedef struct _PangoEngineShapeClass PangoEngineShapeClass;
+
+/**
+ * PangoEngineShape
+ *
+ * The #PangoEngineShape class is implemented by engines that
+ * customize the rendering-system dependent part of the
+ * Pango pipeline for a particular script or language.
+ * A #PangoEngineShape implementation is then specific to both
+ * a particular rendering system or group of rendering systems
+ * and to a particular script. For instance, there is one
+ * #PangoEngineShape implementation to handle shaping Arabic
+ * for Fontconfig-based backends.
+ **/
+struct _PangoEngineShape
+{
+ PangoEngine parent_instance;
+};
+
+/**
+ * PangoEngineShapeClass:
+ * @script_shape: Given a font, a piece of text, and a #PangoAnalysis
+ * structure, converts characters to glyphs and positions the
+ * resulting glyphs. The results are stored in the #PangoGlyphString
+ * that is passed in. (The implementation should resize it
+ * appropriately using pango_glyph_string_set_size()). All fields
+ * of the @log_clusters and @glyphs array must be filled in, with
+ * the exception that Pango will automatically generate
+ * <literal>glyphs->glyphs[i].attr.is_cluster_start</literal>
+ * using the @log_clusters array. Each input character must occur in one
+ * of the output logical clusters;
+ * if no rendering is desired for a character, this may involve
+ * inserting glyphs with the #PangoGlyph ID #PANGO_GLYPH_EMPTY, which
+ * is guaranteed never to render. If the shaping fails for any reason,
+ * the shaper should return with an empty (zero-size) glyph string.
+ * If the shaper has not set the size on the glyph string yet, simply
+ * returning signals the failure too.
+ * @covers: Returns the characters that this engine can cover
+ * with a given font for a given language. If not overridden, the default
+ * implementation simply returns the coverage information for the
+ * font itself unmodified.
+ *
+ * Class structure for #PangoEngineShape
+ **/
+struct _PangoEngineShapeClass
+{
+ /*< private >*/
+ PangoEngineClass parent_class;
+
+ /*< public >*/
+ void (*script_shape) (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs);
+ PangoCoverageLevel (*covers) (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *language,
+ gunichar wc);
+};
+
+GType pango_engine_shape_get_type (void) G_GNUC_CONST;
+
+typedef struct _PangoEngineInfo PangoEngineInfo;
+typedef struct _PangoEngineScriptInfo PangoEngineScriptInfo;
+
+struct _PangoEngineScriptInfo
+{
+ PangoScript script;
+ const gchar *langs;
+};
+
+struct _PangoEngineInfo
+{
+ const gchar *id;
+ const gchar *engine_type;
+ const gchar *render_type;
+ PangoEngineScriptInfo *scripts;
+ gint n_scripts;
+};
+
+/**
+ * script_engine_list:
+ * @engines: location to store a pointer to an array of engines.
+ * @n_engines: location to store the number of elements in @engines.
+ *
+ * Function to be provided by a module to list the engines that the
+ * module supplies. The function stores a pointer to an array
+ * of #PangoEngineInfo structures and the length of that array in
+ * the given location.
+ *
+ * Note that script_engine_init() will not be called before this
+ * function.
+ **/
+void script_engine_list (PangoEngineInfo **engines,
+ int *n_engines);
+
+/**
+ * script_engine_init:
+ * @module: a #GTypeModule structure used to associate any
+ * GObject types created in this module with the module.
+ *
+ * Function to be provided by a module to register any
+ * GObject types in the module.
+ **/
+void script_engine_init (GTypeModule *module);
+
+
+/**
+ * script_engine_exit:
+ *
+ * Function to be provided by the module that is called
+ * when the module is unloading. Frequently does nothing.
+ **/
+void script_engine_exit (void);
+
+/**
+ * script_engine_create:
+ * @id: the ID of an engine as reported by script_engine_list.
+ *
+ * Function to be provided by the module to create an instance
+ * of one of the engines implemented by the module.
+ *
+ * Return value: a newly created #PangoEngine of the specified
+ * type, or %NULL if an error occurred. (In normal operation,
+ * a module should not return %NULL. A %NULL return is only
+ * acceptable in the case where system misconfiguration or
+ * bugs in the driver routine are encountered.)
+ **/
+PangoEngine *script_engine_create (const char *id);
+
+/* Utility macro used by PANGO_ENGINE_LANG_DEFINE_TYPE and
+ * PANGO_ENGINE_LANG_DEFINE_TYPE
+ */
+#define PANGO_ENGINE_DEFINE_TYPE(name, prefix, class_init, instance_init, parent_type) \
+static GType prefix ## _type; \
+static void \
+prefix ## _register_type (GTypeModule *module) \
+{ \
+ const GTypeInfo object_info = \
+ { \
+ sizeof (name ## Class), \
+ (GBaseInitFunc) NULL, \
+ (GBaseFinalizeFunc) NULL, \
+ (GClassInitFunc) class_init, \
+ (GClassFinalizeFunc) NULL, \
+ NULL, /* class_data */ \
+ sizeof (name), \
+ 0, /* n_prelocs */ \
+ (GInstanceInitFunc) instance_init, \
+ NULL /* value_table */ \
+ }; \
+ \
+ prefix ## _type = g_type_module_register_type (module, parent_type, \
+ # name, \
+ &object_info, 0); \
+}
+
+/**
+ * PANGO_ENGINE_LANG_DEFINE_TYPE:
+ * @name: Name of the the type to register (for example:, <literal>ArabicEngineFc</literal>
+ * @prefix: Prefix for symbols that will be defined (for example:, <literal>arabic_engine_fc</literal>
+ * @class_init: Class initialization function for the new type, or %NULL
+ * @instance_init: Instance initialization function for the new type, or %NULL
+ *
+ * Outputs the necessary code for GObject type registration for a
+ * #PangoEngineLang class defined in a module. Two static symbols
+ * are defined.
+ *
+ * <programlisting>
+ * static GType <replaceable>prefix</replaceable>_type;
+ * static void <replaceable>prefix</replaceable>_register_type (GTypeModule module);
+ * </programlisting>
+ *
+ * The <function><replaceable>prefix</replaceable>_register_type()</function>
+ * function should be called in your script_engine_init() function for
+ * each type that your module implements, and then your script_engine_create()
+ * function can create instances of the object as follows:
+ *
+ * <informalexample><programlisting>
+ * PangoEngine *engine = g_object_new (<replaceable>prefix</replaceable>_type, NULL);
+ * </programlisting></informalexample>
+ **/
+#define PANGO_ENGINE_LANG_DEFINE_TYPE(name, prefix, class_init, instance_init) \
+ PANGO_ENGINE_DEFINE_TYPE (name, prefix, \
+ class_init, instance_init, \
+ PANGO_TYPE_ENGINE_LANG)
+
+/**
+ * PANGO_ENGINE_SHAPE_DEFINE_TYPE:
+ * @name: Name of the the type to register (for example:, <literal>ArabicEngineFc</literal>
+ * @prefix: Prefix for symbols that will be defined (for example:, <literal>arabic_engine_fc</literal>
+ * @class_init: Class initialization function for the new type, or %NULL
+ * @instance_init: Instance initialization function for the new type, or %NULL
+ *
+ * Outputs the necessary code for GObject type registration for a
+ * #PangoEngineShape class defined in a module. Two static symbols
+ * are defined.
+ *
+ * <programlisting>
+ * static GType <replaceable>prefix</replaceable>_type;
+ * static void <replaceable>prefix</replaceable>_register_type (GTypeModule module);
+ * </programlisting>
+ *
+ * The <function><replaceable>prefix</replaceable>_register_type()</function>
+ * function should be called in your script_engine_init() function for
+ * each type that your module implements, and then your script_engine_create()
+ * function can create instances of the object as follows:
+ *
+ * <informalexample><programlisting>
+ * PangoEngine *engine = g_object_new (<replaceable>prefix</replaceable>_type, NULL);
+ * </programlisting></informalexample>
+ **/
+#define PANGO_ENGINE_SHAPE_DEFINE_TYPE(name, prefix, class_init, instance_init) \
+ PANGO_ENGINE_DEFINE_TYPE (name, prefix, \
+ class_init, instance_init, \
+ PANGO_TYPE_ENGINE_SHAPE)
+
+/* Macro used for possibly builtin Pango modules. Not useful
+ * for externally build modules. If we are compiling a module standaline,
+ * then we name the entry points script_engine_list, etc. But if we
+ * are compiling it for inclusion directly in Pango, then we need them to
+ * to have distinct names for this module, so we prepend a prefix.
+ *
+ * The two intermediate macros are to deal with details of the C
+ * preprocessor; token pasting tokens must be function arguments,
+ * and macro substitution isn't used on function arguments that
+ * are used for token pasting.
+ */
+#ifdef PANGO_MODULE_PREFIX
+#define PANGO_MODULE_ENTRY(func) _PANGO_MODULE_ENTRY2(PANGO_MODULE_PREFIX,func)
+#define _PANGO_MODULE_ENTRY2(prefix,func) _PANGO_MODULE_ENTRY3(prefix,func)
+#define _PANGO_MODULE_ENTRY3(prefix,func) prefix##_script_engine_##func
+#else
+#define PANGO_MODULE_ENTRY(func) script_engine_##func
+#endif
+
+#endif /* PANGO_ENABLE_ENGINE */
+
+G_END_DECLS
+
+#endif /* __PANGO_ENGINE_H__ */
diff --git a/trunk/pango/pango-font.h b/trunk/pango/pango-font.h
new file mode 100644
index 00000000..0411fb02
--- /dev/null
+++ b/trunk/pango/pango-font.h
@@ -0,0 +1,383 @@
+/* Pango
+ * pango-font.h: Font handling
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_FONT_H__
+#define __PANGO_FONT_H__
+
+#include <pango/pango-coverage.h>
+#include <pango/pango-types.h>
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoFontDescription PangoFontDescription;
+typedef struct _PangoFontMetrics PangoFontMetrics;
+
+/**
+ * PangoStyle:
+ * @PANGO_STYLE_NORMAL: the font is upright.
+ * @PANGO_STYLE_OBLIQUE: the font is slanted, but in a roman style.
+ * @PANGO_STYLE_ITALIC: the font is slanted in an italic style.
+ *
+ * An enumeration specifying the various slant styles possible for a font.
+ **/
+typedef enum {
+ PANGO_STYLE_NORMAL,
+ PANGO_STYLE_OBLIQUE,
+ PANGO_STYLE_ITALIC
+} PangoStyle;
+
+typedef enum {
+ PANGO_VARIANT_NORMAL,
+ PANGO_VARIANT_SMALL_CAPS
+} PangoVariant;
+
+typedef enum {
+ PANGO_WEIGHT_ULTRALIGHT = 200,
+ PANGO_WEIGHT_LIGHT = 300,
+ PANGO_WEIGHT_NORMAL = 400,
+ PANGO_WEIGHT_SEMIBOLD = 600,
+ PANGO_WEIGHT_BOLD = 700,
+ PANGO_WEIGHT_ULTRABOLD = 800,
+ PANGO_WEIGHT_HEAVY = 900
+} PangoWeight;
+
+typedef enum {
+ PANGO_STRETCH_ULTRA_CONDENSED,
+ PANGO_STRETCH_EXTRA_CONDENSED,
+ PANGO_STRETCH_CONDENSED,
+ PANGO_STRETCH_SEMI_CONDENSED,
+ PANGO_STRETCH_NORMAL,
+ PANGO_STRETCH_SEMI_EXPANDED,
+ PANGO_STRETCH_EXPANDED,
+ PANGO_STRETCH_EXTRA_EXPANDED,
+ PANGO_STRETCH_ULTRA_EXPANDED
+} PangoStretch;
+
+typedef enum {
+ PANGO_FONT_MASK_FAMILY = 1 << 0,
+ PANGO_FONT_MASK_STYLE = 1 << 1,
+ PANGO_FONT_MASK_VARIANT = 1 << 2,
+ PANGO_FONT_MASK_WEIGHT = 1 << 3,
+ PANGO_FONT_MASK_STRETCH = 1 << 4,
+ PANGO_FONT_MASK_SIZE = 1 << 5,
+ PANGO_FONT_MASK_GRAVITY = 1 << 6
+} PangoFontMask;
+
+/* CSS scale factors (1.2 factor between each size) */
+#define PANGO_SCALE_XX_SMALL ((double)0.5787037037037)
+#define PANGO_SCALE_X_SMALL ((double)0.6444444444444)
+#define PANGO_SCALE_SMALL ((double)0.8333333333333)
+#define PANGO_SCALE_MEDIUM ((double)1.0)
+#define PANGO_SCALE_LARGE ((double)1.2)
+#define PANGO_SCALE_X_LARGE ((double)1.4399999999999)
+#define PANGO_SCALE_XX_LARGE ((double)1.728)
+
+/*
+ * PangoFontDescription
+ */
+
+#define PANGO_TYPE_FONT_DESCRIPTION (pango_font_description_get_type ())
+
+GType pango_font_description_get_type (void) G_GNUC_CONST;
+PangoFontDescription *pango_font_description_new (void);
+PangoFontDescription *pango_font_description_copy (const PangoFontDescription *desc);
+PangoFontDescription *pango_font_description_copy_static (const PangoFontDescription *desc);
+guint pango_font_description_hash (const PangoFontDescription *desc) G_GNUC_PURE;
+gboolean pango_font_description_equal (const PangoFontDescription *desc1,
+ const PangoFontDescription *desc2) G_GNUC_PURE;
+void pango_font_description_free (PangoFontDescription *desc);
+void pango_font_descriptions_free (PangoFontDescription **descs,
+ int n_descs);
+
+void pango_font_description_set_family (PangoFontDescription *desc,
+ const char *family);
+void pango_font_description_set_family_static (PangoFontDescription *desc,
+ const char *family);
+G_CONST_RETURN char *pango_font_description_get_family (const PangoFontDescription *desc) G_GNUC_PURE;
+void pango_font_description_set_style (PangoFontDescription *desc,
+ PangoStyle style);
+PangoStyle pango_font_description_get_style (const PangoFontDescription *desc) G_GNUC_PURE;
+void pango_font_description_set_variant (PangoFontDescription *desc,
+ PangoVariant variant);
+PangoVariant pango_font_description_get_variant (const PangoFontDescription *desc) G_GNUC_PURE;
+void pango_font_description_set_weight (PangoFontDescription *desc,
+ PangoWeight weight);
+PangoWeight pango_font_description_get_weight (const PangoFontDescription *desc) G_GNUC_PURE;
+void pango_font_description_set_stretch (PangoFontDescription *desc,
+ PangoStretch stretch);
+PangoStretch pango_font_description_get_stretch (const PangoFontDescription *desc) G_GNUC_PURE;
+void pango_font_description_set_size (PangoFontDescription *desc,
+ gint size);
+gint pango_font_description_get_size (const PangoFontDescription *desc) G_GNUC_PURE;
+void pango_font_description_set_absolute_size (PangoFontDescription *desc,
+ double size);
+gboolean pango_font_description_get_size_is_absolute (const PangoFontDescription *desc) G_GNUC_PURE;
+void pango_font_description_set_gravity (PangoFontDescription *desc,
+ PangoGravity gravity);
+PangoGravity pango_font_description_get_gravity (const PangoFontDescription *desc) G_GNUC_PURE;
+
+PangoFontMask pango_font_description_get_set_fields (const PangoFontDescription *desc) G_GNUC_PURE;
+void pango_font_description_unset_fields (PangoFontDescription *desc,
+ PangoFontMask to_unset);
+
+void pango_font_description_merge (PangoFontDescription *desc,
+ const PangoFontDescription *desc_to_merge,
+ gboolean replace_existing);
+void pango_font_description_merge_static (PangoFontDescription *desc,
+ const PangoFontDescription *desc_to_merge,
+ gboolean replace_existing);
+
+gboolean pango_font_description_better_match (const PangoFontDescription *desc,
+ const PangoFontDescription *old_match,
+ const PangoFontDescription *new_match) G_GNUC_PURE;
+
+PangoFontDescription *pango_font_description_from_string (const char *str);
+char * pango_font_description_to_string (const PangoFontDescription *desc);
+char * pango_font_description_to_filename (const PangoFontDescription *desc);
+
+/*
+ * PangoFontMetrics
+ */
+
+#define PANGO_TYPE_FONT_METRICS (pango_font_metrics_get_type ())
+GType pango_font_metrics_get_type (void) G_GNUC_CONST;
+PangoFontMetrics *pango_font_metrics_ref (PangoFontMetrics *metrics);
+void pango_font_metrics_unref (PangoFontMetrics *metrics);
+int pango_font_metrics_get_ascent (PangoFontMetrics *metrics) G_GNUC_PURE;
+int pango_font_metrics_get_descent (PangoFontMetrics *metrics) G_GNUC_PURE;
+int pango_font_metrics_get_approximate_char_width (PangoFontMetrics *metrics) G_GNUC_PURE;
+int pango_font_metrics_get_approximate_digit_width (PangoFontMetrics *metrics) G_GNUC_PURE;
+int pango_font_metrics_get_underline_position (PangoFontMetrics *metrics) G_GNUC_PURE;
+int pango_font_metrics_get_underline_thickness (PangoFontMetrics *metrics) G_GNUC_PURE;
+int pango_font_metrics_get_strikethrough_position (PangoFontMetrics *metrics) G_GNUC_PURE;
+int pango_font_metrics_get_strikethrough_thickness (PangoFontMetrics *metrics) G_GNUC_PURE;
+
+#ifdef PANGO_ENABLE_BACKEND
+
+PangoFontMetrics *pango_font_metrics_new (void);
+
+struct _PangoFontMetrics
+{
+ guint ref_count;
+
+ int ascent;
+ int descent;
+ int approximate_char_width;
+ int approximate_digit_width;
+ int underline_position;
+ int underline_thickness;
+ int strikethrough_position;
+ int strikethrough_thickness;
+};
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+/*
+ * PangoFontFamily
+ */
+
+#define PANGO_TYPE_FONT_FAMILY (pango_font_family_get_type ())
+#define PANGO_FONT_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FONT_FAMILY, PangoFontFamily))
+#define PANGO_IS_FONT_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FONT_FAMILY))
+
+typedef struct _PangoFontFamily PangoFontFamily;
+typedef struct _PangoFontFace PangoFontFace;
+
+GType pango_font_family_get_type (void) G_GNUC_CONST;
+
+void pango_font_family_list_faces (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces);
+G_CONST_RETURN char *pango_font_family_get_name (PangoFontFamily *family) G_GNUC_PURE;
+gboolean pango_font_family_is_monospace (PangoFontFamily *family) G_GNUC_PURE;
+
+#ifdef PANGO_ENABLE_BACKEND
+
+#define PANGO_FONT_FAMILY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONT_FAMILY, PangoFontFamilyClass))
+#define PANGO_IS_FONT_FAMILY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONT_FAMILY))
+#define PANGO_FONT_FAMILY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONT_FAMILY, PangoFontFamilyClass))
+
+typedef struct _PangoFontFamilyClass PangoFontFamilyClass;
+
+struct _PangoFontFamily
+{
+ GObject parent_instance;
+};
+
+struct _PangoFontFamilyClass
+{
+ GObjectClass parent_class;
+
+ /*< public >*/
+
+ void (*list_faces) (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces);
+ const char * (*get_name) (PangoFontFamily *family);
+ gboolean (*is_monospace) (PangoFontFamily *family);
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+/*
+ * PangoFontFace
+ */
+
+#define PANGO_TYPE_FONT_FACE (pango_font_face_get_type ())
+#define PANGO_FONT_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FONT_FACE, PangoFontFace))
+#define PANGO_IS_FONT_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FONT_FACE))
+
+GType pango_font_face_get_type (void) G_GNUC_CONST;
+
+PangoFontDescription *pango_font_face_describe (PangoFontFace *face);
+G_CONST_RETURN char *pango_font_face_get_face_name (PangoFontFace *face) G_GNUC_PURE;
+void pango_font_face_list_sizes (PangoFontFace *face,
+ int **sizes,
+ int *n_sizes);
+gboolean pango_font_face_is_synthesized (PangoFontFace *face) G_GNUC_PURE;
+
+#ifdef PANGO_ENABLE_BACKEND
+
+#define PANGO_FONT_FACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONT_FACE, PangoFontFaceClass))
+#define PANGO_IS_FONT_FACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONT_FACE))
+#define PANGO_FONT_FACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONT_FACE, PangoFontFaceClass))
+
+typedef struct _PangoFontFaceClass PangoFontFaceClass;
+
+struct _PangoFontFace
+{
+ GObject parent_instance;
+};
+
+struct _PangoFontFaceClass
+{
+ GObjectClass parent_class;
+
+ /*< public >*/
+
+ const char * (*get_face_name) (PangoFontFace *face);
+ PangoFontDescription * (*describe) (PangoFontFace *face);
+ void (*list_sizes) (PangoFontFace *face,
+ int **sizes,
+ int *n_sizes);
+ gboolean (*is_synthesized) (PangoFontFace *face);
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+/*
+ * PangoFont
+ */
+
+#define PANGO_TYPE_FONT (pango_font_get_type ())
+#define PANGO_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FONT, PangoFont))
+#define PANGO_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FONT))
+
+GType pango_font_get_type (void) G_GNUC_CONST;
+
+PangoFontDescription *pango_font_describe (PangoFont *font);
+PangoFontDescription *pango_font_describe_with_absolute_size (PangoFont *font);
+PangoCoverage * pango_font_get_coverage (PangoFont *font,
+ PangoLanguage *language);
+PangoEngineShape * pango_font_find_shaper (PangoFont *font,
+ PangoLanguage *language,
+ guint32 ch);
+PangoFontMetrics * pango_font_get_metrics (PangoFont *font,
+ PangoLanguage *language);
+void pango_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+PangoFontMap *pango_font_get_font_map (PangoFont *font);
+
+#ifdef PANGO_ENABLE_BACKEND
+
+#define PANGO_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONT, PangoFontClass))
+#define PANGO_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONT))
+#define PANGO_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONT, PangoFontClass))
+
+typedef struct _PangoFontClass PangoFontClass;
+
+struct _PangoFont
+{
+ GObject parent_instance;
+};
+
+struct _PangoFontClass
+{
+ GObjectClass parent_class;
+
+ /*< public >*/
+
+ PangoFontDescription *(*describe) (PangoFont *font);
+ PangoCoverage * (*get_coverage) (PangoFont *font,
+ PangoLanguage *lang);
+ PangoEngineShape * (*find_shaper) (PangoFont *font,
+ PangoLanguage *lang,
+ guint32 ch);
+ void (*get_glyph_extents) (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+ PangoFontMetrics * (*get_metrics) (PangoFont *font,
+ PangoLanguage *language);
+ PangoFontMap * (*get_font_map) (PangoFont *font);
+ PangoFontDescription *(*describe_absolute) (PangoFont *font);
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+};
+
+/* used for very rare and miserable situtations that we cannot even
+ * draw a hexbox
+ */
+#define PANGO_UNKNOWN_GLYPH_WIDTH 10
+#define PANGO_UNKNOWN_GLYPH_HEIGHT 14
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+#if defined(PANGO_ENABLE_ENGINE) || defined(PANGO_ENABLE_BACKEND)
+#define PANGO_GLYPH_EMPTY ((PangoGlyph)0x0FFFFFFF)
+#define PANGO_GLYPH_UNKNOWN_FLAG ((PangoGlyph)0x10000000)
+#define PANGO_GET_UNKNOWN_GLYPH(wc) ((PangoGlyph)(wc)|PANGO_GLYPH_UNKNOWN_FLAG)
+#endif
+
+
+G_END_DECLS
+
+#endif /* __PANGO_FONT_H__ */
diff --git a/trunk/pango/pango-fontmap.c b/trunk/pango/pango-fontmap.c
new file mode 100644
index 00000000..e50e440d
--- /dev/null
+++ b/trunk/pango/pango-fontmap.c
@@ -0,0 +1,269 @@
+/* Pango
+ * pango-fontmap.c: Font handling
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "pango-fontmap.h"
+#include "pango-impl-utils.h"
+#include <stdlib.h>
+
+static PangoFontset *pango_font_map_real_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
+
+
+G_DEFINE_TYPE (PangoFontMap, pango_font_map, G_TYPE_OBJECT)
+
+static void
+pango_font_map_class_init (PangoFontMapClass *class)
+{
+ class->load_fontset = pango_font_map_real_load_fontset;
+}
+
+static void
+pango_font_map_init (PangoFontMap *fontmap)
+{
+}
+
+/**
+ * pango_font_map_load_font:
+ * @fontmap: a #PangoFontMap
+ * @context: the #PangoContext the font will be used with
+ * @desc: a #PangoFontDescription describing the font to load
+ *
+ * Load the font in the fontmap that is the closest match for @desc.
+ *
+ * Returns the font loaded, or %NULL if no font matched.
+ **/
+PangoFont *
+pango_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (pango_font_description_get_family (desc) != NULL, NULL);
+
+ return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_font (fontmap, context, desc);
+}
+
+/**
+ * pango_font_map_list_families:
+ * @fontmap: a #PangoFontMap
+ * @families: location to store a pointer to an array of #PangoFontFamily *.
+ * This array should be freed with g_free().
+ * @n_families: location to store the number of elements in @families
+ *
+ * List all families for a fontmap.
+ **/
+void
+pango_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families)
+{
+ g_return_if_fail (fontmap != NULL);
+
+ PANGO_FONT_MAP_GET_CLASS (fontmap)->list_families (fontmap, families, n_families);
+}
+
+/**
+ * pango_font_map_load_fontset:
+ * @fontmap: a #PangoFontMap
+ * @context: the #PangoContext the font will be used with
+ * @desc: a #PangoFontDescription describing the font to load
+ * @language: a #PangoLanguage the fonts will be used for
+ *
+ * Load a set of fonts in the fontmap that can be used to render
+ * a font matching @desc.
+ *
+ * Returns the fontset, or %NULL if no font matched.
+ **/
+PangoFontset *
+pango_font_map_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (pango_font_description_get_family (desc) != NULL, NULL);
+
+ return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_fontset (fontmap, context, desc, language);
+}
+
+static void
+pango_font_map_fontset_add_fonts (PangoFontMap *fontmap,
+ PangoContext *context,
+ PangoFontsetSimple *fonts,
+ PangoFontDescription *desc,
+ const char *family)
+{
+ char **aliases;
+ int n_aliases;
+ int j;
+ PangoFont *font;
+
+ pango_lookup_aliases (family,
+ &aliases,
+ &n_aliases);
+
+ if (n_aliases)
+ {
+ for (j = 0; j < n_aliases; j++)
+ {
+ pango_font_description_set_family_static (desc, aliases[j]);
+ font = pango_font_map_load_font (fontmap, context, desc);
+ if (font)
+ pango_fontset_simple_append (fonts, font);
+ }
+ }
+ else
+ {
+ pango_font_description_set_family_static (desc, family);
+ font = pango_font_map_load_font (fontmap, context, desc);
+ if (font)
+ pango_fontset_simple_append (fonts, font);
+ }
+}
+
+static PangoFontset *
+pango_font_map_real_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ PangoFontDescription *tmp_desc = pango_font_description_copy_static (desc);
+ char **families;
+ int i;
+ PangoFontsetSimple *fonts;
+ static GHashTable *warned_fonts = NULL;
+
+ families = g_strsplit (pango_font_description_get_family (desc), ",", -1);
+
+ fonts = pango_fontset_simple_new (language);
+
+ for (i = 0; families[i]; i++)
+ pango_font_map_fontset_add_fonts (fontmap,
+ context,
+ fonts,
+ tmp_desc,
+ families[i]);
+
+ g_strfreev (families);
+
+ /* The font description was completely unloadable, try with
+ * family == "Sans"
+ */
+ if (pango_fontset_simple_size (fonts) == 0)
+ {
+ char *ctmp1, *ctmp2;
+
+ pango_font_description_set_family_static (tmp_desc,
+ pango_font_description_get_family (desc));
+
+ ctmp1 = pango_font_description_to_string (desc);
+ pango_font_description_set_family_static (tmp_desc, "Sans");
+
+ if (!warned_fonts || !g_hash_table_lookup (warned_fonts, ctmp1))
+ {
+ if (!warned_fonts)
+ warned_fonts = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
+
+ ctmp2 = pango_font_description_to_string (tmp_desc);
+ g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
+ "expect ugly output.", ctmp1, ctmp2);
+ g_free (ctmp2);
+ }
+ g_free (ctmp1);
+
+ pango_font_map_fontset_add_fonts (fontmap,
+ context,
+ fonts,
+ tmp_desc,
+ "Sans");
+ }
+
+ /* We couldn't try with Sans and the specified style. Try Sans Normal
+ */
+ if (pango_fontset_simple_size (fonts) == 0)
+ {
+ char *ctmp1, *ctmp2;
+
+ pango_font_description_set_family_static (tmp_desc, "Sans");
+ ctmp1 = pango_font_description_to_string (tmp_desc);
+ pango_font_description_set_style (tmp_desc, PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight (tmp_desc, PANGO_WEIGHT_NORMAL);
+ pango_font_description_set_variant (tmp_desc, PANGO_VARIANT_NORMAL);
+ pango_font_description_set_stretch (tmp_desc, PANGO_STRETCH_NORMAL);
+
+ if (!warned_fonts || !g_hash_table_lookup (warned_fonts, ctmp1))
+ {
+ g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
+
+ ctmp2 = pango_font_description_to_string (tmp_desc);
+
+ g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
+ "expect ugly output.", ctmp1, ctmp2);
+ g_free (ctmp2);
+ }
+
+ g_free (ctmp1);
+
+ pango_font_map_fontset_add_fonts (fontmap,
+ context,
+ fonts,
+ tmp_desc,
+ "Sans");
+ }
+
+ pango_font_description_free (tmp_desc);
+
+ /* Everything failed, we are screwed, there is no way to continue,
+ * but lets just not crash here.
+ */
+ if (pango_fontset_simple_size (fonts) == 0)
+ g_warning ("All font fallbacks failed!!!!");
+
+ return PANGO_FONTSET (fonts);
+}
+
+/**
+ * pango_font_map_get_shape_engine_type:
+ * @fontmap: a #PangoFontMap
+ *
+ * Returns the render ID for shape engines for this fontmap.
+ * See the <structfield>render_type</structfield> field of
+ * #PangoEngineInfo.
+ *
+ * Return value: the ID string for shape engines for
+ * this fontmap. Owned by Pango, should not be modified
+ * or freed.
+ *
+ * Since: 1.4
+ **/
+G_CONST_RETURN char *
+pango_font_map_get_shape_engine_type (PangoFontMap *fontmap)
+{
+ g_return_val_if_fail (PANGO_IS_FONT_MAP (fontmap), NULL);
+
+ return PANGO_FONT_MAP_GET_CLASS (fontmap)->shape_engine_type;
+}
+
diff --git a/trunk/pango/pango-fontmap.h b/trunk/pango/pango-fontmap.h
new file mode 100644
index 00000000..204178fc
--- /dev/null
+++ b/trunk/pango/pango-fontmap.h
@@ -0,0 +1,95 @@
+/* Pango
+ * pango-font.h: Font handling
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_FONTMAP_H__
+#define __PANGO_FONTMAP_H__
+
+#include <pango/pango-font.h>
+#include <pango/pango-fontset.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_FONT_MAP (pango_font_map_get_type ())
+#define PANGO_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FONT_MAP, PangoFontMap))
+#define PANGO_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FONT_MAP))
+
+typedef struct _PangoContext PangoContext;
+
+GType pango_font_map_get_type (void) G_GNUC_CONST;
+PangoFont * pango_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc);
+PangoFontset *pango_font_map_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
+void pango_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families);
+
+#ifdef PANGO_ENABLE_BACKEND
+
+#define PANGO_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONT_MAP, PangoFontMapClass))
+#define PANGO_IS_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONT_MAP))
+#define PANGO_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONT_MAP, PangoFontMapClass))
+
+typedef struct _PangoFontMapClass PangoFontMapClass;
+
+struct _PangoFontMap
+{
+ GObject parent_instance;
+};
+
+struct _PangoFontMapClass
+{
+ GObjectClass parent_class;
+
+ /*< public >*/
+
+ PangoFont * (*load_font) (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc);
+ void (*list_families) (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families);
+ PangoFontset *(*load_fontset) (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
+
+ const char *shape_engine_type;
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+const char *pango_font_map_get_shape_engine_type (PangoFontMap *fontmap);
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+G_END_DECLS
+
+#endif /* __PANGO_FONTMAP_H__ */
diff --git a/trunk/pango/pango-fontset.c b/trunk/pango/pango-fontset.c
new file mode 100644
index 00000000..109d5985
--- /dev/null
+++ b/trunk/pango/pango-fontset.c
@@ -0,0 +1,404 @@
+/* Pango
+ * pango-fontset.c:
+ *
+ * Copyright (C) 2001 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+/*
+ * PangoFontset
+ */
+
+#include "pango-types.h"
+#include "pango-font.h"
+#include "pango-fontset.h"
+#include "pango-impl-utils.h"
+
+static PangoFontMetrics *pango_fontset_real_get_metrics (PangoFontset *fontset);
+
+static void
+pango_fontset_class_init (PangoFontsetClass *class)
+{
+ class->get_metrics = pango_fontset_real_get_metrics;
+}
+
+PANGO_DEFINE_TYPE_ABSTRACT (PangoFontset, pango_fontset,
+ pango_fontset_class_init, NULL, G_TYPE_OBJECT)
+
+/**
+ * pango_fontset_get_font:
+ * @fontset: a #PangoFontset
+ * @wc: a Unicode character
+ *
+ * Returns the font in the fontset that contains the best glyph for the
+ * Unicode character @wc.
+ *
+ * Return value: a #PangoFont. The caller must call g_object_unref when finished
+ * with the font.
+ **/
+PangoFont *
+pango_fontset_get_font (PangoFontset *fontset,
+ guint wc)
+{
+
+ g_return_val_if_fail (PANGO_IS_FONTSET (fontset), NULL);
+
+ return PANGO_FONTSET_GET_CLASS (fontset)->get_font (fontset, wc);
+}
+
+/**
+ * pango_fontset_get_metrics:
+ * @fontset: a #PangoFontset
+ *
+ * Get overall metric information for the fonts in the fontset.
+ *
+ * Return value: a #PangoFontMetrics object. The caller must call pango_font_metrics_unref()
+ * when finished using the object.
+ **/
+PangoFontMetrics *
+pango_fontset_get_metrics (PangoFontset *fontset)
+{
+ g_return_val_if_fail (PANGO_IS_FONTSET (fontset), NULL);
+
+ return PANGO_FONTSET_GET_CLASS (fontset)->get_metrics (fontset);
+}
+
+/**
+ * pango_fontset_foreach:
+ * @fontset: a #PangoFontset
+ * @func: Callback function
+ * @data: data to pass to the callback function
+ *
+ * Iterates through all the fonts in a fontset, calling @func for
+ * each one. If @func returns %TRUE, that stops the iteration.
+ *
+ * Since: 1.4
+ **/
+void
+pango_fontset_foreach (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data)
+{
+ g_return_if_fail (PANGO_IS_FONTSET (fontset));
+ g_return_if_fail (func != NULL);
+
+ PANGO_FONTSET_GET_CLASS (fontset)->foreach (fontset, func, data);
+}
+
+static gboolean
+get_first_metrics_foreach (PangoFontset *fontset,
+ PangoFont *font,
+ gpointer data)
+{
+ PangoFontMetrics *fontset_metrics = data;
+ PangoLanguage *language = PANGO_FONTSET_GET_CLASS (fontset)->get_language (fontset);
+ PangoFontMetrics *font_metrics = pango_font_get_metrics (font, language);
+ guint save_ref_count;
+
+ /* Initialize the fontset metrics to metrics of the first font in the
+ * fontset; saving the refcount and restoring it is a bit of hack but avoids
+ * having to update this code for each metrics addition.
+ */
+ save_ref_count = fontset_metrics->ref_count;
+ *fontset_metrics = *font_metrics;
+ fontset_metrics->ref_count = save_ref_count;
+
+ pango_font_metrics_unref (font_metrics);
+
+ return TRUE; /* Stops iteration */
+}
+
+static PangoFontMetrics *
+pango_fontset_real_get_metrics (PangoFontset *fontset)
+{
+ PangoFontMetrics *metrics, *raw_metrics;
+ const char *sample_str;
+ const char *p;
+ int count;
+ GHashTable *fonts_seen;
+ PangoFont *font;
+ PangoLanguage *language;
+
+ language = PANGO_FONTSET_GET_CLASS (fontset)->get_language (fontset);
+ sample_str = pango_language_get_sample_string (language);
+
+ count = 0;
+ metrics = pango_font_metrics_new ();
+ fonts_seen = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL);
+
+ /* Initialize the metrics from the first font in the fontset */
+ pango_fontset_foreach (fontset, get_first_metrics_foreach, metrics);
+
+ p = sample_str;
+ while (*p)
+ {
+ gunichar wc = g_utf8_get_char (p);
+ font = pango_fontset_get_font (fontset, wc);
+ if (font)
+ {
+ if (g_hash_table_lookup (fonts_seen, font) == NULL)
+ {
+ raw_metrics = pango_font_get_metrics (font, language);
+ g_hash_table_insert (fonts_seen, font, font);
+
+ if (count == 0)
+ {
+ metrics->ascent = raw_metrics->ascent;
+ metrics->descent = raw_metrics->descent;
+ metrics->approximate_char_width = raw_metrics->approximate_char_width;
+ metrics->approximate_digit_width = raw_metrics->approximate_digit_width;
+ }
+ else
+ {
+ metrics->ascent = MAX (metrics->ascent, raw_metrics->ascent);
+ metrics->descent = MAX (metrics->descent, raw_metrics->descent);
+ metrics->approximate_char_width += raw_metrics->approximate_char_width;
+ metrics->approximate_digit_width += raw_metrics->approximate_digit_width;
+ }
+ count++;
+ pango_font_metrics_unref (raw_metrics);
+ }
+ else
+ g_object_unref (font);
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ g_hash_table_destroy (fonts_seen);
+
+ if (count)
+ {
+ metrics->approximate_char_width /= count;
+ metrics->approximate_digit_width /= count;
+ }
+
+ return metrics;
+}
+
+
+/*
+ * PangoFontsetSimple
+ */
+
+#define PANGO_FONTSET_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONTSET_SIMPLE, PangoFontsetSimpleClass))
+#define PANGO_IS_FONTSET_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONTSET_SIMPLE))
+#define PANGO_FONTSET_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONTSET_SIMPLE, PangoFontsetSimpleClass))
+
+static void pango_fontset_simple_finalize (GObject *object);
+static void pango_fontset_simple_init (PangoFontsetSimple *fontset);
+static PangoFontMetrics *pango_fontset_simple_get_metrics (PangoFontset *fontset);
+static PangoLanguage * pango_fontset_simple_get_language (PangoFontset *fontset);
+static PangoFont * pango_fontset_simple_get_font (PangoFontset *fontset,
+ guint wc);
+static void pango_fontset_simple_foreach (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data);
+
+struct _PangoFontsetSimple
+{
+ PangoFontset parent_instance;
+
+ GPtrArray *fonts;
+ GPtrArray *coverages;
+ PangoLanguage *language;
+};
+
+struct _PangoFontsetSimpleClass
+{
+ PangoFontsetClass parent_class;
+};
+
+static PangoFontsetClass *simple_parent_class; /* Parent class structure for PangoFontsetSimple */
+
+/**
+ * pango_fontset_simple_new:
+ * @language: a #PangoLanguage tag
+ *
+ * Creates a new #PangoFontsetSimple for the given language.
+ *
+ * Return value: the newly allocated #PangoFontsetSimple, which should
+ * be freed with g_object_unref().
+ **/
+PangoFontsetSimple *
+pango_fontset_simple_new (PangoLanguage *language)
+{
+ PangoFontsetSimple *fontset;
+
+ fontset = g_object_new (PANGO_TYPE_FONTSET_SIMPLE, NULL);
+ fontset->language = language;
+
+ return fontset;
+}
+
+static void
+pango_fontset_simple_class_init (PangoFontsetSimpleClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontsetClass *fontset_class = PANGO_FONTSET_CLASS (class);
+
+ simple_parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_fontset_simple_finalize;
+ fontset_class->get_font = pango_fontset_simple_get_font;
+ fontset_class->get_metrics = pango_fontset_simple_get_metrics;
+ fontset_class->get_language = pango_fontset_simple_get_language;
+ fontset_class->foreach = pango_fontset_simple_foreach;
+}
+
+static void
+pango_fontset_simple_init (PangoFontsetSimple *fontset)
+{
+ fontset->fonts = g_ptr_array_new ();
+ fontset->coverages = g_ptr_array_new ();
+ fontset->language = NULL;
+}
+
+PANGO_DEFINE_TYPE (PangoFontsetSimple, pango_fontset_simple,
+ pango_fontset_simple_class_init, pango_fontset_simple_init,
+ PANGO_TYPE_FONTSET)
+
+static void
+pango_fontset_simple_finalize (GObject *object)
+{
+ PangoFontsetSimple *fontset = PANGO_FONTSET_SIMPLE (object);
+ PangoCoverage *coverage;
+ unsigned int i;
+
+ for (i = 0; i < fontset->fonts->len; i++)
+ g_object_unref (g_ptr_array_index(fontset->fonts, i));
+
+ g_ptr_array_free (fontset->fonts, TRUE);
+
+ for (i = 0; i < fontset->coverages->len; i++)
+ {
+ coverage = g_ptr_array_index (fontset->coverages, i);
+ if (coverage)
+ pango_coverage_unref (coverage);
+ }
+
+ g_ptr_array_free (fontset->coverages, TRUE);
+
+ G_OBJECT_CLASS (simple_parent_class)->finalize (object);
+}
+
+/**
+ * pango_fontset_simple_append:
+ * @fontset: a #PangoFontsetSimple.
+ * @font: a #PangoFont.
+ *
+ * Adds a font to the fontset.
+ **/
+void
+pango_fontset_simple_append (PangoFontsetSimple *fontset,
+ PangoFont *font)
+{
+ g_ptr_array_add (fontset->fonts, font);
+ g_ptr_array_add (fontset->coverages, NULL);
+}
+
+/**
+ * pango_fontset_simple_size:
+ * @fontset: a #PangoFontsetSimple.
+ *
+ * Returns the number of fonts in the fontset.
+ *
+ * Return value: the size of @fontset.
+ **/
+int
+pango_fontset_simple_size (PangoFontsetSimple *fontset)
+{
+ return fontset->fonts->len;
+}
+
+static PangoLanguage *
+pango_fontset_simple_get_language (PangoFontset *fontset)
+{
+ PangoFontsetSimple *simple = PANGO_FONTSET_SIMPLE (fontset);
+
+ return simple->language;
+}
+
+static PangoFontMetrics *
+pango_fontset_simple_get_metrics (PangoFontset *fontset)
+{
+ PangoFontsetSimple *simple = PANGO_FONTSET_SIMPLE (fontset);
+
+ if (simple->fonts->len == 1)
+ return pango_font_get_metrics (PANGO_FONT (g_ptr_array_index(simple->fonts, 0)),
+ simple->language);
+
+ return PANGO_FONTSET_CLASS (simple_parent_class)->get_metrics (fontset);
+}
+
+static PangoFont *
+pango_fontset_simple_get_font (PangoFontset *fontset,
+ guint wc)
+{
+ PangoFontsetSimple *simple = PANGO_FONTSET_SIMPLE (fontset);
+ PangoCoverageLevel best_level = PANGO_COVERAGE_NONE;
+ PangoCoverageLevel level;
+ PangoFont *font;
+ PangoCoverage *coverage;
+ int result = -1;
+ unsigned int i;
+
+ for (i = 0; i < simple->fonts->len; i++)
+ {
+ coverage = g_ptr_array_index (simple->coverages, i);
+
+ if (coverage == NULL)
+ {
+ font = g_ptr_array_index (simple->fonts, i);
+
+ coverage = pango_font_get_coverage (font, simple->language);
+ g_ptr_array_index (simple->coverages, i) = coverage;
+ }
+
+ level = pango_coverage_get (coverage, wc);
+
+ if (result == -1 || level > best_level)
+ {
+ result = i;
+ best_level = level;
+ if (level == PANGO_COVERAGE_EXACT)
+ break;
+ }
+ }
+
+ font = g_ptr_array_index(simple->fonts, result);
+ return g_object_ref (font);
+}
+
+static void
+pango_fontset_simple_foreach (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data)
+{
+ PangoFontsetSimple *simple = PANGO_FONTSET_SIMPLE (fontset);
+ unsigned int i;
+
+ for (i = 0; i < simple->fonts->len; i++)
+ {
+ if ((*func) (fontset,
+ g_ptr_array_index (simple->fonts, i),
+ data))
+ return;
+ }
+}
diff --git a/trunk/pango/pango-fontset.h b/trunk/pango/pango-fontset.h
new file mode 100644
index 00000000..5c6c7488
--- /dev/null
+++ b/trunk/pango/pango-fontset.h
@@ -0,0 +1,127 @@
+/* Pango
+ * pango-fontset.h: Font set handling
+ *
+ * Copyright (C) 2001 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_FONTSET_H__
+#define __PANGO_FONTSET_H__
+
+#include <pango/pango-coverage.h>
+#include <pango/pango-types.h>
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*
+ * PangoFontset
+ */
+
+#define PANGO_TYPE_FONTSET (pango_fontset_get_type ())
+#define PANGO_FONTSET(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FONTSET, PangoFontset))
+#define PANGO_IS_FONTSET(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FONTSET))
+
+GType pango_fontset_get_type (void) G_GNUC_CONST;
+
+typedef struct _PangoFontset PangoFontset;
+
+/**
+ * PangoFontsetForeachFunc
+ * @fontset: a #PangoFontset
+ * @font: a font from @fontset
+ * @data: callback data
+ *
+ * A callback function used by pango_fontset_foreach() when enumerating
+ * the fonts in a fontset.
+ *
+ * Returns: if %TRUE, stop iteration and return immediately.
+ *
+ * Since: 1.4
+ **/
+typedef gboolean (*PangoFontsetForeachFunc) (PangoFontset *fontset,
+ PangoFont *font,
+ gpointer data);
+
+PangoFont * pango_fontset_get_font (PangoFontset *fontset,
+ guint wc);
+PangoFontMetrics *pango_fontset_get_metrics (PangoFontset *fontset);
+void pango_fontset_foreach (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data);
+
+#ifdef PANGO_ENABLE_BACKEND
+
+typedef struct _PangoFontsetClass PangoFontsetClass;
+
+#define PANGO_FONTSET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONTSET, PangoFontsetClass))
+#define PANGO_IS_FONTSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONTSET))
+#define PANGO_FONTSET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONTSET, PangoFontsetClass))
+
+struct _PangoFontset
+{
+ GObject parent_instance;
+};
+
+struct _PangoFontsetClass
+{
+ GObjectClass parent_class;
+
+ /*< public >*/
+
+ PangoFont * (*get_font) (PangoFontset *fontset,
+ guint wc);
+
+ PangoFontMetrics *(*get_metrics) (PangoFontset *fontset);
+ PangoLanguage * (*get_language) (PangoFontset *fontset);
+ void (*foreach) (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data);
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+/*
+ * PangoFontsetSimple
+ */
+
+#define PANGO_TYPE_FONTSET_SIMPLE (pango_fontset_simple_get_type ())
+#define PANGO_FONTSET_SIMPLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FONTSET_SIMPLE, PangoFontsetSimple))
+#define PANGO_IS_FONTSET_SIMPLE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FONTSET_SIMPLE))
+
+typedef struct _PangoFontsetSimple PangoFontsetSimple;
+typedef struct _PangoFontsetSimpleClass PangoFontsetSimpleClass;
+
+GType pango_fontset_simple_get_type (void) G_GNUC_CONST;
+
+PangoFontsetSimple * pango_fontset_simple_new (PangoLanguage *language);
+void pango_fontset_simple_append (PangoFontsetSimple *fontset,
+ PangoFont *font);
+int pango_fontset_simple_size (PangoFontsetSimple *fontset);
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+G_END_DECLS
+
+#endif /* __PANGO_FONTSET_H__ */
diff --git a/trunk/pango/pango-glyph-item-private.h b/trunk/pango/pango-glyph-item-private.h
new file mode 100644
index 00000000..f936d755
--- /dev/null
+++ b/trunk/pango/pango-glyph-item-private.h
@@ -0,0 +1,63 @@
+/* Pango
+ * pango-glyph-item-private.h: Pair of PangoItem and a glyph string; private
+ * functionality
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_GLYPH_ITEM_PRIVATE_H__
+#define __PANGO_GLYPH_ITEM_PRIVATE_H__
+
+#include <pango-glyph-item.h>
+
+G_BEGIN_DECLS
+
+/* Structure holding state when we're iterating over a GlyphItem.
+ * start_index/cluster_end (and range_start/range_end in
+ * apply_attrs()) are offsets into the text, so note the difference
+ * of glyph_item->item->offset between them and clusters in the
+ * log_clusters[] array.
+ */
+typedef struct _PangoGlyphItemIter PangoGlyphItemIter;
+
+struct _PangoGlyphItemIter
+{
+ PangoGlyphItem *glyph_item;
+ const gchar *text;
+
+ int start_glyph;
+ int start_index;
+ int start_char;
+
+ int end_glyph;
+ int end_index;
+ int end_char;
+};
+
+gboolean _pango_glyph_item_iter_init_start (PangoGlyphItemIter *iter,
+ PangoGlyphItem *glyph_item,
+ const char *text);
+gboolean _pango_glyph_item_iter_init_end (PangoGlyphItemIter *iter,
+ PangoGlyphItem *glyph_item,
+ const char *text);
+gboolean _pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter);
+gboolean _pango_glyph_item_iter_prev_cluster (PangoGlyphItemIter *iter);
+
+G_END_DECLS
+
+#endif /* __PANGO_GLYPH_ITEM_PRIVATE_H__ */
diff --git a/trunk/pango/pango-glyph-item.c b/trunk/pango/pango-glyph-item.c
new file mode 100644
index 00000000..157bb150
--- /dev/null
+++ b/trunk/pango/pango-glyph-item.c
@@ -0,0 +1,664 @@
+/* Pango
+ * pango-glyph-item.c: Pair of PangoItem and a glyph string
+ *
+ * Copyright (C) 2002 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "pango-glyph-item.h"
+#include "pango-glyph-item-private.h"
+
+#define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0)
+
+/**
+ * pango_glyph_item_split:
+ * @orig: a #PangoItem
+ * @text: text to which positions in @orig apply
+ * @split_index: byte index of position to split item, relative to the start of the item
+ *
+ * Modifies @orig to cover only the text after @split_index, and
+ * returns a new item that covers the text before @split_index that
+ * used to be in @orig. You can think of @split_index as the length of
+ * the returned item. @split_index may not be 0, and it may not be
+ * greater than or equal to the length of @orig (that is, there must
+ * be at least one byte assigned to each item, you can't create a
+ * zero-length item).
+ *
+ * This function is similar in function to pango_item_split() (and uses
+ * it internally.)
+ *
+ * Return value: the newly allocated item representing text before
+ * @split_index, which should be freed
+ * with pango_glyph_item_free().
+ *
+ * Since: 1.2
+ **/
+PangoGlyphItem *
+pango_glyph_item_split (PangoGlyphItem *orig,
+ const char *text,
+ int split_index)
+{
+ PangoGlyphItem *new;
+ int i;
+ int num_glyphs;
+ int num_remaining;
+ int split_offset;
+
+ g_return_val_if_fail (orig != NULL, NULL);
+ g_return_val_if_fail (orig->item->length > 0, NULL);
+ g_return_val_if_fail (split_index > 0, NULL);
+ g_return_val_if_fail (split_index < orig->item->length, NULL);
+
+ if (LTR (orig))
+ {
+ for (i = 0; i < orig->glyphs->num_glyphs; i++)
+ {
+ if (orig->glyphs->log_clusters[i] >= split_index)
+ break;
+ }
+
+ if (i == orig->glyphs->num_glyphs) /* No splitting necessary */
+ return NULL;
+
+ split_index = orig->glyphs->log_clusters[i];
+ num_glyphs = i;
+ }
+ else
+ {
+ for (i = orig->glyphs->num_glyphs - 1; i >= 0; i--)
+ {
+ if (orig->glyphs->log_clusters[i] >= split_index)
+ break;
+ }
+
+ if (i < 0) /* No splitting necessary */
+ return NULL;
+
+ split_index = orig->glyphs->log_clusters[i];
+ num_glyphs = orig->glyphs->num_glyphs - 1 - i;
+ }
+
+ num_remaining = orig->glyphs->num_glyphs - num_glyphs;
+
+ new = g_slice_new (PangoGlyphItem);
+ split_offset = g_utf8_pointer_to_offset (text + orig->item->offset,
+ text + orig->item->offset + split_index);
+ new->item = pango_item_split (orig->item, split_index, split_offset);
+
+ new->glyphs = pango_glyph_string_new ();
+ pango_glyph_string_set_size (new->glyphs, num_glyphs);
+
+ if (LTR (orig))
+ {
+ memcpy (new->glyphs->glyphs, orig->glyphs->glyphs, num_glyphs * sizeof (PangoGlyphInfo));
+ memcpy (new->glyphs->log_clusters, orig->glyphs->log_clusters, num_glyphs * sizeof (int));
+
+ memmove (orig->glyphs->glyphs, orig->glyphs->glyphs + num_glyphs,
+ num_remaining * sizeof (PangoGlyphInfo));
+ for (i = num_glyphs; i < orig->glyphs->num_glyphs; i++)
+ orig->glyphs->log_clusters[i - num_glyphs] = orig->glyphs->log_clusters[i] - split_index;
+ }
+ else
+ {
+ memcpy (new->glyphs->glyphs, orig->glyphs->glyphs + num_remaining, num_glyphs * sizeof (PangoGlyphInfo));
+ memcpy (new->glyphs->log_clusters, orig->glyphs->log_clusters + num_remaining, num_glyphs * sizeof (int));
+
+ for (i = 0; i < num_remaining; i++)
+ orig->glyphs->log_clusters[i] = orig->glyphs->log_clusters[i] - split_index;
+ }
+
+ pango_glyph_string_set_size (orig->glyphs, orig->glyphs->num_glyphs - num_glyphs);
+
+ return new;
+}
+
+/**
+ * pango_glyph_item_free:
+ * @glyph_item: a #PangoGlyphItem
+ *
+ * Frees a #PangoGlyphItem and memory to which it points.
+ *
+ * Since: 1.6
+ **/
+void
+pango_glyph_item_free (PangoGlyphItem *glyph_item)
+{
+ if (glyph_item->item)
+ pango_item_free (glyph_item->item);
+ if (glyph_item->glyphs)
+ pango_glyph_string_free (glyph_item->glyphs);
+
+ g_slice_free (PangoGlyphItem, glyph_item);
+}
+
+/**
+ * _pango_glyph_item_iter_next_cluster:
+ * @iter: a #PangoGlyphItemIter
+ *
+ * Advances the iterator to the next cluster in the glyph item.
+ *
+ * Return value: %TRUE if the iterator was advanced, %FALSE if we were already on the
+ * last cluster.
+ **/
+gboolean
+_pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter)
+{
+ int glyph_index = iter->end_glyph;
+ PangoGlyphString *glyphs = iter->glyph_item->glyphs;
+ int cluster;
+ PangoItem *item = iter->glyph_item->item;
+
+ if (LTR (iter->glyph_item))
+ {
+ if (glyph_index == glyphs->num_glyphs)
+ return FALSE;
+ }
+ else
+ {
+ if (glyph_index < 0)
+ return FALSE;
+ }
+
+ iter->start_glyph = iter->end_glyph;
+ iter->start_index = iter->end_index;
+ iter->start_char = iter->end_char;
+
+ if (LTR (iter->glyph_item))
+ {
+ cluster = glyphs->log_clusters[glyph_index];
+ while (TRUE)
+ {
+ glyph_index++;
+
+ if (glyph_index == glyphs->num_glyphs)
+ {
+ iter->end_index = item->offset + item->length;
+ iter->end_char = item->num_chars;
+ break;
+ }
+
+ if (glyphs->log_clusters[glyph_index] != cluster)
+ {
+ iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
+ iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
+ iter->end_index - iter->start_index);
+ break;
+ }
+ }
+ }
+ else /* RTL */
+ {
+ cluster = glyphs->log_clusters[glyph_index];
+ while (TRUE)
+ {
+ glyph_index--;
+
+ if (glyph_index < 0)
+ {
+ iter->end_index = item->offset + item->length;
+ iter->end_char = item->num_chars;
+ break;
+ }
+
+ if (glyphs->log_clusters[glyph_index] != cluster)
+ {
+ iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
+ iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
+ iter->end_index - iter->start_index);
+ break;
+ }
+ }
+ }
+
+ iter->end_glyph = glyph_index;
+ return TRUE;
+}
+
+/**
+ * _pango_glyph_item_iter_prev_cluster:
+ * @iter: a #PangoGlyphItemIter
+ *
+ * Moves the iterator to the preceding cluster in the glyph item.
+ *
+ * Return value: %TRUE if the iterator was moved, %FALSE if we were already on the
+ * first cluster.
+ **/
+gboolean
+_pango_glyph_item_iter_prev_cluster (PangoGlyphItemIter *iter)
+{
+ int glyph_index = iter->start_glyph;
+ PangoGlyphString *glyphs = iter->glyph_item->glyphs;
+ int cluster;
+ PangoItem *item = iter->glyph_item->item;
+
+ if (LTR (iter->glyph_item))
+ {
+ if (glyph_index == 0)
+ return FALSE;
+ }
+ else
+ {
+ if (glyph_index == glyphs->num_glyphs - 1)
+ return FALSE;
+
+ }
+
+ iter->end_glyph = iter->start_glyph;
+ iter->end_index = iter->start_index;
+ iter->end_char = iter->start_char;
+
+ if (LTR (iter->glyph_item))
+ {
+ cluster = glyphs->log_clusters[glyph_index - 1];
+ while (TRUE)
+ {
+ glyph_index--;
+
+ if (glyph_index == 0)
+ {
+ iter->start_index = item->offset;
+ iter->start_char = 0;
+ break;
+ }
+
+ if (glyphs->log_clusters[glyph_index] != cluster)
+ {
+ iter->start_index = item->offset + glyphs->log_clusters[glyph_index];
+ iter->start_char -= g_utf8_strlen (iter->text + iter->start_index,
+ iter->end_index - iter->start_index);
+ break;
+ }
+ }
+ }
+ else /* RTL */
+ {
+ cluster = glyphs->log_clusters[glyph_index + 1];
+ while (TRUE)
+ {
+ glyph_index++;
+
+ if (glyph_index == glyphs->num_glyphs - 1)
+ {
+ iter->start_index = item->offset;
+ iter->start_char = 0;
+ break;
+ }
+
+ if (glyphs->log_clusters[glyph_index] != cluster)
+ {
+ iter->start_index = item->offset + glyphs->log_clusters[glyph_index];
+ iter->start_char -= g_utf8_strlen (iter->text + iter->start_index,
+ iter->end_index - iter->start_index);
+ break;
+ }
+ }
+ }
+
+ iter->start_glyph = glyph_index;
+ return TRUE;
+}
+
+/**
+ * _pango_glyph_item_iter_init_start:
+ * @iter: pointer to a #PangoGlyphItemIter structure
+ * @glyph_item: the glyph item that @iter points into
+ * @text: text corresponding to the glyph item
+ *
+ * Initializes a #PangoGlyphItemIter structure to point to the
+ * first cluster in a glyph item.
+ *
+ * Return value: %FALSE if there are no clusters in the glyph item;
+ * in this case, the state of @iter is undefined.
+ **/
+gboolean
+_pango_glyph_item_iter_init_start (PangoGlyphItemIter *iter,
+ PangoGlyphItem *glyph_item,
+ const char *text)
+{
+ iter->glyph_item = glyph_item;
+ iter->text = text;
+
+ if (LTR (glyph_item))
+ iter->end_glyph = 0;
+ else
+ iter->end_glyph = glyph_item->glyphs->num_glyphs - 1;
+
+ iter->end_index = glyph_item->item->offset;
+ iter->end_char = 0;
+
+ /* Advance onto the first cluster of the glyph item */
+ return _pango_glyph_item_iter_next_cluster (iter);
+}
+
+/**
+ * _pango_glyph_item_iter_init_end:
+ * @iter: pointer to a #PangoGlyphItemIter structure
+ * @glyph_item: the glyph item that @iter points into
+ * @text: text corresponding to the glyph item
+ *
+ * Initializes a #PangoGlyphItemIter structure to point to the
+ * last cluster in a glyph item.
+ *
+ * Return value: %FALSE if there are no clusters in the glyph item;
+ * in this case, the state of @iter is undefined.
+ **/
+gboolean
+_pango_glyph_item_iter_init_end (PangoGlyphItemIter *iter,
+ PangoGlyphItem *glyph_item,
+ const char *text)
+{
+ iter->glyph_item = glyph_item;
+ iter->text = text;
+
+ if (LTR (glyph_item))
+ iter->start_glyph = glyph_item->glyphs->num_glyphs;
+ else
+ iter->start_glyph = -1;
+
+ iter->start_index = glyph_item->item->offset + glyph_item->item->length;
+ iter->start_char = glyph_item->item->num_chars;
+
+ /* Advance onto the first cluster of the glyph item */
+ return _pango_glyph_item_iter_prev_cluster (iter);
+}
+
+typedef struct
+{
+ PangoGlyphItemIter iter;
+
+ GSList *segment_attrs;
+} ApplyAttrsState;
+
+/* Tack @attrs onto the attributes of glyph_item
+ */
+static void
+append_attrs (PangoGlyphItem *glyph_item,
+ GSList *attrs)
+{
+ glyph_item->item->analysis.extra_attrs =
+ g_slist_concat (glyph_item->item->analysis.extra_attrs, attrs);
+}
+
+/* Make a deep copy of a #GSList of PangoAttribute
+ */
+static GSList *
+attr_slist_copy (GSList *attrs)
+{
+ GSList *tmp_list;
+ GSList *new_attrs;
+
+ new_attrs = g_slist_copy (attrs);
+
+ for (tmp_list = new_attrs; tmp_list; tmp_list = tmp_list->next)
+ tmp_list->data = pango_attribute_copy (tmp_list->data);
+
+ return new_attrs;
+}
+
+/* Split the glyph item at the start of the current cluster
+ */
+static PangoGlyphItem *
+split_before_cluster_start (ApplyAttrsState *state)
+{
+ PangoGlyphItem *split_item;
+ int split_len = state->iter.start_index - state->iter.glyph_item->item->offset;
+
+ split_item = pango_glyph_item_split (state->iter.glyph_item, state->iter.text, split_len);
+ append_attrs (split_item, state->segment_attrs);
+
+ /* Adjust iteration to account for the split
+ */
+ if (LTR (state->iter.glyph_item))
+ {
+ state->iter.start_glyph -= split_item->glyphs->num_glyphs;
+ state->iter.end_glyph -= split_item->glyphs->num_glyphs;
+ }
+
+ state->iter.start_char -= split_item->item->num_chars;
+ state->iter.end_char -= split_item->item->num_chars;
+
+ return split_item;
+}
+
+/**
+ * pango_glyph_item_apply_attrs:
+ * @glyph_item: a shaped item
+ * @text: text that @list applies to
+ * @list: a #PangoAttrList
+ *
+ * Splits a shaped item (PangoGlyphItem) into multiple items based
+ * on an attribute list. The idea is that if you have attributes
+ * that don't affect shaping, such as color or underline, to avoid
+ * affecting shaping, you filter them out (pango_attr_list_filter()),
+ * apply the shaping process and then reapply them to the result using
+ * this function.
+ *
+ * All attributes that start or end inside a cluster are applied
+ * to that cluster; for instance, if half of a cluster is underlined
+ * and the other-half strikethrough, then the cluster will end
+ * up with both underline and strikethrough attributes. In these
+ * cases, it may happen that item->extra_attrs for some of the
+ * result items can have multiple attributes of the same type.
+ *
+ * This function takes ownership of @glyph_item; it will be reused
+ * as one of the elements in the list.
+ *
+ * Return value: a list of glyph items resulting from splitting
+ * @glyph_item. Free the elements using pango_glyph_item_free(),
+ * the list using g_slist_free().
+ *
+ * Since: 1.2
+ **/
+GSList *
+pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item,
+ const char *text,
+ PangoAttrList *list)
+{
+ PangoAttrIterator *iter = pango_attr_list_get_iterator (list);
+ GSList *result = NULL;
+ ApplyAttrsState state;
+ gboolean start_new_segment = FALSE;
+ gboolean have_cluster;
+ int range_start, range_end;
+
+ /* This routine works by iterating through the item cluster by
+ * cluster; we accumulate the attributes that we need to
+ * add to the next output item, and decide when to split
+ * off an output item based on two criteria:
+ *
+ * A) If start_index < attribute_start < end_index
+ * (attribute starts within cluster) then we need
+ * to split between the last cluster and this cluster.
+ * B) If start_index < attribute_end <= end_index,
+ * (attribute ends within cluster) then we need to
+ * split between this cluster and the next one.
+ */
+
+ /* Advance the attr iterator to the start of the item
+ */
+ do
+ {
+ pango_attr_iterator_range (iter, &range_start, &range_end);
+ if (range_end > glyph_item->item->offset)
+ break;
+ }
+ while (pango_attr_iterator_next (iter));
+
+ state.segment_attrs = pango_attr_iterator_get_attrs (iter);
+
+ /* Short circuit the case when we don't actually need to
+ * split the item
+ */
+ if (range_start <= glyph_item->item->offset &&
+ range_end >= glyph_item->item->offset + glyph_item->item->length)
+ goto out;
+
+ for (have_cluster = _pango_glyph_item_iter_init_start (&state.iter, glyph_item, text);
+ have_cluster;
+ have_cluster = _pango_glyph_item_iter_next_cluster (&state.iter))
+ {
+ gboolean have_next;
+
+ /* [range_start,range_end] is the first range that intersects
+ * the current cluster.
+ */
+
+ /* Split item into two, if this cluster isn't a continuation
+ * of the last cluster
+ */
+ if (start_new_segment)
+ {
+ result = g_slist_prepend (result,
+ split_before_cluster_start (&state));
+ state.segment_attrs = pango_attr_iterator_get_attrs (iter);
+ }
+
+ start_new_segment = FALSE;
+
+ /* Loop over all ranges that intersect this cluster; exiting
+ * leaving [range_start,range_end] being the first range that
+ * intersects the next cluster.
+ */
+ do
+ {
+ if (range_end > state.iter.end_index) /* Range intersects next cluster */
+ break;
+
+ /* Since ranges end in this cluster, the next cluster goes into a
+ * separate segment
+ */
+ start_new_segment = TRUE;
+
+ have_next = pango_attr_iterator_next (iter);
+ pango_attr_iterator_range (iter, &range_start, &range_end);
+
+ if (range_start >= state.iter.end_index) /* New range doesn't intersect this cluster */
+ {
+ /* No gap between ranges, so previous range must of ended
+ * at cluster boundary.
+ */
+ g_assert (range_start == state.iter.end_index && start_new_segment);
+ break;
+ }
+
+ /* If any ranges start *inside* this cluster, then we need
+ * to split the previous cluster into a separate segment
+ */
+ if (range_start > state.iter.start_index &&
+ state.iter.start_index != glyph_item->item->offset)
+ {
+ GSList *new_attrs = attr_slist_copy (state.segment_attrs);
+ result = g_slist_prepend (result,
+ split_before_cluster_start (&state));
+ state.segment_attrs = new_attrs;
+ }
+
+ state.segment_attrs = g_slist_concat (state.segment_attrs,
+ pango_attr_iterator_get_attrs (iter));
+ }
+ while (have_next);
+ }
+
+ out:
+ /* What's left in glyph_item is the remaining portion
+ */
+ append_attrs (glyph_item, state.segment_attrs);
+ result = g_slist_prepend (result, glyph_item);
+
+ if (LTR (glyph_item))
+ result = g_slist_reverse (result);
+
+ pango_attr_iterator_destroy (iter);
+
+ return result;
+}
+
+/**
+ * pango_glyph_item_letter_space:
+ * @glyph_item: a #PangoGlyphItem
+ * @text: text that @glyph_item corresponds to
+ * (glyph_item->item->offset is an offset from the
+ * start of @text)
+ * @log_attrs: logical attributes for the item (the
+ * first logical attribute refers to the position
+ * before the first character in the item)
+ * @letter_spacing: amount of letter spacing to add
+ * in Pango units. May be negative, though too large
+ * negative values will give ugly results.
+ *
+ * Adds spacing between the graphemes of @glyph_item to
+ * give the effect of typographic letter spacing.
+ *
+ * Since: 1.6
+ **/
+void
+pango_glyph_item_letter_space (PangoGlyphItem *glyph_item,
+ const char *text,
+ PangoLogAttr *log_attrs,
+ int letter_spacing)
+{
+ PangoGlyphItemIter iter;
+ PangoGlyphInfo *glyphs = glyph_item->glyphs->glyphs;
+ gboolean have_cluster;
+ int space_left, space_right;
+
+ space_left = letter_spacing / 2;
+
+ /* hinting */
+ if ((letter_spacing & (PANGO_SCALE - 1)) == 0)
+ {
+ space_left = PANGO_UNITS_ROUND (space_left);
+ }
+
+ space_right = letter_spacing - space_left;
+
+ for (have_cluster = _pango_glyph_item_iter_init_start (&iter, glyph_item, text);
+ have_cluster;
+ have_cluster = _pango_glyph_item_iter_next_cluster (&iter))
+ {
+ if (!log_attrs[iter.start_char].is_cursor_position)
+ continue;
+
+ if (iter.start_glyph < iter.end_glyph) /* LTR */
+ {
+ if (iter.start_char > 0)
+ {
+ glyphs[iter.start_glyph].geometry.width += space_left ;
+ glyphs[iter.start_glyph].geometry.x_offset += space_left ;
+ }
+ if (iter.end_char < glyph_item->item->num_chars)
+ {
+ glyphs[iter.end_glyph-1].geometry.width += space_right;
+ }
+ }
+ else /* RTL */
+ {
+ if (iter.start_char > 0)
+ {
+ glyphs[iter.start_glyph].geometry.width += space_right;
+ }
+ if (iter.end_char < glyph_item->item->num_chars)
+ {
+ glyphs[iter.end_glyph+1].geometry.x_offset += space_left ;
+ glyphs[iter.end_glyph+1].geometry.width += space_left ;
+ }
+ }
+ }
+}
diff --git a/trunk/pango/pango-glyph-item.h b/trunk/pango/pango-glyph-item.h
new file mode 100644
index 00000000..fec086a4
--- /dev/null
+++ b/trunk/pango/pango-glyph-item.h
@@ -0,0 +1,54 @@
+/* Pango
+ * pango-glyph-item.h: Pair of PangoItem and a glyph string
+ *
+ * Copyright (C) 2002 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_GLYPH_ITEM_H__
+#define __PANGO_GLYPH_ITEM_H__
+
+#include <pango/pango-attributes.h>
+#include <pango/pango-break.h>
+#include <pango/pango-item.h>
+#include <pango/pango-glyph.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoGlyphItem PangoGlyphItem;
+
+struct _PangoGlyphItem
+{
+ PangoItem *item;
+ PangoGlyphString *glyphs;
+};
+
+PangoGlyphItem *pango_glyph_item_split (PangoGlyphItem *orig,
+ const char *text,
+ int split_index);
+void pango_glyph_item_free (PangoGlyphItem *glyph_item);
+GSList * pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item,
+ const char *text,
+ PangoAttrList *list);
+void pango_glyph_item_letter_space (PangoGlyphItem *glyph_item,
+ const char *text,
+ PangoLogAttr *log_attrs,
+ int letter_spacing);
+
+G_END_DECLS
+
+#endif /* __PANGO_GLYPH_ITEM_H__ */
diff --git a/trunk/pango/pango-glyph.h b/trunk/pango/pango-glyph.h
new file mode 100644
index 00000000..cd26f53c
--- /dev/null
+++ b/trunk/pango/pango-glyph.h
@@ -0,0 +1,135 @@
+/* Pango
+ * pango-glyph.h: Glyph storage
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_GLYPH_H__
+#define __PANGO_GLYPH_H__
+
+#include <pango/pango-types.h>
+#include <pango/pango-item.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoGlyphGeometry PangoGlyphGeometry;
+typedef struct _PangoGlyphVisAttr PangoGlyphVisAttr;
+typedef struct _PangoGlyphInfo PangoGlyphInfo;
+typedef struct _PangoGlyphString PangoGlyphString;
+
+/* 1024ths of a device unit */
+typedef gint32 PangoGlyphUnit;
+
+/* Positioning information about a glyph
+ */
+struct _PangoGlyphGeometry
+{
+ PangoGlyphUnit width;
+ PangoGlyphUnit x_offset;
+ PangoGlyphUnit y_offset;
+};
+
+/* Visual attributes of a glyph
+ */
+struct _PangoGlyphVisAttr
+{
+ guint is_cluster_start : 1;
+};
+
+/* A single glyph
+ */
+struct _PangoGlyphInfo
+{
+ PangoGlyph glyph;
+ PangoGlyphGeometry geometry;
+ PangoGlyphVisAttr attr;
+};
+
+/* A string of glyphs with positional information and visual attributes -
+ * ready for drawing
+ */
+struct _PangoGlyphString {
+ gint num_glyphs;
+
+ PangoGlyphInfo *glyphs;
+
+ /* This is a memory inefficient way of representing the information
+ * here - each value gives the byte index within the text
+ * corresponding to the glyph string of the start of the cluster to
+ * which the glyph belongs.
+ */
+ gint *log_clusters;
+
+ /*< private >*/
+ gint space;
+};
+
+#define PANGO_TYPE_GLYPH_STRING (pango_glyph_string_get_type ())
+
+PangoGlyphString *pango_glyph_string_new (void);
+void pango_glyph_string_set_size (PangoGlyphString *string,
+ gint new_len);
+GType pango_glyph_string_get_type (void) G_GNUC_CONST;
+PangoGlyphString *pango_glyph_string_copy (PangoGlyphString *string);
+void pango_glyph_string_free (PangoGlyphString *string);
+void pango_glyph_string_extents (PangoGlyphString *glyphs,
+ PangoFont *font,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+int pango_glyph_string_get_width(PangoGlyphString *glyphs) G_GNUC_PURE;
+
+void pango_glyph_string_extents_range (PangoGlyphString *glyphs,
+ int start,
+ int end,
+ PangoFont *font,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+void pango_glyph_string_get_logical_widths (PangoGlyphString *glyphs,
+ const char *text,
+ int length,
+ int embedding_level,
+ int *logical_widths);
+
+void pango_glyph_string_index_to_x (PangoGlyphString *glyphs,
+ char *text,
+ int length,
+ PangoAnalysis *analysis,
+ int index_,
+ gboolean trailing,
+ int *x_pos);
+void pango_glyph_string_x_to_index (PangoGlyphString *glyphs,
+ char *text,
+ int length,
+ PangoAnalysis *analysis,
+ int x_pos,
+ int *index_,
+ int *trailing);
+
+/* Turn a string of characters into a string of glyphs
+ */
+void pango_shape (const gchar *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs);
+
+GList *pango_reorder_items (GList *logical_items);
+
+G_END_DECLS
+
+#endif /* __PANGO_GLYPH_H__ */
diff --git a/trunk/pango/pango-gravity.c b/trunk/pango/pango-gravity.c
new file mode 100644
index 00000000..1c2d8b0d
--- /dev/null
+++ b/trunk/pango/pango-gravity.c
@@ -0,0 +1,298 @@
+/* Pango
+ * pango-gravity.c: Gravity routines
+ *
+ * Copyright (C) 2006, 2007 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-gravity.h"
+
+#include <math.h>
+
+/**
+ * pango_gravity_to_rotation:
+ * @gravity: gravity to query
+ *
+ * Converts a #PangoGravity value to its natural rotation in radians.
+ * @gravity should not be %PANGO_GRAVITY_AUTO.
+ *
+ * Note that pango_matrix_rotate() takes angle in degrees, not radians.
+ * So, to call pango_matrix_rotate() with the output of this function
+ * you should multiply it by (180. / G_PI).
+ *
+ * Return value: the rotation value corresponding to @gravity.
+ *
+ * Since: 1.16
+ */
+double
+pango_gravity_to_rotation (PangoGravity gravity)
+{
+ double rotation;
+
+ g_return_val_if_fail (gravity != PANGO_GRAVITY_AUTO, 0);
+
+ switch (gravity)
+ {
+ default:
+ case PANGO_GRAVITY_AUTO: /* shut gcc up */
+ case PANGO_GRAVITY_SOUTH: rotation = 0; break;
+ case PANGO_GRAVITY_NORTH: rotation = G_PI; break;
+ case PANGO_GRAVITY_EAST: rotation = -G_PI_2; break;
+ case PANGO_GRAVITY_WEST: rotation = +G_PI_2; break;
+ }
+
+ return rotation;
+}
+
+/**
+ * pango_gravity_get_for_matrix:
+ * @matrix: a #PangoMatrix
+ *
+ * Finds the gravity that best matches the rotation component
+ * in a #PangoMatrix.
+ *
+ * Return value: the gravity of @matrix, which will never be
+ * %PANGO_GRAVITY_AUTO, or %PANGO_GRAVITY_SOUTH if @matrix is %NULL
+ *
+ * Since: 1.16
+ */
+PangoGravity
+pango_gravity_get_for_matrix (const PangoMatrix *matrix)
+{
+ PangoGravity gravity;
+ double x;
+ double y;
+
+ if (!matrix)
+ return PANGO_GRAVITY_SOUTH;
+
+ x = matrix->xy;
+ y = matrix->yy;
+
+ if (fabs (x) > fabs (y))
+ gravity = x > 0 ? PANGO_GRAVITY_WEST : PANGO_GRAVITY_EAST;
+ else
+ gravity = y < 0 ? PANGO_GRAVITY_NORTH : PANGO_GRAVITY_SOUTH;
+
+ return gravity;
+}
+
+
+
+typedef enum
+{
+ PANGO_VERTICAL_DIRECTION_NONE,
+ PANGO_VERTICAL_DIRECTION_TTB,
+ PANGO_VERTICAL_DIRECTION_BTT
+} PangoVerticalDirection;
+
+typedef struct {
+ /* PangoDirection */
+ guint8 horiz_dir; /* Orientation in horizontal context */
+
+ /* PangoVerticalDirection */
+ guint8 vert_dir; /* Orientation in vertical context */
+
+ /* PangoGravity */
+ guint8 preferred_gravity; /* Preferred context gravity */
+
+ /* gboolean */
+ guint8 upright; /* Whether glyphs are upright or
+ * rotated in foreign context */
+} PangoScriptProperties;
+
+#define NONE PANGO_VERTICAL_DIRECTION_NONE
+#define TTB PANGO_VERTICAL_DIRECTION_TTB
+#define BTT PANGO_VERTICAL_DIRECTION_BTT
+
+#define LTR PANGO_DIRECTION_LTR
+#define RTL PANGO_DIRECTION_RTL
+#define WEAK PANGO_DIRECTION_WEAK_LTR
+
+#define S PANGO_GRAVITY_SOUTH
+#define E PANGO_GRAVITY_EAST
+#define N PANGO_GRAVITY_NORTH
+#define W PANGO_GRAVITY_WEST
+
+const PangoScriptProperties script_properties[] =
+ { /* ISO 15924 code */
+ {LTR, NONE, S, FALSE}, /* Zyyy */
+ {LTR, NONE, S, FALSE}, /* Qaai */
+ {RTL, NONE, S, FALSE}, /* Arab */
+ {LTR, NONE, S, FALSE}, /* Armn */
+ {LTR, NONE, S, FALSE}, /* Beng */
+ {LTR, TTB, E, TRUE }, /* Bopo */
+ {LTR, NONE, S, FALSE}, /* Cher */
+ {LTR, NONE, S, FALSE}, /* Qaac */
+ {LTR, NONE, S, FALSE}, /* Cyrl (Cyrs) */
+ {LTR, NONE, S, FALSE}, /* Dsrt */
+ {LTR, NONE, S, FALSE}, /* Deva */
+ {LTR, NONE, S, FALSE}, /* Ethi */
+ {LTR, NONE, S, FALSE}, /* Geor (Geon, Geoa) */
+ {LTR, NONE, S, FALSE}, /* Goth */
+ {LTR, NONE, S, FALSE}, /* Grek */
+ {LTR, NONE, S, FALSE}, /* Gujr */
+ {LTR, NONE, S, FALSE}, /* Guru */
+ {LTR, TTB, E, TRUE }, /* Hani */
+ {LTR, TTB, E, TRUE }, /* Hang */
+ {RTL, NONE, S, FALSE}, /* Hebr */
+ {LTR, TTB, E, TRUE }, /* Hira */
+ {LTR, NONE, S, FALSE}, /* Knda */
+ {LTR, TTB, E, TRUE }, /* Kana */
+ {LTR, NONE, S, FALSE}, /* Khmr */
+ {LTR, NONE, S, FALSE}, /* Laoo */
+ {LTR, NONE, S, FALSE}, /* Latn (Latf, Latg) */
+ {LTR, NONE, S, FALSE}, /* Mlym */
+ {WEAK,TTB, W, FALSE}, /* Mong */
+ {LTR, NONE, S, FALSE}, /* Mymr */
+ {LTR, BTT, W, FALSE}, /* Ogam */
+ {LTR, NONE, S, FALSE}, /* Ital */
+ {LTR, NONE, S, FALSE}, /* Orya */
+ {LTR, NONE, S, FALSE}, /* Runr */
+ {LTR, NONE, S, FALSE}, /* Sinh */
+ {RTL, NONE, S, FALSE}, /* Syrc (Syrj, Syrn, Syre) */
+ {LTR, NONE, S, FALSE}, /* Taml */
+ {LTR, NONE, S, FALSE}, /* Telu */
+ {RTL, NONE, S, FALSE}, /* Thaa */
+ {LTR, NONE, S, FALSE}, /* Thai */
+ {LTR, NONE, S, FALSE}, /* Tibt */
+ {LTR, NONE, S, FALSE}, /* Cans */
+ {LTR, TTB, S, TRUE }, /* Yiii */
+ {LTR, NONE, S, FALSE}, /* Tglg */
+ {LTR, NONE, S, FALSE}, /* Hano */
+ {LTR, NONE, S, FALSE}, /* Buhd */
+ {LTR, NONE, S, FALSE}, /* Tagb */
+
+ /* Unicode-4.0 additions */
+ {LTR, NONE, S, FALSE}, /* Brai */
+ {LTR, NONE, S, FALSE}, /* Cprt */
+ {LTR, NONE, S, FALSE}, /* Limb */
+ {LTR, NONE, S, FALSE}, /* Osma */
+ {LTR, NONE, S, FALSE}, /* Shaw */
+ {LTR, NONE, S, FALSE}, /* Linb */
+ {LTR, NONE, S, FALSE}, /* Tale */
+ {LTR, NONE, S, FALSE}, /* Ugar */
+
+ /* Unicode-4.1 additions */
+ {LTR, NONE, S, FALSE}, /* Talu */
+ {LTR, NONE, S, FALSE}, /* Bugi */
+ {LTR, NONE, S, FALSE}, /* Glag */
+ {LTR, NONE, S, FALSE}, /* Tfng */
+ {LTR, NONE, S, FALSE}, /* Sylo */
+ {LTR, NONE, S, FALSE}, /* Xpeo */
+ {LTR, NONE, S, FALSE}, /* Khar */
+
+ /* Unicode-5.0 additions */
+ {LTR, NONE, S, FALSE}, /* Zzzz */
+ {LTR, NONE, S, FALSE}, /* Bali */
+ {LTR, NONE, S, FALSE}, /* Xsux */
+ {RTL, NONE, S, FALSE}, /* Phnx */
+ {LTR, NONE, S, FALSE}, /* Phag */
+ {RTL, NONE, S, FALSE} /* Nkoo */
+};
+
+#undef NONE
+#undef TTB
+#undef BTT
+
+#undef LTR
+#undef RTL
+#undef WEAK
+
+#undef S
+#undef E
+#undef N
+#undef W
+
+static PangoScriptProperties
+get_script_properties (PangoScript script)
+{
+ if ((guint)script >= G_N_ELEMENTS (script_properties))
+ script = 0;
+
+ return script_properties[script];
+}
+
+/**
+ * pango_gravity_get_for_script:
+ * @script: #PangoScript to query
+ * @base_gravity: base gravity of the paragraph
+ * @hint: orientation hint
+ *
+ * Based on the script, base gravity, and hint, returns actual gravity
+ * to use in laying out a single #PangoItem.
+ *
+ * If @base_gravity is %PANGO_GRAVITY_AUTO, it is first replaced with the
+ * preferred gravity of @script. To get the preferred gravity of a script,
+ * pass %PANGO_GRAVITY_AUTO and %PANGO_GRAVITY_HINT_STRONG in.
+ *
+ * Return value: resolved gravity suitable to use for a run of text
+ *
+ * Since: 1.16
+ */
+PangoGravity
+pango_gravity_get_for_script (PangoScript script,
+ PangoGravity base_gravity,
+ PangoGravityHint hint)
+{
+ PangoScriptProperties props = get_script_properties (script);
+ gboolean vertical;
+
+
+ if (G_UNLIKELY (base_gravity == PANGO_GRAVITY_AUTO))
+ base_gravity = props.preferred_gravity;
+
+ vertical = PANGO_GRAVITY_IS_VERTICAL (base_gravity);
+
+ /* Everything is designed such that a system with no vertical support
+ * renders everything correctly horizontally. So, if not in a vertical
+ * gravity, base and resolved gravities are always the same.
+ *
+ * If the script should be upright all the time, like Chinese and Japenese,
+ * any base gravity should resolve to itself.
+ */
+ if (G_LIKELY (!vertical || props.upright))
+ return base_gravity;
+
+ /* If here, we have a non-upright script in a vertical gravity setting.
+ * Resolve depending on the hint.
+ */
+ switch (hint)
+ {
+ default:
+ case PANGO_GRAVITY_HINT_NATURAL:
+ if (props.vert_dir == PANGO_VERTICAL_DIRECTION_NONE)
+ return PANGO_GRAVITY_SOUTH;
+ if ((base_gravity == PANGO_GRAVITY_EAST) ^
+ (props.vert_dir == PANGO_VERTICAL_DIRECTION_BTT))
+ return PANGO_GRAVITY_SOUTH;
+ else
+ return PANGO_GRAVITY_NORTH;
+
+ case PANGO_GRAVITY_HINT_STRONG:
+ return base_gravity;
+
+ case PANGO_GRAVITY_HINT_LINE:
+ if ((base_gravity == PANGO_GRAVITY_EAST) ^
+ (props.horiz_dir == PANGO_DIRECTION_RTL))
+ return PANGO_GRAVITY_SOUTH;
+ else
+ return PANGO_GRAVITY_NORTH;
+ }
+}
diff --git a/trunk/pango/pango-gravity.h b/trunk/pango/pango-gravity.h
new file mode 100644
index 00000000..2e42ebd8
--- /dev/null
+++ b/trunk/pango/pango-gravity.h
@@ -0,0 +1,109 @@
+/* Pango
+ * pango-gravity.h: Gravity routines
+ *
+ * Copyright (C) 2006, 2007 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_GRAVITY_H__
+#define __PANGO_GRAVITY_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PangoGravity:
+ * @PANGO_GRAVITY_SOUTH: Glyphs stand upright (default)
+ * @PANGO_GRAVITY_EAST: Glyphs are rotated 90 degrees clockwise
+ * @PANGO_GRAVITY_NORTH: Glyphs are upside-down
+ * @PANGO_GRAVITY_WEST: Glyphs are rotated 90 degrees counter-clockwise
+ * @PANGO_GRAVITY_AUTO: Gravity is resolved from the context matrix
+ *
+ * The #PangoGravity type represents the orientation of glyphs in a segment
+ * of text. This is useful when rendering vertical text layouts. In
+ * those situations, the layout is rotated using a non-identity PangoMatrix,
+ * and then glyph orientation is controlled using #PangoGravity.
+ * Not every value in this enumeration makes sense for every usage of
+ * #PangoGravity; for example, %PANGO_GRAVITY_AUTO only can be passed to
+ * pango_context_set_base_gravity() and can only be returned by
+ * pango_context_get_base_gravity().
+ *
+ * See also: #PangoGravityHint
+ *
+ * Since: 1.16
+ **/
+typedef enum {
+ PANGO_GRAVITY_SOUTH,
+ PANGO_GRAVITY_EAST,
+ PANGO_GRAVITY_NORTH,
+ PANGO_GRAVITY_WEST,
+ PANGO_GRAVITY_AUTO
+} PangoGravity;
+
+/**
+ * PangoGravityHint:
+ * @PANGO_GRAVITY_HINT_NATURAL: scripts will take their natural gravity based
+ * on the base gravity and the script. This is the default.
+ * @PANGO_GRAVITY_HINT_STRONG: always use the base gravity set, regardless of
+ * the script.
+ * @PANGO_GRAVITY_HINT_LINE: for scripts not in their natural direction (eg.
+ * Latin in East gravity), choose per-script gravity such that every script
+ * respects the line progression. This means, Latin and Arabic will take
+ * opposite gravities and both flow top-to-bottom for example.
+ *
+ * The #PangoGravityHint defines how horizontal scripts should behave in a
+ * vertical context. That is, English excerpt in a vertical paragraph for
+ * example.
+ *
+ * See #PangoGravity.
+ *
+ * Since: 1.16
+ **/
+typedef enum {
+ PANGO_GRAVITY_HINT_NATURAL,
+ PANGO_GRAVITY_HINT_STRONG,
+ PANGO_GRAVITY_HINT_LINE
+} PangoGravityHint;
+
+/**
+ * PANGO_GRAVITY_IS_VERTICAL:
+ * @gravity: the #PangoGravity to check
+ *
+ * Whether a #PangoGravity represents vertical writing directions.
+ *
+ * Returns: %TRUE if @gravity is %PANGO_GRAVITY_EAST or %PANGO_GRAVITY_WEST,
+ * %FALSE otherwise.
+ *
+ * Since: 1.16
+ **/
+#define PANGO_GRAVITY_IS_VERTICAL(gravity) \
+ ((gravity) == PANGO_GRAVITY_EAST || (gravity) == PANGO_GRAVITY_WEST)
+
+#include <pango/pango-matrix.h>
+#include <pango/pango-script.h>
+
+double pango_gravity_to_rotation (PangoGravity gravity) G_GNUC_CONST;
+PangoGravity pango_gravity_get_for_matrix (const PangoMatrix *matrix) G_GNUC_PURE;
+PangoGravity pango_gravity_get_for_script (PangoScript script,
+ PangoGravity base_gravity,
+ PangoGravityHint hint) G_GNUC_CONST;
+
+
+G_END_DECLS
+
+#endif /* __PANGO_GRAVITY_H__ */
diff --git a/trunk/pango/pango-impl-utils.h b/trunk/pango/pango-impl-utils.h
new file mode 100644
index 00000000..2f71dadf
--- /dev/null
+++ b/trunk/pango/pango-impl-utils.h
@@ -0,0 +1,100 @@
+/* Pango
+ * pango-impl-utils.h: Macros for get_type() functions
+ * Inspired by Jody Goldberg's gsf-impl-utils.h
+ *
+ * Copyright (C) 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_IMPL_UTILS_H__
+#define __PANGO_IMPL_UTILS_H__
+
+#include <glib-object.h>
+#include <pango/pango-utils.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_DEFINE_TYPE_FULL(name, prefix, \
+ class_init, instance_init, \
+ parent_type, abstract) \
+GType \
+prefix ## _get_type (void) \
+{ \
+ static GType object_type = 0; \
+ \
+ if (!object_type) \
+ { \
+ static const GTypeInfo object_info = \
+ { \
+ sizeof (name ## Class), \
+ (GBaseInitFunc) NULL, \
+ (GBaseFinalizeFunc) NULL, \
+ (GClassInitFunc) class_init, \
+ (GClassFinalizeFunc) NULL, \
+ NULL, /* class_data */ \
+ sizeof (name), \
+ 0, /* n_prelocs */ \
+ (GInstanceInitFunc) instance_init, \
+ NULL /* value_table */ \
+ }; \
+ \
+ object_type = g_type_register_static (parent_type, \
+ g_intern_static_string (# name), \
+ &object_info, abstract); \
+ } \
+ \
+ return object_type; \
+}
+
+#define PANGO_DEFINE_TYPE(name, prefix, \
+ class_init, instance_init, \
+ parent_type) \
+ PANGO_DEFINE_TYPE_FULL (name, prefix, \
+ class_init, instance_init, \
+ parent_type, 0)
+
+#define PANGO_DEFINE_TYPE_ABSTRACT(name, prefix, \
+ class_init, instance_init, \
+ parent_type) \
+ PANGO_DEFINE_TYPE_FULL (name, prefix, \
+ class_init, instance_init, \
+ parent_type, G_TYPE_FLAG_ABSTRACT)
+
+
+
+/* Warning history. Used to not spew some warnings more than once. */
+typedef struct _PangoWarningHistory PangoWarningHistory;
+
+struct _PangoWarningHistory {
+ guint shape_font : 1;
+ guint shape_shape_engine : 1;
+ guint get_glyph_extents : 1;
+ guint get_metrics : 1;
+ guint get_font_map : 1;
+};
+
+extern PangoWarningHistory _pango_warning_history;
+
+
+/* String interning for static strings */
+#define I_(string) g_intern_static_string (string)
+
+
+G_END_DECLS
+
+#endif /* __PANGO_IMPL_UTILS_H__ */
+
diff --git a/trunk/pango/pango-item.c b/trunk/pango/pango-item.c
new file mode 100644
index 00000000..d5650827
--- /dev/null
+++ b/trunk/pango/pango-item.c
@@ -0,0 +1,154 @@
+/* Pango
+ * pango-item.c: Single run handling
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "pango-attributes.h"
+#include "pango-item.h"
+#include "pango-impl-utils.h"
+
+/**
+ * pango_item_new:
+ *
+ * Creates a new #PangoItem structure initialized to default values.
+ *
+ * Return value: the newly allocated #PangoItem, which should
+ * be freed with pango_item_free().
+ **/
+PangoItem *
+pango_item_new (void)
+{
+ PangoItem *result = g_slice_new0 (PangoItem);
+
+ return result;
+}
+
+/**
+ * pango_item_copy:
+ * @item: a #PangoItem
+ *
+ * Copy an existing #PangoItem structure.
+ *
+ * Return value: the newly allocated #PangoItem, which should
+ * be freed with pango_item_free().
+ **/
+PangoItem *
+pango_item_copy (PangoItem *item)
+{
+ GSList *extra_attrs, *tmp_list;
+ PangoItem *result = g_slice_new (PangoItem);
+
+ result->offset = item->offset;
+ result->length = item->length;
+ result->num_chars = item->num_chars;
+
+ result->analysis = item->analysis;
+ if (result->analysis.font)
+ g_object_ref (result->analysis.font);
+
+ extra_attrs = NULL;
+ tmp_list = item->analysis.extra_attrs;
+ while (tmp_list)
+ {
+ extra_attrs = g_slist_prepend (extra_attrs, pango_attribute_copy (tmp_list->data));
+ tmp_list = tmp_list->next;
+ }
+
+ result->analysis.extra_attrs = g_slist_reverse (extra_attrs);
+
+ return result;
+}
+
+/**
+ * pango_item_free:
+ * @item: a #PangoItem
+ *
+ * Free a #PangoItem and all associated memory.
+ **/
+void
+pango_item_free (PangoItem *item)
+{
+ if (item->analysis.extra_attrs)
+ {
+ g_slist_foreach (item->analysis.extra_attrs, (GFunc)pango_attribute_destroy, NULL);
+ g_slist_free (item->analysis.extra_attrs);
+ }
+
+ if (item->analysis.font)
+ g_object_unref (item->analysis.font);
+
+ g_slice_free (PangoItem, item);
+}
+
+GType
+pango_item_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoItem"),
+ (GBoxedCopyFunc) pango_item_copy,
+ (GBoxedFreeFunc) pango_item_free);
+ return our_type;
+}
+
+/**
+ * pango_item_split:
+ * @orig: a #PangoItem
+ * @split_index: byte index of position to split item, relative to the start of the item
+ * @split_offset: number of chars between start of @orig and @split_index
+ *
+ * Modifies @orig to cover only the text after @split_index, and
+ * returns a new item that covers the text before @split_index that
+ * used to be in @orig. You can think of @split_index as the length of
+ * the returned item. @split_index may not be 0, and it may not be
+ * greater than or equal to the length of @orig (that is, there must
+ * be at least one byte assigned to each item, you can't create a
+ * zero-length item). @split_offset is the length of the first item in
+ * chars, and must be provided because the text used to generate the
+ * item isn't available, so pango_item_split() can't count the char
+ * length of the split items itself.
+ *
+ * Return value: new item representing text before @split_index, which
+ * should be freed with pango_item_free().
+ **/
+PangoItem*
+pango_item_split (PangoItem *orig,
+ int split_index,
+ int split_offset)
+{
+ PangoItem *new_item;
+
+ g_return_val_if_fail (orig != NULL, NULL);
+ g_return_val_if_fail (split_index > 0, NULL);
+ g_return_val_if_fail (split_index < orig->length, NULL);
+ g_return_val_if_fail (split_offset > 0, NULL);
+ g_return_val_if_fail (split_offset < orig->num_chars, NULL);
+
+ new_item = pango_item_copy (orig);
+ new_item->length = split_index;
+ new_item->num_chars = split_offset;
+
+ orig->offset += split_index;
+ orig->length -= split_index;
+ orig->num_chars -= split_offset;
+
+ return new_item;
+}
diff --git a/trunk/pango/pango-item.h b/trunk/pango/pango-item.h
new file mode 100644
index 00000000..0775003c
--- /dev/null
+++ b/trunk/pango/pango-item.h
@@ -0,0 +1,72 @@
+/* Pango
+ * pango-item.h: Structure for storing run information
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_ITEM_H__
+#define __PANGO_ITEM_H__
+
+#include <pango/pango-types.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoAnalysis PangoAnalysis;
+typedef struct _PangoItem PangoItem;
+
+/* TODO: if more flags are needed, turn this into a real PangoAnalysisFlags enum */
+#define PANGO_ANALYSIS_FLAG_CENTERED_BASELINE (1 << 0)
+
+struct _PangoAnalysis
+{
+ PangoEngineShape *shape_engine;
+ PangoEngineLang *lang_engine;
+ PangoFont *font;
+
+ guint8 level;
+ guint8 gravity; /* PangoGravity */
+ guint8 flags;
+
+ guint8 script; /* PangoScript */
+ PangoLanguage *language;
+
+ GSList *extra_attrs;
+};
+
+struct _PangoItem
+{
+ gint offset;
+ gint length;
+ gint num_chars;
+ PangoAnalysis analysis;
+};
+
+#define PANGO_TYPE_ITEM (pango_item_get_type ())
+
+GType pango_item_get_type (void) G_GNUC_CONST;
+
+PangoItem *pango_item_new (void);
+PangoItem *pango_item_copy (PangoItem *item);
+void pango_item_free (PangoItem *item);
+PangoItem *pango_item_split (PangoItem *orig,
+ int split_index,
+ int split_offset);
+
+G_END_DECLS
+
+#endif /* __PANGO_ITEM_H__ */
diff --git a/trunk/pango/pango-language.c b/trunk/pango/pango-language.c
new file mode 100644
index 00000000..e6567924
--- /dev/null
+++ b/trunk/pango/pango-language.c
@@ -0,0 +1,730 @@
+/* Pango
+ * pango-language.c: Language handling routines
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <locale.h>
+
+#include "pango-language.h"
+#include "pango-impl-utils.h"
+
+#define LANGUAGE_SEPARATORS ";:, \t"
+
+static const char canon_map[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0,
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
+ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-',
+ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
+};
+
+static gboolean
+lang_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const guchar *p1 = v1;
+ const guchar *p2 = v2;
+
+ while (canon_map[*p1] && canon_map[*p1] == canon_map[*p2])
+ {
+ p1++, p2++;
+ }
+
+ return (canon_map[*p1] == canon_map[*p2]);
+}
+
+static guint
+lang_hash (gconstpointer key)
+{
+ const guchar *p = key;
+ guint h = 0;
+ while (canon_map[*p])
+ {
+ h = (h << 5) - h + canon_map[*p];
+ p++;
+ }
+
+ return h;
+}
+
+static PangoLanguage *
+pango_language_copy (PangoLanguage *language)
+{
+ return language; /* language tags are const */
+}
+
+static void
+pango_language_free (PangoLanguage *language)
+{
+ return; /* nothing */
+}
+
+GType
+pango_language_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoLanguage"),
+ (GBoxedCopyFunc)pango_language_copy,
+ (GBoxedFreeFunc)pango_language_free);
+ return our_type;
+}
+
+/**
+ * _pango_get_lc_ctype:
+ *
+ * Return the Unix-style locale string for the language currently in
+ * effect. On Unix systems, this is the return value from
+ * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
+ * affect this through the environment variables LC_ALL, LC_CTYPE or
+ * LANG (checked in that order). The locale strings typically is in
+ * the form lang_COUNTRY, where lang is an ISO-639 language code, and
+ * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
+ * Swedish as written in Finland or pt_BR for Portuguese as written in
+ * Brazil.
+ *
+ * On Windows, the C library doesn't use any such environment
+ * variables, and setting them won't affect the behavior of functions
+ * like ctime(). The user sets the locale through the Regional Options
+ * in the Control Panel. The C library (in the setlocale() function)
+ * does not use country and language codes, but country and language
+ * names spelled out in English.
+ * However, this function does check the above environment
+ * variables, and does return a Unix-style locale string based on
+ * either said environment variables or the thread's current locale.
+ *
+ * Return value: a dynamically allocated string, free with g_free().
+ */
+static gchar *
+_pango_get_lc_ctype (void)
+{
+#ifdef G_OS_WIN32
+ /* Somebody might try to set the locale for this process using the
+ * LANG or LC_ environment variables. The Microsoft C library
+ * doesn't know anything about them. You set the locale in the
+ * Control Panel. Setting these env vars won't have any affect on
+ * locale-dependent C library functions like ctime(). But just for
+ * kicks, do obey LC_ALL, LC_CTYPE and LANG in Pango. (This also makes
+ * it easier to test GTK and Pango in various default languages, you
+ * don't have to clickety-click in the Control Panel, you can simply
+ * start the program with LC_ALL=something on the command line.)
+ */
+
+ gchar *p;
+
+ p = getenv ("LC_ALL");
+ if (p != NULL)
+ return g_strdup (p);
+
+ p = getenv ("LC_CTYPE");
+ if (p != NULL)
+ return g_strdup (p);
+
+ p = getenv ("LANG");
+ if (p != NULL)
+ return g_strdup (p);
+
+ return g_win32_getlocale ();
+#else
+ return g_strdup (setlocale (LC_CTYPE, NULL));
+#endif
+}
+
+/**
+ * pango_language_get_default:
+ *
+ * Returns the #PangoLanguage for the current locale of the process.
+ * Note that this can change over the life of an application.
+ *
+ * On Unix systems, this is the return value is derived from
+ * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
+ * affect this through the environment variables LC_ALL, LC_CTYPE or
+ * LANG (checked in that order). The locale string typically is in
+ * the form lang_COUNTRY, where lang is an ISO-639 language code, and
+ * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
+ * Swedish as written in Finland or pt_BR for Portuguese as written in
+ * Brazil.
+ *
+ * On Windows, the C library does not use any such environment
+ * variables, and setting them won't affect the behavior of functions
+ * like ctime(). The user sets the locale through the Regional Options
+ * in the Control Panel. The C library (in the setlocale() function)
+ * does not use country and language codes, but country and language
+ * names spelled out in English.
+ * However, this function does check the above environment
+ * variables, and does return a Unix-style locale string based on
+ * either said environment variables or the thread's current locale.
+ *
+ * Your application should call <literal>setlocale(LC_ALL, "");</literal>
+ * for the user settings to take effect. Gtk+ does this in its initialization
+ * functions automatically (by calling gtk_set_locale()).
+ * See <literal>man setlocale</literal> for more details.
+ *
+ * Return value: the default language as a #PangoLanguage, must not be
+ * freed.
+ *
+ * Since: 1.16
+ **/
+PangoLanguage *
+pango_language_get_default (void)
+{
+ static PangoLanguage *result = NULL;
+
+ if (G_UNLIKELY (!result))
+ {
+ gchar *lang = _pango_get_lc_ctype ();
+ result = pango_language_from_string (lang);
+ g_free (lang);
+ }
+
+ return result;
+}
+
+/**
+ * pango_language_from_string:
+ * @language: a string representing a language tag
+ *
+ * Take a RFC-3066 format language tag as a string and convert it to a
+ * #PangoLanguage pointer that can be efficiently copied (copy the
+ * pointer) and compared with other language tags (compare the
+ * pointer.)
+ *
+ * This function first canonicalizes the string by converting it to
+ * lowercase, mapping '_' to '-', and stripping all characters other
+ * than letters and '-'.
+ *
+ * Use pango_language_get_default() if you want to get the #PangoLanguage for
+ * the current locale of the process.
+ *
+ * Return value: an opaque pointer to a #PangoLanguage structure.
+ * this will be valid forever after.
+ **/
+PangoLanguage *
+pango_language_from_string (const char *language)
+{
+ static GHashTable *hash = NULL;
+ char *result;
+ int len;
+ char *p;
+
+ if (G_UNLIKELY (!hash))
+ hash = g_hash_table_new (lang_hash, lang_equal);
+ else
+ {
+ result = g_hash_table_lookup (hash, language);
+ if (result)
+ return (PangoLanguage *)result;
+ }
+
+ len = strlen (language);
+ result = g_malloc (len + 1);
+
+ p = result;
+ while ((*(p++) = canon_map[*(guchar *)language++]))
+ ;
+
+ g_hash_table_insert (hash, result, result);
+
+ return (PangoLanguage *)result;
+}
+
+/**
+ * pango_language_matches:
+ * @language: a language tag (see pango_language_from_string()),
+ * %NULL is allowed and matches nothing but '*'
+ * @range_list: a list of language ranges, separated by ';', ':',
+ * ',', or space characters.
+ * Each element must either be '*', or a RFC 3066 language range
+ * canonicalized as by pango_language_from_string()
+ *
+ * Checks if a language tag matches one of the elements in a list of
+ * language ranges. A language tag is considered to match a range
+ * in the list if the range is '*', the range is exactly the tag,
+ * or the range is a prefix of the tag, and the character after it
+ * in the tag is '-'.
+ *
+ * Return value: %TRUE if a match was found.
+ **/
+gboolean
+pango_language_matches (PangoLanguage *language,
+ const char *range_list)
+{
+ const char *lang_str = pango_language_to_string (language);
+ const char *p = range_list;
+ gboolean done = FALSE;
+
+ while (!done)
+ {
+ const char *end = strpbrk (p, LANGUAGE_SEPARATORS);
+ if (!end)
+ {
+ end = p + strlen (p);
+ done = TRUE;
+ }
+
+ if (strncmp (p, "*", 1) == 0 ||
+ (lang_str && strncmp (lang_str, p, end - p) == 0 &&
+ (lang_str[end - p] == '\0' || lang_str[end - p] == '-')))
+ return TRUE;
+
+ if (!done)
+ p = end + 1;
+ }
+
+ return FALSE;
+}
+
+typedef struct {
+ const char lang[4];
+ const char *str;
+} LangInfo;
+
+static int
+lang_compare_first_component (gconstpointer pa,
+ gconstpointer pb)
+{
+ const char *a = pa, *b = pb;
+ unsigned int da, db;
+ const char *p;
+
+ p = strstr (a, "-");
+ da = p ? (unsigned int) (p - a) : strlen (a);
+
+ p = strstr (b, "-");
+ db = p ? (unsigned int) (p - b) : strlen (b);
+
+ return strncmp (a, b, MAX (da, db));
+}
+
+static int
+lang_info_compare (gconstpointer key,
+ gconstpointer val)
+{
+ const LangInfo *lang_info = val;
+
+ return lang_compare_first_component (key, lang_info->lang);
+}
+
+/* The following array is supposed to contain enough text to tickle all necessary fonts for each
+ * of the languages in the following. Yes, it's pretty lame. Not all of the languages
+ * in the following have sufficient text to exercise all the accents for the language, and
+ * there are obviously many more languages to include as well.
+ */
+static const LangInfo lang_texts[] = {
+ { "ar", "Arabic \330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205" },
+ { "cs", "Czech (\304\215esky) Dobr\303\275 den" },
+ { "da", "Danish (Dansk) Hej, Goddag" },
+ { "el", "Greek (\316\225\316\273\316\273\316\267\316\275\316\271\316\272\316\254) \316\223\316\265\316\271\316\254 \317\203\316\261\317\202" },
+ { "en", "English Hello" },
+ { "eo", "Esperanto Saluton" },
+ { "es", "Spanish (Espa\303\261ol) \302\241Hola!" },
+ { "et", "Estonian Tere, Tervist" },
+ { "fi", "Finnish (Suomi) Hei, Hyv\303\244\303\244 p\303\244iv\303\244\303\244" },
+ { "fr", "French (Fran\303\247ais)" },
+ { "de", "German Gr\303\274\303\237 Gott" },
+ { "he", "Hebrew \327\251\327\234\327\225\327\235" },
+ { "it", "Italiano Ciao, Buon giorno" },
+ { "ja", "Japanese (\346\227\245\346\234\254\350\252\236) \343\201\223\343\202\223\343\201\253\343\201\241\343\201\257, \357\275\272\357\276\235\357\276\206\357\276\201\357\276\212" },
+ { "ko", "Korean (\355\225\234\352\270\200) \354\225\210\353\205\225\355\225\230\354\204\270\354\232\224, \354\225\210\353\205\225\355\225\230\354\213\255\353\213\210\352\271\214" },
+ { "mt", "Maltese \304\212aw, Sa\304\247\304\247a" },
+ { "nl", "Nederlands, Vlaams Hallo, Dag" },
+ { "no", "Norwegian (Norsk) Hei, God dag" },
+ { "pl", "Polish Dzie\305\204 dobry, Hej" },
+ { "ru", "Russian (\320\240\321\203\321\201\321\201\320\272\320\270\320\271)" },
+ { "sk", "Slovak Dobr\303\275 de\305\210" },
+ { "sv", "Swedish (Svenska) Hej p\303\245 dej, Goddag" },
+ { "tr", "Turkish (T\303\274rk\303\247e) Merhaba" },
+ { "zh", "Chinese (\344\270\255\346\226\207,\346\231\256\351\200\232\350\257\235,\346\261\211\350\257\255)" }
+};
+
+/**
+ * pango_language_get_sample_string:
+ * @language: a #PangoLanguage
+ *
+ * Get a string that is representative of the characters needed to
+ * render a particular language. This function is a bad hack for
+ * internal use by renderers and Pango.
+ *
+ * Return value: the sample string. This value is owned by Pango
+ * and must not be freed.
+ **/
+G_CONST_RETURN char *
+pango_language_get_sample_string (PangoLanguage *language)
+{
+ const char *result;
+
+ if (language)
+ {
+ const char *lang_str = pango_language_to_string (language);
+
+ LangInfo *lang_info = bsearch (lang_str, lang_texts,
+ G_N_ELEMENTS (lang_texts), sizeof (LangInfo),
+ lang_info_compare);
+
+ if (lang_info)
+ result = lang_info->str;
+ else
+ result = "French (Fran\303\247ais)"; /* Assume iso-8859-1 */
+ }
+ else
+ {
+ /* Complete junk
+ */
+
+ result = "\330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205 \304\215esky \316\225\316\273\316\273\316\267\316\275\316\271\316\272\316\254 Fran\303\247ais \346\227\245\346\234\254\350\252\236 \355\225\234\352\270\200 \320\240\321\203\321\201\321\201\320\272\320\270\320\271 \344\270\255\346\226\207,\346\231\256\351\200\232\350\257\235,\346\261\211\350\257\255 T\303\274rk\303\247e";
+ }
+
+ return result;
+}
+
+#include "pango-script-lang-table.h"
+
+static int
+script_for_lang_compare (gconstpointer key,
+ gconstpointer member)
+{
+ PangoLanguage *lang = (PangoLanguage *)key;
+ const PangoScriptForLang *script_for_lang = member;
+
+ return lang_compare_first_component (lang, script_for_lang->lang);
+}
+
+/**
+ * pango_language_includes_script:
+ * @language: a #PangoLanguage, or %NULL
+ * @script: a #PangoScript
+ *
+ * Determines if @script is one of the scripts used to
+ * write @language. The returned value is conservative;
+ * if nothing is known about the language tag @language,
+ * %TRUE will be returned, since, as far as Pango knows,
+ * @script might be used to write @language.
+ *
+ * This routine is used in Pango's itemization process when
+ * determining if a supplied language tag is relevant to
+ * a particular section of text. It probably is not useful for
+ * applications in most circumstances.
+ *
+ * Return value: %TRUE if @script is one of the scripts used
+ * to write @language or if nothing is known about @language
+ * (including the case that @language is %NULL),
+ * %FALSE otherwise.
+ *
+ * Since: 1.4
+ **/
+gboolean
+pango_language_includes_script (PangoLanguage *language,
+ PangoScript script)
+{
+ PangoScriptForLang *script_for_lang;
+ unsigned int j;
+ const char *lang_str;
+
+#define REAL_SCRIPT(script) \
+ ((script) > PANGO_SCRIPT_INHERITED)
+
+ if (language == NULL || !REAL_SCRIPT (script))
+ return TRUE;
+
+ lang_str = pango_language_to_string (language);
+
+ /* This bsearch could be optimized to occur only once if
+ * we store the pointer to the PangoScriptForLang in the
+ * same block as the string value for the PangoLanguage.
+ */
+ script_for_lang = bsearch (lang_str,
+ pango_script_for_lang,
+ G_N_ELEMENTS (pango_script_for_lang),
+ sizeof (PangoScriptForLang),
+ script_for_lang_compare);
+ if (!script_for_lang)
+ return TRUE;
+ else
+ {
+ gboolean found = FALSE;
+
+ /* find the best matching language */
+
+ /* go to the final one matching in the first component */
+ while (script_for_lang + 1 < pango_script_for_lang + G_N_ELEMENTS (pango_script_for_lang) &&
+ script_for_lang_compare (lang_str, script_for_lang + 1) == 0)
+ script_for_lang++;
+
+ /* go back, find which one matches completely */
+ while (script_for_lang >= pango_script_for_lang &&
+ script_for_lang_compare (lang_str, script_for_lang) == 0)
+ {
+ if (pango_language_matches (language, script_for_lang->lang))
+ {
+ found = TRUE;
+ break;
+ }
+
+ script_for_lang--;
+ }
+
+ if (!found)
+ return TRUE;
+ }
+
+ for (j = 0; j < G_N_ELEMENTS (script_for_lang->scripts); j++)
+ if (script_for_lang->scripts[j] == script)
+ return TRUE;
+
+ return FALSE;
+}
+
+static PangoLanguage **
+parse_default_languages (void)
+{
+ char *p;
+ gboolean done = FALSE;
+ GArray *langs;
+
+ p = getenv ("PANGO_LANGUAGE");
+
+ if (p == NULL)
+ p = getenv ("LANGUAGE");
+
+ if (p == NULL)
+ return NULL;
+
+ p = g_strdup (p);
+
+ langs = g_array_new (TRUE, FALSE, sizeof (PangoLanguage *));
+
+ while (!done)
+ {
+ char *end = strpbrk (p, LANGUAGE_SEPARATORS);
+ if (!end)
+ {
+ end = p + strlen (p);
+ done = TRUE;
+ }
+ else
+ *end = '\0';
+
+ /* skip empty languages, and skip the language 'C' */
+ if (p != end && !(p + 1 == end && *p == 'C'))
+ {
+ PangoLanguage *l = pango_language_from_string (p);
+
+ g_array_append_val (langs, l);
+ }
+
+ if (!done)
+ p = end + 1;
+ }
+
+ return (PangoLanguage **) g_array_free (langs, FALSE);
+}
+
+static PangoLanguage *
+_pango_script_get_default_language (PangoScript script)
+{
+ static gboolean initialized = FALSE;
+ static PangoLanguage * const * languages = NULL;
+ static GHashTable *hash = NULL;
+ PangoLanguage *result, * const * p;
+
+ if (G_UNLIKELY (!initialized))
+ {
+ languages = parse_default_languages ();
+
+ if (languages)
+ hash = g_hash_table_new (NULL, NULL);
+
+ initialized = TRUE;
+ }
+
+ if (!languages)
+ return NULL;
+
+ if (g_hash_table_lookup_extended (hash, GINT_TO_POINTER (script), NULL, (gpointer *) (gpointer) &result))
+ return result;
+
+ for (p = languages; *p; p++)
+ if (pango_language_includes_script (*p, script))
+ break;
+ result = *p;
+
+ g_hash_table_insert (hash, GINT_TO_POINTER (script), result);
+
+ return result;
+}
+
+/**
+ * pango_script_get_sample_language:
+ * @script: a #PangoScript
+ *
+ * Given a script, finds a language tag that is reasonably
+ * representative of that script. This will usually be the
+ * most widely spoken or used language written in that script:
+ * for instance, the sample language for %PANGO_SCRIPT_CYRILLIC
+ * is <literal>ru</literal> (Russian), the sample language
+ * for %PANGO_SCRIPT_ARABIC is <literal>ar</literal>.
+ *
+ * For some
+ * scripts, no sample language will be returned because there
+ * is no language that is sufficiently representative. The best
+ * example of this is %PANGO_SCRIPT_HAN, where various different
+ * variants of written Chinese, Japanese, and Korean all use
+ * significantly different sets of Han characters and forms
+ * of shared characters. No sample language can be provided
+ * for many historical scripts as well.
+ *
+ * As of 1.18, this function checks the environment variables
+ * PANGO_LANGUAGE and LANGUAGE (checked in that order) first.
+ * If one of them is set, it is parsed as a list of language tags
+ * separated by colons or other separators. This function
+ * will return the first language in the parsed list that Pango
+ * believes may use @script for writing. This last predicate
+ * is tested using pango_language_includes_script(). This can
+ * be used to control Pango's font selection for non-primary
+ * languages. For example, a PANGO_LANGUAGE enviroment variable
+ * set to "en:fa" makes Pango choose fonts suitable for Persian (fa)
+ * instead of Arabic (ar) when a segment of Arabic text is found
+ * in an otherwise non-Arabic text. The same trick can be used to
+ * choose a default language for %PANGO_SCRIPT_HAN when setting
+ * context language is not feasible.
+ *
+ * Return value: a #PangoLanguage that is representative
+ * of the script, or %NULL if no such language exists.
+ *
+ * Since: 1.4
+ **/
+PangoLanguage *
+pango_script_get_sample_language (PangoScript script)
+{
+ /* Note that in the following, we want
+ * pango_language_includes_script() for the sample language
+ * to include the script, so alternate orthographies
+ * (Shavian for English, Osmanya for Somali, etc), typically
+ * have no sample language
+ */
+ static const char sample_languages[][4] = {
+ "", /* PANGO_SCRIPT_COMMON */
+ "", /* PANGO_SCRIPT_INHERITED */
+ "ar", /* PANGO_SCRIPT_ARABIC */
+ "hy", /* PANGO_SCRIPT_ARMENIAN */
+ "bn", /* PANGO_SCRIPT_BENGALI */
+ /* Used primarily in Taiwan, but not part of the standard
+ * zh-tw orthography */
+ "", /* PANGO_SCRIPT_BOPOMOFO */
+ "chr", /* PANGO_SCRIPT_CHEROKEE */
+ "cop", /* PANGO_SCRIPT_COPTIC */
+ "ru", /* PANGO_SCRIPT_CYRILLIC */
+ /* Deseret was used to write English */
+ "", /* PANGO_SCRIPT_DESERET */
+ "hi", /* PANGO_SCRIPT_DEVANAGARI */
+ "am", /* PANGO_SCRIPT_ETHIOPIC */
+ "ka", /* PANGO_SCRIPT_GEORGIAN */
+ "", /* PANGO_SCRIPT_GOTHIC */
+ "el", /* PANGO_SCRIPT_GREEK */
+ "gu", /* PANGO_SCRIPT_GUJARATI */
+ "pa", /* PANGO_SCRIPT_GURMUKHI */
+ "", /* PANGO_SCRIPT_HAN */
+ "ko", /* PANGO_SCRIPT_HANGUL */
+ "he", /* PANGO_SCRIPT_HEBREW */
+ "ja", /* PANGO_SCRIPT_HIRAGANA */
+ "kn", /* PANGO_SCRIPT_KANNADA */
+ "ja", /* PANGO_SCRIPT_KATAKANA */
+ "km", /* PANGO_SCRIPT_KHMER */
+ "lo", /* PANGO_SCRIPT_LAO */
+ "en", /* PANGO_SCRIPT_LATIN */
+ "ml", /* PANGO_SCRIPT_MALAYALAM */
+ "mn", /* PANGO_SCRIPT_MONGOLIAN */
+ "my", /* PANGO_SCRIPT_MYANMAR */
+ /* Ogham was used to write old Irish */
+ "", /* PANGO_SCRIPT_OGHAM */
+ "", /* PANGO_SCRIPT_OLD_ITALIC */
+ "or", /* PANGO_SCRIPT_ORIYA */
+ "", /* PANGO_SCRIPT_RUNIC */
+ "si", /* PANGO_SCRIPT_SINHALA */
+ "syr", /* PANGO_SCRIPT_SYRIAC */
+ "ta", /* PANGO_SCRIPT_TAMIL */
+ "te", /* PANGO_SCRIPT_TELUGU */
+ "dv", /* PANGO_SCRIPT_THAANA */
+ "th", /* PANGO_SCRIPT_THAI */
+ "bo", /* PANGO_SCRIPT_TIBETAN */
+ "iu", /* PANGO_SCRIPT_CANADIAN_ABORIGINAL */
+ "", /* PANGO_SCRIPT_YI */
+ "tl", /* PANGO_SCRIPT_TAGALOG */
+ /* There are no ISO-636 language codes for the following
+ * Phillipino languages/scripts */
+ "", /* PANGO_SCRIPT_HANUNOO */
+ "", /* PANGO_SCRIPT_BUHID */
+ "", /* PANGO_SCRIPT_TAGBANWA */
+
+ "", /* PANGO_SCRIPT_BRAILLE */
+ "", /* PANGO_SCRIPT_CYPRIOT */
+ "", /* PANGO_SCRIPT_LIMBU */
+ /* Used for Somali (so) in the past */
+ "", /* PANGO_SCRIPT_OSMANYA */
+ /* The Shavian alphabet was designed for English */
+ "", /* PANGO_SCRIPT_SHAVIAN */
+ "", /* PANGO_SCRIPT_LINEAR_B */
+ "", /* PANGO_SCRIPT_TAI_LE */
+ "uga", /* PANGO_SCRIPT_UGARITIC */
+
+ "", /* PANGO_SCRIPT_NEW_TAI_LUE */
+ "bug", /* PANGO_SCRIPT_BUGINESE */
+ /* The original script for Old Church Slavonic (chu), later
+ * written with Cyrillic */
+ "", /* PANGO_SCRIPT_GLAGOLITIC */
+ /* Used for for Berber (ber), but Arabic script is more common */
+ "", /* PANGO_SCRIPT_TIFINAGH */
+ /* Syloti Nagri is used for Sylheti, no ISO 639 code */
+ "", /* PANGO_SCRIPT_SYLOTI_NAGRI */
+ "peo", /* PANGO_SCRIPT_OLD_PERSIAN */
+ "", /* PANGO_SCRIPT_KHAROSHTHI */
+
+ "", /* PANGO_SCRIPT_UNKNOWN */
+ "", /* PANGO_SCRIPT_BALINESE */
+ "", /* PANGO_SCRIPT_CUNEIFORM */
+ "", /* PANGO_SCRIPT_PHOENICIAN */
+ "", /* PANGO_SCRIPT_PHAGS_PA */
+ "nqo" /* PANGO_SCRIPT_NKO */
+ };
+ const char *sample_language;
+ PangoLanguage *result;
+
+ g_return_val_if_fail (script >= 0, NULL);
+ g_return_val_if_fail ((guint)script < G_N_ELEMENTS (sample_languages), NULL);
+
+ result = _pango_script_get_default_language (script);
+ if (result)
+ return result;
+
+ sample_language = sample_languages[script];
+
+ if (!sample_language[0])
+ return NULL;
+ else
+ return pango_language_from_string (sample_language);
+}
diff --git a/trunk/pango/pango-language.h b/trunk/pango/pango-language.h
new file mode 100644
index 00000000..9c1a9d8d
--- /dev/null
+++ b/trunk/pango/pango-language.h
@@ -0,0 +1,48 @@
+/* Pango
+ * pango-language.h: Language handling routines
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_LANGUAGE_H__
+#define __PANGO_LANGUAGE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* Dummy typedef - internally it's a 'const char *' */
+typedef struct _PangoLanguage PangoLanguage;
+
+#define PANGO_TYPE_LANGUAGE (pango_language_get_type ())
+
+GType pango_language_get_type (void) G_GNUC_CONST;
+PangoLanguage *pango_language_from_string (const char *language);
+
+#define pango_language_to_string(language) ((const char *)language)
+
+G_CONST_RETURN char *pango_language_get_sample_string (PangoLanguage *language) G_GNUC_CONST;
+PangoLanguage *pango_language_get_default (void) G_GNUC_CONST;
+
+gboolean pango_language_matches (PangoLanguage *language,
+ const char *range_list) G_GNUC_PURE;
+
+G_END_DECLS
+
+#endif /* __PANGO_LANGUAGE_H__ */
diff --git a/trunk/pango/pango-layout-private.h b/trunk/pango/pango-layout-private.h
new file mode 100644
index 00000000..a71865fc
--- /dev/null
+++ b/trunk/pango/pango-layout-private.h
@@ -0,0 +1,82 @@
+/* Pango
+ * pango-layout-private.h: Internal structures of PangoLayout
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_LAYOUT_PRIVATE_H__
+#define __PANGO_LAYOUT_PRIVATE_H__
+
+#include <pango/pango-layout.h>
+
+G_BEGIN_DECLS
+
+struct _PangoLayout
+{
+ GObject parent_instance;
+
+ /* If you add fields to PangoLayout, be sure to update both
+ * the _copy function
+ */
+
+ PangoContext *context;
+ PangoAttrList *attrs;
+ PangoFontDescription *font_desc;
+
+ gchar *text;
+ int length; /* length of text in bytes */
+ int width; /* wrap width, in device units */
+ int indent; /* amount by which first line should be shorter */
+ int spacing; /* spacing between lines */
+
+ int unknown_glyphs_count; /* number of unknown glyphs */
+
+ guint justify : 1;
+ guint alignment : 2;
+
+ guint single_paragraph : 1;
+ guint auto_dir : 1;
+
+ guint wrap : 2; /* PangoWrapMode */
+ guint is_wrapped : 1; /* Whether the layout has any wrapped lines */
+ guint ellipsize : 2; /* PangoEllipsizeMode */
+ guint is_ellipsized : 1; /* Whether the layout has any ellipsized lines */
+
+ /* some caching */
+ guint logical_rect_cached : 1;
+ guint ink_rect_cached : 1;
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+
+
+ gint n_chars; /* Total number of characters in layout */
+ PangoLogAttr *log_attrs; /* Logical attributes for layout's text */
+
+ int tab_width; /* Cached width of a tab. -1 == not yet calculated */
+
+ PangoTabArray *tabs;
+
+ GSList *lines;
+};
+
+gboolean _pango_layout_line_ellipsize (PangoLayoutLine *line,
+ PangoAttrList *attrs);
+
+G_END_DECLS
+
+#endif /* __PANGO_LAYOUT_PRIVATE_H__ */
diff --git a/trunk/pango/pango-layout.c b/trunk/pango/pango-layout.c
new file mode 100644
index 00000000..8066c646
--- /dev/null
+++ b/trunk/pango/pango-layout.c
@@ -0,0 +1,6074 @@
+/* Pango
+ * pango-layout.c: High-level layout driver
+ *
+ * Copyright (C) 2000, 2001, 2006 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "pango-glyph.h" /* For pango_shape() */
+#include "pango-break.h"
+#include "pango-item.h"
+#include "pango-engine.h"
+#include "pango-impl-utils.h"
+#include "pango-glyph-item-private.h"
+#include <string.h>
+
+#include "pango-layout-private.h"
+
+
+typedef struct _Extents Extents;
+typedef struct _ItemProperties ItemProperties;
+typedef struct _ParaBreakState ParaBreakState;
+
+struct _Extents
+{
+ /* Vertical position of the line's baseline in layout coords */
+ int baseline;
+
+ /* Line extents in layout coords */
+ PangoRectangle ink_rect;
+ PangoRectangle logical_rect;
+};
+
+struct _ItemProperties
+{
+ PangoUnderline uline;
+ gboolean strikethrough;
+ gint rise;
+ gint letter_spacing;
+ gboolean shape_set;
+ PangoRectangle *shape_ink_rect;
+ PangoRectangle *shape_logical_rect;
+};
+
+struct _PangoLayoutIter
+{
+ PangoLayout *layout;
+ GSList *line_list_link;
+ PangoLayoutLine *line;
+
+ /* If run is NULL, it means we're on a "virtual run"
+ * at the end of the line with 0 width
+ */
+ GSList *run_list_link;
+ PangoLayoutRun *run; /* FIXME nuke this, just keep the link */
+ int index;
+
+ /* list of Extents for each line in layout coordinates */
+ GSList *line_extents;
+ GSList *line_extents_link;
+
+ /* X position of the current run */
+ int run_x;
+
+ /* Width of the current run */
+ int run_width;
+
+ /* this run is left-to-right */
+ gboolean ltr;
+
+ /* X position of the left side of the current cluster */
+ int cluster_x;
+
+ /* The width of the current cluster */
+ int cluster_width;
+
+ /* glyph offset to the current cluster start */
+ int cluster_start;
+
+ /* first glyph in the next cluster */
+ int next_cluster_glyph;
+
+ /* number of Unicode chars in current cluster */
+ int cluster_num_chars;
+
+ /* visual position of current character within the cluster */
+ int character_position;
+
+ /* the real width of layout */
+ int layout_width;
+};
+
+typedef struct _PangoLayoutLinePrivate PangoLayoutLinePrivate;
+
+struct _PangoLayoutLinePrivate
+{
+ PangoLayoutLine line;
+ guint ref_count;
+
+ /* Extents cache status:
+ *
+ * LEAKED means that the user has access to this line structure or a
+ * run included in this line, and so can change the glyphs/glyph-widths.
+ * If this is true, extents caching will be disabled.
+ */
+ enum {
+ NOT_CACHED,
+ CACHED,
+ LEAKED
+ } cache_status;
+ PangoRectangle ink_rect;
+ PangoRectangle logical_rect;
+};
+
+struct _PangoLayoutClass
+{
+ GObjectClass parent_class;
+
+
+};
+
+#define LINE_IS_VALID(line) ((line)->layout != NULL)
+
+#ifdef G_DISABLE_CHECKS
+#define ITER_IS_INVALID(iter) FALSE
+#else
+#define ITER_IS_INVALID(iter) G_UNLIKELY (check_invalid ((iter), G_STRLOC))
+static gboolean
+check_invalid (PangoLayoutIter *iter,
+ const char *loc)
+{
+ if (iter->line->layout == NULL)
+ {
+ g_warning ("%s: PangoLayout changed since PangoLayoutIter was created, iterator invalid", loc);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+#endif
+
+static void pango_layout_clear_lines (PangoLayout *layout);
+static void pango_layout_check_lines (PangoLayout *layout);
+
+static PangoAttrList *pango_layout_get_effective_attributes (PangoLayout *layout);
+
+static PangoLayoutLine * pango_layout_line_new (PangoLayout *layout);
+static void pango_layout_line_postprocess (PangoLayoutLine *line,
+ ParaBreakState *state,
+ gboolean wrapped);
+
+static int *pango_layout_line_get_log2vis_map (PangoLayoutLine *line,
+ gboolean strong);
+static int *pango_layout_line_get_vis2log_map (PangoLayoutLine *line,
+ gboolean strong);
+static void pango_layout_line_leaked (PangoLayoutLine *line);
+
+/* doesn't leak line */
+static PangoLayoutLine* _pango_layout_iter_get_line (PangoLayoutIter *iter);
+
+static void pango_layout_get_item_properties (PangoItem *item,
+ ItemProperties *properties);
+
+static void pango_layout_finalize (GObject *object);
+
+G_DEFINE_TYPE (PangoLayout, pango_layout, G_TYPE_OBJECT)
+
+static void
+pango_layout_init (PangoLayout *layout)
+{
+ layout->attrs = NULL;
+ layout->font_desc = NULL;
+ layout->text = NULL;
+ layout->length = 0;
+ layout->width = -1;
+ layout->indent = 0;
+
+ layout->alignment = PANGO_ALIGN_LEFT;
+ layout->justify = FALSE;
+ layout->auto_dir = TRUE;
+
+ layout->log_attrs = NULL;
+ layout->lines = NULL;
+
+ layout->tab_width = -1;
+ layout->unknown_glyphs_count = -1;
+
+ layout->wrap = PANGO_WRAP_WORD;
+ layout->is_wrapped = FALSE;
+ layout->ellipsize = PANGO_ELLIPSIZE_NONE;
+ layout->is_ellipsized = FALSE;
+}
+
+static void
+pango_layout_class_init (PangoLayoutClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = pango_layout_finalize;
+}
+
+static void
+pango_layout_finalize (GObject *object)
+{
+ PangoLayout *layout;
+
+ layout = PANGO_LAYOUT (object);
+
+ pango_layout_clear_lines (layout);
+
+ if (layout->context)
+ g_object_unref (layout->context);
+
+ if (layout->attrs)
+ pango_attr_list_unref (layout->attrs);
+
+ g_free (layout->text);
+
+ if (layout->font_desc)
+ pango_font_description_free (layout->font_desc);
+
+ if (layout->tabs)
+ pango_tab_array_free (layout->tabs);
+
+ G_OBJECT_CLASS (pango_layout_parent_class)->finalize (object);
+}
+
+
+/**
+ * pango_layout_new:
+ * @context: a #PangoContext
+ *
+ * Create a new #PangoLayout object with attributes initialized to
+ * default values for a particular #PangoContext.
+ *
+ * Return value: the newly allocated #PangoLayout, with a reference
+ * count of one, which should be freed with
+ * g_object_unref().
+ **/
+PangoLayout *
+pango_layout_new (PangoContext *context)
+{
+ PangoLayout *layout;
+
+ g_return_val_if_fail (context != NULL, NULL);
+
+ layout = g_object_new (PANGO_TYPE_LAYOUT, NULL);
+
+ layout->context = context;
+ g_object_ref (context);
+
+ return layout;
+}
+
+/**
+ * pango_layout_copy:
+ * @src: a #PangoLayout
+ *
+ * Does a deep copy-by-value of the @src layout. The attribute list,
+ * tab array, and text from the original layout are all copied by
+ * value.
+ *
+ * Return value: the newly allocated #PangoLayout, with a reference
+ * count of one, which should be freed with
+ * g_object_unref().
+ **/
+PangoLayout*
+pango_layout_copy (PangoLayout *src)
+{
+ PangoLayout *layout;
+
+ g_return_val_if_fail (PANGO_IS_LAYOUT (src), NULL);
+
+ layout = pango_layout_new (src->context);
+
+ if (src->attrs)
+ layout->attrs = pango_attr_list_copy (src->attrs);
+
+ if (src->font_desc)
+ layout->font_desc = pango_font_description_copy (src->font_desc);
+
+ layout->text = g_strdup (src->text);
+ layout->length = src->length;
+ layout->width = src->width;
+ layout->indent = src->indent;
+ layout->spacing = src->spacing;
+ layout->justify = src->justify;
+ layout->auto_dir = src->auto_dir;
+ layout->alignment = src->alignment;
+ layout->n_chars = src->n_chars;
+ layout->tab_width = src->tab_width;
+
+ if (src->tabs)
+ layout->tabs = pango_tab_array_copy (src->tabs);
+ layout->wrap = src->wrap;
+ layout->ellipsize = src->ellipsize;
+
+ layout->unknown_glyphs_count = -1;
+
+ /* unknown_glyphs_count, is_wrapped, is_ellipsized, log_attrs, lines
+ * fields are updated by check_lines */
+
+ return layout;
+}
+
+/**
+ * pango_layout_get_context:
+ * @layout: a #PangoLayout
+ *
+ * Retrieves the #PangoContext used for this layout.
+ *
+ * Return value: the #PangoContext for the layout. This does not
+ * have an additional refcount added, so if you want to keep
+ * a copy of this around, you must reference it yourself.
+ **/
+PangoContext *
+pango_layout_get_context (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, NULL);
+
+ return layout->context;
+}
+
+/**
+ * pango_layout_set_width:
+ * @layout: a #PangoLayout.
+ * @width: the desired width in Pango units, or -1 to indicate that no
+ * wrapping should be performed.
+ *
+ * Sets the width to which the lines of the #PangoLayout should wrap.
+ **/
+void
+pango_layout_set_width (PangoLayout *layout,
+ int width)
+{
+ g_return_if_fail (layout != NULL);
+
+ if (width != layout->width)
+ {
+ layout->width = width;
+ pango_layout_clear_lines (layout);
+ }
+}
+
+/**
+ * pango_layout_get_width:
+ * @layout: a #PangoLayout
+ *
+ * Gets the width to which the lines of the #PangoLayout should wrap.
+ *
+ * Return value: the width, or -1 if no width set.
+ **/
+int
+pango_layout_get_width (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, 0);
+ return layout->width;
+}
+
+/**
+ * pango_layout_set_wrap:
+ * @layout: a #PangoLayout
+ * @wrap: the wrap mode
+ *
+ * Sets the wrap mode; the wrap mode only has effect if a width
+ * is set on the layout with pango_layout_set_width(). To turn off wrapping,
+ * set the width to -1.
+ **/
+void
+pango_layout_set_wrap (PangoLayout *layout,
+ PangoWrapMode wrap)
+{
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ if (layout->wrap != wrap)
+ {
+ layout->wrap = wrap;
+
+ if (layout->is_wrapped)
+ pango_layout_clear_lines (layout);
+ }
+}
+
+/**
+ * pango_layout_get_wrap:
+ * @layout: a #PangoLayout
+ *
+ * Gets the wrap mode for the layout.
+ *
+ * Use pango_layout_is_wrapped() to query whether any paragraphs
+ * were actually wrapped.
+ *
+ * Return value: active wrap mode.
+ **/
+PangoWrapMode
+pango_layout_get_wrap (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
+
+ return layout->wrap;
+}
+
+/**
+ * pango_layout_is_wrapped:
+ * @layout: a #PangoLayout
+ *
+ * Queries whether the layout had to wrap any paragraphs.
+ *
+ * This returns %TRUE if a positive width is set on @layout,
+ * ellipsization mode of @layout is set to %PANGO_ELLIPSIZE_NONE,
+ * and there are paragraphs exceeding the layout width that have
+ * to be wrapped.
+ *
+ * Return value: %TRUE if any paragraphs had to be wrapped, %FALSE
+ * otherwise.
+ *
+ * Since: 1.16
+ */
+gboolean
+pango_layout_is_wrapped (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, FALSE);
+
+ pango_layout_check_lines (layout);
+
+ return layout->is_wrapped;
+}
+
+/**
+ * pango_layout_set_indent
+ * @layout: a #PangoLayout.
+ * @indent: the amount by which to indent.
+ *
+ * Sets the width in Pango units to indent each paragraph. A negative value
+ * of @indent will produce a hanging indentation. That is, the first line will
+ * have the full width, and subsequent lines will be indented by the
+ * absolute value of @indent.
+ **/
+void
+pango_layout_set_indent (PangoLayout *layout,
+ int indent)
+{
+ g_return_if_fail (layout != NULL);
+
+ if (indent != layout->indent)
+ {
+ layout->indent = indent;
+ pango_layout_clear_lines (layout);
+ }
+}
+
+/**
+ * pango_layout_get_indent:
+ * @layout: a #PangoLayout
+ *
+ * Gets the paragraph indent width in Pango units. A negative value
+ * indicates a hanging indentation.
+ *
+ * Return value: the indent.
+ **/
+int
+pango_layout_get_indent (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, 0);
+ return layout->indent;
+}
+
+/**
+ * pango_layout_set_spacing:
+ * @layout: a #PangoLayout.
+ * @spacing: the amount of spacing
+ *
+ * Sets the amount of spacing in #PangoGlyphUnit between the lines of the
+ * layout.
+ *
+ **/
+void
+pango_layout_set_spacing (PangoLayout *layout,
+ int spacing)
+{
+ g_return_if_fail (layout != NULL);
+
+ if (spacing != layout->spacing)
+ {
+ layout->spacing = spacing;
+ pango_layout_clear_lines (layout);
+ }
+}
+
+/**
+ * pango_layout_get_spacing:
+ * @layout: a #PangoLayout
+ *
+ * Gets the amount of spacing in #PangoGlyphUnit between the lines of the
+ * layout.
+ *
+ * Return value: the spacing.
+ **/
+int
+pango_layout_get_spacing (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, 0);
+ return layout->spacing;
+}
+
+/**
+ * pango_layout_set_attributes:
+ * @layout: a #PangoLayout
+ * @attrs: a #PangoAttrList
+ *
+ * Sets the text attributes for a layout object.
+ * References @attrs, so the caller can unref its reference.
+ **/
+void
+pango_layout_set_attributes (PangoLayout *layout,
+ PangoAttrList *attrs)
+{
+ PangoAttrList *old_attrs;
+ g_return_if_fail (layout != NULL);
+
+ old_attrs = layout->attrs;
+
+ layout->attrs = attrs;
+ if (layout->attrs)
+ pango_attr_list_ref (layout->attrs);
+ pango_layout_clear_lines (layout);
+
+ if (old_attrs)
+ pango_attr_list_unref (old_attrs);
+ layout->tab_width = -1;
+}
+
+/**
+ * pango_layout_get_attributes:
+ * @layout: a #PangoLayout
+ *
+ * Gets the attribute list for the layout, if any.
+ *
+ * Return value: a #PangoAttrList.
+ **/
+PangoAttrList*
+pango_layout_get_attributes (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
+
+ return layout->attrs;
+}
+
+/**
+ * pango_layout_set_font_description:
+ * @layout: a #PangoLayout
+ * @desc: the new #PangoFontDescription, or %NULL to unset the
+ * current font description
+ *
+ * Sets the default font description for the layout. If no font
+ * description is set on the layout, the font description from
+ * the layout's context is used.
+ **/
+void
+pango_layout_set_font_description (PangoLayout *layout,
+ const PangoFontDescription *desc)
+{
+ g_return_if_fail (layout != NULL);
+
+ if (desc != layout->font_desc)
+ {
+ if (layout->font_desc)
+ pango_font_description_free (layout->font_desc);
+
+ if (desc)
+ layout->font_desc = pango_font_description_copy (desc);
+ else
+ layout->font_desc = NULL;
+
+ pango_layout_clear_lines (layout);
+ layout->tab_width = -1;
+ }
+}
+
+/**
+ * pango_layout_get_font_description:
+ * @layout: a #PangoLayout
+ *
+ * Gets the font description for the layout, if any.
+ *
+ * Return value: a pointer to the layout's font description,
+ * or %NULL if the font description from the layout's
+ * context is inherited. This value is owned by the layout
+ * and must not be modified or freed.
+ *
+ * Since: 1.8
+ **/
+G_CONST_RETURN PangoFontDescription *
+pango_layout_get_font_description (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
+
+ return layout->font_desc;
+}
+
+/**
+ * pango_layout_set_justify:
+ * @layout: a #PangoLayout
+ * @justify: whether the lines in the layout should be justified.
+ *
+ * Sets whether each complete line should be stretched to
+ * fill the entire width of the layout. This stretching is typically
+ * done by adding whitespace, but for some scripts (such as Arabic),
+ * the justification may be done in more complex ways, like extending
+ * the characters.
+ *
+ * Note that this setting is not implemented and so is ignored in Pango
+ * older than 1.18.
+ **/
+void
+pango_layout_set_justify (PangoLayout *layout,
+ gboolean justify)
+{
+ g_return_if_fail (layout != NULL);
+
+ layout->justify = justify;
+}
+
+/**
+ * pango_layout_get_justify:
+ * @layout: a #PangoLayout
+ *
+ * Gets whether each complete line should be stretched to fill the entire
+ * width of the layout.
+ *
+ * Return value: the justify.
+ **/
+gboolean
+pango_layout_get_justify (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, FALSE);
+ return layout->justify;
+}
+
+/**
+ * pango_layout_set_auto_dir:
+ * @layout: a #PangoLayout
+ * @auto_dir: if %TRUE, compute the bidirectional base direction
+ * from the layout's contents.
+ *
+ * Sets whether to calculate the bidirectional base direction
+ * for the layout according to the contents of the layout;
+ * when this flag is on (the default), then paragraphs in
+ @layout that begin with strong right-to-left characters
+ * (Arabic and Hebrew principally), will have right-to-left
+ * layout, paragraphs with letters from other scripts will
+ * have left-to-right layout. Paragraphs with only neutral
+ * characters get their direction from the surrounding paragraphs.
+ *
+ * When %FALSE, the choice between left-to-right and
+ * right-to-left layout is done according to the base direction
+ * of the layout's #PangoContext. (See pango_context_set_base_dir()).
+ *
+ * When the auto-computed direction of a paragraph differs from the
+ * base direction of the context, the interpretation of
+ * %PANGO_ALIGN_LEFT and %PANGO_ALIGN_RIGHT are swapped.
+ *
+ * Since: 1.4
+ **/
+void
+pango_layout_set_auto_dir (PangoLayout *layout,
+ gboolean auto_dir)
+{
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ auto_dir = auto_dir != FALSE;
+
+ if (auto_dir != layout->auto_dir)
+ {
+ layout->auto_dir = auto_dir;
+ pango_layout_clear_lines (layout);
+ }
+}
+
+/**
+ * pango_layout_get_auto_dir:
+ * @layout: a #PangoLayout
+ *
+ * Gets whether to calculate the bidirectional base direction
+ * for the layout according to the contents of the layout.
+ * See pango_layout_set_auto_dir().
+ *
+ * Return value: %TRUE if the bidirectional base direction
+ * is computed from the layout's contents, %FALSE otherwise.
+ *
+ * Since: 1.4
+ **/
+gboolean
+pango_layout_get_auto_dir (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
+
+ return layout->auto_dir;
+}
+
+/**
+ * pango_layout_set_alignment:
+ * @layout: a #PangoLayout
+ * @alignment: the alignment
+ *
+ * Sets the alignment for the layout: how partial lines are
+ * positioned within the horizontal space available.
+ **/
+void
+pango_layout_set_alignment (PangoLayout *layout,
+ PangoAlignment alignment)
+{
+ g_return_if_fail (layout != NULL);
+
+ layout->alignment = alignment;
+}
+
+/**
+ * pango_layout_get_alignment:
+ * @layout: a #PangoLayout
+ *
+ * Gets the alignment for the layout: how partial lines are
+ * positioned within the horizontal space available.
+ *
+ * Return value: the alignment.
+ **/
+PangoAlignment
+pango_layout_get_alignment (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, PANGO_ALIGN_LEFT);
+ return layout->alignment;
+}
+
+
+/**
+ * pango_layout_set_tabs:
+ * @layout: a #PangoLayout
+ * @tabs: a #PangoTabArray
+ *
+ * Sets the tabs to use for @layout, overriding the default tabs
+ * (by default, tabs are every 8 spaces). If @tabs is %NULL, the default
+ * tabs are reinstated. @tabs is copied into the layout; you must
+ * free your copy of @tabs yourself.
+ **/
+void
+pango_layout_set_tabs (PangoLayout *layout,
+ PangoTabArray *tabs)
+{
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ if (layout->tabs)
+ pango_tab_array_free (layout->tabs);
+
+ layout->tabs = tabs ? pango_tab_array_copy (tabs) : NULL;
+}
+
+/**
+ * pango_layout_get_tabs:
+ * @layout: a #PangoLayout
+ *
+ * Gets the current #PangoTabArray used by this layout. If no
+ * #PangoTabArray has been set, then the default tabs are in use
+ * and %NULL is returned. Default tabs are every 8 spaces.
+ * The return value should be freed with pango_tab_array_free().
+ *
+ * Return value: a copy of the tabs for this layout, or %NULL.
+ **/
+PangoTabArray*
+pango_layout_get_tabs (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
+
+ if (layout->tabs)
+ return pango_tab_array_copy (layout->tabs);
+ else
+ return NULL;
+}
+
+/**
+ * pango_layout_set_single_paragraph_mode:
+ * @layout: a #PangoLayout
+ * @setting: new setting
+ *
+ * If @setting is %TRUE, do not treat newlines and similar characters
+ * as paragraph separators; instead, keep all text in a single paragraph,
+ * and display a glyph for paragraph separator characters. Used when
+ * you want to allow editing of newlines on a single text line.
+ *
+ **/
+void
+pango_layout_set_single_paragraph_mode (PangoLayout *layout,
+ gboolean setting)
+{
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ setting = setting != FALSE;
+
+ if (layout->single_paragraph != setting)
+ {
+ layout->single_paragraph = setting;
+
+ pango_layout_clear_lines (layout);
+ }
+}
+
+/**
+ * pango_layout_get_single_paragraph_mode:
+ * @layout: a #PangoLayout
+ *
+ * Obtains the value set by pango_layout_set_single_paragraph_mode().
+ *
+ * Return value: %TRUE if the layout does not break paragraphs at
+ * paragraph separator characters, %FALSE otherwise.
+ **/
+gboolean
+pango_layout_get_single_paragraph_mode (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
+
+ return layout->single_paragraph;
+}
+
+/**
+ * pango_layout_set_ellipsize:
+ * @layout: a #PangoLayout
+ * @ellipsize: the new ellipsization mode for @layout
+ *
+ * Sets the type of ellipsization being performed for @layout.
+ * Depending on the ellipsization mode @ellipsize text is
+ * removed from the start, middle, or end of lines so they
+ * fit within the width of layout set with pango_layout_set_width ().
+ *
+ * If the layout contains characters such as newlines that
+ * force it to be layed out in multiple lines, then each line
+ * is ellipsized separately.
+ *
+ * Since: 1.6
+ **/
+void
+pango_layout_set_ellipsize (PangoLayout *layout,
+ PangoEllipsizeMode ellipsize)
+{
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ if (ellipsize != layout->ellipsize)
+ {
+ layout->ellipsize = ellipsize;
+
+ if (layout->is_ellipsized || layout->is_wrapped)
+ pango_layout_clear_lines (layout);
+ }
+}
+
+/**
+ * pango_layout_get_ellipsize:
+ * @layout: a #PangoLayout
+ *
+ * Gets the type of ellipsization being performed for @layout.
+ * See pango_layout_set_ellipsize()
+ *
+ * Return value: the current ellipsization mode for @layout.
+ *
+ * Use pango_layout_is_ellipsized() to query whether any paragraphs
+ * were actually ellipsized.
+ *
+ * Since: 1.6
+ **/
+PangoEllipsizeMode
+pango_layout_get_ellipsize (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), PANGO_ELLIPSIZE_NONE);
+
+ return layout->ellipsize;
+}
+
+/**
+ * pango_layout_is_ellipsized:
+ * @layout: a #PangoLayout
+ *
+ * Queries whether the layout had to ellipsize any paragraphs.
+ *
+ * This returns %TRUE if the ellipsization mode for @layout
+ * is not %PANGO_ELLIPSIZE_NONE, a positive width is set on @layout,
+ * and there are paragraphs exceeding that width that have to be
+ * ellipsized.
+ *
+ * Return value: %TRUE if any paragraphs had to be ellipsized, %FALSE
+ * otherwise.
+ *
+ * Since: 1.16
+ */
+gboolean
+pango_layout_is_ellipsized (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, FALSE);
+
+ pango_layout_check_lines (layout);
+
+ return layout->is_ellipsized;
+}
+
+/**
+ * pango_layout_set_text:
+ * @layout: a #PangoLayout
+ * @text: a valid UTF-8 string
+ * @length: maximum length of @text, in bytes. -1 indicates that
+ * the string is nul-terminated and the length should be
+ * calculated. The text will also be truncated on
+ * encountering a nul-termination even when @length is
+ * positive.
+ *
+ * Sets the text of the layout.
+ **/
+void
+pango_layout_set_text (PangoLayout *layout,
+ const char *text,
+ int length)
+{
+ char *old_text, *start, *end;
+
+ g_return_if_fail (layout != NULL);
+ g_return_if_fail (length == 0 || text != NULL);
+
+ old_text = layout->text;
+
+ if (length < 0)
+ layout->text = g_strdup (text);
+ else if (length > 0)
+ /* This is not exactly what we want. We don't need the padding...
+ */
+ layout->text = g_strndup (text, length);
+ else
+ layout->text = g_malloc0 (1);
+
+ layout->length = strlen (layout->text);
+
+ /* validate it, and replace invalid bytes with '?'
+ */
+ start = layout->text;
+ for (;;) {
+ gboolean valid;
+
+ valid = g_utf8_validate (start, -1, (const char **)&end);
+
+ if (!*end)
+ break;
+
+ if (!valid)
+ *end++ = '?';
+
+ start = end;
+ }
+
+ if (start != layout->text)
+ /* TODO: Write out the beginning excerpt of text? */
+ g_warning ("Invalid UTF-8 string passed to pango_layout_set_text()");
+
+ layout->n_chars = g_utf8_strlen (layout->text, -1);
+
+ pango_layout_clear_lines (layout);
+
+ g_free (old_text);
+}
+
+/**
+ * pango_layout_get_text:
+ * @layout: a #PangoLayout
+ *
+ * Gets the text in the layout. The returned text should not
+ * be freed or modified.
+ *
+ * Return value: the text in the @layout.
+ **/
+G_CONST_RETURN char*
+pango_layout_get_text (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
+
+ return layout->text;
+}
+
+/**
+ * pango_layout_set_markup:
+ * @layout: a #PangoLayout
+ * @markup: marked-up text
+ * @length: length of marked-up text in bytes, or -1 if @markup is
+ * nul-terminated
+ *
+ * Same as pango_layout_set_markup_with_accel(), but
+ * the markup text isn't scanned for accelerators.
+ *
+ **/
+void
+pango_layout_set_markup (PangoLayout *layout,
+ const char *markup,
+ int length)
+{
+ pango_layout_set_markup_with_accel (layout, markup, length, 0, NULL);
+}
+
+/**
+ * pango_layout_set_markup_with_accel:
+ * @layout: a #PangoLayout
+ * @markup: marked-up text
+ * (see <link linkend="PangoMarkupFormat">markup format</link>)
+ * @length: length of marked-up text in bytes, or -1 if @markup is
+ * nul-terminated
+ * @accel_marker: marker for accelerators in the text
+ * @accel_char: return location for first located accelerator, or %NULL
+ *
+ * Sets the layout text and attribute list from marked-up text (see
+ * <link linkend="PangoMarkupFormat">markup format</link>). Replaces
+ * the current text and attribute list.
+ *
+ * If @accel_marker is nonzero, the given character will mark the
+ * character following it as an accelerator. For example, @accel_marker
+ * might be an ampersand or underscore. All characters marked
+ * as an accelerator will receive a %PANGO_UNDERLINE_LOW attribute,
+ * and the first character so marked will be returned in @accel_char.
+ * Two @accel_marker characters following each other produce a single
+ * literal @accel_marker character.
+ **/
+void
+pango_layout_set_markup_with_accel (PangoLayout *layout,
+ const char *markup,
+ int length,
+ gunichar accel_marker,
+ gunichar *accel_char)
+{
+ PangoAttrList *list = NULL;
+ char *text = NULL;
+ GError *error;
+
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+ g_return_if_fail (markup != NULL);
+
+ error = NULL;
+ if (!pango_parse_markup (markup, length,
+ accel_marker,
+ &list, &text,
+ accel_char,
+ &error))
+ {
+ g_warning ("pango_layout_set_markup_with_accel: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ pango_layout_set_text (layout, text, -1);
+ pango_layout_set_attributes (layout, list);
+ pango_attr_list_unref (list);
+ g_free (text);
+}
+
+/**
+ * pango_layout_get_unknown_glyphs_count:
+ * @layout: a #PangoLayout
+ *
+ * Counts the number unknown glyphs in @layout. That is, zero if
+ * glyphs for all characters in the layout text were found, or more
+ * than zero otherwise.
+ *
+ * Return value: The number of unknown glyphs in @layout.
+ *
+ * Since: 1.16
+ */
+int
+pango_layout_get_unknown_glyphs_count (PangoLayout *layout)
+{
+ PangoLayoutLine *line;
+ PangoLayoutRun *run;
+ GSList *lines_list;
+ GSList *runs_list;
+ int i, count = 0;
+
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
+
+ pango_layout_check_lines (layout);
+
+ if (layout->unknown_glyphs_count >= 0)
+ return layout->unknown_glyphs_count;
+
+ lines_list = layout->lines;
+ while (lines_list)
+ {
+ line = lines_list->data;
+ runs_list = line->runs;
+
+ while (runs_list)
+ {
+ run = runs_list->data;
+
+ for (i = 0; i < run->glyphs->num_glyphs; i++)
+ {
+ if (run->glyphs->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ count++;
+ }
+
+ runs_list = runs_list->next;
+ }
+ lines_list = lines_list->next;
+ }
+
+ layout->unknown_glyphs_count = count;
+ return count;
+}
+
+/**
+ * pango_layout_context_changed:
+ * @layout: a #PangoLayout
+ *
+ * Forces recomputation of any state in the #PangoLayout that
+ * might depend on the layout's context. This function should
+ * be called if you make changes to the context subsequent
+ * to creating the layout.
+ **/
+void
+pango_layout_context_changed (PangoLayout *layout)
+{
+ pango_layout_clear_lines (layout);
+ layout->tab_width = -1;
+}
+
+/**
+ * pango_layout_get_log_attrs:
+ * @layout: a #PangoLayout
+ * @attrs: location to store a pointer to an array of logical attributes
+ * This value must be freed with g_free().
+ * @n_attrs: location to store the number of the attributes in the
+ * array. (The stored value will be one more than the total number
+ * of characters in the layout, since there need to be attributes
+ * corresponding to both the position before the first character
+ * and the position after the last character.)
+ *
+ * Retrieves an array of logical attributes for each character in
+ * the @layout.
+ **/
+void
+pango_layout_get_log_attrs (PangoLayout *layout,
+ PangoLogAttr **attrs,
+ gint *n_attrs)
+{
+ g_return_if_fail (layout != NULL);
+
+ pango_layout_check_lines (layout);
+
+ if (attrs)
+ {
+ *attrs = g_new (PangoLogAttr, layout->n_chars + 1);
+ memcpy (*attrs, layout->log_attrs, sizeof(PangoLogAttr) * (layout->n_chars + 1));
+ }
+
+ if (n_attrs)
+ *n_attrs = layout->n_chars + 1;
+}
+
+
+/**
+ * pango_layout_get_line_count:
+ * @layout: #PangoLayout
+ *
+ * Retrieves the count of lines for the @layout.
+ *
+ * Return value: the line count.
+ **/
+int
+pango_layout_get_line_count (PangoLayout *layout)
+{
+ g_return_val_if_fail (layout != NULL, 0);
+
+ pango_layout_check_lines (layout);
+ return g_slist_length (layout->lines);
+}
+
+/**
+ * pango_layout_get_lines:
+ * @layout: a #PangoLayout
+ *
+ * Returns the lines of the @layout as a list.
+ *
+ * Use the faster pango_layout_get_lines_readonly() if you do not plan
+ * to modify the contents of the lines (glyphs, glyph widths, etc.).
+ *
+ * Return value: a #GSList containing the lines in the layout. This
+ * points to internal data of the #PangoLayout and must be used with
+ * care. It will become invalid on any change to the layout's
+ * text or properties.
+ **/
+GSList *
+pango_layout_get_lines (PangoLayout *layout)
+{
+ pango_layout_check_lines (layout);
+
+ if (layout->lines)
+ {
+ GSList *tmp_list = layout->lines;
+ while (tmp_list)
+ {
+ PangoLayoutLine *line = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ pango_layout_line_leaked (line);
+ }
+ }
+
+ return layout->lines;
+}
+
+/**
+ * pango_layout_get_lines_readonly:
+ * @layout: a #PangoLayout
+ *
+ * Returns the lines of the @layout as a list.
+ *
+ * This is a faster alternative to pango_layout_get_lines(),
+ * but the user is not expected
+ * to modify the contents of the lines (glyphs, glyph widths, etc.).
+ *
+ * Return value: a #GSList containing the lines in the layout. This
+ * points to internal data of the #PangoLayout and must be used with
+ * care. It will become invalid on any change to the layout's
+ * text or properties. No changes should be made to the lines.
+ *
+ * Since: 1.16
+ **/
+GSList *
+pango_layout_get_lines_readonly (PangoLayout *layout)
+{
+ pango_layout_check_lines (layout);
+
+ return layout->lines;
+}
+
+/**
+ * pango_layout_get_line:
+ * @layout: a #PangoLayout
+ * @line: the index of a line, which must be between 0 and
+ * <literal>pango_layout_get_line_count(layout) - 1</literal>, inclusive.
+ *
+ * Retrieves a particular line from a #PangoLayout.
+ *
+ * Use the faster pango_layout_get_line_readonly() if you do not plan
+ * to modify the contents of the line (glyphs, glyph widths, etc.).
+ *
+ * Return value: the requested #PangoLayoutLine, or %NULL if the
+ * index is out of range. This layout line can
+ * be ref'ed and retained, but will become invalid
+ * if changes are made to the #PangoLayout.
+ **/
+PangoLayoutLine *
+pango_layout_get_line (PangoLayout *layout,
+ int line)
+{
+ GSList *list_item;
+ g_return_val_if_fail (layout != NULL, NULL);
+ g_return_val_if_fail (line >= 0, NULL);
+
+ if (line < 0)
+ return NULL;
+
+ pango_layout_check_lines (layout);
+
+ list_item = g_slist_nth (layout->lines, line);
+
+ if (list_item)
+ {
+ PangoLayoutLine *line = list_item->data;
+
+ pango_layout_line_leaked (line);
+ return line;
+ }
+
+ return NULL;
+}
+
+/**
+ * pango_layout_get_line_readonly:
+ * @layout: a #PangoLayout
+ * @line: the index of a line, which must be between 0 and
+ * <literal>pango_layout_get_line_count(layout) - 1</literal>, inclusive.
+ *
+ * Retrieves a particular line from a #PangoLayout.
+ *
+ * This is a faster alternative to pango_layout_get_line(),
+ * but the user is not expected
+ * to modify the contents of the line (glyphs, glyph widths, etc.).
+ *
+ * Return value: the requested #PangoLayoutLine, or %NULL if the
+ * index is out of range. This layout line can
+ * be ref'ed and retained, but will become invalid
+ * if changes are made to the #PangoLayout.
+ * No changes should be made to the line.
+ *
+ * Since: 1.16
+ **/
+PangoLayoutLine *
+pango_layout_get_line_readonly (PangoLayout *layout,
+ int line)
+{
+ GSList *list_item;
+ g_return_val_if_fail (layout != NULL, NULL);
+ g_return_val_if_fail (line >= 0, NULL);
+
+ if (line < 0)
+ return NULL;
+
+ pango_layout_check_lines (layout);
+
+ list_item = g_slist_nth (layout->lines, line);
+
+ if (list_item)
+ {
+ PangoLayoutLine *line = list_item->data;
+ return line;
+ }
+
+ return NULL;
+}
+
+/**
+ * pango_layout_line_index_to_x:
+ * @line: a #PangoLayoutLine
+ * @index_: byte offset of a grapheme within the layout
+ * @trailing: an integer indicating the edge of the grapheme to retrieve
+ * the position of. If 0, the trailing edge of the grapheme,
+ * if > 0, the leading of the grapheme.
+ * @x_pos: location to store the x_offset (in #PangoGlyphUnit)
+ *
+ * Converts an index within a line to a X position.
+ *
+ **/
+void
+pango_layout_line_index_to_x (PangoLayoutLine *line,
+ int index,
+ int trailing,
+ int *x_pos)
+{
+ PangoLayout *layout = line->layout;
+ GSList *run_list = line->runs;
+ int width = 0;
+
+ while (run_list)
+ {
+ PangoLayoutRun *run = run_list->data;
+ ItemProperties properties;
+
+ pango_layout_get_item_properties (run->item, &properties);
+
+ if (run->item->offset <= index && run->item->offset + run->item->length > index)
+ {
+ if (properties.shape_set)
+ {
+ if (x_pos)
+ *x_pos = width + (trailing > 0 ? properties.shape_logical_rect->width : 0);
+ }
+ else
+ {
+ int offset = g_utf8_pointer_to_offset (layout->text, layout->text + index);
+ if (trailing)
+ {
+ while (index < line->start_index + line->length &&
+ offset + 1 < layout->n_chars &&
+ !layout->log_attrs[offset + 1].is_cursor_position)
+ {
+ offset++;
+ index = g_utf8_next_char (layout->text + index) - layout->text;
+ }
+ }
+ else
+ {
+ while (index > line->start_index &&
+ !layout->log_attrs[offset].is_cursor_position)
+ {
+ offset--;
+ index = g_utf8_prev_char (layout->text + index) - layout->text;
+ }
+
+ }
+
+ pango_glyph_string_index_to_x (run->glyphs,
+ layout->text + run->item->offset,
+ run->item->length,
+ &run->item->analysis,
+ index - run->item->offset, trailing, x_pos);
+ if (x_pos)
+ *x_pos += width;
+ }
+
+ return;
+ }
+
+ if (!properties.shape_set)
+ width += pango_glyph_string_get_width (run->glyphs);
+ else
+ width += properties.shape_logical_rect->width;
+
+ run_list = run_list->next;
+ }
+
+ if (x_pos)
+ *x_pos = width;
+}
+
+static PangoLayoutLine *
+pango_layout_index_to_line (PangoLayout *layout,
+ int index,
+ int *line_nr,
+ PangoLayoutLine **line_before,
+ PangoLayoutLine **line_after)
+{
+ GSList *tmp_list;
+ GSList *line_list;
+ PangoLayoutLine *line = NULL;
+ PangoLayoutLine *prev_line = NULL;
+ int i = -1;
+
+ line_list = tmp_list = layout->lines;
+ while (tmp_list)
+ {
+ PangoLayoutLine *tmp_line = tmp_list->data;
+
+ if (tmp_line->start_index > index)
+ break; /* index was in paragraph delimiters */
+
+ prev_line = line;
+ line = tmp_line;
+ line_list = tmp_list;
+ i++;
+
+ if (line->start_index + line->length > index)
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (line_nr)
+ *line_nr = i;
+
+ if (line_before)
+ *line_before = prev_line;
+
+ if (line_after)
+ *line_after = (line_list && line_list->next) ? line_list->next->data : NULL;
+
+ return line;
+}
+
+static PangoLayoutLine *
+pango_layout_index_to_line_and_extents (PangoLayout *layout,
+ int index,
+ PangoRectangle *line_rect)
+{
+ PangoLayoutIter *iter;
+ PangoLayoutLine *line = NULL;
+
+ iter = pango_layout_get_iter (layout);
+
+ if (!ITER_IS_INVALID (iter))
+ while (TRUE)
+ {
+ PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (iter);
+
+ if (tmp_line->start_index > index)
+ break; /* index was in paragraph delimiters */
+
+ line = tmp_line;
+
+ pango_layout_iter_get_line_extents (iter, NULL, line_rect);
+
+ if (line->start_index + line->length > index)
+ break;
+
+ if (!pango_layout_iter_next_line (iter))
+ break; /* Use end of last line */
+ }
+
+ pango_layout_iter_free (iter);
+
+ return line;
+}
+
+/**
+ * pango_layout_index_to_line_x:
+ * @layout: a #PangoLayout
+ * @index_: the byte index of a grapheme within the layout.
+ * @trailing: an integer indicating the edge of the grapheme to retrieve the
+ * position of. If 0, the trailing edge of the grapheme, if > 0,
+ * the leading of the grapheme.
+ * @line: location to store resulting line index. (which will
+ * between 0 and pango_layout_get_line_count(layout) - 1)
+ * @x_pos: location to store resulting position within line
+ * (%PANGO_SCALE units per device unit)
+ *
+ * Converts from byte @index_ within the @layout to line and X position.
+ * (X position is measured from the left edge of the line)
+ */
+void
+pango_layout_index_to_line_x (PangoLayout *layout,
+ int index,
+ gboolean trailing,
+ int *line,
+ int *x_pos)
+{
+ int line_num;
+ PangoLayoutLine *layout_line = NULL;
+
+ g_return_if_fail (layout != NULL);
+ g_return_if_fail (index >= 0);
+ g_return_if_fail (index <= layout->length);
+
+ pango_layout_check_lines (layout);
+
+ layout_line = pango_layout_index_to_line (layout, index,
+ &line_num, NULL, NULL);
+
+ if (layout_line)
+ {
+ /* use end of line if index was in the paragraph delimiters */
+ if (index > layout_line->start_index + layout_line->length)
+ index = layout_line->start_index + layout_line->length;
+
+ if (line)
+ *line = line_num;
+
+ pango_layout_line_index_to_x (layout_line, index, trailing, x_pos);
+ }
+ else
+ {
+ if (line)
+ *line = -1;
+ if (x_pos)
+ *x_pos = -1;
+ }
+}
+
+/**
+ * pango_layout_move_cursor_visually:
+ * @layout: a #PangoLayout.
+ * @strong: whether the moving cursor is the strong cursor or the
+ * weak cursor. The strong cursor is the cursor corresponding
+ * to text insertion in the base direction for the layout.
+ * @old_index: the byte index of the grapheme for the old index
+ * @old_trailing: if 0, the cursor was at the trailing edge of the
+ * grapheme indicated by @old_index, if > 0, the cursor
+ * was at the leading edge.
+ * @direction: direction to move cursor. A negative
+ * value indicates motion to the left.
+ * @new_index: location to store the new cursor byte index. A value of -1
+ * indicates that the cursor has been moved off the beginning
+ * of the layout. A value of %G_MAXINT indicates that
+ * the cursor has been moved off the end of the layout.
+ * @new_trailing: number of characters to move forward from the location returned
+ * for @new_index to get the position where the cursor should
+ * be displayed. This allows distinguishing the position at
+ * the beginning of one line from the position at the end
+ * of the preceding line. @new_index is always on the line
+ * where the cursor should be displayed.
+ *
+ * Computes a new cursor position from an old position and
+ * a count of positions to move visually. If @direction is positive,
+ * then the new strong cursor position will be one position
+ * to the right of the old cursor position. If @direction is negative,
+ * then the new strong cursor position will be one position
+ * to the left of the old cursor position.
+ *
+ * In the presence of bidirectional text, the correspondence
+ * between logical and visual order will depend on the direction
+ * of the current run, and there may be jumps when the cursor
+ * is moved off of the end of a run.
+ *
+ * Motion here is in cursor positions, not in characters, so a
+ * single call to pango_layout_move_cursor_visually() may move the
+ * cursor over multiple characters when multiple characters combine
+ * to form a single grapheme.
+ **/
+void
+pango_layout_move_cursor_visually (PangoLayout *layout,
+ gboolean strong,
+ int old_index,
+ int old_trailing,
+ int direction,
+ int *new_index,
+ int *new_trailing)
+{
+ PangoLayoutLine *line = NULL;
+ PangoLayoutLine *prev_line;
+ PangoLayoutLine *next_line;
+
+ int *log2vis_map;
+ int *vis2log_map;
+ int n_vis;
+ int vis_pos, vis_pos_old, log_pos;
+ int start_offset;
+ gboolean off_start = FALSE;
+ gboolean off_end = FALSE;
+
+ g_return_if_fail (layout != NULL);
+ g_return_if_fail (old_index >= 0 && old_index <= layout->length);
+ g_return_if_fail (old_index < layout->length || old_trailing == 0);
+ g_return_if_fail (new_index != NULL);
+ g_return_if_fail (new_trailing != NULL);
+
+ direction = (direction >= 0 ? 1 : -1);
+
+ pango_layout_check_lines (layout);
+
+ /* Find the line the old cursor is on */
+ line = pango_layout_index_to_line (layout, old_index,
+ NULL, &prev_line, &next_line);
+
+ start_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index);
+
+ while (old_trailing--)
+ old_index = g_utf8_next_char (layout->text + old_index) - layout->text;
+
+ log2vis_map = pango_layout_line_get_log2vis_map (line, strong);
+ n_vis = g_utf8_strlen (layout->text + line->start_index, line->length);
+
+ /* Clamp old_index to fit on the line */
+ if (old_index > (line->start_index + line->length))
+ old_index = line->start_index + line->length;
+
+ vis_pos = log2vis_map[old_index - line->start_index];
+
+ g_free (log2vis_map);
+
+ /* Handling movement between lines */
+ if (vis_pos == 0 && direction < 0)
+ {
+ if (line->resolved_dir == PANGO_DIRECTION_LTR)
+ off_start = TRUE;
+ else
+ off_end = TRUE;
+ }
+ else if (vis_pos == n_vis && direction > 0)
+ {
+ if (line->resolved_dir == PANGO_DIRECTION_LTR)
+ off_end = TRUE;
+ else
+ off_start = TRUE;
+ }
+
+ if (off_start || off_end)
+ {
+ /* If we move over a paragraph boundary, count that as
+ * an extra position in the motion
+ */
+ gboolean paragraph_boundary;
+
+ if (off_start)
+ {
+ if (!prev_line)
+ {
+ *new_index = -1;
+ *new_trailing = 0;
+ return;
+ }
+ line = prev_line;
+ paragraph_boundary = (line->start_index + line->length != old_index);
+ }
+ else
+ {
+ if (!next_line)
+ {
+ *new_index = G_MAXINT;
+ *new_trailing = 0;
+ return;
+ }
+ line = next_line;
+ paragraph_boundary = (line->start_index != old_index);
+ }
+
+ n_vis = g_utf8_strlen (layout->text + line->start_index, line->length);
+ start_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index);
+
+ if (vis_pos == 0 && direction < 0)
+ {
+ vis_pos = n_vis;
+ if (paragraph_boundary)
+ vis_pos++;
+ }
+ else /* (vis_pos == n_vis && direction > 0) */
+ {
+ vis_pos = 0;
+ if (paragraph_boundary)
+ vis_pos--;
+ }
+ }
+
+ vis2log_map = pango_layout_line_get_vis2log_map (line, strong);
+
+ vis_pos_old = vis_pos + direction;
+ log_pos = g_utf8_pointer_to_offset (layout->text + line->start_index,
+ layout->text + line->start_index + vis2log_map[vis_pos_old]);
+ do
+ {
+ vis_pos += direction;
+ log_pos += g_utf8_pointer_to_offset (layout->text + line->start_index + vis2log_map[vis_pos_old],
+ layout->text + line->start_index + vis2log_map[vis_pos]);
+ vis_pos_old = vis_pos;
+ }
+ while (vis_pos > 0 && vis_pos < n_vis &&
+ !layout->log_attrs[start_offset + log_pos].is_cursor_position);
+
+ *new_index = line->start_index + vis2log_map[vis_pos];
+ g_free (vis2log_map);
+
+ *new_trailing = 0;
+
+ if (*new_index == line->start_index + line->length && line->length > 0)
+ {
+ do
+ {
+ log_pos--;
+ *new_index = g_utf8_prev_char (layout->text + *new_index) - layout->text;
+ (*new_trailing)++;
+ }
+ while (log_pos > 0 && !layout->log_attrs[start_offset + log_pos].is_cursor_position);
+ }
+}
+
+/**
+ * pango_layout_xy_to_index:
+ * @layout: a #PangoLayout
+ * @x: the X offset (in #PangoGlyphUnit)
+ * from the left edge of the layout.
+ * @y: the Y offset (in #PangoGlyphUnit)
+ * from the top edge of the layout
+ * @index_: location to store calculated byte index
+ * @trailing: location to store a integer indicating where
+ * in the grapheme the user clicked. It will either
+ * be zero, or the number of characters in the
+ * grapheme. 0 represents the trailing edge of the grapheme.
+ *
+ * Converts from X and Y position within a layout to the byte
+ * index to the character at that logical position. If the
+ * Y position is not inside the layout, the closest position is chosen
+ * (the position will be clamped inside the layout). If the
+ * X position is not within the layout, then the start or the
+ * end of the line is chosen as described for pango_layout_x_to_index().
+ * If either the X or Y positions were not inside the layout, then the
+ * function returns %FALSE; on an exact hit, it returns %TRUE.
+ *
+ * Return value: %TRUE if the coordinates were inside text, %FALSE otherwise.
+ **/
+gboolean
+pango_layout_xy_to_index (PangoLayout *layout,
+ int x,
+ int y,
+ int *index,
+ gint *trailing)
+{
+ PangoLayoutIter *iter;
+ PangoLayoutLine *prev_line = NULL;
+ PangoLayoutLine *found = NULL;
+ int found_line_x = 0;
+ int prev_last = 0;
+ int prev_line_x = 0;
+ gboolean retval = FALSE;
+ gboolean outside = FALSE;
+
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
+
+ iter = pango_layout_get_iter (layout);
+
+ do
+ {
+ PangoRectangle line_logical;
+ int first_y, last_y;
+
+ pango_layout_iter_get_line_extents (iter, NULL, &line_logical);
+ pango_layout_iter_get_line_yrange (iter, &first_y, &last_y);
+
+ if (y < first_y)
+ {
+ if (prev_line && y < (prev_last + (first_y - prev_last) / 2))
+ {
+ found = prev_line;
+ found_line_x = prev_line_x;
+ }
+ else
+ {
+ if (prev_line == NULL)
+ outside = TRUE; /* off the top */
+
+ found = _pango_layout_iter_get_line (iter);
+ found_line_x = x - line_logical.x;
+ }
+ }
+ else if (y >= first_y &&
+ y < last_y)
+ {
+ found = _pango_layout_iter_get_line (iter);
+ found_line_x = x - line_logical.x;
+ }
+
+ prev_line = _pango_layout_iter_get_line (iter);
+ prev_last = last_y;
+ prev_line_x = x - line_logical.x;
+
+ if (found != NULL)
+ break;
+ }
+ while (pango_layout_iter_next_line (iter));
+
+ pango_layout_iter_free (iter);
+
+ if (found == NULL)
+ {
+ /* Off the bottom of the layout */
+ outside = TRUE;
+
+ found = prev_line;
+ found_line_x = prev_line_x;
+ }
+
+ retval = pango_layout_line_x_to_index (found,
+ found_line_x,
+ index, trailing);
+
+ if (outside)
+ retval = FALSE;
+
+ return retval;
+}
+
+/**
+ * pango_layout_index_to_pos:
+ * @layout: a #PangoLayout
+ * @index_: byte index within @layout
+ * @pos: rectangle in which to store the position of the grapheme
+ *
+ * Converts from an index within a #PangoLayout to the onscreen position
+ * corresponding to the grapheme at that index, which is represented
+ * as rectangle. Note that <literal>pos->x</literal> is always the leading
+ * edge of the grapheme and <literal>pos->x + pos->width</literal> the trailing
+ * edge of the grapheme. If the directionality of the grapheme is right-to-left,
+ * then <literal>pos->width</literal> will be negative.
+ **/
+void
+pango_layout_index_to_pos (PangoLayout *layout,
+ int index,
+ PangoRectangle *pos)
+{
+ PangoRectangle logical_rect;
+ PangoLayoutIter *iter;
+ PangoLayoutLine *layout_line = NULL;
+ int x_pos;
+
+ g_return_if_fail (layout != NULL);
+ g_return_if_fail (index >= 0);
+ g_return_if_fail (pos != NULL);
+
+ iter = pango_layout_get_iter (layout);
+
+ if (!ITER_IS_INVALID (iter))
+ {
+ while (TRUE)
+ {
+ PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (iter);
+
+ if (tmp_line->start_index > index)
+ {
+ /* index is in the paragraph delimiters, move to
+ * end of previous line
+ */
+ index = layout_line->start_index + layout_line->length;
+ break;
+ }
+
+ layout_line = tmp_line;
+
+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+
+ if (layout_line->start_index + layout_line->length > index)
+ break;
+
+ if (!pango_layout_iter_next_line (iter))
+ {
+ index = layout_line->start_index + layout_line->length;
+ break;
+ }
+ }
+
+ pos->y = logical_rect.y;
+ pos->height = logical_rect.height;
+
+ pango_layout_line_index_to_x (layout_line, index, 0, &x_pos);
+ pos->x = logical_rect.x + x_pos;
+
+ if (index < layout_line->start_index + layout_line->length)
+ {
+ pango_layout_line_index_to_x (layout_line, index, 1, &x_pos);
+ pos->width = (logical_rect.x + x_pos) - pos->x;
+ }
+ else
+ pos->width = 0;
+ }
+
+ pango_layout_iter_free (iter);
+}
+
+static void
+pango_layout_line_get_range (PangoLayoutLine *line,
+ char **start,
+ char **end)
+{
+ char *p;
+
+ p = line->layout->text + line->start_index;
+
+ if (start)
+ *start = p;
+ if (end)
+ *end = p + line->length;
+}
+
+static int *
+pango_layout_line_get_vis2log_map (PangoLayoutLine *line,
+ gboolean strong)
+{
+ PangoLayout *layout = line->layout;
+ PangoDirection prev_dir;
+ PangoDirection cursor_dir;
+ GSList *tmp_list;
+ gchar *start, *end;
+ int *result;
+ int pos;
+ int n_chars;
+
+ pango_layout_line_get_range (line, &start, &end);
+ n_chars = g_utf8_strlen (start, end - start);
+
+ result = g_new (int, n_chars + 1);
+
+ if (strong)
+ cursor_dir = line->resolved_dir;
+ else
+ cursor_dir = (line->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+
+ /* Handle the first visual position
+ */
+ if (line->resolved_dir == cursor_dir)
+ result[0] = line->resolved_dir == PANGO_DIRECTION_LTR ? 0 : end - start;
+
+ prev_dir = line->resolved_dir;
+ pos = 0;
+ tmp_list = line->runs;
+ while (tmp_list)
+ {
+ PangoLayoutRun *run = tmp_list->data;
+ int run_n_chars = run->item->num_chars;
+ PangoDirection run_dir = (run->item->analysis.level % 2) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+ char *p = layout->text + run->item->offset;
+ int i;
+
+ /* pos is the visual position at the start of the run */
+ /* p is the logical byte index at the start of the run */
+
+ if (run_dir == PANGO_DIRECTION_LTR)
+ {
+ if ((cursor_dir == PANGO_DIRECTION_LTR) ||
+ (prev_dir == run_dir))
+ result[pos] = p - start;
+
+ p = g_utf8_next_char (p);
+
+ for (i = 1; i < run_n_chars; i++)
+ {
+ result[pos + i] = p - start;
+ p = g_utf8_next_char (p);
+ }
+
+ if (cursor_dir == PANGO_DIRECTION_LTR)
+ result[pos + run_n_chars] = p - start;
+ }
+ else
+ {
+ if (cursor_dir == PANGO_DIRECTION_RTL)
+ result[pos + run_n_chars] = p - start;
+
+ p = g_utf8_next_char (p);
+
+ for (i = 1; i < run_n_chars; i++)
+ {
+ result[pos + run_n_chars - i] = p - start;
+ p = g_utf8_next_char (p);
+ }
+
+ if ((cursor_dir == PANGO_DIRECTION_RTL) ||
+ (prev_dir == run_dir))
+ result[pos] = p - start;
+ }
+
+ pos += run_n_chars;
+ prev_dir = run_dir;
+ tmp_list = tmp_list->next;
+ }
+
+ /* And the last visual position
+ */
+ if ((cursor_dir == line->resolved_dir) || (prev_dir == line->resolved_dir))
+ result[pos] = line->resolved_dir == PANGO_DIRECTION_LTR ? end - start : 0;
+
+ return result;
+}
+
+static int *
+pango_layout_line_get_log2vis_map (PangoLayoutLine *line,
+ gboolean strong)
+{
+ gchar *start, *end;
+ int *reverse_map;
+ int *result;
+ int i;
+ int n_chars;
+
+ pango_layout_line_get_range (line, &start, &end);
+ n_chars = g_utf8_strlen (start, end - start);
+ result = g_new0 (int, end - start + 1);
+
+ reverse_map = pango_layout_line_get_vis2log_map (line, strong);
+
+ for (i=0; i <= n_chars; i++)
+ result[reverse_map[i]] = i;
+
+ g_free (reverse_map);
+
+ return result;
+}
+
+static PangoDirection
+pango_layout_line_get_char_direction (PangoLayoutLine *layout_line,
+ int index)
+{
+ GSList *run_list;
+
+ run_list = layout_line->runs;
+ while (run_list)
+ {
+ PangoLayoutRun *run = run_list->data;
+
+ if (run->item->offset <= index && run->item->offset + run->item->length > index)
+ return run->item->analysis.level % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+
+ run_list = run_list->next;
+ }
+
+ g_assert_not_reached ();
+
+ return PANGO_DIRECTION_LTR;
+}
+
+/**
+ * pango_layout_get_cursor_pos:
+ * @layout: a #PangoLayout
+ * @index_: the byte index of the cursor
+ * @strong_pos: location to store the strong cursor position (may be %NULL)
+ * @weak_pos: location to store the weak cursor position (may be %NULL)
+ *
+ * Given an index within a layout, determines the positions that of the
+ * strong and weak cursors if the insertion point is at that
+ * index. The position of each cursor is stored as a zero-width
+ * rectangle. The strong cursor location is the location where
+ * characters of the directionality equal to the base direction of the
+ * layout are inserted. The weak cursor location is the location
+ * where characters of the directionality opposite to the base
+ * direction of the layout are inserted.
+ **/
+void
+pango_layout_get_cursor_pos (PangoLayout *layout,
+ int index,
+ PangoRectangle *strong_pos,
+ PangoRectangle *weak_pos)
+{
+ PangoDirection dir1;
+ PangoRectangle line_rect;
+ PangoLayoutLine *layout_line = NULL; /* Quiet GCC */
+ int x1_trailing;
+ int x2;
+
+ g_return_if_fail (layout != NULL);
+ g_return_if_fail (index >= 0 && index <= layout->length);
+
+ layout_line = pango_layout_index_to_line_and_extents (layout, index,
+ &line_rect);
+
+ g_assert (index >= layout_line->start_index);
+
+ /* Examine the trailing edge of the character before the cursor */
+ if (index == layout_line->start_index)
+ {
+ dir1 = layout_line->resolved_dir;
+ if (layout_line->resolved_dir == PANGO_DIRECTION_LTR)
+ x1_trailing = 0;
+ else
+ x1_trailing = line_rect.width;
+ }
+ else
+ {
+ gint prev_index = g_utf8_prev_char (layout->text + index) - layout->text;
+ dir1 = pango_layout_line_get_char_direction (layout_line, prev_index);
+ pango_layout_line_index_to_x (layout_line, prev_index, TRUE, &x1_trailing);
+ }
+
+ /* Examine the leading edge of the character after the cursor */
+ if (index >= layout_line->start_index + layout_line->length)
+ {
+ if (layout_line->resolved_dir == PANGO_DIRECTION_LTR)
+ x2 = line_rect.width;
+ else
+ x2 = 0;
+ }
+ else
+ {
+ pango_layout_line_index_to_x (layout_line, index, FALSE, &x2);
+ }
+
+ if (strong_pos)
+ {
+ strong_pos->x = line_rect.x;
+
+ if (dir1 == layout_line->resolved_dir)
+ strong_pos->x += x1_trailing;
+ else
+ strong_pos->x += x2;
+
+ strong_pos->y = line_rect.y;
+ strong_pos->width = 0;
+ strong_pos->height = line_rect.height;
+ }
+
+ if (weak_pos)
+ {
+ weak_pos->x = line_rect.x;
+
+ if (dir1 == layout_line->resolved_dir)
+ weak_pos->x += x2;
+ else
+ weak_pos->x += x1_trailing;
+
+ weak_pos->y = line_rect.y;
+ weak_pos->width = 0;
+ weak_pos->height = line_rect.height;
+ }
+}
+
+static inline int
+direction_simple (PangoDirection d)
+{
+ switch (d)
+ {
+ case PANGO_DIRECTION_LTR :
+ case PANGO_DIRECTION_WEAK_LTR :
+ case PANGO_DIRECTION_TTB_RTL :
+ return 1;
+ case PANGO_DIRECTION_RTL :
+ case PANGO_DIRECTION_WEAK_RTL :
+ case PANGO_DIRECTION_TTB_LTR :
+ return -1;
+ case PANGO_DIRECTION_NEUTRAL :
+ return 0;
+ /* no default, compiler should complain if a new values is added */
+ }
+ /* not reached */
+ return 0;
+}
+
+static PangoAlignment
+get_alignment (PangoLayout *layout,
+ PangoLayoutLine *line)
+{
+ PangoAlignment alignment = layout->alignment;
+
+ if (alignment != PANGO_ALIGN_CENTER && line->layout->auto_dir &&
+ direction_simple (line->resolved_dir) ==
+ -direction_simple (pango_context_get_base_dir (layout->context)))
+ {
+ if (alignment == PANGO_ALIGN_LEFT)
+ alignment = PANGO_ALIGN_RIGHT;
+ else if (alignment == PANGO_ALIGN_RIGHT)
+ alignment = PANGO_ALIGN_LEFT;
+ }
+
+ return alignment;
+}
+
+static void
+get_x_offset (PangoLayout *layout,
+ PangoLayoutLine *line,
+ int layout_width,
+ int line_width,
+ int *x_offset)
+{
+ PangoAlignment alignment = get_alignment (layout, line);
+
+ /* Alignment */
+ if (alignment == PANGO_ALIGN_RIGHT)
+ *x_offset = layout_width - line_width;
+ else if (alignment == PANGO_ALIGN_CENTER)
+ *x_offset = (layout_width - line_width) / 2;
+ else
+ *x_offset = 0;
+
+ /* Indentation */
+
+
+ /* For center, we ignore indentation; I think I've seen word
+ * processors that still do the indentation here as if it were
+ * indented left/right, though we can't sensibly do that without
+ * knowing whether left/right is the "normal" thing for this text
+ */
+
+ if (alignment == PANGO_ALIGN_CENTER)
+ return;
+
+ if (line->is_paragraph_start)
+ {
+ if (layout->indent > 0)
+ {
+ if (alignment == PANGO_ALIGN_LEFT)
+ *x_offset += layout->indent;
+ else
+ *x_offset -= layout->indent;
+ }
+ }
+ else
+ {
+ if (layout->indent < 0)
+ {
+ if (alignment == PANGO_ALIGN_LEFT)
+ *x_offset -= layout->indent;
+ else
+ *x_offset += layout->indent;
+ }
+ }
+}
+
+static void
+get_line_extents_layout_coords (PangoLayout *layout,
+ PangoLayoutLine *line,
+ int layout_width,
+ int y_offset,
+ int *baseline,
+ PangoRectangle *line_ink_layout,
+ PangoRectangle *line_logical_layout)
+{
+ int x_offset;
+ /* Line extents in line coords (origin at line baseline) */
+ PangoRectangle line_ink;
+ PangoRectangle line_logical;
+
+ pango_layout_line_get_extents (line, line_ink_layout ? &line_ink : NULL,
+ &line_logical);
+
+ get_x_offset (layout, line, layout_width, line_logical.width, &x_offset);
+
+ /* Convert the line's extents into layout coordinates */
+ if (line_ink_layout)
+ {
+ *line_ink_layout = line_ink;
+ line_ink_layout->x = line_ink.x + x_offset;
+ line_ink_layout->y = y_offset - line_logical.y + line_ink.y;
+ }
+
+ if (line_logical_layout)
+ {
+ *line_logical_layout = line_logical;
+ line_logical_layout->x = line_logical.x + x_offset;
+ line_logical_layout->y = y_offset;
+ }
+
+ if (baseline)
+ *baseline = y_offset - line_logical.y;
+}
+
+/* if non-NULL line_extents returns a list of line extents
+ * in layout coordinates
+ */
+static void
+pango_layout_get_extents_internal (PangoLayout *layout,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect,
+ GSList **line_extents)
+{
+ GSList *line_list;
+ int y_offset = 0;
+ int width;
+ gboolean need_width = FALSE;
+
+ g_return_if_fail (layout != NULL);
+
+ if (ink_rect && layout->ink_rect_cached)
+ {
+ *ink_rect = layout->ink_rect;
+ ink_rect = NULL;
+ }
+ if (logical_rect && layout->logical_rect_cached)
+ {
+ *logical_rect = layout->logical_rect;
+ logical_rect = NULL;
+ }
+ if (!ink_rect && !logical_rect && !line_extents)
+ return;
+
+ pango_layout_check_lines (layout);
+
+ /* When we are not wrapping, we need the overall width of the layout to
+ * figure out the x_offsets of each line. However, we only need the
+ * x_offsets if we are computing the ink_rect or individual line extents.
+ */
+ width = layout->width;
+
+ if (layout->auto_dir)
+ {
+ /* If one of the lines of the layout is not left aligned, then we need
+ * the width of the layout to calculate line x-offsets; this requires
+ * looping through the lines for layout->auto_dir.
+ */
+ line_list = layout->lines;
+ while (line_list && !need_width)
+ {
+ PangoLayoutLine *line = line_list->data;
+
+ if (get_alignment (layout, line) != PANGO_ALIGN_LEFT)
+ need_width = TRUE;
+
+ line_list = line_list->next;
+ }
+ }
+ else if (layout->alignment != PANGO_ALIGN_LEFT)
+ need_width = TRUE;
+
+ if (width == -1 && need_width && (ink_rect || line_extents))
+ {
+ PangoRectangle overall_logical;
+
+ pango_layout_get_extents_internal (layout, NULL, &overall_logical, NULL);
+ width = overall_logical.width;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = 0;
+ logical_rect->width = 0;
+ logical_rect->height = 0;
+ }
+
+ line_list = layout->lines;
+ while (line_list)
+ {
+ PangoLayoutLine *line = line_list->data;
+ /* Line extents in layout coords (origin at 0,0 of the layout) */
+ PangoRectangle line_ink_layout;
+ PangoRectangle line_logical_layout;
+
+ int new_pos;
+
+ /* This block gets the line extents in layout coords */
+ {
+ int baseline;
+
+ get_line_extents_layout_coords (layout, line,
+ width, y_offset,
+ &baseline,
+ ink_rect ? &line_ink_layout : NULL,
+ &line_logical_layout);
+
+ if (line_extents)
+ {
+ Extents *ext = g_slice_new (Extents);
+ ext->baseline = baseline;
+ ext->ink_rect = line_ink_layout;
+ ext->logical_rect = line_logical_layout;
+ *line_extents = g_slist_prepend (*line_extents, ext);
+ }
+ }
+
+ if (ink_rect)
+ {
+ /* Compute the union of the current ink_rect with
+ * line_ink_layout
+ */
+
+ if (line_list == layout->lines)
+ {
+ *ink_rect = line_ink_layout;
+ }
+ else
+ {
+ new_pos = MIN (ink_rect->x, line_ink_layout.x);
+ ink_rect->width =
+ MAX (ink_rect->x + ink_rect->width,
+ line_ink_layout.x + line_ink_layout.width) - new_pos;
+ ink_rect->x = new_pos;
+
+ new_pos = MIN (ink_rect->y, line_ink_layout.y);
+ ink_rect->height =
+ MAX (ink_rect->y + ink_rect->height,
+ line_ink_layout.y + line_ink_layout.height) - new_pos;
+ ink_rect->y = new_pos;
+ }
+ }
+
+ if (logical_rect)
+ {
+ if (layout->width == -1)
+ {
+ /* When no width is set on layout, we can just compute the max of the
+ * line lengths to get the horizontal extents ... logical_rect.x = 0.
+ */
+ logical_rect->width = MAX (logical_rect->width, line_logical_layout.width);
+ }
+ else
+ {
+ /* When a width is set, we have to compute the union of the horizontal
+ * extents of all the lines.
+ */
+ if (line_list == layout->lines)
+ {
+ logical_rect->x = line_logical_layout.x;
+ logical_rect->width = line_logical_layout.width;
+ }
+ else
+ {
+ new_pos = MIN (logical_rect->x, line_logical_layout.x);
+ logical_rect->width =
+ MAX (logical_rect->x + logical_rect->width,
+ line_logical_layout.x + line_logical_layout.width) - new_pos;
+ logical_rect->x = new_pos;
+
+ }
+ }
+
+ logical_rect->height += line_logical_layout.height;
+
+ /* No space after the last line, of course. */
+ if (line_list->next != NULL)
+ logical_rect->height += layout->spacing;
+ }
+
+ y_offset += line_logical_layout.height + layout->spacing;
+ line_list = line_list->next;
+ }
+
+ if (ink_rect)
+ {
+ layout->ink_rect = *ink_rect;
+ layout->ink_rect_cached = TRUE;
+ }
+ if (logical_rect)
+ {
+ layout->logical_rect = *logical_rect;
+ layout->logical_rect_cached = TRUE;
+ }
+ if (line_extents)
+ *line_extents = g_slist_reverse (*line_extents);
+}
+
+/**
+ * pango_layout_get_extents:
+ * @layout: a #PangoLayout
+ * @ink_rect: rectangle used to store the extents of the layout as drawn
+ * or %NULL to indicate that the result is not needed.
+ * @logical_rect: rectangle used to store the logical extents of the layout
+ or %NULL to indicate that the result is not needed.
+ *
+ * Computes the logical and ink extents of @layout. Logical extents
+ * are usually what you want for positioning things. Note that both extents
+ * may have non-zero x and y. You may want to use those to offset where you
+ * render the layout. Not doing that is a very typical bug that shows up as
+ * right-to-left layouts not being correctly positioned in a layout with
+ * a set width.
+ *
+ * The extents are given in layout coordinates and in Pango units; layout
+ * coordinates begin at the top left corner of the layout.
+ */
+void
+pango_layout_get_extents (PangoLayout *layout,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ g_return_if_fail (layout != NULL);
+
+ pango_layout_get_extents_internal (layout, ink_rect, logical_rect, NULL);
+}
+
+/**
+ * pango_layout_get_pixel_extents:
+ * @layout: a #PangoLayout
+ * @ink_rect: rectangle used to store the extents of the layout as drawn
+ * or %NULL to indicate that the result is not needed.
+ * @logical_rect: rectangle used to store the logical extents of the
+ * layout or %NULL to indicate that the result is not needed.
+ *
+ * Computes the logical and ink extents of @layout in device units.
+ * This function just calls pango_layout_get_extents() followed by
+ * pango_extents_to_pixels().
+ *
+ * See pango_extents_to_pixels() for details of how ink and logical rectangles
+ * are rounded to pixels. In certain situations you may want to use
+ * pango_layout_get_extents() directly and pass the resulting logical
+ * rectangle to pango_extents_to_pixels() as an ink rectangle().
+ **/
+void
+pango_layout_get_pixel_extents (PangoLayout *layout,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ pango_layout_get_extents (layout, ink_rect, logical_rect);
+ pango_extents_to_pixels (ink_rect, logical_rect);
+}
+
+/**
+ * pango_layout_get_size:
+ * @layout: a #PangoLayout
+ * @width: location to store the logical width, or %NULL
+ * @height: location to store the logical height, or %NULL
+ *
+ * Determines the logical width and height of a #PangoLayout
+ * in Pango units (device units scaled by %PANGO_SCALE). This
+ * is simply a convenience function around pango_layout_get_extents().
+ **/
+void
+pango_layout_get_size (PangoLayout *layout,
+ int *width,
+ int *height)
+{
+ PangoRectangle logical_rect;
+
+ pango_layout_get_extents (layout, NULL, &logical_rect);
+
+ if (width)
+ *width = logical_rect.width;
+ if (height)
+ *height = logical_rect.height;
+}
+
+/**
+ * pango_layout_get_pixel_size:
+ * @layout: a #PangoLayout
+ * @width: location to store the logical width, or %NULL
+ * @height: location to store the logical height, or %NULL
+ *
+ * Determines the logical width and height of a #PangoLayout
+ * in device units. (pango_layout_get_size() returns the width
+ * and height scaled by %PANGO_SCALE.) This
+ * is simply a convenience function around
+ * pango_layout_get_pixel_extents().
+ **/
+void
+pango_layout_get_pixel_size (PangoLayout *layout,
+ int *width,
+ int *height)
+{
+ PangoRectangle logical_rect;
+
+ pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+
+ if (width)
+ *width = logical_rect.width;
+ if (height)
+ *height = logical_rect.height;
+}
+
+static void
+pango_layout_clear_lines (PangoLayout *layout)
+{
+ if (layout->lines)
+ {
+ GSList *tmp_list = layout->lines;
+ while (tmp_list)
+ {
+ PangoLayoutLine *line = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ line->layout = NULL;
+ pango_layout_line_unref (line);
+ }
+
+ g_slist_free (layout->lines);
+ layout->lines = NULL;
+
+ /* This could be handled separately, since we don't need to
+ * recompute log_attrs on a width change, but this is easiest
+ */
+ g_free (layout->log_attrs);
+ layout->log_attrs = NULL;
+ }
+
+ layout->unknown_glyphs_count = -1;
+ layout->logical_rect_cached = FALSE;
+ layout->ink_rect_cached = FALSE;
+ layout->is_ellipsized = FALSE;
+ layout->is_wrapped = FALSE;
+}
+
+static void
+pango_layout_line_leaked (PangoLayoutLine *line)
+{
+ PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line;
+
+ private->cache_status = LEAKED;
+
+ if (line->layout)
+ {
+ line->layout->logical_rect_cached = FALSE;
+ line->layout->ink_rect_cached = FALSE;
+ }
+}
+
+
+/************************************************
+ * Some functions for handling PANGO_ATTR_SHAPE *
+ ************************************************/
+
+static void
+imposed_shape (const char *text,
+ gint n_chars,
+ PangoRectangle *shape_ink,
+ PangoRectangle *shape_logical,
+ PangoGlyphString *glyphs)
+{
+ int i;
+ const char *p;
+
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ for (i=0, p = text; i < n_chars; i++, p = g_utf8_next_char (p))
+ {
+ glyphs->glyphs[i].glyph = PANGO_GLYPH_EMPTY;
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+ glyphs->glyphs[i].geometry.width = shape_logical->width;
+ glyphs->glyphs[i].attr.is_cluster_start = 1;
+
+ glyphs->log_clusters[i] = p - text;
+ }
+}
+
+static void
+imposed_extents (gint n_chars,
+ PangoRectangle *shape_ink,
+ PangoRectangle *shape_logical,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ if (n_chars > 0)
+ {
+ if (ink_rect)
+ {
+ ink_rect->x = MIN (shape_ink->x, shape_ink->x + shape_logical->width * (n_chars - 1));
+ ink_rect->width = MAX (shape_ink->width, shape_ink->width + shape_logical->width * (n_chars - 1));
+ ink_rect->y = shape_ink->y;
+ ink_rect->height = shape_ink->height;
+ }
+ if (logical_rect)
+ {
+ logical_rect->x = MIN (shape_logical->x, shape_logical->x + shape_logical->width * (n_chars - 1));
+ logical_rect->width = MAX (shape_logical->width, shape_logical->width + shape_logical->width * (n_chars - 1));
+ logical_rect->y = shape_logical->y;
+ logical_rect->height = shape_logical->height;
+ }
+ }
+ else
+ {
+ if (ink_rect)
+ {
+ ink_rect->x = 0;
+ ink_rect->y = 0;
+ ink_rect->width = 0;
+ ink_rect->height = 0;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = 0;
+ logical_rect->width = 0;
+ logical_rect->height = 0;
+ }
+ }
+}
+
+
+/*****************
+ * Line Breaking *
+ *****************/
+
+static void shape_tab (PangoLayoutLine *line,
+ PangoGlyphString *glyphs);
+
+static void
+free_run (PangoLayoutRun *run, gpointer data)
+{
+ gboolean free_item = data != NULL;
+ if (free_item)
+ pango_item_free (run->item);
+
+ pango_glyph_string_free (run->glyphs);
+ g_slice_free (PangoLayoutRun, run);
+}
+
+static void
+extents_free (Extents *ext, gpointer data)
+{
+ g_slice_free (Extents, ext);
+}
+
+static PangoItem *
+uninsert_run (PangoLayoutLine *line)
+{
+ PangoLayoutRun *run;
+ PangoItem *item;
+
+ GSList *tmp_node = line->runs;
+
+ run = tmp_node->data;
+ item = run->item;
+
+ line->runs = tmp_node->next;
+ line->length -= item->length;
+
+ g_slist_free_1 (tmp_node);
+ free_run (run, (gpointer)FALSE);
+
+ return item;
+}
+
+static void
+ensure_tab_width (PangoLayout *layout)
+{
+ if (layout->tab_width == -1)
+ {
+ /* Find out how wide 8 spaces are in the context's default
+ * font. Utter performance killer. :-(
+ */
+ PangoGlyphString *glyphs = pango_glyph_string_new ();
+ PangoItem *item;
+ GList *items;
+ PangoAttribute *attr;
+ PangoAttrList *layout_attrs;
+ PangoAttrList *tmp_attrs;
+ PangoAttrIterator *iter;
+ PangoFontDescription *font_desc = pango_font_description_copy_static (pango_context_get_font_description (layout->context));
+ PangoLanguage *language;
+ int i;
+
+ layout_attrs = pango_layout_get_effective_attributes (layout);
+ iter = pango_attr_list_get_iterator (layout_attrs);
+ pango_attr_iterator_get_font (iter, font_desc, &language, NULL);
+
+ tmp_attrs = pango_attr_list_new ();
+
+ attr = pango_attr_font_desc_new (font_desc);
+ pango_font_description_free (font_desc);
+
+ attr->start_index = 0;
+ attr->end_index = 1;
+ pango_attr_list_insert_before (tmp_attrs, attr);
+
+ if (language)
+ {
+ attr = pango_attr_language_new (language);
+ attr->start_index = 0;
+ attr->end_index = 1;
+ pango_attr_list_insert_before (tmp_attrs, attr);
+ }
+
+ items = pango_itemize (layout->context, " ", 0, 1, tmp_attrs, NULL);
+
+ pango_attr_iterator_destroy (iter);
+ if (layout_attrs != layout->attrs)
+ pango_attr_list_unref (layout_attrs);
+ pango_attr_list_unref (tmp_attrs);
+
+ item = items->data;
+ pango_shape (" ", 8, &item->analysis, glyphs);
+
+ pango_item_free (item);
+ g_list_free (items);
+
+ layout->tab_width = 0;
+ for (i=0; i < glyphs->num_glyphs; i++)
+ layout->tab_width += glyphs->glyphs[i].geometry.width;
+
+ pango_glyph_string_free (glyphs);
+
+ /* We need to make sure the tab_width is > 0 so finding tab positions
+ * terminates. This check should be necessary only under extreme
+ * problems with the font.
+ */
+ if (layout->tab_width <= 0)
+ layout->tab_width = 50 * PANGO_SCALE; /* pretty much arbitrary */
+ }
+}
+
+/* For now we only need the tab position, we assume
+ * all tabs are left-aligned.
+ */
+static int
+get_tab_pos (PangoLayout *layout, int index)
+{
+ gint n_tabs;
+ gboolean in_pixels;
+
+ if (layout->tabs)
+ {
+ n_tabs = pango_tab_array_get_size (layout->tabs);
+ in_pixels = pango_tab_array_get_positions_in_pixels (layout->tabs);
+ }
+ else
+ {
+ n_tabs = 0;
+ in_pixels = FALSE;
+ }
+
+ if (index < n_tabs)
+ {
+ gint pos = 0;
+
+ pango_tab_array_get_tab (layout->tabs, index, NULL, &pos);
+
+ if (in_pixels)
+ return pos * PANGO_SCALE;
+ else
+ return pos;
+ }
+
+ if (n_tabs > 0)
+ {
+ /* Extrapolate tab position, repeating the last tab gap to
+ * infinity.
+ */
+ int last_pos = 0;
+ int next_to_last_pos = 0;
+ int tab_width;
+
+ pango_tab_array_get_tab (layout->tabs, n_tabs - 1, NULL, &last_pos);
+
+ if (n_tabs > 1)
+ pango_tab_array_get_tab (layout->tabs, n_tabs - 2, NULL, &next_to_last_pos);
+ else
+ next_to_last_pos = 0;
+
+ if (in_pixels)
+ {
+ next_to_last_pos *= PANGO_SCALE;
+ last_pos *= PANGO_SCALE;
+ }
+
+ if (last_pos > next_to_last_pos)
+ {
+ tab_width = last_pos - next_to_last_pos;
+ }
+ else
+ {
+ tab_width = layout->tab_width;
+ }
+
+ return last_pos + tab_width * (index - n_tabs + 1);
+ }
+ else
+ {
+ /* No tab array set, so use default tab width
+ */
+ return layout->tab_width * index;
+ }
+}
+
+static int
+line_width (PangoLayoutLine *line)
+{
+ GSList *l;
+ int i;
+ int width = 0;
+
+ /* Compute the width of the line currently - inefficient, but easier
+ * than keeping the current width of the line up to date everywhere
+ */
+ for (l = line->runs; l; l = l->next)
+ {
+ PangoLayoutRun *run = l->data;
+
+ for (i=0; i < run->glyphs->num_glyphs; i++)
+ width += run->glyphs->glyphs[i].geometry.width;
+ }
+
+ return width;
+}
+
+static void
+shape_tab (PangoLayoutLine *line,
+ PangoGlyphString *glyphs)
+{
+ int i, space_width;
+
+ int current_width = line_width (line);
+
+ pango_glyph_string_set_size (glyphs, 1);
+
+ glyphs->glyphs[0].glyph = PANGO_GLYPH_EMPTY;
+ glyphs->glyphs[0].geometry.x_offset = 0;
+ glyphs->glyphs[0].geometry.y_offset = 0;
+ glyphs->glyphs[0].attr.is_cluster_start = 1;
+
+ glyphs->log_clusters[0] = 0;
+
+ ensure_tab_width (line->layout);
+ space_width = line->layout->tab_width / 8;
+
+ for (i=0;;i++)
+ {
+ int tab_pos = get_tab_pos (line->layout, i);
+ if (tab_pos >= current_width + space_width)
+ {
+ glyphs->glyphs[0].geometry.width = tab_pos - current_width;
+ break;
+ }
+ }
+}
+
+static inline gboolean
+can_break_at (PangoLayout *layout,
+ gint offset,
+ gboolean always_wrap_char)
+{
+ PangoWrapMode wrap;
+ /* We probably should have a mode where we treat all white-space as
+ * of fungible width - appropriate for typography but not for
+ * editing.
+ */
+ wrap = layout->wrap;
+
+ if (wrap == PANGO_WRAP_WORD_CHAR)
+ wrap = always_wrap_char ? PANGO_WRAP_CHAR : PANGO_WRAP_WORD;
+
+ if (offset == layout->n_chars)
+ return TRUE;
+ else if (wrap == PANGO_WRAP_WORD)
+ return layout->log_attrs[offset].is_line_break;
+ else if (wrap == PANGO_WRAP_CHAR)
+ return layout->log_attrs[offset].is_char_break;
+ else
+ {
+ g_warning (G_STRLOC": broken PangoLayout");
+ return TRUE;
+ }
+}
+
+static inline gboolean
+can_break_in (PangoLayout *layout,
+ int start_offset,
+ int num_chars,
+ gboolean allow_break_at_start)
+{
+ int i;
+
+ for (i = allow_break_at_start ? 0 : 1; i < num_chars; i++)
+ if (can_break_at (layout, start_offset + i, FALSE))
+ return TRUE;
+
+ return FALSE;
+}
+
+static inline void
+distribute_letter_spacing (int letter_spacing,
+ int *space_left,
+ int *space_right)
+{
+ *space_left = letter_spacing / 2;
+ /* hinting */
+ if ((letter_spacing & (PANGO_SCALE - 1)) == 0)
+ {
+ *space_left = PANGO_UNITS_ROUND (*space_left);
+ }
+ *space_right = letter_spacing - *space_left;
+}
+
+typedef enum
+{
+ BREAK_NONE_FIT,
+ BREAK_SOME_FIT,
+ BREAK_ALL_FIT,
+ BREAK_EMPTY_FIT,
+ BREAK_LINE_SEPARATOR
+} BreakResult;
+
+struct _ParaBreakState
+{
+ PangoAttrList *attrs; /* Attributes being used for itemization */
+ GList *items; /* This paragraph turned into items */
+ PangoDirection base_dir; /* Current resolved base direction */
+ gboolean first_line; /* TRUE if this is the first line of the paragraph */
+ int line_start_index; /* Start index (byte offset) of line in layout->text */
+ int line_start_offset; /* Character offset of line in layout->text */
+
+ int remaining_width; /* Amount of space remaining on line; < 0 is infinite */
+
+ int start_offset; /* Character offset of first item in state->items in layout->text */
+ PangoGlyphString *glyphs; /* Glyphs for the first item in state->items */
+ ItemProperties properties; /* Properties for the first item in state->items */
+ PangoGlyphUnit *log_widths; /* Logical widths for first item in state->items.. */
+ int log_widths_offset; /* Offset into log_widths to the point corresponding
+ * to the remaining portion of the first item */
+};
+
+static PangoGlyphString *
+shape_run (PangoLayoutLine *line,
+ ParaBreakState *state,
+ PangoItem *item)
+{
+ PangoLayout *layout = line->layout;
+ PangoGlyphString *glyphs = pango_glyph_string_new ();
+
+ if (layout->text[item->offset] == '\t')
+ shape_tab (line, glyphs);
+ else
+ {
+ if (state->properties.shape_set)
+ imposed_shape (layout->text + item->offset, item->num_chars,
+ state->properties.shape_ink_rect, state->properties.shape_logical_rect,
+ glyphs);
+ else
+ pango_shape (layout->text + item->offset, item->length, &item->analysis, glyphs);
+
+ if (state->properties.letter_spacing)
+ {
+ PangoGlyphItem glyph_item;
+ int space_left, space_right;
+
+ glyph_item.item = item;
+ glyph_item.glyphs = glyphs;
+
+ pango_glyph_item_letter_space (&glyph_item,
+ layout->text,
+ layout->log_attrs + state->start_offset,
+ state->properties.letter_spacing);
+
+ distribute_letter_spacing (state->properties.letter_spacing, &space_left, &space_right);
+
+ glyphs->glyphs[0].geometry.width += space_left;
+ glyphs->glyphs[0].geometry.x_offset += space_left;
+ glyphs->glyphs[glyphs->num_glyphs - 1].geometry.width += space_right;
+ }
+ }
+
+ return glyphs;
+}
+
+static void
+insert_run (PangoLayoutLine *line,
+ ParaBreakState *state,
+ PangoItem *run_item,
+ gboolean last_run)
+{
+ PangoLayoutRun *run = g_slice_new (PangoLayoutRun);
+
+ run->item = run_item;
+
+ if (last_run && state->log_widths_offset == 0)
+ run->glyphs = state->glyphs;
+ else
+ run->glyphs = shape_run (line, state, run_item);
+
+ if (last_run)
+ {
+ if (state->log_widths_offset > 0)
+ pango_glyph_string_free (state->glyphs);
+ state->glyphs = NULL;
+ g_free (state->log_widths);
+ }
+
+ line->runs = g_slist_prepend (line->runs, run);
+ line->length += run_item->length;
+}
+
+#if 0
+# define DEBUG debug
+void
+debug (const char *where, PangoLayoutLine *line, ParaBreakState *state)
+{
+ int line_width = 0;
+
+ GSList *tmp_list;
+
+ tmp_list = line->runs;
+ while (tmp_list)
+ {
+ PangoLayoutRun *run = tmp_list->data;
+
+ line_width += pango_glyph_string_get_width (run->glyphs);
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_message ("rem %d + line %d = %d %s",
+ state->remaining_width,
+ line_width,
+ state->remaining_width + line_width,
+ where);
+}
+#else
+# define DEBUG(where, line, state) do { } while (0)
+#endif
+
+/* Tries to insert as much as possible of the item at the head of
+ * state->items onto @line. Five results are possible:
+ *
+ * %BREAK_NONE_FIT: Couldn't fit anything.
+ * %BREAK_SOME_FIT: The item was broken in the middle.
+ * %BREAK_ALL_FIT: Everything fit.
+ * %BREAK_EMPTY_FIT: Nothing fit, but that was ok, as we can break at the first char.
+ * %BREAK_LINE_SEPARATOR: Item begins with a line separator.
+ *
+ * If @force_fit is %TRUE, then %BREAK_NONE_FIT will never
+ * be returned, a run will be added even if inserting the minimum amount
+ * will cause the line to overflow. This is used at the start of a line
+ * and until we've found at least some place to break.
+ *
+ * If @no_break_at_end is %TRUE, then %BREAK_ALL_FIT will never be
+ * returned even everything fits; the run will be broken earlier,
+ * or %BREAK_NONE_FIT returned. This is used when the end of the
+ * run is not a break position.
+ */
+static BreakResult
+process_item (PangoLayout *layout,
+ PangoLayoutLine *line,
+ ParaBreakState *state,
+ gboolean force_fit,
+ gboolean no_break_at_end)
+{
+ PangoItem *item = state->items->data;
+ gboolean shape_set = FALSE;
+ int width;
+ int length;
+ int i;
+ gboolean processing_new_item = FALSE;
+
+ /* Only one character has type G_UNICODE_LINE_SEPARATOR in Unicode 5.0;
+ * update this if that changes. */
+#define LINE_SEPARATOR 0x2028
+
+ if (!state->glyphs)
+ {
+ pango_layout_get_item_properties (item, &state->properties);
+ state->glyphs = shape_run (line, state, item);
+
+ state->log_widths = NULL;
+ state->log_widths_offset = 0;
+
+ processing_new_item = TRUE;
+ }
+
+ if (!layout->single_paragraph &&
+ g_utf8_get_char (layout->text + item->offset) == LINE_SEPARATOR)
+ {
+ insert_run (line, state, item, TRUE);
+ state->log_widths_offset += item->num_chars;
+ return BREAK_LINE_SEPARATOR;
+ }
+
+ if (state->remaining_width < 0 && !no_break_at_end) /* Wrapping off */
+ {
+ insert_run (line, state, item, TRUE);
+
+ return BREAK_ALL_FIT;
+ }
+
+ width = 0;
+ if (processing_new_item)
+ {
+ width = pango_glyph_string_get_width (state->glyphs);
+ }
+ else
+ {
+ for (i = 0; i < item->num_chars; i++)
+ width += state->log_widths[state->log_widths_offset + i];
+ }
+
+ if ((width <= state->remaining_width || (item->num_chars == 1 && !line->runs)) &&
+ !no_break_at_end)
+ {
+ state->remaining_width -= width;
+ state->remaining_width = MAX (state->remaining_width, 0);
+ insert_run (line, state, item, TRUE);
+
+ return BREAK_ALL_FIT;
+ }
+ else
+ {
+ int num_chars = item->num_chars;
+ int break_num_chars = num_chars;
+ int break_width = width;
+ int orig_width = width;
+ gboolean retrying_with_char_breaks = FALSE;
+
+ if (processing_new_item)
+ {
+ state->log_widths = g_new (PangoGlyphUnit, item->num_chars);
+ pango_glyph_string_get_logical_widths (state->glyphs,
+ layout->text + item->offset, item->length, item->analysis.level,
+ state->log_widths);
+ }
+
+ retry_break:
+
+ /* See how much of the item we can stuff in the line
+ */
+ width = 0;
+ for (num_chars = 0; num_chars < item->num_chars; num_chars++)
+ {
+ if (width > state->remaining_width && break_num_chars < item->num_chars)
+ break;
+
+ /* If there are no previous runs we have to take care to grab at least one char. */
+ if (can_break_at (layout, state->start_offset + num_chars, retrying_with_char_breaks) &&
+ (num_chars > 0 || line->runs))
+ {
+ break_num_chars = num_chars;
+ break_width = width;
+ }
+
+ width += state->log_widths[state->log_widths_offset + num_chars];
+ }
+
+ if (layout->wrap == PANGO_WRAP_WORD_CHAR && force_fit && break_width > state->remaining_width && !retrying_with_char_breaks)
+ {
+ retrying_with_char_breaks = TRUE;
+ num_chars = item->num_chars;
+ width = orig_width;
+ break_num_chars = num_chars;
+ break_width = width;
+ goto retry_break;
+ }
+
+ if (force_fit || break_width <= state->remaining_width) /* Successfully broke the item */
+ {
+ if (state->remaining_width >= 0)
+ {
+ state->remaining_width -= break_width;
+ state->remaining_width = MAX (state->remaining_width, 0);
+ }
+
+ if (break_num_chars == item->num_chars)
+ {
+ insert_run (line, state, item, TRUE);
+
+ return BREAK_ALL_FIT;
+ }
+ else if (break_num_chars == 0)
+ {
+ return BREAK_EMPTY_FIT;
+ }
+ else
+ {
+ PangoItem *new_item;
+ int new_break_width;
+
+ length = g_utf8_offset_to_pointer (layout->text + item->offset, break_num_chars) - (layout->text + item->offset);
+
+ new_item = pango_item_split (item, length, break_num_chars);
+
+ /* reshaping may slightly change the item width. update
+ * remaining_width if we are justifying */
+
+ state->remaining_width += break_width;
+
+ insert_run (line, state, new_item, FALSE);
+
+ if (layout->justify)
+ break_width = pango_glyph_string_get_width (((PangoGlyphItem *)(line->runs->data))->glyphs);
+
+ state->remaining_width -= break_width;
+
+ state->log_widths_offset += break_num_chars;
+
+ /* Shaped items should never be broken */
+ g_assert (!shape_set);
+
+ return BREAK_SOME_FIT;
+ }
+ }
+ else
+ {
+ pango_glyph_string_free (state->glyphs);
+ state->glyphs = NULL;
+ g_free (state->log_widths);
+
+ return BREAK_NONE_FIT;
+ }
+ }
+}
+
+/* The resolved direction for the line is always one
+ * of LTR/RTL; not a week or neutral directions
+ */
+static void
+line_set_resolved_dir (PangoLayoutLine *line,
+ PangoDirection direction)
+{
+ switch (direction)
+ {
+ default:
+ case PANGO_DIRECTION_LTR:
+ case PANGO_DIRECTION_TTB_RTL:
+ case PANGO_DIRECTION_WEAK_LTR:
+ case PANGO_DIRECTION_NEUTRAL:
+ line->resolved_dir = PANGO_DIRECTION_LTR;
+ break;
+ case PANGO_DIRECTION_RTL:
+ case PANGO_DIRECTION_WEAK_RTL:
+ case PANGO_DIRECTION_TTB_LTR:
+ line->resolved_dir = PANGO_DIRECTION_RTL;
+ break;
+ }
+
+ /* The direction vs. gravity dance:
+ * - If gravity is SOUTH, leave direction untouched.
+ * - If gravity is NORTH, switch direction.
+ * - If gravity is EAST, set to LTR, as
+ * it's a clockwise-rotated layout, so the rotated
+ * top is unrotated left.
+ * - If gravity is WEST, set to RTL, as
+ * it's a counter-clockwise-rotated layout, so the rotated
+ * top is unrotated right.
+ *
+ * A similar dance is performed in pango-context.c:
+ * itemize_state_add_character(). Keep in synch.
+ */
+ switch (pango_context_get_gravity (line->layout->context))
+ {
+ default:
+ case PANGO_GRAVITY_AUTO:
+ case PANGO_GRAVITY_SOUTH:
+ break;
+ case PANGO_GRAVITY_NORTH:
+ line->resolved_dir = PANGO_DIRECTION_LTR
+ + PANGO_DIRECTION_RTL
+ - line->resolved_dir;
+ break;
+ case PANGO_GRAVITY_EAST:
+ /* This is in fact why deprecated TTB_RTL is LTR */
+ line->resolved_dir = PANGO_DIRECTION_LTR;
+ break;
+ case PANGO_GRAVITY_WEST:
+ /* This is in fact why deprecated TTB_LTR is RTL */
+ line->resolved_dir = PANGO_DIRECTION_RTL;
+ break;
+ }
+}
+
+static void
+process_line (PangoLayout *layout,
+ ParaBreakState *state)
+{
+ PangoLayoutLine *line;
+
+ gboolean have_break = FALSE; /* If we've seen a possible break yet */
+ int break_remaining_width = 0; /* Remaining width before adding run with break */
+ int break_start_offset = 0; /* Start width before adding run with break */
+ GSList *break_link = NULL; /* Link holding run before break */
+ gboolean wrapped = FALSE; /* If we had to wrap the line */
+
+ line = pango_layout_line_new (layout);
+ line->start_index = state->line_start_index;
+ line->is_paragraph_start = state->first_line;
+ line_set_resolved_dir (line, state->base_dir);
+
+ if (layout->ellipsize != PANGO_ELLIPSIZE_NONE)
+ state->remaining_width = -1;
+ else if (state->first_line)
+ state->remaining_width = (layout->indent >= 0) ? layout->width - layout->indent : layout->width;
+ else
+ state->remaining_width = (layout->indent >= 0) ? layout->width : layout->width + layout->indent;
+ DEBUG ("starting to fill line", line, state);
+
+ while (state->items)
+ {
+ PangoItem *item = state->items->data;
+ BreakResult result;
+ int old_num_chars;
+ int old_remaining_width;
+ gboolean first_item_in_line;
+
+ old_num_chars = item->num_chars;
+ old_remaining_width = state->remaining_width;
+ first_item_in_line = line->runs != NULL;
+
+ result = process_item (layout, line, state, !have_break, FALSE);
+
+ switch (result)
+ {
+ case BREAK_ALL_FIT:
+ if (can_break_in (layout, state->start_offset, old_num_chars, first_item_in_line))
+ {
+ have_break = TRUE;
+ break_remaining_width = old_remaining_width;
+ break_start_offset = state->start_offset;
+ break_link = line->runs->next;
+ }
+
+ state->items = g_list_delete_link (state->items, state->items);
+ state->start_offset += old_num_chars;
+
+ break;
+
+ case BREAK_EMPTY_FIT:
+ wrapped = TRUE;
+ goto done;
+
+ case BREAK_SOME_FIT:
+ state->start_offset += old_num_chars - item->num_chars;
+ wrapped = TRUE;
+ goto done;
+
+ case BREAK_NONE_FIT:
+ /* Back up over unused runs to run where there is a break */
+ while (line->runs && line->runs != break_link)
+ state->items = g_list_prepend (state->items, uninsert_run (line));
+
+ state->start_offset = break_start_offset;
+ state->remaining_width = break_remaining_width;
+
+ /* Reshape run to break */
+ item = state->items->data;
+
+ old_num_chars = item->num_chars;
+ result = process_item (layout, line, state, TRUE, TRUE);
+ g_assert (result == BREAK_SOME_FIT || result == BREAK_EMPTY_FIT);
+
+ state->start_offset += old_num_chars - item->num_chars;
+
+ wrapped = TRUE;
+ goto done;
+
+ case BREAK_LINE_SEPARATOR:
+ state->items = g_list_delete_link (state->items, state->items);
+ state->start_offset += old_num_chars;
+ goto done;
+ }
+ }
+
+ done:
+ layout->is_wrapped = layout->is_wrapped || wrapped;
+ pango_layout_line_postprocess (line, state, wrapped);
+ layout->lines = g_slist_prepend (layout->lines, line);
+ state->first_line = FALSE;
+ state->line_start_index += line->length;
+ state->line_start_offset = state->start_offset;
+}
+
+static void
+get_items_log_attrs (const char *text,
+ GList *items,
+ PangoLogAttr *log_attrs,
+ int para_delimiter_len)
+{
+ int offset = 0;
+ int index = 0;
+
+ while (items)
+ {
+ PangoItem tmp_item = *(PangoItem *)items->data;
+
+ /* Accumulate all the consecutive items that match in language
+ * characteristics, ignoring font, style tags, etc.
+ */
+ while (items->next)
+ {
+ PangoItem *next_item = items->next->data;
+
+ /* FIXME: Handle language tags */
+ if (next_item->analysis.lang_engine != tmp_item.analysis.lang_engine)
+ break;
+ else
+ {
+ tmp_item.length += next_item->length;
+ tmp_item.num_chars += next_item->num_chars;
+ }
+
+ items = items->next;
+ }
+
+ /* Break the paragraph delimiters with the last item */
+ if (items->next == NULL)
+ {
+ tmp_item.num_chars += g_utf8_strlen (text + index + tmp_item.length, para_delimiter_len);
+ tmp_item.length += para_delimiter_len;
+ }
+
+ /* XXX This is wrong. we should call pango_default_break on the entire
+ * layout text and then tailor_break on each lang_engine change, like
+ * pango_get_log_attrs does.
+ */
+ pango_break (text + index, tmp_item.length, &tmp_item.analysis,
+ log_attrs + offset, tmp_item.num_chars + 1);
+
+ offset += tmp_item.num_chars;
+ index += tmp_item.length;
+
+ items = items->next;
+ }
+}
+
+static PangoAttrList *
+pango_layout_get_effective_attributes (PangoLayout *layout)
+{
+ PangoAttrList *attrs;
+
+ if (layout->attrs)
+ attrs = pango_attr_list_copy (layout->attrs);
+ else
+ attrs = pango_attr_list_new ();
+
+ if (layout->font_desc)
+ {
+ PangoAttribute *attr = pango_attr_font_desc_new (layout->font_desc);
+ attr->start_index = 0;
+ attr->end_index = layout->length;
+
+ pango_attr_list_insert_before (attrs, attr);
+ }
+
+ return attrs;
+}
+
+static gboolean
+no_shape_filter_func (PangoAttribute *attribute,
+ gpointer data)
+{
+ static const PangoAttrType no_shape_types[] = {
+ PANGO_ATTR_FOREGROUND,
+ PANGO_ATTR_BACKGROUND,
+ PANGO_ATTR_UNDERLINE,
+ PANGO_ATTR_STRIKETHROUGH,
+ PANGO_ATTR_RISE
+ };
+
+ int i;
+
+ for (i = 0; i < (int)G_N_ELEMENTS (no_shape_types); i++)
+ if (attribute->klass->type == no_shape_types[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+static PangoAttrList *
+filter_no_shape_attributes (PangoAttrList *attrs)
+{
+ return pango_attr_list_filter (attrs,
+ no_shape_filter_func,
+ NULL);
+}
+
+static void
+apply_no_shape_attributes (PangoLayout *layout,
+ PangoAttrList *no_shape_attrs)
+{
+ GSList *line_list;
+
+ for (line_list = layout->lines; line_list; line_list = line_list->next)
+ {
+ PangoLayoutLine *line = line_list->data;
+ GSList *old_runs = g_slist_reverse (line->runs);
+ GSList *run_list;
+
+ line->runs = NULL;
+ for (run_list = old_runs; run_list; run_list = run_list->next)
+ {
+ PangoGlyphItem *glyph_item = run_list->data;
+ GSList *new_runs;
+
+ new_runs = pango_glyph_item_apply_attrs (glyph_item,
+ layout->text,
+ no_shape_attrs);
+
+ line->runs = g_slist_concat (new_runs, line->runs);
+ }
+
+ g_slist_free (old_runs);
+ }
+}
+
+static void
+pango_layout_check_lines (PangoLayout *layout)
+{
+ const char *start;
+ gboolean done = FALSE;
+ int start_offset;
+ PangoAttrList *attrs;
+ PangoAttrList *no_shape_attrs;
+ PangoAttrIterator *iter;
+ PangoDirection prev_base_dir = PANGO_DIRECTION_NEUTRAL, base_dir = PANGO_DIRECTION_NEUTRAL;
+
+ if (layout->lines)
+ return;
+
+ g_assert (!layout->log_attrs);
+
+ /* For simplicity, we make sure at this point that layout->text
+ * is non-NULL even if it is zero length
+ */
+ if (!layout->text)
+ pango_layout_set_text (layout, NULL, 0);
+
+ attrs = pango_layout_get_effective_attributes (layout);
+ no_shape_attrs = filter_no_shape_attributes (attrs);
+ iter = pango_attr_list_get_iterator (attrs);
+
+ layout->log_attrs = g_new (PangoLogAttr, layout->n_chars + 1);
+
+ start_offset = 0;
+ start = layout->text;
+
+ /* Find the first strong direction of the text */
+ if (layout->auto_dir)
+ {
+ prev_base_dir = pango_find_base_dir (layout->text, layout->length);
+ if (prev_base_dir == PANGO_DIRECTION_NEUTRAL)
+ prev_base_dir = pango_context_get_base_dir (layout->context);
+ }
+ else
+ base_dir = pango_context_get_base_dir (layout->context);
+
+ do
+ {
+ int delim_len;
+ const char *end;
+ int delimiter_index, next_para_index;
+ ParaBreakState state;
+
+ if (layout->single_paragraph)
+ {
+ delimiter_index = layout->length;
+ next_para_index = layout->length;
+ }
+ else
+ {
+ pango_find_paragraph_boundary (start,
+ (layout->text + layout->length) - start,
+ &delimiter_index,
+ &next_para_index);
+ }
+
+ g_assert (next_para_index >= delimiter_index);
+
+ if (layout->auto_dir)
+ {
+ base_dir = pango_find_base_dir (start, delimiter_index);
+
+ /* Propagate the base direction for neutral paragraphs */
+ if (base_dir == PANGO_DIRECTION_NEUTRAL)
+ base_dir = prev_base_dir;
+ else
+ prev_base_dir = base_dir;
+ }
+
+ end = start + delimiter_index;
+
+ delim_len = next_para_index - delimiter_index;
+
+ if (end == (layout->text + layout->length))
+ done = TRUE;
+
+ g_assert (end <= (layout->text + layout->length));
+ g_assert (start <= (layout->text + layout->length));
+ g_assert (delim_len < 4); /* PS is 3 bytes */
+ g_assert (delim_len >= 0);
+
+ state.attrs = attrs;
+ state.items = pango_itemize_with_base_dir (layout->context,
+ base_dir,
+ layout->text,
+ start - layout->text,
+ end - start,
+ attrs,
+ iter);
+
+ get_items_log_attrs (start, state.items,
+ layout->log_attrs + start_offset,
+ delim_len);
+
+ if (state.items)
+ {
+ state.first_line = TRUE;
+ state.base_dir = base_dir;
+ state.start_offset = start_offset;
+ state.line_start_offset = start_offset;
+ state.line_start_index = start - layout->text;
+
+ state.glyphs = NULL;
+ state.log_widths = NULL;
+
+ while (state.items)
+ process_line (layout, &state);
+ }
+ else
+ {
+ PangoLayoutLine *empty_line;
+
+ empty_line = pango_layout_line_new (layout);
+ empty_line->start_index = start - layout->text;
+ empty_line->is_paragraph_start = TRUE;
+ line_set_resolved_dir (empty_line, base_dir);
+
+ layout->lines = g_slist_prepend (layout->lines,
+ empty_line);
+ }
+
+ if (!done)
+ start_offset += g_utf8_strlen (start, (end - start) + delim_len);
+
+ start = end + delim_len;
+ }
+ while (!done);
+
+ pango_attr_iterator_destroy (iter);
+ pango_attr_list_unref (attrs);
+
+ if (no_shape_attrs)
+ {
+ apply_no_shape_attributes (layout, no_shape_attrs);
+ pango_attr_list_unref (no_shape_attrs);
+ }
+
+ layout->lines = g_slist_reverse (layout->lines);
+}
+
+/**
+ * pango_layout_line_ref:
+ * @line: a #PangoLayoutLine
+ *
+ * Increase the reference count of a #PangoLayoutLine by one.
+ *
+ * Return value: the line passed in.
+ *
+ * Since: 1.10
+ **/
+PangoLayoutLine *
+pango_layout_line_ref (PangoLayoutLine *line)
+{
+ PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line;
+
+ g_return_val_if_fail (line != NULL, NULL);
+
+ private->ref_count++;
+
+ return line;
+}
+
+/**
+ * pango_layout_line_unref:
+ * @line: a #PangoLayoutLine
+ *
+ * Decrease the reference count of a #PangoLayoutLine by one.
+ * If the result is zero, the line and all associated memory
+ * will be freed.
+ **/
+void
+pango_layout_line_unref (PangoLayoutLine *line)
+{
+ PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line;
+
+ g_return_if_fail (line != NULL);
+ g_return_if_fail (private->ref_count > 0);
+
+ private->ref_count--;
+ if (private->ref_count == 0)
+ {
+ g_slist_foreach (line->runs, (GFunc)free_run, GINT_TO_POINTER (1));
+ g_slist_free (line->runs);
+ g_slice_free (PangoLayoutLinePrivate, private);
+ }
+}
+
+GType
+pango_layout_line_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoLayoutLine"),
+ (GBoxedCopyFunc) pango_layout_line_ref,
+ (GBoxedFreeFunc) pango_layout_line_unref);
+ return our_type;
+}
+
+/**
+ * pango_layout_line_x_to_index:
+ * @line: a #PangoLayoutLine
+ * @x_pos: the X offset (in #PangoGlyphUnit)
+ * from the left edge of the line.
+ * @index_: location to store calculated byte index for
+ * the grapheme in which the user clicked.
+ * @trailing: location to store a integer indicating where
+ * in the grapheme the user clicked. It will either
+ * be zero, or the number of characters in the
+ * grapheme. 0 represents the trailing edge of the grapheme.
+ *
+ * Converts from x offset to the byte index of the corresponding
+ * character within the text of the layout. If @x_pos is outside the line,
+ * @index_ and @trailing will point to the very first or very last position
+ * in the line. This determination is based on the resolved direction
+ * of the paragraph; for example, if the resolved direction is
+ * right-to-left, then an X position to the right of the line (after it)
+ * results in 0 being stored in @index_ and @trailing. An X position to the
+ * left of the line results in @index_ pointing to the (logical) last
+ * grapheme in the line and @trailing being set to the number of characters
+ * in that grapheme. The reverse is true for a left-to-right line.
+ *
+ * Return value: %FALSE if @x_pos was outside the line, %TRUE if inside
+ **/
+gboolean
+pango_layout_line_x_to_index (PangoLayoutLine *line,
+ int x_pos,
+ int *index,
+ int *trailing)
+{
+ GSList *tmp_list;
+ gint start_pos = 0;
+ gint first_index = 0; /* line->start_index */
+ gint first_offset;
+ gint last_index; /* start of last grapheme in line */
+ gint last_offset;
+ gint end_index; /* end iterator for line */
+ gint end_offset; /* end iterator for line */
+ PangoLayout *layout;
+ gint last_trailing;
+ gboolean suppress_last_trailing;
+
+ g_return_val_if_fail (line != NULL, FALSE);
+ g_return_val_if_fail (LINE_IS_VALID (line), FALSE);
+
+ if (!LINE_IS_VALID (line))
+ return FALSE;
+
+ layout = line->layout;
+
+ /* Find the last index in the line
+ */
+ first_index = line->start_index;
+
+ if (line->length == 0)
+ {
+ if (index)
+ *index = first_index;
+ if (trailing)
+ *trailing = 0;
+
+ return FALSE;
+ }
+
+ g_assert (line->length > 0);
+
+ first_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index);
+
+ end_index = first_index + line->length;
+ end_offset = first_offset + g_utf8_pointer_to_offset (layout->text + first_index, layout->text + end_index);
+
+ last_index = end_index;
+ last_offset = end_offset;
+ last_trailing = 0;
+ do
+ {
+ last_index = g_utf8_prev_char (layout->text + last_index) - layout->text;
+ last_offset--;
+ last_trailing++;
+ }
+ while (last_offset > first_offset && !layout->log_attrs[last_offset].is_cursor_position);
+
+ /* This is a HACK. If a program only keeps track if cursor (etc)
+ * indices and not the trailing flag, then the trailing index of the
+ * last character on a wrapped line is identical to the leading
+ * index of the next line. So, we fake it and set the trailing flag
+ * to zero.
+ *
+ * That is, if the text is "now is the time", and is broken between
+ * 'now' and 'is'
+ *
+ * Then when the cursor is actually at:
+ *
+ * n|o|w| |i|s|
+ * ^
+ * we lie and say it is at:
+ *
+ * n|o|w| |i|s|
+ * ^
+ *
+ * So the cursor won't appear on the next line before 'the'.
+ *
+ * Actually, any program keeping cursor
+ * positions with wrapped lines should distinguish leading and
+ * trailing cursors.
+ */
+ tmp_list = layout->lines;
+ while (tmp_list->data != line)
+ tmp_list = tmp_list->next;
+
+ if (tmp_list->next &&
+ line->start_index + line->length == ((PangoLayoutLine *)tmp_list->next->data)->start_index)
+ suppress_last_trailing = TRUE;
+ else
+ suppress_last_trailing = FALSE;
+
+ if (x_pos < 0)
+ {
+ /* pick the leftmost char */
+ if (index)
+ *index = (line->resolved_dir == PANGO_DIRECTION_LTR) ? first_index : last_index;
+ /* and its leftmost edge */
+ if (trailing)
+ *trailing = (line->resolved_dir == PANGO_DIRECTION_LTR || suppress_last_trailing) ? 0 : last_trailing;
+
+ return FALSE;
+ }
+
+ tmp_list = line->runs;
+ while (tmp_list)
+ {
+ PangoLayoutRun *run = tmp_list->data;
+ ItemProperties properties;
+ int logical_width;
+
+ pango_layout_get_item_properties (run->item, &properties);
+
+ if (properties.shape_set)
+ logical_width = properties.shape_logical_rect->width;
+ else
+ logical_width = pango_glyph_string_get_width (run->glyphs);
+
+ if (x_pos >= start_pos && x_pos < start_pos + logical_width)
+ {
+ int offset;
+ gboolean char_trailing;
+ int grapheme_start_index;
+ int grapheme_start_offset;
+ int grapheme_end_offset;
+ int pos;
+ int char_index;
+
+ char_index = run->item->offset;
+
+ if (properties.shape_set)
+ {
+ char_trailing = FALSE;
+ }
+ else
+ {
+ pango_glyph_string_x_to_index (run->glyphs,
+ layout->text + run->item->offset, run->item->length,
+ &run->item->analysis,
+ x_pos - start_pos,
+ &pos, &char_trailing);
+
+ char_index += pos;
+ }
+
+ /* Convert from characters to graphemes */
+
+ offset = g_utf8_pointer_to_offset (layout->text, layout->text + char_index);
+
+ grapheme_start_offset = offset;
+ grapheme_start_index = char_index;
+ while (grapheme_start_offset > first_offset &&
+ !layout->log_attrs[grapheme_start_offset].is_cursor_position)
+ {
+ grapheme_start_index = g_utf8_prev_char (layout->text + grapheme_start_index) - layout->text;
+ grapheme_start_offset--;
+ }
+
+ grapheme_end_offset = offset;
+ do
+ {
+ grapheme_end_offset++;
+ }
+ while (grapheme_end_offset < end_offset &&
+ !layout->log_attrs[grapheme_end_offset].is_cursor_position);
+
+ if (index)
+ *index = grapheme_start_index;
+
+ if (trailing)
+ {
+ if ((grapheme_end_offset == end_offset && suppress_last_trailing) ||
+ offset + char_trailing <= (grapheme_start_offset + grapheme_end_offset) / 2)
+ *trailing = 0;
+ else
+ *trailing = grapheme_end_offset - grapheme_start_offset;
+ }
+
+ return TRUE;
+ }
+
+ start_pos += logical_width;
+ tmp_list = tmp_list->next;
+ }
+
+ /* pick the rightmost char */
+ if (index)
+ *index = (line->resolved_dir == PANGO_DIRECTION_LTR) ? last_index : first_index;
+
+ /* and its rightmost edge */
+ if (trailing)
+ *trailing = (line->resolved_dir == PANGO_DIRECTION_LTR && !suppress_last_trailing) ? last_trailing : 0;
+
+ return FALSE;
+}
+
+/**
+ * pango_layout_line_get_x_ranges:
+ * @line: a #PangoLayoutLine
+ * @start_index: Start byte index of the logical range. If this value
+ * is less than the start index for the line, then
+ * the first range will extend all the way to the leading
+ * edge of the layout. Otherwise it will start at the
+ * leading edge of the first character.
+ * @end_index: Ending byte index of the logical range. If this value
+ * is greater than the end index for the line, then
+ * the last range will extend all the way to the trailing
+ * edge of the layout. Otherwise, it will end at the
+ * trailing edge of the last character.
+ * @ranges: location to store a pointer to an array of ranges.
+ * The array will be of length <literal>2*n_ranges</literal>,
+ * with each range starting at <literal>(*ranges)[2*n]</literal>
+ * and of width <literal>(*ranges)[2*n + 1] - (*ranges)[2*n]</literal>.
+ * This array must be freed with g_free(). The coordinates are relative
+ * to the layout and are in #PangoGlyphUnit.
+ * @n_ranges: The number of ranges stored in @ranges.
+ *
+ * Gets a list of visual ranges corresponding to a given logical range.
+ * This list is not necessarily minimal - there may be consecutive
+ * ranges which are adjacent. The ranges will be sorted from left to
+ * right. The ranges are with respect to the left edge of the entire
+ * layout, not with respect to the line.
+ **/
+void
+pango_layout_line_get_x_ranges (PangoLayoutLine *line,
+ int start_index,
+ int end_index,
+ int **ranges,
+ int *n_ranges)
+{
+ PangoRectangle logical_rect;
+ gint line_start_index = 0;
+ GSList *tmp_list;
+ int range_count = 0;
+ int accumulated_width = 0;
+ int x_offset;
+ int width;
+ PangoAlignment alignment;
+
+ g_return_if_fail (line != NULL);
+ g_return_if_fail (line->layout != NULL);
+ g_return_if_fail (start_index <= end_index);
+
+ alignment = get_alignment (line->layout, line);
+
+ width = line->layout->width;
+ if (width == -1 && alignment != PANGO_ALIGN_LEFT)
+ {
+ pango_layout_get_extents (line->layout, NULL, &logical_rect);
+ width = logical_rect.width;
+ }
+
+ /* FIXME: The computations here could be optimized, by moving the
+ * computations of the x_offset after we go through and figure
+ * out where each range is.
+ */
+ pango_layout_line_get_extents (line, NULL, &logical_rect);
+
+ /* FIXME it seems to me that width can be -1 here? */
+ get_x_offset (line->layout, line, width, logical_rect.width, &x_offset);
+
+ line_start_index = line->start_index;
+
+ /* Allocate the maximum possible size */
+ if (ranges)
+ *ranges = g_new (int, 2 * (2 + g_slist_length (line->runs)));
+
+ if (x_offset > 0 &&
+ ((line->resolved_dir == PANGO_DIRECTION_LTR && start_index < line_start_index) ||
+ (line->resolved_dir == PANGO_DIRECTION_RTL && end_index > line_start_index + line->length)))
+ {
+ if (ranges)
+ {
+ (*ranges)[2*range_count] = 0;
+ (*ranges)[2*range_count + 1] = x_offset;
+ }
+
+ range_count ++;
+ }
+
+ tmp_list = line->runs;
+ while (tmp_list)
+ {
+ PangoLayoutRun *run = (PangoLayoutRun *)tmp_list->data;
+
+ if ((start_index < run->item->offset + run->item->length &&
+ end_index > run->item->offset))
+ {
+ if (ranges)
+ {
+ int run_start_index = MAX (start_index, run->item->offset);
+ int run_end_index = MIN (end_index, run->item->offset + run->item->length);
+ int run_start_x, run_end_x;
+
+ g_assert (run_end_index > 0);
+
+ /* Back the end_index off one since we want to find the trailing edge of the preceding character */
+
+ run_end_index = g_utf8_prev_char (line->layout->text + run_end_index) - line->layout->text;
+
+ pango_glyph_string_index_to_x (run->glyphs,
+ line->layout->text + run->item->offset,
+ run->item->length,
+ &run->item->analysis,
+ run_start_index - run->item->offset, FALSE,
+ &run_start_x);
+ pango_glyph_string_index_to_x (run->glyphs,
+ line->layout->text + run->item->offset,
+ run->item->length,
+ &run->item->analysis,
+ run_end_index - run->item->offset, TRUE,
+ &run_end_x);
+
+ (*ranges)[2*range_count] = x_offset + accumulated_width + MIN (run_start_x, run_end_x);
+ (*ranges)[2*range_count + 1] = x_offset + accumulated_width + MAX (run_start_x, run_end_x);
+ }
+
+ range_count++;
+ }
+
+ if (tmp_list->next)
+ accumulated_width += pango_glyph_string_get_width (run->glyphs);
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (x_offset + logical_rect.width < line->layout->width &&
+ ((line->resolved_dir == PANGO_DIRECTION_LTR && end_index > line_start_index + line->length) ||
+ (line->resolved_dir == PANGO_DIRECTION_RTL && start_index < line_start_index)))
+ {
+ if (ranges)
+ {
+ (*ranges)[2*range_count] = x_offset + logical_rect.width;
+ (*ranges)[2*range_count + 1] = line->layout->width;
+ }
+
+ range_count ++;
+ }
+
+ if (n_ranges)
+ *n_ranges = range_count;
+}
+
+static void
+pango_layout_line_get_empty_extents (PangoLayoutLine *line,
+ PangoRectangle *logical_rect)
+{
+ if (logical_rect)
+ {
+ char *line_start;
+ int index;
+ PangoLayout *layout = line->layout;
+ PangoFont *font;
+ PangoFontDescription *font_desc = NULL;
+ gboolean free_font_desc = FALSE;
+
+ pango_layout_line_get_range (line, &line_start, NULL);
+ index = line_start - layout->text;
+
+ /* Find the font description for this line
+ */
+ if (layout->attrs)
+ {
+ PangoAttrIterator *iter = pango_attr_list_get_iterator (layout->attrs);
+ int start, end;
+
+ do
+ {
+ pango_attr_iterator_range (iter, &start, &end);
+
+ if (start <= index && index < end)
+ {
+ PangoFontDescription *base_font_desc;
+
+ if (layout->font_desc)
+ base_font_desc = layout->font_desc;
+ else
+ base_font_desc = pango_context_get_font_description (layout->context);
+
+ font_desc = pango_font_description_copy_static (base_font_desc);
+ free_font_desc = TRUE;
+
+ pango_attr_iterator_get_font (iter,
+ font_desc,
+ NULL,
+ NULL);
+
+ break;
+ }
+
+ }
+ while (pango_attr_iterator_next (iter));
+
+ pango_attr_iterator_destroy (iter);
+ }
+ else
+ {
+ if (layout->font_desc)
+ font_desc = layout->font_desc;
+ else
+ font_desc = pango_context_get_font_description (layout->context);
+ }
+
+ font = pango_context_load_font (layout->context, font_desc);
+ if (font)
+ {
+ PangoFontMetrics *metrics;
+
+ metrics = pango_font_get_metrics (font,
+ pango_context_get_language (layout->context));
+
+ if (metrics)
+ {
+ logical_rect->y = - pango_font_metrics_get_ascent (metrics);
+ logical_rect->height = - logical_rect->y + pango_font_metrics_get_descent (metrics);
+
+ pango_font_metrics_unref (metrics);
+ }
+ else
+ {
+ logical_rect->y = 0;
+ logical_rect->height = 0;
+ }
+ g_object_unref (font);
+ }
+ else
+ {
+ logical_rect->y = 0;
+ logical_rect->height = 0;
+ }
+
+ if (free_font_desc)
+ pango_font_description_free (font_desc);
+
+ logical_rect->x = 0;
+ logical_rect->width = 0;
+ }
+}
+
+static int
+pango_layout_run_get_width (PangoLayoutRun *run)
+{
+ ItemProperties properties;
+
+ pango_layout_get_item_properties (run->item, &properties);
+
+ if (properties.shape_set) {
+ PangoRectangle run_logical;
+
+ imposed_extents (run->item->num_chars,
+ properties.shape_ink_rect,
+ properties.shape_logical_rect,
+ NULL, &run_logical);
+
+ return run_logical.width;
+ } else
+ return pango_glyph_string_get_width (run->glyphs);
+}
+
+static void
+pango_layout_run_get_extents (PangoLayoutRun *run,
+ PangoRectangle *run_ink,
+ PangoRectangle *run_logical)
+{
+ PangoRectangle logical;
+ ItemProperties properties;
+
+ if (G_UNLIKELY (!run_ink && !run_logical))
+ return;
+
+ pango_layout_get_item_properties (run->item, &properties);
+
+ if (!run_logical && (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE))
+ run_logical = &logical;
+
+ if (!run_logical && (properties.uline != PANGO_UNDERLINE_NONE || properties.strikethrough))
+ run_logical = &logical;
+
+ if (properties.shape_set)
+ imposed_extents (run->item->num_chars,
+ properties.shape_ink_rect,
+ properties.shape_logical_rect,
+ run_ink, run_logical);
+ else
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ run_ink, run_logical);
+
+ if (run_ink && (properties.uline != PANGO_UNDERLINE_NONE || properties.strikethrough))
+ {
+ PangoFontMetrics *metrics = pango_font_get_metrics (run->item->analysis.font,
+ run->item->analysis.language);
+ int underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
+ int underline_position = pango_font_metrics_get_underline_position (metrics);
+ int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics);
+ int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics);
+
+ int new_pos;
+
+ /* the underline/strikethrough takes x,width of logical_rect. reflect
+ * that into ink_rect.
+ */
+ new_pos = MIN (run_ink->x, run_logical->x);
+ run_ink->width = MAX (run_ink->x + run_ink->width, run_logical->x + run_logical->width) - new_pos;
+ run_ink->x = new_pos;
+
+ /* We should better handle the case of height==0 in the following cases.
+ * If run_ink->height == 0, we should adjust run_ink->y appropriately.
+ */
+
+ if (properties.strikethrough)
+ {
+ if (run_ink->height == 0)
+ {
+ run_ink->height = strikethrough_thickness;
+ run_ink->y = -strikethrough_position;
+ }
+ }
+
+ switch (properties.uline)
+ {
+ case PANGO_UNDERLINE_ERROR:
+ run_ink->height = MAX (run_ink->height,
+ 3 * underline_thickness - underline_position - run_ink->y);
+ break;
+ case PANGO_UNDERLINE_SINGLE:
+ run_ink->height = MAX (run_ink->height,
+ underline_thickness - underline_position - run_ink->y);
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ run_ink->height = MAX (run_ink->height,
+ 3 * underline_thickness - underline_position - run_ink->y);
+ break;
+ case PANGO_UNDERLINE_LOW:
+ run_ink->height += 2 * underline_thickness;
+ break;
+ case PANGO_UNDERLINE_NONE:
+ break;
+ default:
+ g_critical ("unknown underline mode");
+ break;
+ }
+
+ pango_font_metrics_unref (metrics);
+ }
+
+ if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ {
+ gboolean is_hinted = (run_logical->y & run_logical->height & (PANGO_SCALE - 1)) == 0;
+ int adjustment = run_logical->y + run_logical->height / 2;
+
+ if (is_hinted)
+ adjustment = PANGO_UNITS_ROUND (adjustment);
+
+ properties.rise += adjustment;
+ }
+
+ if (properties.rise != 0)
+ {
+ if (run_ink)
+ run_ink->y -= properties.rise;
+
+ if (run_logical)
+ run_logical->y -= properties.rise;
+ }
+}
+
+/**
+ * pango_layout_line_get_extents:
+ * @line: a #PangoLayoutLine
+ * @ink_rect: rectangle used to store the extents of the glyph string
+ * as drawn, or %NULL
+ * @logical_rect: rectangle used to store the logical extents of the glyph
+ * string, or %NULL
+ *
+ * Computes the logical and ink extents of a layout line. See
+ * pango_font_get_glyph_extents() for details about the interpretation
+ * of the rectangles.
+ */
+void
+pango_layout_line_get_extents (PangoLayoutLine *line,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line;
+ GSList *tmp_list;
+ int x_pos = 0;
+ gboolean caching = FALSE;
+
+ g_return_if_fail (LINE_IS_VALID (line));
+
+ if (!LINE_IS_VALID (line))
+ return;
+
+ if (G_UNLIKELY (!ink_rect && !logical_rect))
+ return;
+
+ switch (private->cache_status)
+ {
+ case CACHED:
+ {
+ if (ink_rect)
+ *ink_rect = private->ink_rect;
+ if (logical_rect)
+ *logical_rect = private->logical_rect;
+ return;
+ }
+ case NOT_CACHED:
+ {
+ caching = TRUE;
+ if (!ink_rect)
+ ink_rect = &private->ink_rect;
+ if (!logical_rect)
+ logical_rect = &private->logical_rect;
+ break;
+ }
+ case LEAKED:
+ {
+ break;
+ }
+ }
+
+ if (ink_rect)
+ {
+ ink_rect->x = 0;
+ ink_rect->y = 0;
+ ink_rect->width = 0;
+ ink_rect->height = 0;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = 0;
+ logical_rect->width = 0;
+ logical_rect->height = 0;
+ }
+
+ tmp_list = line->runs;
+ while (tmp_list)
+ {
+ PangoLayoutRun *run = tmp_list->data;
+ int new_pos;
+ PangoRectangle run_ink;
+ PangoRectangle run_logical;
+
+ pango_layout_run_get_extents (run,
+ ink_rect ? &run_ink : NULL,
+ &run_logical);
+
+ if (ink_rect)
+ {
+ if (ink_rect->width == 0 || ink_rect->height == 0)
+ {
+ *ink_rect = run_ink;
+ ink_rect->x += x_pos;
+ }
+ else if (run_ink.width != 0 && run_ink.height != 0)
+ {
+ new_pos = MIN (ink_rect->x, x_pos + run_ink.x);
+ ink_rect->width = MAX (ink_rect->x + ink_rect->width,
+ x_pos + run_ink.x + run_ink.width) - new_pos;
+ ink_rect->x = new_pos;
+
+ new_pos = MIN (ink_rect->y, run_ink.y);
+ ink_rect->height = MAX (ink_rect->y + ink_rect->height,
+ run_ink.y + run_ink.height) - new_pos;
+ ink_rect->y = new_pos;
+ }
+ }
+
+ if (logical_rect)
+ {
+ new_pos = MIN (logical_rect->x, x_pos + run_logical.x);
+ logical_rect->width = MAX (logical_rect->x + logical_rect->width,
+ x_pos + run_logical.x + run_logical.width) - new_pos;
+ logical_rect->x = new_pos;
+
+ new_pos = MIN (logical_rect->y, run_logical.y);
+ logical_rect->height = MAX (logical_rect->y + logical_rect->height,
+ run_logical.y + run_logical.height) - new_pos;
+ logical_rect->y = new_pos;
+ }
+
+ x_pos += run_logical.width;
+ tmp_list = tmp_list->next;
+ }
+
+ if (logical_rect && !line->runs)
+ pango_layout_line_get_empty_extents (line, logical_rect);
+
+ if (caching)
+ {
+ if (&private->ink_rect != ink_rect)
+ private->ink_rect = *ink_rect;
+ if (&private->logical_rect != logical_rect)
+ private->logical_rect = *logical_rect;
+ private->cache_status = CACHED;
+ }
+}
+
+static PangoLayoutLine *
+pango_layout_line_new (PangoLayout *layout)
+{
+ PangoLayoutLinePrivate *private = g_slice_new (PangoLayoutLinePrivate);
+
+ private->ref_count = 1;
+ private->line.layout = layout;
+ private->line.runs = NULL;
+ private->line.length = 0;
+ private->cache_status = NOT_CACHED;
+
+ /* Note that we leave start_index, resolved_dir, and is_paragraph_start
+ * uninitialized */
+
+ return (PangoLayoutLine *) private;
+}
+
+/**
+ * pango_layout_line_get_pixel_extents:
+ * @layout_line: a #PangoLayoutLine
+ * @ink_rect: rectangle used to store the extents of the glyph string
+ * as drawn, or %NULL
+ * @logical_rect: rectangle used to store the logical extents of the glyph
+ * string, or %NULL
+ *
+ * Computes the logical and ink extents of @layout_line in device units.
+ * This function just calls pango_layout_line_get_extents() followed by
+ * pango_extents_to_pixels().
+ **/
+void
+pango_layout_line_get_pixel_extents (PangoLayoutLine *layout_line,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ g_return_if_fail (LINE_IS_VALID (layout_line));
+
+ pango_layout_line_get_extents (layout_line, ink_rect, logical_rect);
+ pango_extents_to_pixels (ink_rect, logical_rect);
+}
+
+/*
+ * NB: This implement the exact same algorithm as
+ * reorder-items.c:pango_reorder_items().
+ */
+
+static GSList *
+reorder_runs_recurse (GSList *items, int n_items)
+{
+ GSList *tmp_list, *level_start_node;
+ int i, level_start_i;
+ int min_level = G_MAXINT;
+ GSList *result = NULL;
+
+ if (n_items == 0)
+ return NULL;
+
+ tmp_list = items;
+ for (i=0; i<n_items; i++)
+ {
+ PangoLayoutRun *run = tmp_list->data;
+
+ min_level = MIN (min_level, run->item->analysis.level);
+
+ tmp_list = tmp_list->next;
+ }
+
+ level_start_i = 0;
+ level_start_node = items;
+ tmp_list = items;
+ for (i=0; i<n_items; i++)
+ {
+ PangoLayoutRun *run = tmp_list->data;
+
+ if (run->item->analysis.level == min_level)
+ {
+ if (min_level % 2)
+ {
+ if (i > level_start_i)
+ result = g_slist_concat (reorder_runs_recurse (level_start_node, i - level_start_i), result);
+ result = g_slist_prepend (result, run);
+ }
+ else
+ {
+ if (i > level_start_i)
+ result = g_slist_concat (result, reorder_runs_recurse (level_start_node, i - level_start_i));
+ result = g_slist_append (result, run);
+ }
+
+ level_start_i = i + 1;
+ level_start_node = tmp_list->next;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (min_level % 2)
+ {
+ if (i > level_start_i)
+ result = g_slist_concat (reorder_runs_recurse (level_start_node, i - level_start_i), result);
+ }
+ else
+ {
+ if (i > level_start_i)
+ result = g_slist_concat (result, reorder_runs_recurse (level_start_node, i - level_start_i));
+ }
+
+ return result;
+}
+
+static void
+pango_layout_line_reorder (PangoLayoutLine *line)
+{
+ GSList *logical_runs = line->runs;
+ line->runs = reorder_runs_recurse (logical_runs, g_slist_length (logical_runs));
+ g_slist_free (logical_runs);
+}
+
+static int
+get_item_letter_spacing (PangoItem *item)
+{
+ ItemProperties properties;
+
+ pango_layout_get_item_properties (item, &properties);
+
+ return properties.letter_spacing;
+}
+
+static void
+pad_glyphstring_right (PangoGlyphString *glyphs,
+ ParaBreakState *state,
+ int adjustment)
+{
+ int glyph = glyphs->num_glyphs - 1;
+
+ while (glyph >= 0 && glyphs->glyphs[glyph].geometry.width == 0)
+ glyph--;
+
+ if (glyph < 0)
+ return;
+
+ state->remaining_width -= adjustment;
+ glyphs->glyphs[glyph].geometry.width += adjustment;
+ if (glyphs->glyphs[glyph].geometry.width < 0)
+ {
+ state->remaining_width += glyphs->glyphs[glyph].geometry.width;
+ glyphs->glyphs[glyph].geometry.width = 0;
+ }
+}
+
+static void
+pad_glyphstring_left (PangoGlyphString *glyphs,
+ ParaBreakState *state,
+ int adjustment)
+{
+ int glyph = 0;
+
+ while (glyph < glyphs->num_glyphs && glyphs->glyphs[glyph].geometry.width == 0)
+ glyph++;
+
+ if (glyph == glyphs->num_glyphs)
+ return;
+
+ state->remaining_width -= adjustment;
+ glyphs->glyphs[glyph].geometry.width += adjustment;
+ glyphs->glyphs[glyph].geometry.x_offset += adjustment;
+}
+
+static gboolean
+is_tab_run (PangoLayout *layout,
+ PangoLayoutRun *run)
+{
+ return (layout->text[run->item->offset] == '\t');
+}
+
+static void
+zero_line_final_space (PangoLayoutLine *line,
+ ParaBreakState *state,
+ PangoLayoutRun *run)
+{
+ PangoLayout *layout = line->layout;
+ PangoItem *item = run->item;
+ PangoGlyphString *glyphs = run->glyphs;
+ int glyph = item->analysis.level % 2 ? 0 : glyphs->num_glyphs - 1;
+ const char *p;
+
+ /* if the final char of line forms a cluster, and it's
+ * a whitespace char, zero its glyph's width as it's been wrapped
+ */
+
+ if (glyphs->num_glyphs < 1 || state->start_offset == 0 ||
+ !layout->log_attrs[state->start_offset - 1].is_white)
+ return;
+
+ p = g_utf8_prev_char (layout->text + item->offset + item->length);
+ if (p != layout->text + item->offset + glyphs->log_clusters[glyph])
+ return;
+
+ state->remaining_width += glyphs->glyphs[glyph].geometry.width;
+ glyphs->glyphs[glyph].geometry.width = 0;
+}
+
+/* When doing shaping, we add the letter spacing value for a
+ * run after every grapheme in the run. This produces ugly
+ * asymmetrical results, so what this routine is redistributes
+ * that space to the beginning and the end of the run.
+ *
+ * We also trim the letter spacing from runs adjacent to
+ * tabs and from the outside runs of the lines so that things
+ * line up properly. The line breaking and tab positioning
+ * were computed without this trimming so they are no longer
+ * exactly correct, but this won't be very noticeable in most
+ * cases.
+ */
+static void
+adjust_line_letter_spacing (PangoLayoutLine *line,
+ ParaBreakState *state)
+{
+ PangoLayout *layout = line->layout;
+ gboolean reversed;
+ PangoLayoutRun *last_run;
+ int tab_adjustment;
+ GSList *l;
+
+ /* If we have tab stops and the resolved direction of the
+ * line is RTL, then we need to walk through the line
+ * in reverse direction to figure out the corrections for
+ * tab stops.
+ */
+ reversed = FALSE;
+ if (line->resolved_dir == PANGO_DIRECTION_RTL)
+ {
+ for (l = line->runs; l; l = l->next)
+ if (is_tab_run (layout, l->data))
+ {
+ line->runs = g_slist_reverse (line->runs);
+ reversed = TRUE;
+ break;
+ }
+ }
+
+ /* Walk over the runs in the line, redistributing letter
+ * spacing from the end of the run to the start of the
+ * run and trimming letter spacing from the ends of the
+ * runs adjacent to the ends of the line or tab stops.
+ *
+ * We accumulate a correction factor from this trimming
+ * which we add onto the next tab stop space to keep the
+ * things properly aligned.
+ */
+
+ last_run = NULL;
+ tab_adjustment = 0;
+ for (l = line->runs; l; l = l->next)
+ {
+ PangoLayoutRun *run = l->data;
+ PangoLayoutRun *next_run = l->next ? l->next->data : NULL;
+
+ if (is_tab_run (layout, run))
+ {
+ pad_glyphstring_right (run->glyphs, state, tab_adjustment);
+ tab_adjustment = 0;
+ }
+ else
+ {
+ PangoLayoutRun *visual_next_run = reversed ? last_run : next_run;
+ PangoLayoutRun *visual_last_run = reversed ? next_run : last_run;
+ int run_spacing = get_item_letter_spacing (run->item);
+ int space_left, space_right;
+
+ distribute_letter_spacing (run_spacing, &space_left, &space_right);
+
+ if (run->glyphs->glyphs[0].geometry.width == 0)
+ {
+ /* we've zeroed this space glyph at the end of line, now remove
+ * the letter spacing added to its adjacent glyph */
+ pad_glyphstring_left (run->glyphs, state, - space_left);
+ }
+ else if (!visual_last_run || is_tab_run (layout, visual_last_run))
+ {
+ pad_glyphstring_left (run->glyphs, state, - space_left);
+ tab_adjustment += space_left;
+ }
+
+ if (run->glyphs->glyphs[run->glyphs->num_glyphs - 1].geometry.width == 0)
+ {
+ /* we've zeroed this space glyph at the end of line, now remove
+ * the letter spacing added to its adjacent glyph */
+ pad_glyphstring_right (run->glyphs, state, - space_right);
+ }
+ else if (!visual_next_run || is_tab_run (layout, visual_next_run))
+ {
+ pad_glyphstring_right (run->glyphs, state, - space_right);
+ tab_adjustment += space_right;
+ }
+ }
+
+ last_run = run;
+ }
+
+ if (reversed)
+ line->runs = g_slist_reverse (line->runs);
+}
+
+static void
+justify_clusters (PangoLayoutLine *line,
+ ParaBreakState *state)
+{
+ int offset;
+ int total_remaining_width, total_gaps = 0;
+ int added_so_far, gaps_so_far;
+ gboolean is_hinted;
+ GSList *run_iter;
+ enum {
+ MEASURE,
+ ADJUST
+ } mode;
+
+ total_remaining_width = state->remaining_width;
+ if (total_remaining_width <= 0)
+ return;
+
+ /* hint to full pixel if total remaining width was so */
+ is_hinted = (total_remaining_width & (PANGO_SCALE - 1)) == 0;
+
+ for (mode = MEASURE; mode <= ADJUST; mode++)
+ {
+ added_so_far = 0;
+ gaps_so_far = 0;
+
+ for (run_iter = line->runs; run_iter; run_iter = run_iter->next)
+ {
+ PangoLayoutRun *run = run_iter->data;
+ PangoGlyphString *glyphs = run->glyphs;
+ PangoGlyphItemIter cluster_iter;
+ gboolean have_cluster;
+ gboolean is_first_gap = TRUE;
+
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ if (!glyphs->glyphs[i].attr.is_cluster_start)
+ continue;
+
+ /* also don't expand zero-width spaces at the end of runs */
+ if (glyphs->glyphs[i].geometry.width == 0)
+ {
+ if (i == glyphs->num_glyphs -1)
+ continue;
+
+ if (i == 0 && glyphs->num_glyphs > 1 && glyphs->glyphs[i+1].attr.is_cluster_start)
+ continue;
+ }
+
+ if (is_first_gap)
+ {
+ is_first_gap = FALSE;
+ continue;
+ }
+
+ gaps_so_far++;
+
+ if (mode == ADJUST)
+ {
+ int adjustment, space_left, space_right;
+
+ adjustment = (gaps_so_far * total_remaining_width) / total_gaps - added_so_far;
+ if (is_hinted)
+ adjustment = PANGO_UNITS_ROUND (adjustment);
+ /* distribute to before/after */
+ distribute_letter_spacing (adjustment, &space_left, &space_right);
+
+ glyphs->glyphs[i-1].geometry.width += space_left ;
+ glyphs->glyphs[i ].geometry.width += space_right;
+ glyphs->glyphs[i ].geometry.x_offset += space_right;
+
+ added_so_far += adjustment;
+ }
+ }
+ }
+
+ if (mode == MEASURE)
+ {
+ total_gaps = gaps_so_far;
+
+ if (total_gaps == 0)
+ {
+ /* a single cluster, can't really justify it */
+ return;
+ }
+ }
+ }
+
+ state->remaining_width -= added_so_far;
+}
+
+static void
+justify_words (PangoLayoutLine *line,
+ ParaBreakState *state)
+{
+ const gchar *text = line->layout->text;
+ const PangoLogAttr *log_attrs = line->layout->log_attrs;
+
+ int offset;
+ int total_remaining_width, total_space_width = 0;
+ int added_so_far, spaces_so_far;
+ gboolean is_hinted;
+ GSList *run_iter;
+ enum {
+ MEASURE,
+ ADJUST
+ } mode;
+
+ total_remaining_width = state->remaining_width;
+ if (total_remaining_width <= 0)
+ return;
+
+ /* hint to full pixel if total remaining width was so */
+ is_hinted = (total_remaining_width & (PANGO_SCALE - 1)) == 0;
+
+ for (mode = MEASURE; mode <= ADJUST; mode++)
+ {
+ added_so_far = 0;
+ spaces_so_far = 0;
+
+ offset = state->line_start_offset;
+ for (run_iter = line->runs; run_iter; run_iter = run_iter->next)
+ {
+ PangoLayoutRun *run = run_iter->data;
+ PangoGlyphString *glyphs = run->glyphs;
+ PangoGlyphItemIter cluster_iter;
+ gboolean have_cluster;
+
+ for (have_cluster = _pango_glyph_item_iter_init_start (&cluster_iter, run, text);
+ have_cluster;
+ have_cluster = _pango_glyph_item_iter_next_cluster (&cluster_iter))
+ {
+ int i;
+ int dir;
+
+ if (!log_attrs[offset + cluster_iter.start_char].is_expandable_space)
+ continue;
+
+ dir = (cluster_iter.start_glyph < cluster_iter.end_glyph) ? 1 : -1;
+ for (i = cluster_iter.start_glyph; i != cluster_iter.end_glyph; i += dir)
+ {
+ int glyph_width = glyphs->glyphs[i].geometry.width;
+
+ if (glyph_width == 0)
+ continue;
+
+ spaces_so_far += glyph_width;
+
+ if (mode == ADJUST)
+ {
+ int adjustment;
+
+ adjustment = ((guint64) spaces_so_far * total_remaining_width) / total_space_width - added_so_far;
+ if (is_hinted)
+ adjustment = PANGO_UNITS_ROUND (adjustment);
+
+ glyphs->glyphs[i].geometry.width += adjustment;
+ added_so_far += adjustment;
+ }
+ }
+ }
+
+ offset += glyphs->num_glyphs;
+ }
+
+ if (mode == MEASURE)
+ {
+ total_space_width = spaces_so_far;
+
+ if (total_space_width == 0)
+ {
+ justify_clusters (line, state);
+ return;
+ }
+ }
+ }
+
+ state->remaining_width -= added_so_far;
+}
+
+static void
+pango_layout_line_postprocess (PangoLayoutLine *line,
+ ParaBreakState *state,
+ gboolean wrapped)
+{
+ PangoLayoutRun *last_run = line->runs->data;
+
+ /* NB: the runs are in reverse order at this point, since we prepended them to the list
+ */
+
+ /* Reverse the runs
+ */
+ line->runs = g_slist_reverse (line->runs);
+
+ DEBUG ("postprocessing", line, state);
+
+ /* Ellipsize the line if necessary
+ */
+ if (_pango_layout_line_ellipsize (line, state->attrs))
+ line->layout->is_ellipsized = TRUE;
+
+ /* Truncate the logical-final whitespace in the line if we broke the line at it
+ */
+ if (wrapped)
+ zero_line_final_space (line, state, last_run);
+
+ DEBUG ("after removing final space", line, state);
+
+ /* Now convert logical to visual order
+ */
+ pango_layout_line_reorder (line);
+
+ DEBUG ("after reordering", line, state);
+
+ /* Fixup letter spacing between runs
+ */
+ adjust_line_letter_spacing (line, state);
+
+ DEBUG ("after letter spacing", line, state);
+
+ /* Distribute extra space between words if justifying and line was wrapped
+ */
+ if (wrapped && line->layout->justify)
+ justify_words (line, state);
+
+ DEBUG ("after justification", line, state);
+}
+
+static void
+pango_layout_get_item_properties (PangoItem *item,
+ ItemProperties *properties)
+{
+ GSList *tmp_list = item->analysis.extra_attrs;
+
+ properties->uline = PANGO_UNDERLINE_NONE;
+ properties->strikethrough = FALSE;
+ properties->letter_spacing = 0;
+ properties->rise = 0;
+ properties->shape_set = FALSE;
+ properties->shape_ink_rect = NULL;
+ properties->shape_logical_rect = NULL;
+
+ while (tmp_list)
+ {
+ PangoAttribute *attr = tmp_list->data;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_UNDERLINE:
+ properties->uline = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_STRIKETHROUGH:
+ properties->strikethrough = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_RISE:
+ properties->rise = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_LETTER_SPACING:
+ properties->letter_spacing = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_SHAPE:
+ properties->shape_set = TRUE;
+ properties->shape_logical_rect = &((PangoAttrShape *)attr)->logical_rect;
+ properties->shape_ink_rect = &((PangoAttrShape *)attr)->ink_rect;
+ break;
+
+ default:
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+}
+
+static int
+next_cluster_start (PangoGlyphString *gs,
+ int cluster_start)
+{
+ int i;
+
+ i = cluster_start + 1;
+ while (i < gs->num_glyphs)
+ {
+ if (gs->glyphs[i].attr.is_cluster_start)
+ return i;
+
+ i++;
+ }
+
+ return gs->num_glyphs;
+}
+
+static int
+cluster_width (PangoGlyphString *gs,
+ int cluster_start)
+{
+ int i;
+ int width;
+
+ width = gs->glyphs[cluster_start].geometry.width;
+ i = cluster_start + 1;
+ while (i < gs->num_glyphs)
+ {
+ if (gs->glyphs[i].attr.is_cluster_start)
+ break;
+
+ width += gs->glyphs[i].geometry.width;
+ i++;
+ }
+
+ return width;
+}
+
+static inline void
+offset_y (PangoLayoutIter *iter,
+ int *y)
+{
+ Extents *line_ext;
+
+ line_ext = (Extents*)iter->line_extents_link->data;
+
+ *y += line_ext->baseline;
+}
+
+/* Sets up the iter for the start of a new cluster. cluster_start_index
+ * is the byte index of the cluster start relative to the run.
+ */
+static void
+update_cluster (PangoLayoutIter *iter,
+ int cluster_start_index)
+{
+ char *cluster_text;
+ PangoGlyphString *gs;
+ int cluster_length;
+
+ iter->character_position = 0;
+
+ gs = iter->run->glyphs;
+ iter->cluster_width = cluster_width (gs, iter->cluster_start);
+ iter->next_cluster_glyph = next_cluster_start (gs, iter->cluster_start);
+
+ if (iter->ltr)
+ {
+ /* For LTR text, finding the length of the cluster is easy
+ * since logical and visual runs are in the same direction.
+ */
+ if (iter->next_cluster_glyph < gs->num_glyphs)
+ cluster_length = gs->log_clusters[iter->next_cluster_glyph] - cluster_start_index;
+ else
+ cluster_length = iter->run->item->length - cluster_start_index;
+ }
+ else
+ {
+ /* For RTL text, we have to scan backwards to find the previous
+ * visual cluster which is the next logical cluster.
+ */
+ int i = iter->cluster_start;
+ while (i > 0 && gs->log_clusters[i - 1] == cluster_start_index)
+ i--;
+
+ if (i == 0)
+ cluster_length = iter->run->item->length - cluster_start_index;
+ else
+ cluster_length = gs->log_clusters[i - 1] - cluster_start_index;
+ }
+
+ cluster_text = iter->layout->text + iter->run->item->offset + cluster_start_index;
+ iter->cluster_num_chars = g_utf8_strlen (cluster_text, cluster_length);
+
+ if (iter->ltr)
+ iter->index = cluster_text - iter->layout->text;
+ else
+ iter->index = g_utf8_prev_char (cluster_text + cluster_length) - iter->layout->text;
+}
+
+static void
+update_run (PangoLayoutIter *iter,
+ int run_start_index)
+{
+ Extents *line_ext;
+
+ line_ext = (Extents*)iter->line_extents_link->data;
+
+ /* Note that in iter_new() the iter->run_width
+ * is garbage but we don't use it since we're on the first run of
+ * a line.
+ */
+ if (iter->run_list_link == iter->line->runs)
+ iter->run_x = line_ext->logical_rect.x;
+ else
+ iter->run_x += iter->run_width;
+
+ if (iter->run)
+ {
+ iter->run_width = pango_layout_run_get_width (iter->run);
+ }
+ else
+ {
+ /* The empty run at the end of a line */
+ iter->run_width = 0;
+ }
+
+ if (iter->run)
+ iter->ltr = (iter->run->item->analysis.level % 2) == 0;
+ else
+ iter->ltr = TRUE;
+
+ iter->cluster_start = 0;
+ iter->cluster_x = iter->run_x;
+
+ if (iter->run)
+ {
+ update_cluster (iter, iter->run->glyphs->log_clusters[0]);
+ }
+ else
+ {
+ iter->cluster_width = 0;
+ iter->character_position = 0;
+ iter->cluster_num_chars = 0;
+ iter->index = run_start_index;
+ }
+}
+
+static PangoLayoutIter *
+pango_layout_iter_copy (PangoLayoutIter *iter)
+{
+ PangoLayoutIter *new;
+ GSList *l;
+
+ new = g_slice_new (PangoLayoutIter);
+
+ new->layout = g_object_ref (iter->layout);
+ new->line_list_link = iter->line_list_link;
+ new->line = iter->line;
+ pango_layout_line_ref (new->line);
+
+ new->run_list_link = iter->run_list_link;
+ new->run = iter->run;
+ new->index = iter->index;
+
+ new->line_extents = NULL;
+ new->line_extents_link = NULL;
+ for (l = iter->line_extents; l; l = l->next)
+ {
+ new->line_extents = g_slist_prepend (new->line_extents,
+ g_memdup (l->data,
+ sizeof (Extents)));
+ if (l == iter->line_extents_link)
+ new->line_extents_link = new->line_extents;
+ }
+ new->line_extents = g_slist_reverse (new->line_extents);
+
+ new->run_x = iter->run_x;
+ new->run_width = iter->run_width;
+ new->ltr = iter->ltr;
+
+ new->cluster_x = iter->cluster_x;
+ new->cluster_width = iter->cluster_width;
+
+ new->cluster_start = iter->cluster_start;
+ new->next_cluster_glyph = iter->next_cluster_glyph;
+
+ new->cluster_num_chars = iter->cluster_num_chars;
+ new->character_position = iter->character_position;
+
+ new->layout_width = iter->layout_width;
+
+ return new;
+}
+
+GType
+pango_layout_iter_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoLayoutIter"),
+ (GBoxedCopyFunc) pango_layout_iter_copy,
+ (GBoxedFreeFunc) pango_layout_iter_free);
+
+ return our_type;
+}
+
+/**
+ * pango_layout_get_iter:
+ * @layout: a #PangoLayout
+ *
+ * Returns an iterator to iterate over the visual extents of the layout.
+ *
+ * Return value: the new #PangoLayoutIter that should be freed using
+ * pango_layout_iter_free().
+ **/
+PangoLayoutIter*
+pango_layout_get_iter (PangoLayout *layout)
+{
+ int run_start_index;
+ PangoLayoutIter *iter;
+ PangoRectangle logical_rect;
+
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
+
+ iter = g_slice_new (PangoLayoutIter);
+
+ iter->layout = layout;
+ g_object_ref (iter->layout);
+
+ pango_layout_check_lines (layout);
+
+ iter->line_list_link = layout->lines;
+ iter->line = iter->line_list_link->data;
+ pango_layout_line_ref (iter->line);
+
+ run_start_index = iter->line->start_index;
+ iter->run_list_link = iter->line->runs;
+
+ if (iter->run_list_link)
+ {
+ iter->run = iter->run_list_link->data;
+ run_start_index = iter->run->item->offset;
+ }
+ else
+ iter->run = NULL;
+
+ iter->line_extents = NULL;
+ pango_layout_get_extents_internal (layout,
+ NULL,
+ &logical_rect,
+ &iter->line_extents);
+ iter->layout_width = layout->width == -1 ? logical_rect.width : layout->width;
+
+ iter->line_extents_link = iter->line_extents;
+
+ update_run (iter, run_start_index);
+
+ return iter;
+}
+
+/**
+ * pango_layout_iter_free:
+ * @iter: a #PangoLayoutIter
+ *
+ * Frees an iterator that's no longer in use.
+ **/
+void
+pango_layout_iter_free (PangoLayoutIter *iter)
+{
+ g_return_if_fail (iter != NULL);
+
+ g_slist_foreach (iter->line_extents, (GFunc)extents_free, NULL);
+ g_slist_free (iter->line_extents);
+ pango_layout_line_unref (iter->line);
+ g_object_unref (iter->layout);
+ g_slice_free (PangoLayoutIter, iter);
+}
+
+/**
+ * pango_layout_iter_get_index:
+ * @iter: a #PangoLayoutIter
+ *
+ * Gets the current byte index. Note that iterating forward by char
+ * moves in visual order, not logical order, so indexes may not be
+ * sequential. Also, the index may be equal to the length of the text
+ * in the layout, if on the %NULL run (see pango_layout_iter_get_run()).
+ *
+ * Return value: current byte index.
+ **/
+int
+pango_layout_iter_get_index (PangoLayoutIter *iter)
+{
+ if (ITER_IS_INVALID (iter))
+ return 0;
+
+ return iter->index;
+}
+
+/**
+ * pango_layout_iter_get_run:
+ * @iter: a #PangoLayoutIter
+ *
+ * Gets the current run. When iterating by run, at the end of each
+ * line, there's a position with a %NULL run, so this function can return
+ * %NULL. The %NULL run at the end of each line ensures that all lines have
+ * at least one run, even lines consisting of only a newline.
+ *
+ * Use the faster pango_layout_iter_get_run_readonly() if you do not plan
+ * to modify the contents of the run (glyphs, glyph widths, etc.).
+ *
+ * Return value: the current run.
+ **/
+PangoLayoutRun*
+pango_layout_iter_get_run (PangoLayoutIter *iter)
+{
+ if (ITER_IS_INVALID (iter))
+ return NULL;
+
+ pango_layout_line_leaked (iter->line);
+
+ return iter->run;
+}
+
+/**
+ * pango_layout_iter_get_run_readonly:
+ * @iter: a #PangoLayoutIter
+ *
+ * Gets the current run. When iterating by run, at the end of each
+ * line, there's a position with a %NULL run, so this function can return
+ * %NULL. The %NULL run at the end of each line ensures that all lines have
+ * at least one run, even lines consisting of only a newline.
+ *
+ * This is a faster alternative to pango_layout_iter_get_run(),
+ * but the user is not expected
+ * to modify the contents of the run (glyphs, glyph widths, etc.).
+ *
+ * Return value: the current run, that should not be modified.
+ *
+ * Since: 1.16
+ **/
+PangoLayoutRun*
+pango_layout_iter_get_run_readonly (PangoLayoutIter *iter)
+{
+ if (ITER_IS_INVALID (iter))
+ return NULL;
+
+ pango_layout_line_leaked (iter->line);
+
+ return iter->run;
+}
+
+/* an inline-able version for local use */
+static PangoLayoutLine*
+_pango_layout_iter_get_line (PangoLayoutIter *iter)
+{
+ return iter->line;
+}
+
+/**
+ * pango_layout_iter_get_line:
+ * @iter: a #PangoLayoutIter
+ *
+ * Gets the current line.
+ *
+ * Use the faster pango_layout_iter_get_line_readonly() if you do not plan
+ * to modify the contents of the line (glyphs, glyph widths, etc.).
+ *
+ * Return value: the current line.
+ **/
+PangoLayoutLine*
+pango_layout_iter_get_line (PangoLayoutIter *iter)
+{
+ if (ITER_IS_INVALID (iter))
+ return NULL;
+
+ pango_layout_line_leaked (iter->line);
+
+ return iter->line;
+}
+
+/**
+ * pango_layout_iter_get_line_readonly:
+ * @iter: a #PangoLayoutIter
+ *
+ * Gets the current line for read-only access.
+ *
+ * This is a faster alternative to pango_layout_iter_get_line(),
+ * but the user is not expected
+ * to modify the contents of the line (glyphs, glyph widths, etc.).
+ *
+ * Return value: the current line, that should not be modified.
+ *
+ * Since: 1.16
+ **/
+PangoLayoutLine*
+pango_layout_iter_get_line_readonly (PangoLayoutIter *iter)
+{
+ if (ITER_IS_INVALID (iter))
+ return NULL;
+
+ return iter->line;
+}
+
+/**
+ * pango_layout_iter_at_last_line:
+ * @iter: a #PangoLayoutIter
+ *
+ * Determines whether @iter is on the last line of the layout.
+ *
+ * Return value: %TRUE if @iter is on the last line.
+ **/
+gboolean
+pango_layout_iter_at_last_line (PangoLayoutIter *iter)
+{
+ if (ITER_IS_INVALID (iter))
+ return FALSE;
+
+ return iter->line_extents_link->next == NULL;
+}
+
+static gboolean
+line_is_terminated (PangoLayoutIter *iter)
+{
+ /* There is a real terminator at the end of each paragraph other
+ * than the last.
+ */
+ if (iter->line_list_link->next)
+ {
+ PangoLayoutLine *next_line = iter->line_list_link->next->data;
+ if (next_line->is_paragraph_start)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Moves to the next non-empty line. If @include_terminators
+ * is set, a line with just an explicit paragraph separator
+ * is considered non-empty.
+ */
+static gboolean
+next_nonempty_line (PangoLayoutIter *iter,
+ gboolean include_terminators)
+{
+ gboolean result;
+
+ while (TRUE)
+ {
+ result = pango_layout_iter_next_line (iter);
+ if (!result)
+ break;
+
+ if (iter->line->runs)
+ break;
+
+ if (include_terminators && line_is_terminated (iter))
+ break;
+ }
+
+ return result;
+}
+
+/* Moves to the next non-empty run. If @include_terminators
+ * is set, the trailing run at the end of a line with an explicit
+ * paragraph separator is considered non-empty.
+ */
+static gboolean
+next_nonempty_run (PangoLayoutIter *iter,
+ gboolean include_terminators)
+{
+ gboolean result;
+
+ while (TRUE)
+ {
+ result = pango_layout_iter_next_run (iter);
+ if (!result)
+ break;
+
+ if (iter->run)
+ break;
+
+ if (include_terminators && line_is_terminated (iter))
+ break;
+ }
+
+ return result;
+}
+
+/* Like pango_layout_next_cluster(), but if @include_terminators
+ * is set, includes the fake runs/clusters for empty lines.
+ * (But not positions introduced by line wrapping).
+ */
+static gboolean
+next_cluster_internal (PangoLayoutIter *iter,
+ gboolean include_terminators)
+{
+ PangoGlyphString *gs;
+ int next_start;
+
+ if (ITER_IS_INVALID (iter))
+ return FALSE;
+
+ if (iter->run == NULL)
+ return next_nonempty_line (iter, include_terminators);
+
+ gs = iter->run->glyphs;
+
+ next_start = iter->next_cluster_glyph;
+ if (next_start == gs->num_glyphs)
+ {
+ return next_nonempty_run (iter, include_terminators);
+ }
+ else
+ {
+ iter->cluster_start = next_start;
+ iter->cluster_x += iter->cluster_width;
+ update_cluster(iter, gs->log_clusters[iter->cluster_start]);
+
+ return TRUE;
+ }
+}
+
+/**
+ * pango_layout_iter_next_char:
+ * @iter: a #PangoLayoutIter
+ *
+ * Moves @iter forward to the next character in visual order. If @iter was already at
+ * the end of the layout, returns %FALSE.
+ *
+ * Return value: whether motion was possible.
+ **/
+gboolean
+pango_layout_iter_next_char (PangoLayoutIter *iter)
+{
+ const char *text;
+
+ if (ITER_IS_INVALID (iter))
+ return FALSE;
+
+ if (iter->run == NULL)
+ {
+ /* We need to fake an iterator position in the middle of a \r\n line terminator */
+ if (line_is_terminated (iter) &&
+ strncmp (iter->layout->text + iter->line->start_index + iter->line->length, "\r\n", 2) == 0 &&
+ iter->character_position == 0)
+ {
+ iter->character_position++;
+ return TRUE;
+ }
+
+ return next_nonempty_line (iter, TRUE);
+ }
+
+ iter->character_position++;
+ if (iter->character_position >= iter->cluster_num_chars)
+ return next_cluster_internal (iter, TRUE);
+
+ text = iter->layout->text;
+ if (iter->ltr)
+ iter->index = g_utf8_next_char (text + iter->index) - text;
+ else
+ iter->index = g_utf8_prev_char (text + iter->index) - text;
+
+ return TRUE;
+}
+
+/**
+ * pango_layout_iter_next_cluster:
+ * @iter: a #PangoLayoutIter
+ *
+ * Moves @iter forward to the next cluster in visual order. If @iter
+ * was already at the end of the layout, returns %FALSE.
+ *
+ * Return value: whether motion was possible.
+ **/
+gboolean
+pango_layout_iter_next_cluster (PangoLayoutIter *iter)
+{
+ return next_cluster_internal (iter, FALSE);
+}
+
+/**
+ * pango_layout_iter_next_run:
+ * @iter: a #PangoLayoutIter
+ *
+ * Moves @iter forward to the next run in visual order. If @iter was
+ * already at the end of the layout, returns %FALSE.
+ *
+ * Return value: whether motion was possible.
+ **/
+gboolean
+pango_layout_iter_next_run (PangoLayoutIter *iter)
+{
+ int next_run_start; /* byte index */
+ GSList *next_link;
+
+ if (ITER_IS_INVALID (iter))
+ return FALSE;
+
+ if (iter->run == NULL)
+ return pango_layout_iter_next_line (iter);
+
+ next_link = iter->run_list_link->next;
+
+ if (next_link == NULL)
+ {
+ /* Moving on to the zero-width "virtual run" at the end of each
+ * line
+ */
+ next_run_start = iter->run->item->offset + iter->run->item->length;
+ iter->run = NULL;
+ iter->run_list_link = NULL;
+ }
+ else
+ {
+ iter->run_list_link = next_link;
+ iter->run = iter->run_list_link->data;
+ next_run_start = iter->run->item->offset;
+ }
+
+ update_run (iter, next_run_start);
+
+ return TRUE;
+}
+
+/**
+ * pango_layout_iter_next_line:
+ * @iter: a #PangoLayoutIter
+ *
+ * Moves @iter forward to the start of the next line. If @iter is
+ * already on the last line, returns %FALSE.
+ *
+ * Return value: whether motion was possible.
+ **/
+gboolean
+pango_layout_iter_next_line (PangoLayoutIter *iter)
+{
+ GSList *next_link;
+
+ if (ITER_IS_INVALID (iter))
+ return FALSE;
+
+ next_link = iter->line_list_link->next;
+
+ if (next_link == NULL)
+ return FALSE;
+
+ iter->line_list_link = next_link;
+
+ pango_layout_line_unref (iter->line);
+
+ iter->line = iter->line_list_link->data;
+
+ pango_layout_line_ref (iter->line);
+
+ iter->run_list_link = iter->line->runs;
+
+ if (iter->run_list_link)
+ iter->run = iter->run_list_link->data;
+ else
+ iter->run = NULL;
+
+ iter->line_extents_link = iter->line_extents_link->next;
+ g_assert (iter->line_extents_link != NULL);
+
+ update_run (iter, iter->line->start_index);
+
+ return TRUE;
+}
+
+/**
+ * pango_layout_iter_get_char_extents:
+ * @iter: a #PangoLayoutIter
+ * @logical_rect: rectangle to fill with logical extents
+ *
+ * Gets the extents of the current character, in layout coordinates
+ * (origin is the top left of the entire layout). Only logical extents
+ * can sensibly be obtained for characters; ink extents make sense only
+ * down to the level of clusters.
+ *
+ **/
+void
+pango_layout_iter_get_char_extents (PangoLayoutIter *iter,
+ PangoRectangle *logical_rect)
+{
+ PangoRectangle cluster_rect;
+ int x0, x1;
+
+ if (ITER_IS_INVALID (iter))
+ return;
+
+ if (logical_rect == NULL)
+ return;
+
+ pango_layout_iter_get_cluster_extents (iter, NULL, &cluster_rect);
+
+ if (iter->run == NULL)
+ {
+ /* When on the NULL run, cluster, char, and run all have the
+ * same extents
+ */
+ *logical_rect = cluster_rect;
+ return;
+ }
+
+ x0 = (iter->character_position * cluster_rect.width) / iter->cluster_num_chars;
+ x1 = ((iter->character_position + 1) * cluster_rect.width) / iter->cluster_num_chars;
+
+ logical_rect->width = x1 - x0;
+ logical_rect->height = cluster_rect.height;
+ logical_rect->y = cluster_rect.y;
+ logical_rect->x = cluster_rect.x + x0;
+}
+
+/**
+ * pango_layout_iter_get_cluster_extents:
+ * @iter: a #PangoLayoutIter
+ * @ink_rect: rectangle to fill with ink extents, or %NULL
+ * @logical_rect: rectangle to fill with logical extents, or %NULL
+ *
+ * Gets the extents of the current cluster, in layout coordinates
+ * (origin is the top left of the entire layout).
+ *
+ **/
+void
+pango_layout_iter_get_cluster_extents (PangoLayoutIter *iter,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ if (ITER_IS_INVALID (iter))
+ return;
+
+ if (iter->run == NULL)
+ {
+ /* When on the NULL run, cluster, char, and run all have the
+ * same extents
+ */
+ pango_layout_iter_get_run_extents (iter, ink_rect, logical_rect);
+ return;
+ }
+
+ pango_glyph_string_extents_range (iter->run->glyphs,
+ iter->cluster_start,
+ iter->next_cluster_glyph,
+ iter->run->item->analysis.font,
+ ink_rect,
+ logical_rect);
+
+ if (ink_rect)
+ {
+ ink_rect->x += iter->cluster_x;
+ offset_y (iter, &ink_rect->y);
+ }
+
+ if (logical_rect)
+ {
+ g_assert (logical_rect->width == iter->cluster_width);
+ logical_rect->x += iter->cluster_x;
+ offset_y (iter, &logical_rect->y);
+ }
+}
+
+/**
+ * pango_layout_iter_get_run_extents:
+ * @iter: a #PangoLayoutIter
+ * @ink_rect: rectangle to fill with ink extents, or %NULL
+ * @logical_rect: rectangle to fill with logical extents, or %NULL
+ *
+ * Gets the extents of the current run in layout coordinates
+ * (origin is the top left of the entire layout).
+ *
+ **/
+void
+pango_layout_iter_get_run_extents (PangoLayoutIter *iter,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ if (G_UNLIKELY (!ink_rect && !logical_rect))
+ return;
+
+ if (ITER_IS_INVALID (iter))
+ return;
+
+ if (iter->run)
+ {
+ pango_layout_run_get_extents (iter->run, ink_rect, logical_rect);
+
+ if (ink_rect)
+ {
+ offset_y (iter, &ink_rect->y);
+ ink_rect->x += iter->run_x;
+ }
+
+ if (logical_rect)
+ {
+ offset_y (iter, &logical_rect->y);
+ logical_rect->x += iter->run_x;
+ }
+ }
+ else
+ {
+ /* The empty run at the end of a line */
+
+ pango_layout_iter_get_line_extents (iter, ink_rect, logical_rect);
+
+ if (ink_rect)
+ {
+ ink_rect->x = iter->run_x;
+ ink_rect->width = 0;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = iter->run_x;
+ logical_rect->width = 0;
+ }
+ }
+}
+
+/**
+ * pango_layout_iter_get_line_extents:
+ * @iter: a #PangoLayoutIter
+ * @ink_rect: rectangle to fill with ink extents, or %NULL
+ * @logical_rect: rectangle to fill with logical extents, or %NULL
+ *
+ * Obtains the extents of the current line. @ink_rect or @logical_rect
+ * can be %NULL if you aren't interested in them. Extents are in layout
+ * coordinates (origin is the top-left corner of the entire
+ * #PangoLayout). Thus the extents returned by this function will be
+ * the same width/height but not at the same x/y as the extents
+ * returned from pango_layout_line_get_extents().
+ *
+ **/
+void
+pango_layout_iter_get_line_extents (PangoLayoutIter *iter,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ Extents *ext;
+
+ if (ITER_IS_INVALID (iter))
+ return;
+
+ ext = iter->line_extents_link->data;
+
+ if (ink_rect)
+ {
+ get_line_extents_layout_coords (iter->layout, iter->line,
+ iter->layout_width,
+ ext->logical_rect.y,
+ NULL,
+ ink_rect,
+ NULL);
+ }
+
+ if (logical_rect)
+ *logical_rect = ext->logical_rect;
+}
+
+/**
+ * pango_layout_iter_get_line_yrange:
+ * @iter: a #PangoLayoutIter
+ * @y0_: start of line
+ * @y1_: end of line
+ *
+ * Divides the vertical space in the #PangoLayout being iterated over
+ * between the lines in the layout, and returns the space belonging to
+ * the current line. A line's range includes the line's logical
+ * extents, plus half of the spacing above and below the line, if
+ * pango_layout_set_spacing() has been called to set layout spacing.
+ * The Y positions are in layout coordinates (origin at top left of the
+ * entire layout).
+ *
+ **/
+void
+pango_layout_iter_get_line_yrange (PangoLayoutIter *iter,
+ int *y0,
+ int *y1)
+{
+ Extents *ext;
+ int half_spacing;
+
+ if (ITER_IS_INVALID (iter))
+ return;
+
+ ext = iter->line_extents_link->data;
+
+ half_spacing = iter->layout->spacing / 2;
+
+ /* Note that if layout->spacing is odd, the remainder spacing goes
+ * above the line (this is pretty arbitrary of course)
+ */
+
+ if (y0)
+ {
+ /* No spacing above the first line */
+
+ if (iter->line_extents_link == iter->line_extents)
+ *y0 = ext->logical_rect.y;
+ else
+ *y0 = ext->logical_rect.y - (iter->layout->spacing - half_spacing);
+ }
+
+ if (y1)
+ {
+ /* No spacing below the last line */
+ if (iter->line_extents_link->next == NULL)
+ *y1 = ext->logical_rect.y + ext->logical_rect.height;
+ else
+ *y1 = ext->logical_rect.y + ext->logical_rect.height + half_spacing;
+ }
+}
+
+/**
+ * pango_layout_iter_get_baseline:
+ * @iter: a #PangoLayoutIter
+ *
+ * Gets the Y position of the current line's baseline, in layout
+ * coordinates (origin at top left of the entire layout).
+ *
+ * Return value: baseline of current line.
+ **/
+int
+pango_layout_iter_get_baseline (PangoLayoutIter *iter)
+{
+ Extents *ext;
+
+ if (ITER_IS_INVALID (iter))
+ return 0;
+
+ ext = iter->line_extents_link->data;
+
+ return ext->baseline;
+}
+
+/**
+ * pango_layout_iter_get_layout_extents:
+ * @iter: a #PangoLayoutIter
+ * @ink_rect: rectangle to fill with ink extents, or %NULL
+ * @logical_rect: rectangle to fill with logical extents, or %NULL
+ *
+ * Obtains the extents of the #PangoLayout being iterated
+ * over. @ink_rect or @logical_rect can be %NULL if you
+ * aren't interested in them.
+ *
+ **/
+void
+pango_layout_iter_get_layout_extents (PangoLayoutIter *iter,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ if (ITER_IS_INVALID (iter))
+ return;
+
+ pango_layout_get_extents (iter->layout, ink_rect, logical_rect);
+}
diff --git a/trunk/pango/pango-layout.h b/trunk/pango/pango-layout.h
new file mode 100644
index 00000000..d84b1f79
--- /dev/null
+++ b/trunk/pango/pango-layout.h
@@ -0,0 +1,286 @@
+/* Pango
+ * pango-layout.h: High-level layout driver
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_LAYOUT_H__
+#define __PANGO_LAYOUT_H__
+
+#include <pango/pango-attributes.h>
+#include <pango/pango-context.h>
+#include <pango/pango-glyph-item.h>
+#include <pango/pango-tabs.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoLayout PangoLayout;
+typedef struct _PangoLayoutClass PangoLayoutClass;
+typedef struct _PangoLayoutLine PangoLayoutLine;
+
+/* For backwards compatiblity */
+typedef PangoGlyphItem PangoLayoutRun;
+
+typedef enum {
+ PANGO_ALIGN_LEFT,
+ PANGO_ALIGN_CENTER,
+ PANGO_ALIGN_RIGHT
+} PangoAlignment;
+
+typedef enum {
+ PANGO_WRAP_WORD,
+ PANGO_WRAP_CHAR,
+ PANGO_WRAP_WORD_CHAR
+} PangoWrapMode;
+
+/**
+ * PangoEllipsizeMode
+ * @PANGO_ELLIPSIZE_NONE: No ellipsization
+ * @PANGO_ELLIPSIZE_START: Omit characters at the start of the text
+ * @PANGO_ELLIPSIZE_MIDDLE: Omit characters in the middle of the text
+ * @PANGO_ELLIPSIZE_END: Omit characters at the end of the text
+ *
+ * The #PangoEllipsizeMode type describes what sort of (if any)
+ * ellipsization should be applied to a line of text. In
+ * the ellipsization process characters are removed from the
+ * text in order to make it fit to a given width and replaced
+ * with an ellipsis.
+ */
+typedef enum {
+ PANGO_ELLIPSIZE_NONE,
+ PANGO_ELLIPSIZE_START,
+ PANGO_ELLIPSIZE_MIDDLE,
+ PANGO_ELLIPSIZE_END
+} PangoEllipsizeMode;
+
+struct _PangoLayoutLine
+{
+ PangoLayout *layout;
+ gint start_index; /* start of line as byte index into layout->text */
+ gint length; /* length of line in bytes */
+ GSList *runs;
+ guint is_paragraph_start : 1; /* TRUE if this is the first line of the paragraph */
+ guint resolved_dir : 3; /* Resolved PangoDirection of line */
+};
+
+#define PANGO_TYPE_LAYOUT (pango_layout_get_type ())
+#define PANGO_LAYOUT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_LAYOUT, PangoLayout))
+#define PANGO_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_LAYOUT, PangoLayoutClass))
+#define PANGO_IS_LAYOUT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_LAYOUT))
+#define PANGO_IS_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_LAYOUT))
+#define PANGO_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_LAYOUT, PangoLayoutClass))
+
+/* The PangoLayout and PangoLayoutClass structs are private; if you
+ * need to create a subclass of these, file a bug.
+ */
+
+GType pango_layout_get_type (void) G_GNUC_CONST;
+PangoLayout *pango_layout_new (PangoContext *context);
+PangoLayout *pango_layout_copy (PangoLayout *src);
+
+PangoContext *pango_layout_get_context (PangoLayout *layout);
+
+void pango_layout_set_attributes (PangoLayout *layout,
+ PangoAttrList *attrs);
+PangoAttrList *pango_layout_get_attributes (PangoLayout *layout);
+
+void pango_layout_set_text (PangoLayout *layout,
+ const char *text,
+ int length);
+const char *pango_layout_get_text (PangoLayout *layout);
+
+void pango_layout_set_markup (PangoLayout *layout,
+ const char *markup,
+ int length);
+
+void pango_layout_set_markup_with_accel (PangoLayout *layout,
+ const char *markup,
+ int length,
+ gunichar accel_marker,
+ gunichar *accel_char);
+
+void pango_layout_set_font_description (PangoLayout *layout,
+ const PangoFontDescription *desc);
+
+G_CONST_RETURN PangoFontDescription *pango_layout_get_font_description (PangoLayout *layout);
+
+void pango_layout_set_width (PangoLayout *layout,
+ int width);
+int pango_layout_get_width (PangoLayout *layout);
+void pango_layout_set_wrap (PangoLayout *layout,
+ PangoWrapMode wrap);
+PangoWrapMode pango_layout_get_wrap (PangoLayout *layout);
+gboolean pango_layout_is_wrapped (PangoLayout *layout);
+void pango_layout_set_indent (PangoLayout *layout,
+ int indent);
+int pango_layout_get_indent (PangoLayout *layout);
+void pango_layout_set_spacing (PangoLayout *layout,
+ int spacing);
+int pango_layout_get_spacing (PangoLayout *layout);
+void pango_layout_set_justify (PangoLayout *layout,
+ gboolean justify);
+gboolean pango_layout_get_justify (PangoLayout *layout);
+void pango_layout_set_auto_dir (PangoLayout *layout,
+ gboolean auto_dir);
+gboolean pango_layout_get_auto_dir (PangoLayout *layout);
+void pango_layout_set_alignment (PangoLayout *layout,
+ PangoAlignment alignment);
+PangoAlignment pango_layout_get_alignment (PangoLayout *layout);
+
+void pango_layout_set_tabs (PangoLayout *layout,
+ PangoTabArray *tabs);
+
+PangoTabArray* pango_layout_get_tabs (PangoLayout *layout);
+
+void pango_layout_set_single_paragraph_mode (PangoLayout *layout,
+ gboolean setting);
+gboolean pango_layout_get_single_paragraph_mode (PangoLayout *layout);
+
+void pango_layout_set_ellipsize (PangoLayout *layout,
+ PangoEllipsizeMode ellipsize);
+PangoEllipsizeMode pango_layout_get_ellipsize (PangoLayout *layout);
+gboolean pango_layout_is_ellipsized (PangoLayout *layout);
+
+int pango_layout_get_unknown_glyphs_count (PangoLayout *layout);
+
+void pango_layout_context_changed (PangoLayout *layout);
+
+void pango_layout_get_log_attrs (PangoLayout *layout,
+ PangoLogAttr **attrs,
+ gint *n_attrs);
+
+void pango_layout_index_to_pos (PangoLayout *layout,
+ int index_,
+ PangoRectangle *pos);
+void pango_layout_index_to_line_x (PangoLayout *layout,
+ int index_,
+ gboolean trailing,
+ int *line,
+ int *x_pos);
+void pango_layout_get_cursor_pos (PangoLayout *layout,
+ int index_,
+ PangoRectangle *strong_pos,
+ PangoRectangle *weak_pos);
+void pango_layout_move_cursor_visually (PangoLayout *layout,
+ gboolean strong,
+ int old_index,
+ int old_trailing,
+ int direction,
+ int *new_index,
+ int *new_trailing);
+gboolean pango_layout_xy_to_index (PangoLayout *layout,
+ int x,
+ int y,
+ int *index_,
+ int *trailing);
+void pango_layout_get_extents (PangoLayout *layout,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+void pango_layout_get_pixel_extents (PangoLayout *layout,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+void pango_layout_get_size (PangoLayout *layout,
+ int *width,
+ int *height);
+void pango_layout_get_pixel_size (PangoLayout *layout,
+ int *width,
+ int *height);
+
+int pango_layout_get_line_count (PangoLayout *layout);
+PangoLayoutLine *pango_layout_get_line (PangoLayout *layout,
+ int line);
+PangoLayoutLine *pango_layout_get_line_readonly (PangoLayout *layout,
+ int line);
+GSList * pango_layout_get_lines (PangoLayout *layout);
+GSList * pango_layout_get_lines_readonly (PangoLayout *layout);
+
+
+#define PANGO_TYPE_LAYOUT_LINE (pango_layout_line_get_type ())
+
+GType pango_layout_line_get_type (void) G_GNUC_CONST;
+
+PangoLayoutLine *pango_layout_line_ref (PangoLayoutLine *line);
+void pango_layout_line_unref (PangoLayoutLine *line);
+
+gboolean pango_layout_line_x_to_index (PangoLayoutLine *line,
+ int x_pos,
+ int *index_,
+ int *trailing);
+void pango_layout_line_index_to_x (PangoLayoutLine *line,
+ int index_,
+ gboolean trailing,
+ int *x_pos);
+void pango_layout_line_get_x_ranges (PangoLayoutLine *line,
+ int start_index,
+ int end_index,
+ int **ranges,
+ int *n_ranges);
+void pango_layout_line_get_extents (PangoLayoutLine *line,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+void pango_layout_line_get_pixel_extents (PangoLayoutLine *layout_line,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+typedef struct _PangoLayoutIter PangoLayoutIter;
+
+#define PANGO_TYPE_LAYOUT_ITER (pango_layout_iter_get_type ())
+
+GType pango_layout_iter_get_type (void) G_GNUC_CONST;
+
+PangoLayoutIter *pango_layout_get_iter (PangoLayout *layout);
+void pango_layout_iter_free (PangoLayoutIter *iter);
+
+int pango_layout_iter_get_index (PangoLayoutIter *iter);
+PangoLayoutRun *pango_layout_iter_get_run (PangoLayoutIter *iter);
+PangoLayoutRun *pango_layout_iter_get_run_readonly (PangoLayoutIter *iter);
+PangoLayoutLine *pango_layout_iter_get_line (PangoLayoutIter *iter);
+PangoLayoutLine *pango_layout_iter_get_line_readonly (PangoLayoutIter *iter);
+gboolean pango_layout_iter_at_last_line (PangoLayoutIter *iter);
+
+gboolean pango_layout_iter_next_char (PangoLayoutIter *iter);
+gboolean pango_layout_iter_next_cluster (PangoLayoutIter *iter);
+gboolean pango_layout_iter_next_run (PangoLayoutIter *iter);
+gboolean pango_layout_iter_next_line (PangoLayoutIter *iter);
+
+void pango_layout_iter_get_char_extents (PangoLayoutIter *iter,
+ PangoRectangle *logical_rect);
+void pango_layout_iter_get_cluster_extents (PangoLayoutIter *iter,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+void pango_layout_iter_get_run_extents (PangoLayoutIter *iter,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+void pango_layout_iter_get_line_extents (PangoLayoutIter *iter,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+/* All the yranges meet, unlike the logical_rect's (i.e. the yranges
+ * assign between-line spacing to the nearest line)
+ */
+void pango_layout_iter_get_line_yrange (PangoLayoutIter *iter,
+ int *y0_,
+ int *y1_);
+void pango_layout_iter_get_layout_extents (PangoLayoutIter *iter,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+int pango_layout_iter_get_baseline (PangoLayoutIter *iter);
+
+G_END_DECLS
+
+#endif /* __PANGO_LAYOUT_H__ */
+
diff --git a/trunk/pango/pango-markup.c b/trunk/pango/pango-markup.c
new file mode 100644
index 00000000..47fda6fc
--- /dev/null
+++ b/trunk/pango/pango-markup.c
@@ -0,0 +1,1471 @@
+/* Pango
+ * pango-markup.c: Parse markup into attributed text
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "pango-attributes.h"
+#include "pango-font.h"
+#include "pango-enum-types.h"
+#include "pango-impl-utils.h"
+
+/* FIXME */
+#define _(x) x
+
+/* CSS size levels */
+typedef enum
+{
+ XXSmall = -3,
+ XSmall = -2,
+ Small = -1,
+ Medium = 0,
+ Large = 1,
+ XLarge = 2,
+ XXLarge = 3
+} SizeLevel;
+
+typedef struct _MarkupData MarkupData;
+
+struct _MarkupData
+{
+ PangoAttrList *attr_list;
+ GString *text;
+ GSList *tag_stack;
+ gsize index;
+ GSList *to_apply;
+ gunichar accel_marker;
+ gunichar accel_char;
+};
+
+typedef struct _OpenTag OpenTag;
+
+struct _OpenTag
+{
+ GSList *attrs;
+ gsize start_index;
+ /* Current total scale level; reset whenever
+ * an absolute size is set.
+ * Each "larger" ups it 1, each "smaller" decrements it 1
+ */
+ gint scale_level;
+ /* Our impact on scale_level, so we know whether we
+ * need to create an attribute ourselves on close
+ */
+ gint scale_level_delta;
+ /* Base scale factor currently in effect
+ * or size that this tag
+ * forces, or parent's scale factor or size.
+ */
+ double base_scale_factor;
+ int base_font_size;
+ guint has_base_font_size : 1;
+};
+
+typedef gboolean (*TagParseFunc) (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+
+static gboolean b_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean big_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean span_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean i_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean markup_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean s_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean sub_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean sup_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean small_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean tt_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+static gboolean u_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error);
+
+static double
+scale_factor (int scale_level, double base)
+{
+ double factor = base;
+ int i;
+
+ /* 1.2 is the CSS scale factor between sizes */
+
+ if (scale_level > 0)
+ {
+ i = 0;
+ while (i < scale_level)
+ {
+ factor *= 1.2;
+
+ ++i;
+ }
+ }
+ else if (scale_level < 0)
+ {
+ i = scale_level;
+ while (i < 0)
+ {
+ factor /= 1.2;
+
+ ++i;
+ }
+ }
+
+ return factor;
+}
+
+static void
+open_tag_free (OpenTag *ot)
+{
+ g_slist_foreach (ot->attrs, (GFunc) pango_attribute_destroy, NULL);
+ g_slist_free (ot->attrs);
+ g_slice_free (OpenTag, ot);
+}
+
+static void
+open_tag_set_absolute_font_size (OpenTag *ot,
+ int font_size)
+{
+ ot->base_font_size = font_size;
+ ot->has_base_font_size = TRUE;
+ ot->scale_level = 0;
+ ot->scale_level_delta = 0;
+}
+
+static void
+open_tag_set_absolute_font_scale (OpenTag *ot,
+ double scale)
+{
+ ot->base_scale_factor = scale;
+ ot->has_base_font_size = FALSE;
+ ot->scale_level = 0;
+ ot->scale_level_delta = 0;
+}
+
+static OpenTag*
+markup_data_open_tag (MarkupData *md)
+{
+ OpenTag *ot;
+ OpenTag *parent = NULL;
+
+ if (md->attr_list == NULL)
+ return NULL;
+
+ if (md->tag_stack)
+ parent = md->tag_stack->data;
+
+ ot = g_slice_new (OpenTag);
+ ot->attrs = NULL;
+ ot->start_index = md->index;
+ ot->scale_level_delta = 0;
+
+ if (parent == NULL)
+ {
+ ot->base_scale_factor = 1.0;
+ ot->base_font_size = 0;
+ ot->has_base_font_size = FALSE;
+ ot->scale_level = 0;
+ }
+ else
+ {
+ ot->base_scale_factor = parent->base_scale_factor;
+ ot->base_font_size = parent->base_font_size;
+ ot->has_base_font_size = parent->has_base_font_size;
+ ot->scale_level = parent->scale_level;
+ }
+
+ md->tag_stack = g_slist_prepend (md->tag_stack, ot);
+
+ return ot;
+}
+
+static void
+markup_data_close_tag (MarkupData *md)
+{
+ OpenTag *ot;
+ GSList *tmp_list;
+
+ if (md->attr_list == NULL)
+ return;
+
+ /* pop the stack */
+ ot = md->tag_stack->data;
+ md->tag_stack = g_slist_delete_link (md->tag_stack,
+ md->tag_stack);
+
+ /* Adjust end indexes, and push each attr onto the front of the
+ * to_apply list. This means that outermost tags are on the front of
+ * that list; if we apply the list in order, then the innermost
+ * tags will "win" which is correct.
+ */
+ tmp_list = ot->attrs;
+ while (tmp_list != NULL)
+ {
+ PangoAttribute *a = tmp_list->data;
+
+ a->start_index = ot->start_index;
+ a->end_index = md->index;
+
+ md->to_apply = g_slist_prepend (md->to_apply, a);
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+
+ if (ot->scale_level_delta != 0)
+ {
+ /* We affected relative font size; create an appropriate
+ * attribute and reverse our effects on the current level
+ */
+ PangoAttribute *a;
+
+ if (ot->has_base_font_size)
+ {
+ /* Create a font using the absolute point size
+ * as the base size to be scaled from
+ */
+ a = pango_attr_size_new (scale_factor (ot->scale_level,
+ 1.0) *
+ ot->base_font_size);
+ }
+ else
+ {
+ /* Create a font using the current scale factor
+ * as the base size to be scaled from
+ */
+ a = pango_attr_scale_new (scale_factor (ot->scale_level,
+ ot->base_scale_factor));
+ }
+
+ a->start_index = ot->start_index;
+ a->end_index = md->index;
+
+ md->to_apply = g_slist_prepend (md->to_apply, a);
+ }
+
+ g_slist_free (ot->attrs);
+ g_slice_free (OpenTag, ot);
+}
+
+static void
+start_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ TagParseFunc parse_func = NULL;
+ OpenTag *ot;
+
+ switch (*element_name)
+ {
+ case 'b':
+ if (strcmp ("b", element_name) == 0)
+ parse_func = b_parse_func;
+ else if (strcmp ("big", element_name) == 0)
+ parse_func = big_parse_func;
+ break;
+
+ case 'i':
+ if (strcmp ("i", element_name) == 0)
+ parse_func = i_parse_func;
+ break;
+
+ case 'm':
+ if (strcmp ("markup", element_name) == 0)
+ parse_func = markup_parse_func;
+ break;
+
+ case 's':
+ if (strcmp ("span", element_name) == 0)
+ parse_func = span_parse_func;
+ else if (strcmp ("s", element_name) == 0)
+ parse_func = s_parse_func;
+ else if (strcmp ("sub", element_name) == 0)
+ parse_func = sub_parse_func;
+ else if (strcmp ("sup", element_name) == 0)
+ parse_func = sup_parse_func;
+ else if (strcmp ("small", element_name) == 0)
+ parse_func = small_parse_func;
+ break;
+
+ case 't':
+ if (strcmp ("tt", element_name) == 0)
+ parse_func = tt_parse_func;
+ break;
+
+ case 'u':
+ if (strcmp ("u", element_name) == 0)
+ parse_func = u_parse_func;
+ break;
+ }
+
+ if (parse_func == NULL)
+ {
+ gint line_number, char_number;
+
+ g_markup_parse_context_get_position (context,
+ &line_number, &char_number);
+
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ _("Unknown tag '%s' on line %d char %d"),
+ element_name,
+ line_number, char_number);
+
+ return;
+ }
+
+ ot = markup_data_open_tag (user_data);
+
+ /* note ot may be NULL if the user didn't want the attribute list */
+
+ if (!(*parse_func) (user_data, ot,
+ attribute_names, attribute_values,
+ context, error))
+ {
+ /* there's nothing to do; we return an error, and end up
+ * freeing ot off the tag stack later.
+ */
+ }
+}
+
+static void
+end_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ markup_data_close_tag (user_data);
+}
+
+static void
+text_handler (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ MarkupData *md = user_data;
+
+ if (md->accel_marker == 0)
+ {
+ /* Just append all the text */
+
+ md->index += text_len;
+
+ g_string_append_len (md->text, text, text_len);
+ }
+ else
+ {
+ /* Parse the accelerator */
+ const gchar *p;
+ const gchar *end;
+ const gchar *range_start;
+ const gchar *range_end;
+ gssize uline_index = -1;
+ gsize uline_len = 0; /* Quiet GCC */
+
+ range_end = NULL;
+ range_start = text;
+ p = text;
+ end = text + text_len;
+
+ while (p != end)
+ {
+ gunichar c;
+
+ c = g_utf8_get_char (p);
+
+ if (range_end)
+ {
+ if (c == md->accel_marker)
+ {
+ /* escaped accel marker; move range_end
+ * past the accel marker that came before,
+ * append the whole thing
+ */
+ range_end = g_utf8_next_char (range_end);
+ g_string_append_len (md->text,
+ range_start,
+ range_end - range_start);
+ md->index += range_end - range_start;
+
+ /* set next range_start, skipping accel marker */
+ range_start = g_utf8_next_char (p);
+ }
+ else
+ {
+ /* Don't append the accel marker (leave range_end
+ * alone); set the accel char to c; record location for
+ * underline attribute
+ */
+ if (md->accel_char == 0)
+ md->accel_char = c;
+
+ g_string_append_len (md->text,
+ range_start,
+ range_end - range_start);
+ md->index += range_end - range_start;
+
+ /* The underline should go underneath the char
+ * we're setting as the next range_start
+ */
+ uline_index = md->index;
+ uline_len = g_utf8_next_char (p) - p;
+
+ /* set next range_start to include this char */
+ range_start = p;
+ }
+
+ /* reset range_end */
+ range_end = NULL;
+ }
+ else if (c == md->accel_marker)
+ {
+ range_end = p;
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ if (range_end)
+ {
+ g_string_append_len (md->text,
+ range_start,
+ range_end - range_start);
+ md->index += range_end - range_start;
+ }
+ else
+ {
+ g_string_append_len (md->text,
+ range_start,
+ end - range_start);
+ md->index += end - range_start;
+ }
+
+ if (md->attr_list != NULL && uline_index >= 0)
+ {
+ /* Add the underline indicating the accelerator */
+ PangoAttribute *attr;
+
+ attr = pango_attr_underline_new (PANGO_UNDERLINE_LOW);
+
+ attr->start_index = uline_index;
+ attr->end_index = uline_index + uline_len;
+
+ pango_attr_list_change (md->attr_list, attr);
+ }
+ }
+}
+
+static gboolean
+xml_isspace (char c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r';
+}
+
+static const GMarkupParser pango_markup_parser = {
+ start_element_handler,
+ end_element_handler,
+ text_handler,
+ NULL,
+ NULL
+};
+
+/**
+ * pango_parse_markup:
+ * @markup_text: markup to parse (see <link linkend="PangoMarkupFormat">markup format</link>)
+ * @length: length of @markup_text, or -1 if nul-terminated
+ * @accel_marker: character that precedes an accelerator, or 0 for none
+ * @attr_list: address of return location for a #PangoAttrList, or %NULL
+ * @text: address of return location for text with tags stripped, or %NULL
+ * @accel_char: address of return location for accelerator char, or %NULL
+ * @error: address of return location for errors, or %NULL
+ *
+ * Parses marked-up text (see
+ * <link linkend="PangoMarkupFormat">markup format</link>) to create
+ * a plain-text string and an attribute list.
+ *
+ * If @accel_marker is nonzero, the given character will mark the
+ * character following it as an accelerator. For example, @accel_marker
+ * might be an ampersand or underscore. All characters marked
+ * as an accelerator will receive a %PANGO_UNDERLINE_LOW attribute,
+ * and the first character so marked will be returned in @accel_char.
+ * Two @accel_marker characters following each other produce a single
+ * literal @accel_marker character.
+ *
+ * If any error happens, none of the output arguments are touched except
+ * for @error.
+ *
+ * Return value: %FALSE if @error is set, otherwise %TRUE
+ **/
+gboolean
+pango_parse_markup (const char *markup_text,
+ int length,
+ gunichar accel_marker,
+ PangoAttrList **attr_list,
+ char **text,
+ gunichar *accel_char,
+ GError **error)
+{
+ GMarkupParseContext *context = NULL;
+ MarkupData *md = NULL;
+ gboolean needs_root = TRUE;
+ GSList *tmp_list;
+ const char *p;
+ const char *end;
+
+ g_return_val_if_fail (markup_text != NULL, FALSE);
+
+ md = g_slice_new (MarkupData);
+
+ /* Don't bother creating these if they weren't requested;
+ * might be useful e.g. if you just want to validate
+ * some markup.
+ */
+ if (attr_list)
+ md->attr_list = pango_attr_list_new ();
+ else
+ md->attr_list = NULL;
+
+ md->text = g_string_new (NULL);
+
+ if (accel_char)
+ *accel_char = 0;
+
+ md->accel_marker = accel_marker;
+ md->accel_char = 0;
+
+ md->index = 0;
+ md->tag_stack = NULL;
+ md->to_apply = NULL;
+
+ context = g_markup_parse_context_new (&pango_markup_parser,
+ 0, md, NULL);
+
+ if (length < 0)
+ length = strlen (markup_text);
+
+ p = markup_text;
+ end = markup_text + length;
+ while (p != end && xml_isspace (*p))
+ ++p;
+
+ if (end - p >= 8 && strncmp (p, "<markup>", 8) == 0)
+ needs_root = FALSE;
+
+ if (needs_root)
+ if (!g_markup_parse_context_parse (context,
+ "<markup>",
+ -1,
+ error))
+ goto error;
+
+
+ if (!g_markup_parse_context_parse (context,
+ markup_text,
+ length,
+ error))
+ goto error;
+
+ if (needs_root)
+ if (!g_markup_parse_context_parse (context,
+ "</markup>",
+ -1,
+ error))
+ goto error;
+
+ if (!g_markup_parse_context_end_parse (context, error))
+ goto error;
+
+ g_markup_parse_context_free (context);
+
+ if (md->attr_list)
+ {
+ /* The apply list has the most-recently-closed tags first;
+ * we want to apply the least-recently-closed tag last.
+ */
+ tmp_list = md->to_apply;
+ while (tmp_list != NULL)
+ {
+ PangoAttribute *attr = tmp_list->data;
+
+ /* Innermost tags before outermost */
+ pango_attr_list_insert (md->attr_list, attr);
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+ g_slist_free (md->to_apply);
+ md->to_apply = NULL;
+ }
+
+ if (attr_list)
+ *attr_list = md->attr_list;
+
+ if (text)
+ *text = g_string_free (md->text, FALSE);
+ else
+ g_string_free (md->text, TRUE);
+
+ if (accel_char)
+ *accel_char = md->accel_char;
+
+ g_assert (md->tag_stack == NULL);
+
+ g_slice_free (MarkupData, md);
+
+ return TRUE;
+
+ error:
+ g_slist_foreach (md->tag_stack, (GFunc) open_tag_free, NULL);
+ g_slist_free (md->tag_stack);
+ g_slist_foreach (md->to_apply, (GFunc) pango_attribute_destroy, NULL);
+ g_slist_free (md->to_apply);
+ g_string_free (md->text, TRUE);
+
+ if (md->attr_list)
+ pango_attr_list_unref (md->attr_list);
+
+ g_slice_free (MarkupData, md);
+
+ if (context)
+ g_markup_parse_context_free (context);
+
+ return FALSE;
+}
+
+static void
+set_bad_attribute (GError **error,
+ GMarkupParseContext *context,
+ const char *element_name,
+ const char *attribute_name)
+{
+ gint line_number, char_number;
+
+ g_markup_parse_context_get_position (context,
+ &line_number, &char_number);
+
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ _("Tag '%s' does not support attribute '%s' on line %d char %d"),
+ element_name,
+ attribute_name,
+ line_number, char_number);
+}
+
+static void
+add_attribute (OpenTag *ot,
+ PangoAttribute *attr)
+{
+ if (ot == NULL)
+ pango_attribute_destroy (attr);
+ else
+ ot->attrs = g_slist_prepend (ot->attrs, attr);
+}
+
+#define CHECK_NO_ATTRS(elem) G_STMT_START { \
+ if (*names != NULL) { \
+ set_bad_attribute (error, context, (elem), *names); \
+ return FALSE; \
+ } }G_STMT_END
+
+static gboolean
+b_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("b");
+ add_attribute (tag, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+ return TRUE;
+}
+
+static gboolean
+big_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("big");
+
+ /* Grow text one level */
+ if (tag)
+ {
+ tag->scale_level_delta += 1;
+ tag->scale_level += 1;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+parse_absolute_size (OpenTag *tag,
+ const char *size)
+{
+ SizeLevel level = Medium;
+ double factor;
+
+ if (strcmp (size, "xx-small") == 0)
+ level = XXSmall;
+ else if (strcmp (size, "x-small") == 0)
+ level = XSmall;
+ else if (strcmp (size, "small") == 0)
+ level = Small;
+ else if (strcmp (size, "medium") == 0)
+ level = Medium;
+ else if (strcmp (size, "large") == 0)
+ level = Large;
+ else if (strcmp (size, "x-large") == 0)
+ level = XLarge;
+ else if (strcmp (size, "xx-large") == 0)
+ level = XXLarge;
+ else
+ return FALSE;
+
+ /* This is "absolute" in that it's relative to the base font,
+ * but not to sizes created by any other tags
+ */
+ factor = scale_factor (level, 1.0);
+ add_attribute (tag, pango_attr_scale_new (factor));
+ if (tag)
+ open_tag_set_absolute_font_scale (tag, factor);
+
+ return TRUE;
+}
+
+/* a string compare func that ignores '-' vs '_' differences */
+static gint
+attr_strcmp (gconstpointer pa,
+ gconstpointer pb)
+{
+ const char *a = pa;
+ const char *b = pb;
+
+ int ca;
+ int cb;
+
+ while (*a && *b)
+ {
+ ca = *a++;
+ cb = *b++;
+
+ if (ca == cb)
+ continue;
+
+ ca = ca == '_' ? '-' : ca;
+ cb = cb == '_' ? '-' : cb;
+
+ if (ca != cb)
+ return cb - ca;
+ }
+
+ ca = *a;
+ cb = *b;
+
+ return cb - ca;
+}
+
+static gboolean
+span_parse_int (const char *attr_name,
+ const char *attr_val,
+ int *val,
+ int line_number,
+ GError **error)
+{
+ const char *end = attr_val;
+
+ if (!pango_scan_int (&end, val) || *end != '\0')
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Value of '%s' attribute on <span> tag "
+ "on line %d could not be parsed; "
+ "should be an integer, not '%s'"),
+ attr_name, line_number, attr_val);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+span_parse_boolean (const char *attr_name,
+ const char *attr_val,
+ gboolean *val,
+ int line_number,
+ GError **error)
+{
+ const char *end = attr_val;
+
+ if (strcmp (attr_val, "true") == 0 ||
+ strcmp (attr_val, "yes") == 0 ||
+ strcmp (attr_val, "t") == 0 ||
+ strcmp (attr_val, "y") == 0)
+ *val = TRUE;
+ else if (strcmp (attr_val, "false") == 0 ||
+ strcmp (attr_val, "no") == 0 ||
+ strcmp (attr_val, "f") == 0 ||
+ strcmp (attr_val, "n") == 0)
+ *val = FALSE;
+ else
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Value of '%s' attribute on <span> tag "
+ "line %d should have one of "
+ "'true/yes/t/y' or 'false/no/f/n': '%s' is not valid"),
+ attr_name, line_number, attr_val);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+span_parse_color (const char *attr_name,
+ const char *attr_val,
+ PangoColor *color,
+ int line_number,
+ GError **error)
+{
+ if (!pango_color_parse (color, attr_val))
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Value of '%s' attribute on <span> tag "
+ "on line %d could not be parsed; "
+ "should be a color specification, not '%s'"),
+ attr_name, line_number, attr_val);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+span_parse_enum (const char *attr_name,
+ const char *attr_val,
+ GType type,
+ int *val,
+ int line_number,
+ GError **error)
+{
+ char *possible_values = NULL;
+
+ if (!pango_parse_enum (type, attr_val, val, FALSE, &possible_values))
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("'%s' is not a valid value for the '%s' "
+ "attribute on <span> tag, line %d; valid "
+ "values are %s"),
+ attr_val, attr_name, line_number, possible_values);
+ g_free (possible_values);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+span_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ int line_number, char_number;
+ int i;
+
+ const char *family = NULL;
+ const char *size = NULL;
+ const char *style = NULL;
+ const char *weight = NULL;
+ const char *variant = NULL;
+ const char *stretch = NULL;
+ const char *desc = NULL;
+ const char *foreground = NULL;
+ const char *background = NULL;
+ const char *underline = NULL;
+ const char *underline_color = NULL;
+ const char *strikethrough = NULL;
+ const char *strikethrough_color = NULL;
+ const char *rise = NULL;
+ const char *letter_spacing = NULL;
+ const char *lang = NULL;
+ const char *fallback = NULL;
+ const char *gravity = NULL;
+ const char *gravity_hint = NULL;
+
+ g_markup_parse_context_get_position (context,
+ &line_number, &char_number);
+
+#define CHECK_DUPLICATE(var) G_STMT_START{ \
+ if ((var) != NULL) { \
+ g_set_error (error, G_MARKUP_ERROR, \
+ G_MARKUP_ERROR_INVALID_CONTENT, \
+ _("Attribute '%s' occurs twice on <span> tag " \
+ "on line %d char %d, may only occur once"), \
+ names[i], line_number, char_number); \
+ return FALSE; \
+ }}G_STMT_END
+#define CHECK_ATTRIBUTE2(var, name) \
+ if (attr_strcmp (names[i], (name)) == 0) { \
+ CHECK_DUPLICATE (var); \
+ (var) = values[i]; \
+ found = TRUE; \
+ break; \
+ }
+#define CHECK_ATTRIBUTE(var) CHECK_ATTRIBUTE2 (var, G_STRINGIFY (var))
+
+ i = 0;
+ while (names[i])
+ {
+ gboolean found = FALSE;
+
+ switch (names[i][0]) {
+ case 'f':
+ CHECK_ATTRIBUTE2(family, "face");
+ CHECK_ATTRIBUTE (fallback);
+ CHECK_ATTRIBUTE2(desc, "font_desc");
+ CHECK_ATTRIBUTE2(family, "font_family");
+ CHECK_ATTRIBUTE (foreground);
+ break;
+ case 's':
+ CHECK_ATTRIBUTE (size);
+ CHECK_ATTRIBUTE (stretch);
+ CHECK_ATTRIBUTE (strikethrough);
+ CHECK_ATTRIBUTE (strikethrough_color);
+ CHECK_ATTRIBUTE (style);
+ break;
+ case 'g':
+ CHECK_ATTRIBUTE (gravity);
+ CHECK_ATTRIBUTE (gravity_hint);
+ break;
+ case 'l':
+ CHECK_ATTRIBUTE (lang);
+ CHECK_ATTRIBUTE (letter_spacing);
+ break;
+ case 'u':
+ CHECK_ATTRIBUTE (underline);
+ CHECK_ATTRIBUTE (underline_color);
+ break;
+ default:
+ CHECK_ATTRIBUTE (background);
+ CHECK_ATTRIBUTE2(foreground, "color");
+ CHECK_ATTRIBUTE (rise);
+ CHECK_ATTRIBUTE (variant);
+ CHECK_ATTRIBUTE (weight);
+ break;
+ }
+
+ if (!found)
+ {
+ g_set_error (error, G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ _("Attribute '%s' is not allowed on the <span> tag "
+ "on line %d char %d"),
+ names[i], line_number, char_number);
+ return FALSE;
+ }
+
+ ++i;
+ }
+
+ /* Parse desc first, then modify it with other font-related attributes. */
+ if (G_UNLIKELY (desc))
+ {
+ PangoFontDescription *parsed;
+
+ parsed = pango_font_description_from_string (desc);
+ if (parsed)
+ {
+ add_attribute (tag, pango_attr_font_desc_new (parsed));
+ if (tag)
+ open_tag_set_absolute_font_size (tag, pango_font_description_get_size (parsed));
+ pango_font_description_free (parsed);
+ }
+ }
+
+ if (G_UNLIKELY (family))
+ {
+ add_attribute (tag, pango_attr_family_new (family));
+ }
+
+ if (G_UNLIKELY (size))
+ {
+ if (g_ascii_isdigit (*size))
+ {
+ char *end = NULL;
+ gulong n;
+
+ n = strtoul (size, &end, 10);
+
+ if (*end != '\0' || n < 0 || n > 1000000)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Value of 'size' attribute on <span> tag on line %d"
+ "could not be parsed; should be an integer, or a "
+ "string such as 'small', not '%s'"),
+ line_number, size);
+ goto error;
+ }
+
+ add_attribute (tag, pango_attr_size_new (n));
+ if (tag)
+ open_tag_set_absolute_font_size (tag, n);
+ }
+ else if (strcmp (size, "smaller") == 0)
+ {
+ if (tag)
+ {
+ tag->scale_level_delta -= 1;
+ tag->scale_level -= 1;
+ }
+ }
+ else if (strcmp (size, "larger") == 0)
+ {
+ if (tag)
+ {
+ tag->scale_level_delta += 1;
+ tag->scale_level += 1;
+ }
+ }
+ else if (parse_absolute_size (tag, size))
+ ; /* nothing */
+ else
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Value of 'size' attribute on <span> tag on line %d"
+ "could not be parsed; should be an integer, or a "
+ "string such as 'small', not '%s'"),
+ line_number, size);
+ goto error;
+ }
+ }
+
+ if (G_UNLIKELY (style))
+ {
+ PangoStyle pango_style;
+
+ if (pango_parse_style (style, &pango_style, FALSE))
+ add_attribute (tag, pango_attr_style_new (pango_style));
+ else
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("'%s' is not a valid value for the 'style' attribute "
+ "on <span> tag, line %d; valid values are "
+ "'normal', 'oblique', 'italic'"),
+ style, line_number);
+ goto error;
+ }
+ }
+
+ if (G_UNLIKELY (weight))
+ {
+ PangoWeight pango_weight;
+
+ if (pango_parse_weight (weight, &pango_weight, FALSE))
+ add_attribute (tag,
+ pango_attr_weight_new (pango_weight));
+ else
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("'%s' is not a valid value for the 'weight' "
+ "attribute on <span> tag, line %d; valid "
+ "values are for example 'light', 'ultrabold' or a number"),
+ weight, line_number);
+ goto error;
+ }
+ }
+
+ if (G_UNLIKELY (variant))
+ {
+ PangoVariant pango_variant;
+
+ if (pango_parse_variant (variant, &pango_variant, FALSE))
+ add_attribute (tag, pango_attr_variant_new (pango_variant));
+ else
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("'%s' is not a valid value for the 'variant' "
+ "attribute on <span> tag, line %d; valid values are "
+ "'normal', 'smallcaps'"),
+ variant, line_number);
+ goto error;
+ }
+ }
+
+ if (G_UNLIKELY (stretch))
+ {
+ PangoStretch pango_stretch;
+
+ if (pango_parse_stretch (stretch, &pango_stretch, FALSE))
+ add_attribute (tag, pango_attr_stretch_new (pango_stretch));
+ else
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("'%s' is not a valid value for the 'stretch' "
+ "attribute on <span> tag, line %d; valid "
+ "values are for example 'condensed', "
+ "'ultraexpanded', 'normal'"),
+ stretch, line_number);
+ goto error;
+ }
+ }
+
+ if (G_UNLIKELY (foreground))
+ {
+ PangoColor color;
+
+ if (!span_parse_color ("foreground", foreground, &color, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_foreground_new (color.red, color.green, color.blue));
+ }
+
+ if (G_UNLIKELY (background))
+ {
+ PangoColor color;
+
+ if (!span_parse_color ("background", background, &color, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_background_new (color.red, color.green, color.blue));
+ }
+
+ if (G_UNLIKELY (underline))
+ {
+ PangoUnderline ul = PANGO_UNDERLINE_NONE;
+
+ if (!span_parse_enum ("underline", underline, PANGO_TYPE_UNDERLINE, &ul, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_underline_new (ul));
+ }
+
+ if (G_UNLIKELY (underline_color))
+ {
+ PangoColor color;
+
+ if (!span_parse_color ("underline_color", underline_color, &color, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_underline_color_new (color.red, color.green, color.blue));
+ }
+
+ if (G_UNLIKELY (gravity))
+ {
+ PangoGravity gr = PANGO_GRAVITY_SOUTH;
+
+ if (!span_parse_enum ("gravity", gravity, PANGO_TYPE_GRAVITY, &gr, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_gravity_new (gr));
+ }
+
+ if (G_UNLIKELY (gravity_hint))
+ {
+ PangoGravityHint hint = PANGO_GRAVITY_HINT_NATURAL;
+
+ if (!span_parse_enum ("gravity_hint", gravity_hint, PANGO_TYPE_GRAVITY_HINT, &hint, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_gravity_hint_new (hint));
+ }
+
+ if (G_UNLIKELY (strikethrough))
+ {
+ gboolean b = FALSE;
+
+ if (!span_parse_boolean ("strikethrough", strikethrough, &b, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_strikethrough_new (b));
+ }
+
+ if (G_UNLIKELY (strikethrough_color))
+ {
+ PangoColor color;
+
+ if (!span_parse_color ("strikethrough_color", strikethrough_color, &color, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_strikethrough_color_new (color.red, color.green, color.blue));
+ }
+
+ if (G_UNLIKELY (fallback))
+ {
+ gboolean b = FALSE;
+
+ if (!span_parse_boolean ("fallback", fallback, &b, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_fallback_new (b));
+ }
+
+ if (G_UNLIKELY (rise))
+ {
+ gint n = 0;
+
+ if (!span_parse_int ("rise", rise, &n, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_rise_new (n));
+ }
+
+ if (G_UNLIKELY (letter_spacing))
+ {
+ gint n = 0;
+
+ if (!span_parse_int ("letter_spacing", letter_spacing, &n, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_letter_spacing_new (n));
+ }
+
+ if (G_UNLIKELY (lang))
+ {
+ add_attribute (tag,
+ pango_attr_language_new (pango_language_from_string (lang)));
+ }
+
+ return TRUE;
+
+ error:
+
+ return FALSE;
+}
+
+static gboolean
+i_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("i");
+ add_attribute (tag, pango_attr_style_new (PANGO_STYLE_ITALIC));
+
+ return TRUE;
+}
+
+static gboolean
+markup_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ /* We don't do anything with this tag at the moment. */
+
+ return TRUE;
+}
+
+static gboolean
+s_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("s");
+ add_attribute (tag, pango_attr_strikethrough_new (TRUE));
+
+ return TRUE;
+}
+
+#define SUPERSUB_RISE 5000
+
+static gboolean
+sub_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("sub");
+
+ /* Shrink font, and set a negative rise */
+ if (tag)
+ {
+ tag->scale_level_delta -= 1;
+ tag->scale_level -= 1;
+ }
+
+ add_attribute (tag, pango_attr_rise_new (-SUPERSUB_RISE));
+
+ return TRUE;
+}
+
+static gboolean
+sup_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("sup");
+
+ /* Shrink font, and set a positive rise */
+ if (tag)
+ {
+ tag->scale_level_delta -= 1;
+ tag->scale_level -= 1;
+ }
+
+ add_attribute (tag, pango_attr_rise_new (SUPERSUB_RISE));
+
+ return TRUE;
+}
+
+static gboolean
+small_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("small");
+
+ /* Shrink text one level */
+ if (tag)
+ {
+ tag->scale_level_delta -= 1;
+ tag->scale_level -= 1;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+tt_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("tt");
+
+ add_attribute (tag, pango_attr_family_new ("Monospace"));
+
+ return TRUE;
+}
+
+static gboolean
+u_parse_func (MarkupData *md,
+ OpenTag *tag,
+ const gchar **names,
+ const gchar **values,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ CHECK_NO_ATTRS("u");
+ add_attribute (tag, pango_attr_underline_new (PANGO_UNDERLINE_SINGLE));
+
+ return TRUE;
+}
diff --git a/trunk/pango/pango-matrix.c b/trunk/pango/pango-matrix.c
new file mode 100644
index 00000000..828d4f90
--- /dev/null
+++ b/trunk/pango/pango-matrix.c
@@ -0,0 +1,467 @@
+/* Pango
+ * pango-matrix.c: Matrix manipulation routines
+ *
+ * Copyright (C) 2000, 2006 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "pango-matrix.h"
+#include "pango-impl-utils.h"
+
+GType
+pango_matrix_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoMatrix"),
+ (GBoxedCopyFunc) pango_matrix_copy,
+ (GBoxedFreeFunc) pango_matrix_free);
+
+ return our_type;
+}
+
+/**
+ * pango_matrix_copy:
+ * @matrix: a #PangoMatrix, can be %NULL
+ *
+ * Copies a #PangoMatrix.
+ *
+ * Return value: the newly allocated #PangoMatrix, which should
+ * be freed with pango_matrix_free(), or %NULL if
+ * @matrix was %NULL.
+ *
+ * Since: 1.6
+ **/
+PangoMatrix *
+pango_matrix_copy (const PangoMatrix *matrix)
+{
+ PangoMatrix *new_matrix;
+
+ if (matrix)
+ {
+ new_matrix = g_slice_new (PangoMatrix);
+ *new_matrix = *matrix;
+ }
+ else
+ new_matrix = NULL;
+
+ return new_matrix;
+}
+
+/**
+ * pango_matrix_free:
+ * @matrix: a #PangoMatrix, or %NULL
+ *
+ * Free a #PangoMatrix created with pango_matrix_copy().
+ * Does nothing if @matrix is %NULL.
+ *
+ * Since: 1.6
+ **/
+void
+pango_matrix_free (PangoMatrix *matrix)
+{
+ if (matrix)
+ g_slice_free (PangoMatrix, matrix);
+}
+
+/**
+ * pango_matrix_translate:
+ * @matrix: a #PangoMatrix
+ * @tx: amount to translate in the X direction
+ * @ty: amount to translate in the Y direction
+ *
+ * Changes the transformation represented by @matrix to be the
+ * transformation given by first translating by (@tx, @ty)
+ * then applying the original transformation.
+ *
+ * Since: 1.6
+ **/
+void
+pango_matrix_translate (PangoMatrix *matrix,
+ double tx,
+ double ty)
+{
+ g_return_if_fail (matrix != NULL);
+
+ matrix->x0 = matrix->xx * tx + matrix->xy * ty + matrix->x0;
+ matrix->y0 = matrix->yx * tx + matrix->yy * ty + matrix->y0;
+}
+
+/**
+ * pango_matrix_scale:
+ * @matrix: a #PangoMatrix
+ * @scale_x: amount to scale by in X direction
+ * @scale_y: amount to scale by in Y direction
+ *
+ * Changes the transformation represented by @matrix to be the
+ * transformation given by first scaling by @sx in the X direction
+ * and @sy in the Y direction then applying the original
+ * transformation.
+ *
+ * Since: 1.6
+ **/
+void
+pango_matrix_scale (PangoMatrix *matrix,
+ double scale_x,
+ double scale_y)
+{
+ g_return_if_fail (matrix != NULL);
+
+ matrix->xx *= scale_x;
+ matrix->xy *= scale_y;
+ matrix->yx *= scale_x;
+ matrix->yy *= scale_y;
+}
+
+/**
+ * pango_matrix_rotate:
+ * @matrix: a #PangoMatrix
+ * @degrees: degrees to rotate counter-clockwise
+ *
+ * Changes the transformation represented by @matrix to be the
+ * transformation given by first rotating by @degrees degrees
+ * counter-clockwise then applying the original transformation.
+ *
+ * Since: 1.6
+ **/
+void
+pango_matrix_rotate (PangoMatrix *matrix,
+ double degrees)
+{
+ PangoMatrix tmp;
+ gdouble r, s, c;
+
+ g_return_if_fail (matrix != NULL);
+
+ r = degrees * (G_PI / 180.);
+ s = sin (r);
+ c = cos (r);
+
+ tmp.xx = c;
+ tmp.xy = s;
+ tmp.yx = -s;
+ tmp.yy = c;
+ tmp.x0 = 0;
+ tmp.y0 = 0;
+
+ pango_matrix_concat (matrix, &tmp);
+}
+
+/**
+ * pango_matrix_concat:
+ * @matrix: a #PangoMatrix
+ * @new_matrix: a #PangoMatrix
+ *
+ * Changes the transformation represented by @matrix to be the
+ * transformation given by first applying transformation
+ * given by @new_matrix then applying the original transformation.
+ *
+ * Since: 1.6
+ **/
+void
+pango_matrix_concat (PangoMatrix *matrix,
+ const PangoMatrix *new_matrix)
+{
+ PangoMatrix tmp;
+
+ g_return_if_fail (matrix != NULL);
+
+ tmp = *matrix;
+
+ matrix->xx = tmp.xx * new_matrix->xx + tmp.xy * new_matrix->yx;
+ matrix->xy = tmp.xx * new_matrix->xy + tmp.xy * new_matrix->yy;
+ matrix->yx = tmp.yx * new_matrix->xx + tmp.yy * new_matrix->yx;
+ matrix->yy = tmp.yx * new_matrix->xy + tmp.yy * new_matrix->yy;
+ matrix->x0 = tmp.xx * new_matrix->x0 + tmp.xy * new_matrix->y0 + tmp.x0;
+ matrix->y0 = tmp.yx * new_matrix->y0 + tmp.yy * new_matrix->y0 + tmp.y0;
+}
+
+/**
+ * pango_matrix_get_font_scale_factor:
+ * @matrix: a #PangoMatrix, may be %NULL
+ *
+ * Returns the scale factor of a matrix on the height of the font.
+ * That is, the scale factor in the direction perpendicular to the
+ * vector that the X coordinate is mapped to.
+ *
+ * Return value: the scale factor of @matrix on the height of the font,
+ * or 1.0 if @matrix is %NULL.
+ *
+ * Since: 1.12
+ **/
+double
+pango_matrix_get_font_scale_factor (const PangoMatrix *matrix)
+{
+/*
+ * Based on cairo-matrix.c:_cairo_matrix_compute_scale_factors()
+ *
+ * Copyright 2005, Keith Packard
+ */
+ double det;
+
+ if (!matrix)
+ return 1.0;
+
+ det = matrix->xx * matrix->yy - matrix->yx * matrix->xy;
+
+ if (det == 0)
+ {
+ return 0.0;
+ }
+ else
+ {
+ double x = matrix->xx;
+ double y = matrix->yx;
+ double major, minor;
+
+ major = sqrt (x*x + y*y);
+
+ /*
+ * ignore mirroring
+ */
+ if (det < 0)
+ det = - det;
+
+ if (major)
+ minor = det / major;
+ else
+ minor = 0.0;
+
+ return minor;
+ }
+}
+
+/**
+ * pango_matrix_transform_distance:
+ * @matrix: a #PangoMatrix, or %NULL
+ * @dx: in/out X component of a distance vector
+ * @dy: yn/out Y component of a distance vector
+ *
+ * Transforms the distance vector (@dx,@dy) by @matrix. This is
+ * similar to pango_matrix_transform_point() except that the translation
+ * components of the transformation are ignored. The calculation of
+ * the returned vector is as follows:
+ *
+ * <programlisting>
+ * dx2 = dx1 * xx + dy1 * xy;
+ * dy2 = dx1 * yx + dy1 * yy;
+ * </programlisting>
+ *
+ * Affine transformations are position invariant, so the same vector
+ * always transforms to the same vector. If (@x1,@y1) transforms
+ * to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to
+ * (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2.
+ *
+ * Since: 1.16
+ **/
+void
+pango_matrix_transform_distance (const PangoMatrix *matrix,
+ double *dx,
+ double *dy)
+{
+ if (matrix)
+ {
+ double new_x, new_y;
+
+ new_x = (matrix->xx * *dx + matrix->xy * *dy);
+ new_y = (matrix->yx * *dx + matrix->yy * *dy);
+
+ *dx = new_x;
+ *dy = new_y;
+ }
+}
+
+/**
+ * pango_matrix_transform_point:
+ * @matrix: a #PangoMatrix, or %NULL
+ * @x: in/out X position
+ * @y: in/out Y position
+ *
+ * Transforms the point (@x, @y) by @matrix.
+ *
+ * Since: 1.16
+ **/
+void
+pango_matrix_transform_point (const PangoMatrix *matrix,
+ double *x,
+ double *y)
+{
+ if (matrix)
+ {
+ pango_matrix_transform_distance (matrix, x, y);
+
+ *x += matrix->x0;
+ *y += matrix->y0;
+ }
+}
+
+/**
+ * pango_matrix_transform_rectangle:
+ * @matrix: a #PangoMatrix, or %NULL
+ * @rect: in/out bounding box in Pango units, or %NULL
+ *
+ * First transforms @rect using @matrix, then calculates the bounding box
+ * of the transformed rectangle. The rectangle should be in Pango units.
+ *
+ * This function is useful for example when you want to draw a rotated
+ * @PangoLayout to an image buffer, and want to know how large the image
+ * should be and how much you should shift the layout when rendering.
+ *
+ * If you have a rectangle in device units (pixels), use
+ * pango_matrix_transform_pixel_rectangle().
+ *
+ * If you have the rectangle in Pango units and want to convert to
+ * transformed pixel bounding box, it is more accurate to transform it first
+ * (using this function) and pass the result to pango_extents_to_pixels(),
+ * as @ink_rect. However, there is a reason that you may want to convert
+ * to pixels first and then transform, and that is when the transformed
+ * coordinates may overflow in Pango units (large matrix translation for
+ * example).
+ *
+ * Since: 1.16
+ **/
+void
+pango_matrix_transform_rectangle (const PangoMatrix *matrix,
+ PangoRectangle *rect)
+{
+ int i;
+ double quad_x[4], quad_y[4];
+ double dx1, dy1;
+ double dx2, dy2;
+ double min_x, max_x;
+ double min_y, max_y;
+
+ if (!rect || !matrix)
+ return;
+
+ quad_x[0] = pango_units_to_double (rect->x);
+ quad_y[0] = pango_units_to_double (rect->y);
+ pango_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);
+
+ dx1 = pango_units_to_double (rect->width);
+ dy1 = 0;
+ pango_matrix_transform_distance (matrix, &dx1, &dy1);
+ quad_x[1] = quad_x[0] + dx1;
+ quad_y[1] = quad_y[0] + dy1;
+
+ dx2 = 0;
+ dy2 = pango_units_to_double (rect->height);
+ pango_matrix_transform_distance (matrix, &dx2, &dy2);
+ quad_x[2] = quad_x[0] + dx2;
+ quad_y[2] = quad_y[0] + dy2;
+
+ quad_x[3] = quad_x[0] + dx1 + dx2;
+ quad_y[3] = quad_y[0] + dy1 + dy2;
+
+ min_x = max_x = quad_x[0];
+ min_y = max_y = quad_y[0];
+
+ for (i=1; i < 4; i++) {
+ if (quad_x[i] < min_x)
+ min_x = quad_x[i];
+ else if (quad_x[i] > max_x)
+ max_x = quad_x[i];
+
+ if (quad_y[i] < min_y)
+ min_y = quad_y[i];
+ else if (quad_y[i] > max_y)
+ max_y = quad_y[i];
+ }
+
+ rect->x = pango_units_from_double (min_x);
+ rect->y = pango_units_from_double (min_y);
+ rect->width = pango_units_from_double (max_x) - rect->x;
+ rect->height = pango_units_from_double (max_y) - rect->y;
+}
+
+/**
+ * pango_matrix_transform_pixel_rectangle:
+ * @matrix: a #PangoMatrix, or %NULL
+ * @rect: in/out bounding box in device units, or %NULL
+ *
+ * First transforms the @rect using @matrix, then calculates the bounding box
+ * of the transformed rectangle. The rectangle should be in device units
+ * (pixels).
+ *
+ * This function is useful for example when you want to draw a rotated
+ * @PangoLayout to an image buffer, and want to know how large the image
+ * should be and how much you should shift the layout when rendering.
+ *
+ * For better accuracy, you should use pango_matrix_transform_rectangle() on
+ * original rectangle in Pango units and convert to pixels afterward
+ * using pango_extents_to_pixels() as @ink_rect.
+ *
+ * Since: 1.16
+ **/
+void
+pango_matrix_transform_pixel_rectangle (const PangoMatrix *matrix,
+ PangoRectangle *rect)
+{
+ int i;
+ double quad_x[4], quad_y[4];
+ double dx1, dy1;
+ double dx2, dy2;
+ double min_x, max_x;
+ double min_y, max_y;
+
+ if (!rect || !matrix)
+ return;
+
+ quad_x[0] = rect->x;
+ quad_y[0] = rect->y;
+ pango_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);
+
+ dx1 = rect->width;
+ dy1 = 0;
+ pango_matrix_transform_distance (matrix, &dx1, &dy1);
+ quad_x[1] = quad_x[0] + dx1;
+ quad_y[1] = quad_y[0] + dy1;
+
+ dx2 = 0;
+ dy2 = rect->height;
+ pango_matrix_transform_distance (matrix, &dx2, &dy2);
+ quad_x[2] = quad_x[0] + dx2;
+ quad_y[2] = quad_y[0] + dy2;
+
+ quad_x[3] = quad_x[0] + dx1 + dx2;
+ quad_y[3] = quad_y[0] + dy1 + dy2;
+
+ min_x = max_x = quad_x[0];
+ min_y = max_y = quad_y[0];
+
+ for (i=1; i < 4; i++) {
+ if (quad_x[i] < min_x)
+ min_x = quad_x[i];
+ else if (quad_x[i] > max_x)
+ max_x = quad_x[i];
+
+ if (quad_y[i] < min_y)
+ min_y = quad_y[i];
+ else if (quad_y[i] > max_y)
+ max_y = quad_y[i];
+ }
+
+ rect->x = min_x;
+ rect->y = min_y;
+ rect->width = max_x - rect->x;
+ rect->height = max_y - rect->y;
+}
diff --git a/trunk/pango/pango-matrix.h b/trunk/pango/pango-matrix.h
new file mode 100644
index 00000000..5909367d
--- /dev/null
+++ b/trunk/pango/pango-matrix.h
@@ -0,0 +1,117 @@
+/* Pango
+ * pango-matrix.h: Matrix manipulation routines
+ *
+ * Copyright (C) 2002, 2006 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_MATRIX_H__
+#define __PANGO_MATRIX_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoMatrix PangoMatrix;
+
+/**
+ * PangoMatrix:
+ * @xx: 1st component of the transformation matrix
+ * @xy: 2nd component of the transformation matrix
+ * @yx: 3rd component of the transformation matrix
+ * @yy: 4th component of the transformation matrix
+ * @x0: x translation
+ * @y0: y translation
+ *
+ * A structure specifying a transformation between user-space
+ * coordinates and device coordinates. The transformation
+ * is given by
+ *
+ * <programlisting>
+ * x_device = x_user * matrix->xx + y_user * matrix->xy + matrix->x0;
+ * y_device = x_user * matrix->yx + y_user * matrix->yy + matrix->y0;
+ * </programlisting>
+ *
+ * Since: 1.6
+ **/
+struct _PangoMatrix
+{
+ double xx;
+ double xy;
+ double yx;
+ double yy;
+ double x0;
+ double y0;
+};
+
+/**
+ * PANGO_TYPE_MATRIX
+ *
+ * The GObject type for #PangoMatrix
+ **/
+#define PANGO_TYPE_MATRIX (pango_matrix_get_type ())
+
+/**
+ * PANGO_MATRIX_INIT
+ *
+ * Constant that can be used to initialize a PangoMatrix to
+ * the identity transform.
+ *
+ * <informalexample><programlisting>
+ * PangoMatrix matrix = PANGO_MATRIX_INIT;
+ * pango_matrix_rotate (&amp;matrix, 45.);
+ * </programlisting></informalexample>
+ *
+ * Since: 1.6
+ **/
+#define PANGO_MATRIX_INIT { 1., 0., 0., 1., 0., 0. }
+
+/* for PangoRectangle */
+#include <pango/pango-types.h>
+
+GType pango_matrix_get_type (void) G_GNUC_CONST;
+
+PangoMatrix *pango_matrix_copy (const PangoMatrix *matrix);
+void pango_matrix_free (PangoMatrix *matrix);
+
+void pango_matrix_translate (PangoMatrix *matrix,
+ double tx,
+ double ty);
+void pango_matrix_scale (PangoMatrix *matrix,
+ double scale_x,
+ double scale_y);
+void pango_matrix_rotate (PangoMatrix *matrix,
+ double degrees);
+void pango_matrix_concat (PangoMatrix *matrix,
+ const PangoMatrix *new_matrix);
+void pango_matrix_transform_point (const PangoMatrix *matrix,
+ double *x,
+ double *y);
+void pango_matrix_transform_distance (const PangoMatrix *matrix,
+ double *dx,
+ double *dy);
+void pango_matrix_transform_rectangle (const PangoMatrix *matrix,
+ PangoRectangle *rect);
+void pango_matrix_transform_pixel_rectangle (const PangoMatrix *matrix,
+ PangoRectangle *rect);
+double pango_matrix_get_font_scale_factor (const PangoMatrix *matrix) G_GNUC_PURE;
+
+
+G_END_DECLS
+
+#endif /* __PANGO_MATRIX_H__ */
diff --git a/trunk/pango/pango-modules.h b/trunk/pango/pango-modules.h
new file mode 100644
index 00000000..5dbcfe9f
--- /dev/null
+++ b/trunk/pango/pango-modules.h
@@ -0,0 +1,60 @@
+/* Pango
+ * pango-modules.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_MODULES_H__
+#define __PANGO_MODULES_H__
+
+#include <pango/pango-engine.h>
+
+G_BEGIN_DECLS
+
+#ifdef PANGO_ENABLE_BACKEND
+
+typedef struct _PangoMap PangoMap;
+typedef struct _PangoMapEntry PangoMapEntry;
+
+typedef struct _PangoIncludedModule PangoIncludedModule;
+
+struct _PangoIncludedModule
+{
+ void (*list) (PangoEngineInfo **engines,
+ int *n_engines);
+ void (*init) (GTypeModule *module);
+ void (*exit) (void);
+ PangoEngine *(*create) (const char *id);
+};
+
+PangoMap * pango_find_map (PangoLanguage *language,
+ guint engine_type_id,
+ guint render_type_id);
+PangoEngine * pango_map_get_engine (PangoMap *map,
+ PangoScript script);
+void pango_map_get_engines (PangoMap *map,
+ PangoScript script,
+ GSList **exact_engines,
+ GSList **fallback_engines);
+void pango_module_register (PangoIncludedModule *module);
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+G_END_DECLS
+
+#endif /* __PANGO_MODULES_H__ */
diff --git a/trunk/pango/pango-ot-buffer.c b/trunk/pango/pango-ot-buffer.c
new file mode 100644
index 00000000..f84c4cd3
--- /dev/null
+++ b/trunk/pango/pango-ot-buffer.c
@@ -0,0 +1,380 @@
+/* Pango
+ * pango-ot-buffer.c: Buffer of glyphs for shaping/positioning
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-ot-private.h"
+#include "pangofc-private.h"
+
+/**
+ * pango_ot_buffer_new
+ * @font: a #PangoFcFont
+ *
+ * Creates a new #PangoOTBuffer for the given OpenType font.
+ *
+ * Return value: the newly allocated #PangoOTBuffer, which should
+ * be freed with pango_ot_buffer_destroy().
+ *
+ * Since: 1.4
+ **/
+PangoOTBuffer *
+pango_ot_buffer_new (PangoFcFont *font)
+{
+ /* We lock the font here immediately for the silly reason
+ * of getting the FT_Memory; otherwise we'd have to
+ * add a new operation to PangoFcFontmap; callers will
+ * probably already have the font locked, however,
+ * so there is little performance penalty.
+ */
+ PangoOTBuffer *buffer = g_slice_new (PangoOTBuffer);
+ FT_Face face = pango_fc_font_lock_face (font);
+
+ if (hb_buffer_new (face->memory, &buffer->buffer) != FT_Err_Ok)
+ g_warning ("Allocation of HB_Buffer failed"); /* this doesn't happen */
+
+ buffer->font = g_object_ref (font);
+ buffer->applied_gpos = FALSE;
+ buffer->rtl = FALSE;
+ buffer->zero_width_marks = FALSE;
+
+ pango_fc_font_unlock_face (font);
+
+ return buffer;
+}
+
+/**
+ * pango_ot_buffer_destroy
+ * @buffer: a #PangoOTBuffer
+ *
+ * Destroys a #PangoOTBuffer and free all associated memory.
+ *
+ * Since: 1.4
+ **/
+void
+pango_ot_buffer_destroy (PangoOTBuffer *buffer)
+{
+ hb_buffer_free (buffer->buffer);
+ g_object_unref (buffer->font);
+ g_slice_free (PangoOTBuffer, buffer);
+}
+
+/**
+ * pango_ot_buffer_clear
+ * @buffer: a #PangoOTBuffer
+ *
+ * Empties a #PangoOTBuffer, make it ready to add glyphs to.
+ *
+ * Since: 1.4
+ **/
+void
+pango_ot_buffer_clear (PangoOTBuffer *buffer)
+{
+ hb_buffer_clear (buffer->buffer);
+ buffer->applied_gpos = FALSE;
+}
+
+/**
+ * pango_ot_buffer_add_glyph
+ * @buffer: a #PangoOTBuffer
+ * @glyph: the glyph index to add, like a #PangoGlyph
+ * @properties: the glyph properties
+ * @cluster: the cluster that this glyph belongs to
+ *
+ * Appends a glyph to a #PangoOTBuffer, with @properties identifying which
+ * features should be applied on this glyph. See pango_ruleset_add_feature().
+ *
+ * Since: 1.4
+ **/
+void
+pango_ot_buffer_add_glyph (PangoOTBuffer *buffer,
+ guint glyph,
+ guint properties,
+ guint cluster)
+{
+ hb_buffer_add_glyph (buffer->buffer,
+ glyph, properties, cluster);
+}
+
+/**
+ * pango_ot_buffer_set_rtl
+ * @buffer: a #PangoOTBuffer
+ * @rtl: %TRUE for right-to-left text
+ *
+ * Sets whether glyphs will be rendered right-to-left. This setting
+ * is needed for proper horizontal positioning of right-to-left scripts.
+ *
+ * Since: 1.4
+ **/
+void
+pango_ot_buffer_set_rtl (PangoOTBuffer *buffer,
+ gboolean rtl)
+{
+ buffer->rtl = rtl != FALSE;
+}
+
+/**
+ * pango_ot_buffer_set_zero_width_marks
+ * @buffer: a #PangoOTBuffer
+ * @zero_width_marks: %TRUE if characters with a mark class should
+ * be forced to zero width.
+ *
+ * Sets whether characters with a mark class should be forced to zero width.
+ * This setting is needed for proper positioning of Arabic accents,
+ * but will produce incorrect results with standard OpenType Indic
+ * fonts.
+ *
+ * Since: 1.6
+ **/
+void
+pango_ot_buffer_set_zero_width_marks (PangoOTBuffer *buffer,
+ gboolean zero_width_marks)
+{
+ buffer->zero_width_marks = zero_width_marks != FALSE;
+}
+
+/**
+ * pango_ot_buffer_get_glyphs
+ * @buffer: a #PangoOTBuffer
+ * @glyphs: location to store the array of glyphs, or %NULL
+ * @n_glyphs: location to store the number of glyphs, or %NULL
+ *
+ * Gets the glyph array contained in a #PangoOTBuffer. The glyphs are
+ * owned by the buffer and should not be freed, and are only valid as long
+ * as buffer is not modified.
+ *
+ * Since: 1.4
+ **/
+void
+pango_ot_buffer_get_glyphs (const PangoOTBuffer *buffer,
+ PangoOTGlyph **glyphs,
+ int *n_glyphs)
+{
+ if (glyphs)
+ *glyphs = (PangoOTGlyph *)buffer->buffer->in_string;
+
+ if (n_glyphs)
+ *n_glyphs = buffer->buffer->in_length;
+}
+
+static void
+swap_range (PangoGlyphString *glyphs, int start, int end)
+{
+ int i, j;
+
+ for (i = start, j = end - 1; i < j; i++, j--)
+ {
+ PangoGlyphInfo glyph_info;
+ gint log_cluster;
+
+ glyph_info = glyphs->glyphs[i];
+ glyphs->glyphs[i] = glyphs->glyphs[j];
+ glyphs->glyphs[j] = glyph_info;
+
+ log_cluster = glyphs->log_clusters[i];
+ glyphs->log_clusters[i] = glyphs->log_clusters[j];
+ glyphs->log_clusters[j] = log_cluster;
+ }
+}
+
+static void
+apply_gpos_ltr (PangoGlyphString *glyphs,
+ HB_Position positions,
+ gboolean is_hinted)
+{
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ FT_Pos x_pos = positions[i].x_pos;
+ FT_Pos y_pos = positions[i].y_pos;
+ int back = i;
+ int j;
+ int adjustment;
+
+
+ adjustment = PANGO_UNITS_26_6(positions[i].x_advance);
+
+ if (is_hinted)
+ adjustment = PANGO_UNITS_ROUND (adjustment);
+
+ if (positions[i].new_advance)
+ glyphs->glyphs[i].geometry.width = adjustment;
+ else
+ glyphs->glyphs[i].geometry.width += adjustment;
+
+
+ while (positions[back].back != 0)
+ {
+ back -= positions[back].back;
+ x_pos += positions[back].x_pos;
+ y_pos += positions[back].y_pos;
+ }
+
+ for (j = back; j < i; j++)
+ glyphs->glyphs[i].geometry.x_offset -= glyphs->glyphs[j].geometry.width;
+
+ glyphs->glyphs[i].geometry.x_offset += PANGO_UNITS_26_6(x_pos);
+ glyphs->glyphs[i].geometry.y_offset -= PANGO_UNITS_26_6(y_pos);
+ }
+}
+
+static void
+apply_gpos_rtl (PangoGlyphString *glyphs,
+ HB_Position positions,
+ gboolean is_hinted)
+{
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ int i_rev = glyphs->num_glyphs - i - 1;
+ int back_rev = i_rev;
+ int back;
+ FT_Pos x_pos = positions[i_rev].x_pos;
+ FT_Pos y_pos = positions[i_rev].y_pos;
+ int j;
+ int adjustment;
+
+
+ adjustment = PANGO_UNITS_26_6(positions[i_rev].x_advance);
+
+ if (is_hinted)
+ adjustment = PANGO_UNITS_ROUND (adjustment);
+
+ if (positions[i_rev].new_advance)
+ glyphs->glyphs[i].geometry.width = adjustment;
+ else
+ glyphs->glyphs[i].geometry.width += adjustment;
+
+
+ while (positions[back_rev].back != 0)
+ {
+ back_rev -= positions[back_rev].back;
+ x_pos += positions[back_rev].x_pos;
+ y_pos += positions[back_rev].y_pos;
+ }
+
+ back = glyphs->num_glyphs - back_rev - 1;
+
+ for (j = i; j < back; j++)
+ glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[j].geometry.width;
+
+ glyphs->glyphs[i].geometry.x_offset += PANGO_UNITS_26_6(x_pos);
+ glyphs->glyphs[i].geometry.y_offset -= PANGO_UNITS_26_6(y_pos);
+ }
+}
+
+/**
+ * pango_ot_buffer_output
+ * @buffer: a #PangoOTBuffer
+ * @glyphs: a #PangoGlyphString
+ *
+ * Exports the glyphs in a #PangoOTBuffer into a #PangoGlyphString. This is
+ * typically used after the OpenType layout processing is over, to convert the
+ * resulting glyphs into a generic Pango glyph string.
+ *
+ * Since: 1.4
+ **/
+void
+pango_ot_buffer_output (const PangoOTBuffer *buffer,
+ PangoGlyphString *glyphs)
+{
+ FT_Face face;
+ PangoOTInfo *info;
+ HB_GDEF gdef = NULL;
+ unsigned int i;
+ int last_cluster;
+
+ face = pango_fc_font_lock_face (buffer->font);
+ g_assert (face);
+
+ /* Copy glyphs into output glyph string */
+ pango_glyph_string_set_size (glyphs, buffer->buffer->in_length);
+
+ last_cluster = -1;
+ for (i = 0; i < buffer->buffer->in_length; i++)
+ {
+ HB_GlyphItem item = &buffer->buffer->in_string[i];
+
+ glyphs->glyphs[i].glyph = item->gindex;
+
+ glyphs->log_clusters[i] = item->cluster;
+ if (glyphs->log_clusters[i] != last_cluster)
+ glyphs->glyphs[i].attr.is_cluster_start = 1;
+ else
+ glyphs->glyphs[i].attr.is_cluster_start = 0;
+
+ last_cluster = glyphs->log_clusters[i];
+ }
+
+ info = pango_ot_info_get (face);
+ gdef = pango_ot_info_get_gdef (info);
+
+ /* Apply default positioning */
+ for (i = 0; i < (unsigned int)glyphs->num_glyphs; i++)
+ {
+ if (glyphs->glyphs[i].glyph)
+ {
+ PangoRectangle logical_rect;
+
+ FT_UShort property;
+
+ if (buffer->zero_width_marks &&
+ gdef &&
+ HB_GDEF_Get_Glyph_Property (gdef, glyphs->glyphs[i].glyph, &property) == FT_Err_Ok &&
+ (property == HB_GDEF_MARK || (property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS) != 0))
+ {
+ glyphs->glyphs[i].geometry.width = 0;
+ }
+ else
+ {
+ pango_font_get_glyph_extents ((PangoFont *)buffer->font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+ }
+ }
+ else
+ glyphs->glyphs[i].geometry.width = 0;
+
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+ }
+
+ if (buffer->rtl)
+ {
+ /* Swap all glyphs */
+ swap_range (glyphs, 0, glyphs->num_glyphs);
+ }
+
+ if (buffer->applied_gpos)
+ {
+ if (buffer->rtl)
+ apply_gpos_rtl (glyphs, buffer->buffer->positions, buffer->font->is_hinted);
+ else
+ apply_gpos_ltr (glyphs, buffer->buffer->positions, buffer->font->is_hinted);
+ }
+ else
+ {
+ /* FIXME we should only do this if the 'kern' feature was requested */
+ pango_fc_font_kern_glyphs (buffer->font, glyphs);
+ }
+
+ pango_fc_font_unlock_face (buffer->font);
+}
diff --git a/trunk/pango/pango-ot-info.c b/trunk/pango/pango-ot-info.c
new file mode 100644
index 00000000..73779370
--- /dev/null
+++ b/trunk/pango/pango-ot-info.c
@@ -0,0 +1,791 @@
+/* Pango
+ * pango-ot-info.c: Store tables for OpenType
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-ot-private.h"
+#include "pango-impl-utils.h"
+#include FT_MODULE_H
+
+static void pango_ot_info_class_init (GObjectClass *object_class);
+static void pango_ot_info_finalize (GObject *object);
+
+static GObjectClass *parent_class;
+
+enum
+{
+ INFO_LOADED_GDEF = 1 << 0,
+ INFO_LOADED_GSUB = 1 << 1,
+ INFO_LOADED_GPOS = 1 << 2
+};
+
+GType
+pango_ot_info_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoOTInfoClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc)pango_ot_info_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoOTInfo),
+ 0, /* n_preallocs */
+ NULL, /* init */
+ NULL, /* value_table */
+ };
+
+ object_type = g_type_register_static (G_TYPE_OBJECT,
+ I_("PangoOTInfo"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+pango_ot_info_class_init (GObjectClass *object_class)
+{
+ parent_class = g_type_class_peek_parent (object_class);
+
+ object_class->finalize = pango_ot_info_finalize;
+}
+
+static void
+pango_ot_info_finalize (GObject *object)
+{
+ PangoOTInfo *info = PANGO_OT_INFO (object);
+
+ if (info->gdef)
+ {
+ HB_Done_GDEF_Table (info->gdef);
+ info->gdef = NULL;
+ }
+ if (info->gsub)
+ {
+ HB_Done_GSUB_Table (info->gsub);
+ info->gsub = NULL;
+ }
+ if (info->gpos)
+ {
+ HB_Done_GPOS_Table (info->gpos);
+ info->gpos = NULL;
+ }
+
+ parent_class->finalize (object);
+}
+
+static void
+pango_ot_info_finalizer (void *object)
+{
+ FT_Face face = object;
+ PangoOTInfo *info = face->generic.data;
+
+ info->face = NULL;
+ g_object_unref (info);
+}
+
+/**
+ * pango_ot_info_get:
+ * @face: a <type>FT_Face</type>.
+ *
+ * Returns the #PangoOTInfo structure for the given FreeType font.
+ *
+ * Return value: the #PangoOTInfo for @face. This object will have
+ * the same lifetime as @face.
+ *
+ * Since: 1.2
+ **/
+PangoOTInfo *
+pango_ot_info_get (FT_Face face)
+{
+ PangoOTInfo *info;
+
+ if (face->generic.data)
+ return face->generic.data;
+ else
+ {
+ info = face->generic.data = g_object_new (PANGO_TYPE_OT_INFO, NULL);
+ face->generic.finalizer = pango_ot_info_finalizer;
+
+ info->face = face;
+ }
+
+ return info;
+}
+
+/* There must be be a better way to do this
+ */
+static gboolean
+is_truetype (FT_Face face)
+{
+ return FT_IS_SFNT(face);
+}
+
+typedef struct _GlyphInfo GlyphInfo;
+
+struct _GlyphInfo {
+ FT_UShort glyph;
+ FT_UShort class;
+};
+
+static int
+compare_glyph_info (gconstpointer a,
+ gconstpointer b)
+{
+ const GlyphInfo *info_a = a;
+ const GlyphInfo *info_b = b;
+
+ return (info_a->glyph < info_b->glyph) ? -1 :
+ (info_a->glyph == info_b->glyph) ? 0 : 1;
+}
+
+/* Make a guess at the appropriate class for a glyph given
+ * a character code that maps to the glyph
+ */
+static gboolean
+get_glyph_class (gunichar charcode,
+ FT_UShort *class)
+{
+ /* For characters mapped into the Arabic Presentation forms, using properties
+ * derived as we apply GSUB substitutions will be more reliable
+ */
+ if ((charcode >= 0xFB50 && charcode <= 0xFDFF) || /* Arabic Presentation Forms-A */
+ (charcode >= 0xFE70 && charcode <= 0XFEFF)) /* Arabic Presentation Forms-B */
+ return FALSE;
+
+ switch (g_unichar_type (charcode))
+ {
+ case G_UNICODE_COMBINING_MARK:
+ case G_UNICODE_ENCLOSING_MARK:
+ case G_UNICODE_NON_SPACING_MARK:
+ *class = 3; /* Mark glyph (non-spacing combining glyph) */
+ return TRUE;
+ case G_UNICODE_UNASSIGNED:
+ case G_UNICODE_PRIVATE_USE:
+ return FALSE; /* Unknown, don't assign a class; classes get
+ * propagated during GSUB application */
+ default:
+ *class = 1; /* Base glyph (single character, spacing glyph) */
+ return TRUE;
+ }
+}
+
+static gboolean
+set_unicode_charmap (FT_Face face)
+{
+ int charmap;
+
+ for (charmap = 0; charmap < face->num_charmaps; charmap++)
+ if (face->charmaps[charmap]->encoding == ft_encoding_unicode)
+ {
+ FT_Error error = FT_Set_Charmap(face, face->charmaps[charmap]);
+ return error == FT_Err_Ok;
+ }
+
+ return FALSE;
+}
+
+/* Synthesize a GDEF table using the font's charmap and the
+ * Unicode property database. We'll fill in class definitions
+ * for glyphs not in the charmap as we walk through the tables.
+ */
+static void
+synthesize_class_def (PangoOTInfo *info)
+{
+ GArray *glyph_infos;
+ FT_UShort *glyph_indices;
+ FT_UShort *classes;
+ FT_ULong charcode;
+ FT_UInt glyph;
+ unsigned int i, j;
+ FT_CharMap old_charmap;
+
+ old_charmap = info->face->charmap;
+
+ if (!old_charmap || !old_charmap->encoding != ft_encoding_unicode)
+ if (!set_unicode_charmap (info->face))
+ return;
+
+ glyph_infos = g_array_new (FALSE, FALSE, sizeof (GlyphInfo));
+
+ /* Collect all the glyphs in the charmap, and guess
+ * the appropriate classes for them
+ */
+ charcode = FT_Get_First_Char (info->face, &glyph);
+ while (glyph != 0)
+ {
+ GlyphInfo glyph_info;
+
+ if (glyph <= 65535)
+ {
+ glyph_info.glyph = glyph;
+ if (get_glyph_class (charcode, &glyph_info.class))
+ g_array_append_val (glyph_infos, glyph_info);
+ }
+
+ charcode = FT_Get_Next_Char (info->face, charcode, &glyph);
+ }
+
+ /* Sort and remove duplicates
+ */
+ g_array_sort (glyph_infos, compare_glyph_info);
+
+ glyph_indices = g_new (FT_UShort, glyph_infos->len);
+ classes = g_new (FT_UShort, glyph_infos->len);
+
+ for (i = 0, j = 0; i < glyph_infos->len; i++)
+ {
+ GlyphInfo *info = &g_array_index (glyph_infos, GlyphInfo, i);
+
+ if (j == 0 || info->glyph != glyph_indices[j - 1])
+ {
+ glyph_indices[j] = info->glyph;
+ classes[j] = info->class;
+
+ j++;
+ }
+ }
+
+ g_array_free (glyph_infos, TRUE);
+
+ HB_GDEF_Build_ClassDefinition (info->gdef, info->face->num_glyphs, j,
+ glyph_indices, classes);
+
+ g_free (glyph_indices);
+ g_free (classes);
+
+ if (old_charmap && info->face->charmap != old_charmap)
+ FT_Set_Charmap (info->face, old_charmap);
+}
+
+HB_GDEF
+pango_ot_info_get_gdef (PangoOTInfo *info)
+{
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
+
+ if (!(info->loaded & INFO_LOADED_GDEF))
+ {
+ FT_Error error;
+
+ info->loaded |= INFO_LOADED_GDEF;
+
+ if (is_truetype (info->face))
+ {
+ error = HB_Load_GDEF_Table (info->face, &info->gdef);
+
+ if (error && error != FT_Err_Table_Missing)
+ g_warning ("Error loading GDEF table %d", error);
+
+ if (!info->gdef)
+ error = HB_New_GDEF_Table (info->face, &info->gdef);
+
+ if (info->gdef && !info->gdef->GlyphClassDef.loaded)
+ synthesize_class_def (info);
+ }
+ }
+
+ return info->gdef;
+}
+
+HB_GSUB
+pango_ot_info_get_gsub (PangoOTInfo *info)
+{
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
+
+ if (!(info->loaded & INFO_LOADED_GSUB))
+ {
+ FT_Error error;
+ HB_GDEF gdef = pango_ot_info_get_gdef (info);
+
+ info->loaded |= INFO_LOADED_GSUB;
+
+ if (is_truetype (info->face))
+ {
+ error = HB_Load_GSUB_Table (info->face, &info->gsub, gdef);
+
+ if (error && error != FT_Err_Table_Missing)
+ g_warning ("Error loading GSUB table %d", error);
+ }
+ }
+
+ return info->gsub;
+}
+
+HB_GPOS
+pango_ot_info_get_gpos (PangoOTInfo *info)
+{
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
+
+ if (!(info->loaded & INFO_LOADED_GPOS))
+ {
+ FT_Error error;
+ HB_GDEF gdef = pango_ot_info_get_gdef (info);
+
+ info->loaded |= INFO_LOADED_GPOS;
+
+ if (is_truetype (info->face))
+ {
+ error = HB_Load_GPOS_Table (info->face, &info->gpos, gdef);
+
+ if (error && error != FT_Err_Table_Missing)
+ g_warning ("Error loading GPOS table %d", error);
+ }
+ }
+
+ return info->gpos;
+}
+
+static gboolean
+get_tables (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ HB_ScriptList **script_list,
+ HB_FeatureList **feature_list)
+{
+ if (table_type == PANGO_OT_TABLE_GSUB)
+ {
+ HB_GSUB gsub = pango_ot_info_get_gsub (info);
+
+ if (!gsub)
+ return FALSE;
+ else
+ {
+ if (script_list)
+ *script_list = &gsub->ScriptList;
+ if (feature_list)
+ *feature_list = &gsub->FeatureList;
+ return TRUE;
+ }
+ }
+ else
+ {
+ HB_GPOS gpos = pango_ot_info_get_gpos (info);
+
+ if (!gpos)
+ return FALSE;
+ else
+ {
+ if (script_list)
+ *script_list = &gpos->ScriptList;
+ if (feature_list)
+ *feature_list = &gpos->FeatureList;
+ return TRUE;
+ }
+ }
+}
+
+/**
+ * pango_ot_info_find_script:
+ * @info: a #PangoOTInfo.
+ * @table_type: the table type to obtain information about.
+ * @script_tag: the tag of the script to find.
+ * @script_index: location to store the index of the script, or %NULL.
+ *
+ * Finds the index of a script. If not found, tries to find the 'DFLT'
+ * and then 'dflt' scripts and return the index of that in @script_index.
+ * If none of those is found either, %PANGO_OT_NO_SCRIPT is placed in
+ * @script_index.
+ *
+ * All other functions taking an input script_index parameter know
+ * how to handle %PANGO_OT_NO_SCRIPT, so one can ignore the return
+ * value of this function completely and proceed, to enjoy the automatic
+ * fallback to the 'DFLT'/'dflt' script.
+ *
+ * Return value: %TRUE if the script was found.
+ **/
+gboolean
+pango_ot_info_find_script (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ PangoOTTag script_tag,
+ guint *script_index)
+{
+ HB_ScriptList *script_list;
+ int i;
+
+ if (script_index)
+ *script_index = PANGO_OT_NO_SCRIPT;
+
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), FALSE);
+
+ if (!get_tables (info, table_type, &script_list, NULL))
+ return FALSE;
+
+ for (i=0; i < script_list->ScriptCount; i++)
+ {
+ if (script_list->ScriptRecord[i].ScriptTag == script_tag)
+ {
+ if (script_index)
+ *script_index = i;
+
+ return TRUE;
+ }
+ }
+
+ /* try finding 'DFLT' */
+ script_tag = PANGO_OT_TAG_DEFAULT_SCRIPT;
+
+ for (i=0; i < script_list->ScriptCount; i++)
+ {
+ if (script_list->ScriptRecord[i].ScriptTag == script_tag)
+ {
+ if (script_index)
+ *script_index = i;
+
+ return FALSE;
+ }
+ }
+
+ /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
+ script_tag = FT_MAKE_TAG ('d', 'f', 'l', 't');
+
+ for (i=0; i < script_list->ScriptCount; i++)
+ {
+ if (script_list->ScriptRecord[i].ScriptTag == script_tag)
+ {
+ if (script_index)
+ *script_index = i;
+
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * pango_ot_info_find_language:
+ * @info: a #PangoOTInfo.
+ * @table_type: the table type to obtain information about.
+ * @script_index: the index of the script whose languages are searched.
+ * @language_tag: the tag of the language to find.
+ * @language_index: location to store the index of the language, or %NULL.
+ * @required_feature_index: location to store the required feature index of
+ * the language, or %NULL.
+ *
+ * Finds the index of a language and its required feature index.
+ * If the language is not found, sets @language_index to
+ * PANGO_OT_DEFAULT_LANGUAGE and the required feature of the default language
+ * system is returned in required_feature_index. For best compatibility with
+ * some fonts, also searches the language system tag 'dflt' before falling
+ * back to the default language system, but that is transparent to the user.
+ * The user can simply ignore the return value of this function to
+ * automatically fall back to the default language system.
+ *
+ * Return value: %TRUE if the language was found.
+ **/
+gboolean
+pango_ot_info_find_language (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ guint script_index,
+ PangoOTTag language_tag,
+ guint *language_index,
+ guint *required_feature_index)
+{
+ HB_ScriptList *script_list;
+ HB_Script *script;
+ int i;
+
+ if (language_index)
+ *language_index = PANGO_OT_DEFAULT_LANGUAGE;
+ if (required_feature_index)
+ *required_feature_index = PANGO_OT_NO_FEATURE;
+
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), FALSE);
+
+ if (script_index == PANGO_OT_NO_SCRIPT)
+ return FALSE;
+
+ if (!get_tables (info, table_type, &script_list, NULL))
+ return FALSE;
+
+ g_return_val_if_fail (script_index < script_list->ScriptCount, FALSE);
+
+ script = &script_list->ScriptRecord[script_index].Script;
+
+ for (i = 0; i < script->LangSysCount; i++)
+ {
+ if (script->LangSysRecord[i].LangSysTag == language_tag)
+ {
+ if (language_index)
+ *language_index = i;
+ if (required_feature_index)
+ *required_feature_index = script->LangSysRecord[i].LangSys.ReqFeatureIndex;
+ return TRUE;
+ }
+ }
+
+ /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
+ language_tag = FT_MAKE_TAG ('d', 'f', 'l', 't');
+
+ for (i = 0; i < script->LangSysCount; i++)
+ {
+ if (script->LangSysRecord[i].LangSysTag == language_tag)
+ {
+ if (language_index)
+ *language_index = i;
+ if (required_feature_index)
+ *required_feature_index = script->LangSysRecord[i].LangSys.ReqFeatureIndex;
+ return FALSE;
+ }
+ }
+
+ /* DefaultLangSys */
+ if (language_index)
+ *language_index = PANGO_OT_DEFAULT_LANGUAGE;
+ if (required_feature_index)
+ *required_feature_index = script->DefaultLangSys.ReqFeatureIndex;
+
+ return FALSE;
+}
+
+/**
+ * pango_ot_info_find_feature:
+ * @info: a #PangoOTInfo.
+ * @table_type: the table type to obtain information about.
+ * @feature_tag: the tag of the feature to find.
+ * @script_index: the index of the script.
+ * @language_index: the index of the language whose features are searched,
+ * or %PANGO_OT_DEFAULT_LANGUAGE to use the default language of the script.
+ * @feature_index: location to store the index of the feature, or %NULL.
+ *
+ * Finds the index of a feature. If the feature is not found, sets
+ * @feature_index to PANGO_OT_NO_FEATURE, which is safe to pass to
+ * pango_ot_ruleset_add_feature() and similar functions.
+ *
+ * In the future, this may set @feature_index to an special value that if used
+ * in pango_ot_ruleset_add_feature() will ask Pango to synthesize the
+ * requested feature based on Unicode properties and data. However, this
+ * function will still return %FALSE in those cases. So, users may want to
+ * ignore the return value of this function in certain cases.
+ *
+ * Return value: %TRUE if the feature was found.
+ **/
+gboolean
+pango_ot_info_find_feature (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ PangoOTTag feature_tag,
+ guint script_index,
+ guint language_index,
+ guint *feature_index)
+{
+ HB_ScriptList *script_list;
+ HB_FeatureList *feature_list;
+ HB_Script *script;
+ HB_LangSys *lang_sys;
+
+ int i;
+
+ if (feature_index)
+ *feature_index = PANGO_OT_NO_FEATURE;
+
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), FALSE);
+
+ if (script_index == PANGO_OT_NO_SCRIPT)
+ return FALSE;
+
+ if (!get_tables (info, table_type, &script_list, &feature_list))
+ return FALSE;
+
+ g_return_val_if_fail (script_index < script_list->ScriptCount, FALSE);
+
+ script = &script_list->ScriptRecord[script_index].Script;
+
+ if (language_index == PANGO_OT_DEFAULT_LANGUAGE)
+ lang_sys = &script->DefaultLangSys;
+ else
+ {
+ g_return_val_if_fail (language_index < script->LangSysCount, FALSE);
+ lang_sys = &script->LangSysRecord[language_index].LangSys;
+ }
+
+ for (i = 0; i < lang_sys->FeatureCount; i++)
+ {
+ FT_UShort index = lang_sys->FeatureIndex[i];
+
+ if (feature_list->FeatureRecord[index].FeatureTag == feature_tag)
+ {
+ if (feature_index)
+ *feature_index = index;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * pango_ot_info_list_scripts:
+ * @info: a #PangoOTInfo.
+ * @table_type: the table type to obtain information about.
+ *
+ * Obtains the list of available scripts.
+ *
+ * Return value: a newly-allocated zero-terminated array containing the tags of the
+ * available scripts. Should be freed using g_free().
+ **/
+PangoOTTag *
+pango_ot_info_list_scripts (PangoOTInfo *info,
+ PangoOTTableType table_type)
+{
+ PangoOTTag *result;
+ HB_ScriptList *script_list;
+ int i;
+
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
+
+ if (!get_tables (info, table_type, &script_list, NULL))
+ return NULL;
+
+ result = g_new (PangoOTTag, script_list->ScriptCount + 1);
+
+ for (i=0; i < script_list->ScriptCount; i++)
+ result[i] = script_list->ScriptRecord[i].ScriptTag;
+
+ result[i] = 0;
+
+ return result;
+}
+
+/**
+ * pango_ot_info_list_languages:
+ * @info: a #PangoOTInfo.
+ * @table_type: the table type to obtain information about.
+ * @script_index: the index of the script to list languages for.
+ * @language_tag: unused parameter.
+ *
+ * Obtains the list of available languages for a given script.
+ *
+ * Return value: a newly-allocated zero-terminated array containing the tags of the
+ * available languages. Should be freed using g_free().
+ **/
+PangoOTTag *
+pango_ot_info_list_languages (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ guint script_index,
+ PangoOTTag language_tag G_GNUC_UNUSED)
+{
+ PangoOTTag *result;
+ HB_ScriptList *script_list;
+ HB_Script *script;
+ int i;
+
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
+
+ if (script_index == PANGO_OT_NO_SCRIPT)
+ {
+ result = g_new (PangoOTTag, 1);
+ result[0] = 0;
+ return result;
+ }
+
+ if (!get_tables (info, table_type, &script_list, NULL))
+ return NULL;
+
+ g_return_val_if_fail (script_index < script_list->ScriptCount, NULL);
+
+ script = &script_list->ScriptRecord[script_index].Script;
+
+ result = g_new (PangoOTTag, script->LangSysCount + 1);
+
+ for (i = 0; i < script->LangSysCount; i++)
+ result[i] = script->LangSysRecord[i].LangSysTag;
+
+ result[i] = 0;
+
+ return result;
+}
+
+/**
+ * pango_ot_info_list_features:
+ * @info: a #PangoOTInfo.
+ * @table_type: the table type to obtain information about.
+ * @tag: unused parameter.
+ * @script_index: the index of the script to obtain information about.
+ * @language_index: the index of the language to list features for, or
+ * %PANGO_OT_DEFAULT_LANGUAGE, to list features for the default
+ * language of the script.
+ *
+ * Obtains the list of features for the given language of the given script.
+ *
+ * Return value: a newly-allocated zero-terminated array containing the tags of the
+ * available features. Should be freed using g_free().
+ **/
+PangoOTTag *
+pango_ot_info_list_features (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ PangoOTTag tag G_GNUC_UNUSED,
+ guint script_index,
+ guint language_index)
+{
+ PangoOTTag *result;
+
+ HB_ScriptList *script_list;
+ HB_FeatureList *feature_list;
+ HB_Script *script;
+ HB_LangSys *lang_sys;
+
+ int i;
+
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
+
+ if (script_index == PANGO_OT_NO_SCRIPT)
+ {
+ result = g_new (PangoOTTag, 1);
+ result[0] = 0;
+ return result;
+ }
+
+ if (!get_tables (info, table_type, &script_list, &feature_list))
+ return NULL;
+
+ g_return_val_if_fail (script_index < script_list->ScriptCount, NULL);
+
+ script = &script_list->ScriptRecord[script_index].Script;
+
+ if (language_index == PANGO_OT_DEFAULT_LANGUAGE)
+ lang_sys = &script->DefaultLangSys;
+ else
+ {
+ g_return_val_if_fail (language_index < script->LangSysCount, NULL);
+ lang_sys = &script->LangSysRecord[language_index].LangSys;
+ }
+
+ result = g_new (PangoOTTag, lang_sys->FeatureCount + 1);
+
+ for (i = 0; i < lang_sys->FeatureCount; i++)
+ {
+ FT_UShort index = lang_sys->FeatureIndex[i];
+
+ result[i] = feature_list->FeatureRecord[index].FeatureTag;
+ }
+
+ result[i] = 0;
+
+ return result;
+}
+
+
diff --git a/trunk/pango/pango-ot-private.h b/trunk/pango/pango-ot-private.h
new file mode 100644
index 00000000..88875e74
--- /dev/null
+++ b/trunk/pango/pango-ot-private.h
@@ -0,0 +1,105 @@
+/* Pango
+ * pango-ot-private.h: Implementation details for Pango OpenType code
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_OT_PRIVATE_H__
+#define __PANGO_OT_PRIVATE_H__
+
+#include <glib-object.h>
+
+#include <pango/pango-ot.h>
+#include "opentype/harfbuzz.h"
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_OT_INFO (pango_ot_info_get_type ())
+#define PANGO_OT_INFO(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_OT_INFO, PangoOTInfo))
+#define PANGO_OT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_OT_INFO, PangoOTInfoClass))
+#define PANGO_IS_OT_INFO(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_OT_INFO))
+#define PANGO_IS_OT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_OT_INFO))
+#define PANGO_OT_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_OT_INFO, PangoOTInfoClass))
+
+typedef struct _PangoOTInfoClass PangoOTInfoClass;
+
+struct _PangoOTInfo
+{
+ GObject parent_instance;
+
+ guint loaded;
+
+ FT_Face face;
+
+ HB_GSUB gsub;
+ HB_GDEF gdef;
+ HB_GPOS gpos;
+};
+
+struct _PangoOTInfoClass
+{
+ GObjectClass parent_class;
+};
+
+#define PANGO_TYPE_OT_RULESET (pango_ot_ruleset_get_type ())
+#define PANGO_OT_RULESET(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_OT_RULESET, PangoOTRuleset))
+#define PANGO_OT_RULESET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_OT_RULESET, PangoOTRulesetClass))f
+#define PANGO_IS_OT_RULESET(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_OT_RULESET))
+#define PANGO_IS_OT_RULESET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_OT_RULESET))
+#define PANGO_OT_RULESET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_OT_RULESET, PangoOTRulesetClass))
+
+typedef struct _PangoOTRulesetClass PangoOTRulesetClass;
+
+struct _PangoOTRuleset
+{
+ GObject parent_instance;
+
+ GArray *rules;
+ PangoOTInfo *info;
+
+ /* the index into these arrays is a PangoOTTableType */
+ guint n_features[2];
+ guint script_index[2];
+ guint language_index[2];
+};
+
+struct _PangoOTRulesetClass
+{
+ GObjectClass parent_class;
+};
+
+struct _PangoOTBuffer
+{
+ HB_Buffer buffer;
+ PangoFcFont *font;
+ guint rtl : 1;
+ guint zero_width_marks : 1;
+ guint applied_gpos : 1;
+};
+
+GType pango_ot_info_get_type (void) G_GNUC_CONST;
+
+HB_GDEF pango_ot_info_get_gdef (PangoOTInfo *info);
+HB_GSUB pango_ot_info_get_gsub (PangoOTInfo *info);
+HB_GPOS pango_ot_info_get_gpos (PangoOTInfo *info);
+
+GType pango_ot_ruleset_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __PANGO_OT_PRIVATE_H__ */
diff --git a/trunk/pango/pango-ot-ruleset.c b/trunk/pango/pango-ot-ruleset.c
new file mode 100644
index 00000000..141ce262
--- /dev/null
+++ b/trunk/pango/pango-ot-ruleset.c
@@ -0,0 +1,716 @@
+/* Pango
+ * pango-ot-ruleset.c: Shaping using OpenType features
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-ot-private.h"
+#include "pango-impl-utils.h"
+
+typedef struct _PangoOTRule PangoOTRule;
+
+struct _PangoOTRule
+{
+ gulong property_bit;
+ FT_UShort feature_index;
+ guint table_type : 1;
+};
+
+static void pango_ot_ruleset_class_init (GObjectClass *object_class);
+static void pango_ot_ruleset_init (PangoOTRuleset *ruleset);
+static void pango_ot_ruleset_finalize (GObject *object);
+
+static GObjectClass *parent_class;
+
+GType
+pango_ot_ruleset_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoOTRulesetClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc)pango_ot_ruleset_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoOTRuleset),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc)pango_ot_ruleset_init,
+ NULL /* value_table */
+ };
+
+ object_type = g_type_register_static (G_TYPE_OBJECT,
+ I_("PangoOTRuleset"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+pango_ot_ruleset_class_init (GObjectClass *object_class)
+{
+ parent_class = g_type_class_peek_parent (object_class);
+
+ object_class->finalize = pango_ot_ruleset_finalize;
+}
+
+static void
+pango_ot_ruleset_init (PangoOTRuleset *ruleset)
+{
+ ruleset->rules = g_array_new (FALSE, FALSE, sizeof (PangoOTRule));
+}
+
+static void
+pango_ot_ruleset_finalize (GObject *object)
+{
+ PangoOTRuleset *ruleset = PANGO_OT_RULESET (object);
+
+ g_array_free (ruleset->rules, TRUE);
+ if (ruleset->info)
+ g_object_remove_weak_pointer (ruleset->info, &ruleset->info);
+
+ parent_class->finalize (object);
+}
+
+/**
+ * pango_ot_ruleset_get_for_description:
+ * @info: a #PangoOTInfo.
+ * @desc: a #PangoOTRulesetDescription.
+ *
+ * Returns a ruleset for the given OpenType info and ruleset
+ * description. Rulesets are created on demand using
+ * pango_ot_ruleset_new_from_description().
+ * The returned ruleset should not be modified or destroyed.
+ *
+ * The static feature map members of @desc should be alive as
+ * long as @info is.
+ *
+ * Return value: the #PangoOTRuleset for @desc. This object will have
+ * the same lifetime as @info.
+ *
+ * Since: 1.18
+ **/
+G_CONST_RETURN PangoOTRuleset *
+pango_ot_ruleset_get_for_description (PangoOTInfo *info,
+ const PangoOTRulesetDescription *desc)
+{
+ PangoOTRuleset *ruleset;
+ static GQuark rulesets_quark = 0;
+ GHashTable *rulesets;
+
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ if (!rulesets_quark)
+ rulesets_quark = g_quark_from_string ("pango-info-rulesets");
+
+ rulesets = g_object_get_qdata (G_OBJECT (info), rulesets_quark);
+
+ if (!rulesets)
+ {
+ rulesets = g_hash_table_new_full ((GHashFunc) pango_ot_ruleset_description_hash,
+ (GEqualFunc) pango_ot_ruleset_description_equal,
+ (GDestroyNotify) pango_ot_ruleset_description_free,
+ (GDestroyNotify) g_object_unref);
+
+ g_object_set_qdata_full (G_OBJECT (info), rulesets_quark, rulesets, (GDestroyNotify) g_hash_table_destroy);
+ }
+
+ ruleset = g_hash_table_lookup (rulesets, desc);
+
+ if (!ruleset)
+ {
+ ruleset = pango_ot_ruleset_new_from_description (info, desc);
+
+ g_hash_table_insert (rulesets,
+ pango_ot_ruleset_description_copy (desc),
+ ruleset);
+ }
+
+ return ruleset;
+}
+
+/**
+ * pango_ot_ruleset_new:
+ * @info: a #PangoOTInfo.
+ *
+ * Creates a new #PangoOTRuleset for the given OpenType info.
+ *
+ * Return value: the newly allocated #PangoOTRuleset, which
+ * should be freed with g_object_unref().
+ **/
+PangoOTRuleset *
+pango_ot_ruleset_new (PangoOTInfo *info)
+{
+ PangoOTRuleset *ruleset;
+
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
+
+ ruleset = g_object_new (PANGO_TYPE_OT_RULESET, NULL);
+
+ ruleset->info = info;
+ g_object_add_weak_pointer (ruleset->info, &ruleset->info);
+
+ ruleset->script_index[0] = PANGO_OT_NO_SCRIPT;
+ ruleset->script_index[1] = PANGO_OT_NO_SCRIPT;
+ ruleset->language_index[0] = PANGO_OT_DEFAULT_LANGUAGE;
+ ruleset->language_index[1] = PANGO_OT_DEFAULT_LANGUAGE;
+
+ return ruleset;
+}
+
+/**
+ * pango_ot_ruleset_new_for:
+ * @info: a #PangoOTInfo.
+ * @script: a #PangoScript.
+ * @language: a #PangoLanguage.
+ *
+ * Creates a new #PangoOTRuleset for the given OpenType info, script, and
+ * language.
+ *
+ * This function is part of a convenience scheme that highly simplifies
+ * using a #PangoOTRuleset to represent features for a specific pair of script
+ * and language. So one can use this function passing in the script and
+ * language of interest, and later try to add features to the ruleset by just
+ * specifying the feature name or tag, without having to deal with finding
+ * script, language, or feature indices manually.
+ *
+ * In excess to what pango_ot_ruleset_new() does, this function will:
+ * <itemizedlist>
+ * <listitem>
+ * Find the #PangoOTTag script and language tags associated with
+ * @script and @language using pango_ot_tag_from_script() and
+ * pango_ot_tag_from_language(),
+ * </listitem>
+ * <listitem>
+ * For each of table types %PANGO_OT_TABLE_GSUB and %PANGO_OT_TABLE_GPOS,
+ * find the script index of the script tag found and the language
+ * system index of the language tag found in that script system, using
+ * pango_ot_info_find_script() and pango_ot_info_find_language(),
+ * </listitem>
+ * <listitem>
+ * For found language-systems, if they have required feature
+ * index, add that feature to the ruleset using
+ * pango_ot_ruleset_add_feature(),
+ * </listitem>
+ * <listitem>
+ * Remember found script and language indices for both table types,
+ * and use them in future pango_ot_ruleset_maybe_add_feature() and
+ * pango_ot_ruleset_maybe_add_features().
+ * </listitem>
+ * </itemizedlist>
+ *
+ * Because of the way return values of pango_ot_info_find_script() and
+ * pango_ot_info_find_language() are ignored, this function automatically
+ * finds and uses the 'DFLT' script and the default language-system.
+ *
+ * Return value: the newly allocated #PangoOTRuleset, which
+ * should be freed with g_object_unref().
+ *
+ * Since: 1.18
+ **/
+PangoOTRuleset *
+pango_ot_ruleset_new_for (PangoOTInfo *info,
+ PangoScript script,
+ PangoLanguage *language)
+{
+ PangoOTRuleset *ruleset;
+ PangoOTTag script_tag, language_tag;
+ PangoOTTableType table_type;
+
+ g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
+
+ ruleset = pango_ot_ruleset_new (info);
+
+ script_tag = pango_ot_tag_from_script (script);
+ language_tag = pango_ot_tag_from_language (language);
+
+ for (table_type = PANGO_OT_TABLE_GSUB; table_type <= PANGO_OT_TABLE_GPOS; table_type++)
+ {
+ guint script_index, language_index, feature_index;
+
+ pango_ot_info_find_script (ruleset->info, table_type,
+ script_tag, &script_index);
+ pango_ot_info_find_language (ruleset->info, table_type, script_index,
+ language_tag, &language_index,
+ &feature_index);
+
+ ruleset->script_index[table_type] = script_index;
+ ruleset->language_index[table_type] = language_index;
+
+ /* add required feature of the language */
+ pango_ot_ruleset_add_feature (ruleset, table_type,
+ feature_index, PANGO_OT_ALL_GLYPHS);
+ }
+
+ return ruleset;
+}
+
+/**
+ * pango_ot_ruleset_new_from_description:
+ * @info: a #PangoOTInfo.
+ * @desc: a #PangoOTRulesetDescription.
+ *
+ * Creates a new #PangoOTRuleset for the given OpenType infor and
+ * matching the given ruleset description.
+ *
+ * This is a convenience function that calls pango_ot_ruleset_new_for() and
+ * adds the static GSUB/GPOS features to the resulting ruleset, followed by
+ * adding other features to both GSUB and GPOS.
+ *
+ * The static feature map members of @desc should be alive as
+ * long as @info is.
+ *
+ * Return value: the newly allocated #PangoOTRuleset, which
+ * should be freed with g_object_unref().
+ *
+ * Since: 1.18
+ **/
+PangoOTRuleset *
+pango_ot_ruleset_new_from_description (PangoOTInfo *info,
+ const PangoOTRulesetDescription *desc)
+{
+ PangoOTRuleset *ruleset;
+
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ ruleset = pango_ot_ruleset_new_for (info,
+ desc->script,
+ desc->language);
+
+ if (desc->n_static_gsub_features)
+ pango_ot_ruleset_maybe_add_features (ruleset, PANGO_OT_TABLE_GSUB,
+ desc->static_gsub_features,
+ desc->n_static_gsub_features);
+ if (desc->n_static_gpos_features)
+ pango_ot_ruleset_maybe_add_features (ruleset, PANGO_OT_TABLE_GPOS,
+ desc->static_gpos_features,
+ desc->n_static_gpos_features);
+
+ if (desc->n_other_features)
+ {
+ pango_ot_ruleset_maybe_add_features (ruleset, PANGO_OT_TABLE_GSUB,
+ desc->other_features,
+ desc->n_other_features);
+ pango_ot_ruleset_maybe_add_features (ruleset, PANGO_OT_TABLE_GPOS,
+ desc->other_features,
+ desc->n_other_features);
+ }
+
+ return ruleset;
+}
+
+/**
+ * pango_ot_ruleset_add_feature:
+ * @ruleset: a #PangoOTRuleset.
+ * @table_type: the table type to add a feature to.
+ * @feature_index: the index of the feature to add.
+ * @property_bit: the property bit to use for this feature. Used to identify
+ * the glyphs that this feature should be applied to, or
+ * %PANGO_OT_ALL_GLYPHS if it should be applied to all glyphs.
+ *
+ * Adds a feature to the ruleset.
+ **/
+void
+pango_ot_ruleset_add_feature (PangoOTRuleset *ruleset,
+ PangoOTTableType table_type,
+ guint feature_index,
+ gulong property_bit)
+{
+ PangoOTRule tmp_rule;
+
+ g_return_if_fail (PANGO_IS_OT_RULESET (ruleset));
+ g_return_if_fail (ruleset->info != NULL);
+
+ if (feature_index == PANGO_OT_NO_FEATURE)
+ return;
+
+ tmp_rule.table_type = table_type;
+ tmp_rule.feature_index = feature_index;
+ tmp_rule.property_bit = property_bit;
+
+ g_array_append_val (ruleset->rules, tmp_rule);
+
+ ruleset->n_features[table_type]++;
+}
+
+/**
+ * pango_ot_ruleset_maybe_add_feature:
+ * @ruleset: a #PangoOTRuleset.
+ * @table_type: the table type to add a feature to.
+ * @feature_tag: the tag of the feature to add.
+ * @property_bit: the property bit to use for this feature. Used to identify
+ * the glyphs that this feature should be applied to, or
+ * %PANGO_OT_ALL_GLYPHS if it should be applied to all glyphs.
+ *
+ * This is a convenience function that first tries to find the feature
+ * using pango_ot_info_find_feature() and the ruleset script and language
+ * passed to pango_ot_ruleset_new_for(),
+ * and if the feature is found, adds it to the ruleset.
+ *
+ * If @ruleset was not created using pango_ot_ruleset_new_for(), this function
+ * does nothing.
+ *
+ * Return value: %TRUE if the feature was found and added to ruleset,
+ * %FALSE otherwise.
+ *
+ * Since: 1.18
+ **/
+gboolean
+pango_ot_ruleset_maybe_add_feature (PangoOTRuleset *ruleset,
+ PangoOTTableType table_type,
+ PangoOTTag feature_tag,
+ gulong property_bit)
+{
+ guint feature_index;
+
+ g_return_val_if_fail (PANGO_IS_OT_RULESET (ruleset), FALSE);
+ g_return_val_if_fail (ruleset->info != NULL, FALSE);
+
+ pango_ot_info_find_feature (ruleset->info, table_type,
+ feature_tag,
+ ruleset->script_index[table_type],
+ ruleset->language_index[table_type],
+ &feature_index);
+
+ if (feature_index != PANGO_OT_NO_FEATURE)
+ {
+ pango_ot_ruleset_add_feature (ruleset, table_type,
+ feature_index, property_bit);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * pango_ot_ruleset_maybe_add_features:
+ * @ruleset: a #PangoOTRuleset.
+ * @table_type: the table type to add features to.
+ * @features: array of feature name and property bits to add.
+ * @n_features: number of feature records in @features array.
+ *
+ * This is a convenience function that
+ * for each feature in the feature map array @features
+ * converts the feature name to a #PangoOTTag feature tag using FT_MAKE_TAG()
+ * and calls pango_ot_ruleset_maybe_add_feature() on it.
+ *
+ * Return value: The number of features in @features that were found
+ * and added to @ruleset.
+ *
+ * Since: 1.18
+ **/
+guint
+pango_ot_ruleset_maybe_add_features (PangoOTRuleset *ruleset,
+ PangoOTTableType table_type,
+ const PangoOTFeatureMap *features,
+ guint n_features)
+{
+ guint i, n_found_features = 0;
+
+ g_return_val_if_fail (PANGO_IS_OT_RULESET (ruleset), 0);
+ g_return_val_if_fail (ruleset->info != NULL, 0);
+
+ for (i = 0; i < n_features; i++)
+ {
+ PangoOTTag feature_tag = FT_MAKE_TAG (features[i].feature_name[0],
+ features[i].feature_name[1],
+ features[i].feature_name[2],
+ features[i].feature_name[3]);
+
+ n_found_features += pango_ot_ruleset_maybe_add_feature (ruleset,
+ table_type,
+ feature_tag,
+ features[i].property_bit);
+ }
+
+ return n_found_features;
+}
+
+/**
+ * pango_ot_ruleset_get_feature_count:
+ * @ruleset: a #PangoOTRuleset.
+ * @n_gsub_features: location to store number of GSUB features, or %NULL.
+ * @n_gpos_features: location to store number of GPOS features, or %NULL.
+ *
+ * Gets the number of GSUB and GPOS features in the ruleset.
+ *
+ * Return value: Total number of features in the @ruleset.
+ *
+ * Since: 1.18
+ **/
+guint
+pango_ot_ruleset_get_feature_count (const PangoOTRuleset *ruleset,
+ guint *n_gsub_features,
+ guint *n_gpos_features)
+{
+ g_return_val_if_fail (PANGO_IS_OT_RULESET (ruleset), 0);
+
+ if (n_gsub_features)
+ *n_gsub_features = ruleset->n_features[PANGO_OT_TABLE_GSUB];
+
+ if (n_gpos_features)
+ *n_gpos_features = ruleset->n_features[PANGO_OT_TABLE_GPOS];
+
+ return ruleset->n_features[PANGO_OT_TABLE_GSUB] + ruleset->n_features[PANGO_OT_TABLE_GPOS];
+}
+
+/**
+ * pango_ot_ruleset_substitute:
+ * @ruleset: a #PangoOTRuleset.
+ * @buffer: a #PangoOTBuffer.
+ *
+ * Performs the OpenType GSUB substitution on @buffer using the features
+ * in @ruleset
+ *
+ * Since: 1.4
+ **/
+void
+pango_ot_ruleset_substitute (const PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer)
+{
+ unsigned int i;
+
+ HB_GSUB gsub = NULL;
+
+ g_return_if_fail (PANGO_IS_OT_RULESET (ruleset));
+ g_return_if_fail (ruleset->info != NULL);
+
+ for (i = 0; i < ruleset->rules->len; i++)
+ {
+ PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
+
+ if (rule->table_type != PANGO_OT_TABLE_GSUB)
+ continue;
+
+ if (!gsub)
+ {
+ gsub = pango_ot_info_get_gsub (ruleset->info);
+
+ if (gsub)
+ HB_GSUB_Clear_Features (gsub);
+ else
+ return;
+ }
+
+ HB_GSUB_Add_Feature (gsub, rule->feature_index, rule->property_bit);
+ }
+
+ HB_GSUB_Apply_String (gsub, buffer->buffer);
+}
+
+/**
+ * pango_ot_ruleset_position:
+ * @ruleset: a #PangoOTRuleset.
+ * @buffer: a #PangoOTBuffer.
+ *
+ * Performs the OpenType GPOS positioning on @buffer using the features
+ * in @ruleset
+ *
+ * Since: 1.4
+ **/
+void
+pango_ot_ruleset_position (const PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer)
+{
+ unsigned int i;
+
+ HB_GPOS gpos = NULL;
+
+ g_return_if_fail (PANGO_IS_OT_RULESET (ruleset));
+ g_return_if_fail (ruleset->info != NULL);
+
+ for (i = 0; i < ruleset->rules->len; i++)
+ {
+ PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
+
+ if (rule->table_type != PANGO_OT_TABLE_GPOS)
+ continue;
+
+ if (!gpos)
+ {
+ gpos = pango_ot_info_get_gpos (ruleset->info);
+
+ if (gpos)
+ HB_GPOS_Clear_Features (gpos);
+ else
+ return;
+ }
+
+ HB_GPOS_Add_Feature (gpos, rule->feature_index, rule->property_bit);
+ }
+
+ if (HB_GPOS_Apply_String (ruleset->info->face, gpos, 0, buffer->buffer,
+ FALSE /* enable device-dependant values */,
+ buffer->rtl) == FT_Err_Ok)
+ buffer->applied_gpos = TRUE;
+}
+
+/* ruleset descriptions */
+
+/**
+ * pango_ot_ruleset_description_hash:
+ * @desc: a ruleset description
+ *
+ * Computes a hash of a #PangoOTRulesetDescription structure suitable
+ * to be used, for example, as an argument to g_hash_table_new().
+ *
+ * Return value: the hash value.
+ *
+ * Since: 1.18
+ **/
+guint
+pango_ot_ruleset_description_hash (const PangoOTRulesetDescription *desc)
+{
+ guint hash = 0;
+ guint i;
+
+ hash ^= desc->script;
+ hash ^= GPOINTER_TO_UINT (desc->language);
+
+ hash ^= desc->n_static_gsub_features << 8;
+ hash ^= GPOINTER_TO_UINT (desc->static_gsub_features);
+
+ hash ^= desc->n_static_gpos_features << 12;
+ hash ^= GPOINTER_TO_UINT (desc->static_gpos_features);
+
+ hash ^= desc->n_other_features << 16;
+ for (i = 0; i < desc->n_other_features; i++)
+ {
+ hash ^= * (guint32 *) desc->other_features[i].feature_name;
+ hash ^= desc->other_features[i].property_bit;
+ }
+
+ return hash;
+}
+
+/**
+ * pango_ot_ruleset_description_equal:
+ * @desc1: a ruleset description
+ * @desc2: a ruleset description
+ *
+ * Compares two ruleset descriptions for equality.
+ * Two ruleset descriptions are considered equal if the rulesets
+ * they describe are provably identical. This means that their
+ * script, language, and all feature sets should be equal. For static feature
+ * sets, the array addresses are compared directly, while for other
+ * features, the list of features is compared one by one.
+ * (Two ruleset descriptions may result in identical rulesets
+ * being created, but still compare %FALSE.)
+ *
+ * Return value: %TRUE if two ruleset descriptions are identical,
+ * %FALSE otherwise.
+ *
+ * Since: 1.18
+ **/
+gboolean
+pango_ot_ruleset_description_equal (const PangoOTRulesetDescription *desc1,
+ const PangoOTRulesetDescription *desc2)
+{
+ guint i;
+
+#undef CHECK
+#define CHECK(x) if (desc1->x != desc2->x) return FALSE;
+#define CHECK_FEATURE_NAME(x) if (*(guint32 *)desc1->x != *(guint32 *)desc2->x) return FALSE
+
+ CHECK (script);
+ CHECK (language);
+
+ CHECK (static_gsub_features);
+ CHECK (n_static_gsub_features);
+ CHECK (static_gpos_features);
+ CHECK (n_static_gpos_features);
+
+ CHECK (n_other_features);
+
+ for (i = 0; i < desc1->n_other_features; i++)
+ {
+ CHECK_FEATURE_NAME (other_features[i].feature_name);
+ CHECK (other_features[i].property_bit);
+ }
+
+#undef CHECK
+
+ return TRUE;
+}
+
+/**
+ * pango_ot_ruleset_description_copy:
+ * @desc: ruleset description to copy
+ *
+ * Creates a copy of @desc, which should be freed with
+ * pango_ot_ruleset_description_free(). Primarily used internally
+ * by pango_ot_ruleset_get_for_description() to cache rulesets for
+ * ruleset descriptions.
+ *
+ * Return value: the newly allocated #PangoOTRulesetDescription, which
+ * should be freed with pango_ot_ruleset_description_free().
+ *
+ * Since: 1.18
+ **/
+PangoOTRulesetDescription *
+pango_ot_ruleset_description_copy (const PangoOTRulesetDescription *desc)
+{
+ PangoOTRulesetDescription *copy;
+
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ copy = g_slice_new (PangoOTRulesetDescription);
+
+ *copy = *desc;
+
+ if (desc->n_other_features)
+ {
+ PangoOTFeatureMap *map = g_new (PangoOTFeatureMap, desc->n_other_features);
+ memcpy (map, desc->other_features, desc->n_other_features * sizeof (PangoOTFeatureMap));
+ copy->other_features = map;
+ }
+ else
+ {
+ copy->other_features = NULL;
+ }
+
+ return copy;
+}
+
+/**
+ * pango_ot_ruleset_description_free:
+ * @desc: an allocated #PangoOTRulesetDescription
+ *
+ * Frees a ruleset description allocated by
+ * pango_ot_ruleset_description_copy().
+ *
+ * Since: 1.18
+ **/
+void
+pango_ot_ruleset_description_free (PangoOTRulesetDescription *desc)
+{
+ g_return_if_fail (desc != NULL);
+
+ free ((gpointer) desc->other_features);
+
+ g_slice_free (PangoOTRulesetDescription, desc);
+}
diff --git a/trunk/pango/pango-ot-tag.c b/trunk/pango/pango-ot-tag.c
new file mode 100644
index 00000000..e12d8f4e
--- /dev/null
+++ b/trunk/pango/pango-ot-tag.c
@@ -0,0 +1,489 @@
+/* Pango
+ * pango-ot-tag.h:
+ *
+ * Copyright (C) 2007 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-ot.h"
+
+typedef union {
+ char string[4];
+ guint32 integer;
+} Tag;
+
+/*
+ * complete list at:
+ * http://www.microsoft.com/typography/developers/opentype/scripttags.aspx
+ */
+static const Tag ot_scripts[] = {
+ {"DFLT"}, /* PANGO_SCRIPT_COMMON */
+ {"DFLT"}, /* PANGO_SCRIPT_INHERITED */
+ {"arab"}, /* PANGO_SCRIPT_ARABIC */
+ {"armn"}, /* PANGO_SCRIPT_ARMENIAN */
+ {"beng"}, /* PANGO_SCRIPT_BENGALI */
+ {"bopo"}, /* PANGO_SCRIPT_BOPOMOFO */
+ {"cher"}, /* PANGO_SCRIPT_CHEROKEE */
+ {"copt"}, /* PANGO_SCRIPT_COPTIC */
+ {"cyrl"}, /* PANGO_SCRIPT_CYRILLIC */
+ {"dsrt"}, /* PANGO_SCRIPT_DESERET */
+ {"deva"}, /* PANGO_SCRIPT_DEVANAGARI */
+ {"ethi"}, /* PANGO_SCRIPT_ETHIOPIC */
+ {"geor"}, /* PANGO_SCRIPT_GEORGIAN */
+ {"goth"}, /* PANGO_SCRIPT_GOTHIC */
+ {"grek"}, /* PANGO_SCRIPT_GREEK */
+ {"gujr"}, /* PANGO_SCRIPT_GUJARATI */
+ {"guru"}, /* PANGO_SCRIPT_GURMUKHI */
+ {"hani"}, /* PANGO_SCRIPT_HAN */
+ {"hang"}, /* PANGO_SCRIPT_HANGUL */
+ {"hebr"}, /* PANGO_SCRIPT_HEBREW */
+ {"kana"}, /* PANGO_SCRIPT_HIRAGANA */
+ {"knda"}, /* PANGO_SCRIPT_KANNADA */
+ {"kana"}, /* PANGO_SCRIPT_KATAKANA */
+ {"khmr"}, /* PANGO_SCRIPT_KHMER */
+ {"lao "}, /* PANGO_SCRIPT_LAO */
+ {"latn"}, /* PANGO_SCRIPT_LATIN */
+ {"mlym"}, /* PANGO_SCRIPT_MALAYALAM */
+ {"mong"}, /* PANGO_SCRIPT_MONGOLIAN */
+ {"mymr"}, /* PANGO_SCRIPT_MYANMAR */
+ {"ogam"}, /* PANGO_SCRIPT_OGHAM */
+ {"ital"}, /* PANGO_SCRIPT_OLD_ITALIC */
+ {"orya"}, /* PANGO_SCRIPT_ORIYA */
+ {"runr"}, /* PANGO_SCRIPT_RUNIC */
+ {"sinh"}, /* PANGO_SCRIPT_SINHALA */
+ {"syrc"}, /* PANGO_SCRIPT_SYRIAC */
+ {"taml"}, /* PANGO_SCRIPT_TAMIL */
+ {"telu"}, /* PANGO_SCRIPT_TELUGU */
+ {"thaa"}, /* PANGO_SCRIPT_THAANA */
+ {"thai"}, /* PANGO_SCRIPT_THAI */
+ {"tibt"}, /* PANGO_SCRIPT_TIBETAN */
+ {"cans"}, /* PANGO_SCRIPT_CANADIAN_ABORIGINAL */
+ {"yi "}, /* PANGO_SCRIPT_YI */
+ {"tglg"}, /* PANGO_SCRIPT_TAGALOG */
+ {"hano"}, /* PANGO_SCRIPT_HANUNOO */
+ {"buhd"}, /* PANGO_SCRIPT_BUHID */
+ {"tagb"}, /* PANGO_SCRIPT_TAGBANWA */
+ {"brai"}, /* PANGO_SCRIPT_BRAILLE */
+ {"cprt"}, /* PANGO_SCRIPT_CYPRIOT */
+ {"limb"}, /* PANGO_SCRIPT_LIMBU */
+ {"osma"}, /* PANGO_SCRIPT_OSMANYA */
+ {"shaw"}, /* PANGO_SCRIPT_SHAVIAN */
+ {"linb"}, /* PANGO_SCRIPT_LINEAR_B */
+ {"tale"}, /* PANGO_SCRIPT_TAI_LE */
+ {"ugar"}, /* PANGO_SCRIPT_UGARITIC */
+ {"talu"}, /* PANGO_SCRIPT_NEW_TAI_LUE */
+ {"bugi"}, /* PANGO_SCRIPT_BUGINESE */
+ {"glag"}, /* PANGO_SCRIPT_GLAGOLITIC */
+ {"tfng"}, /* PANGO_SCRIPT_TIFINAGH */
+ {"sylo"}, /* PANGO_SCRIPT_SYLOTI_NAGRI */
+ {"xpeo"}, /* PANGO_SCRIPT_OLD_PERSIAN */
+ {"khar"}, /* PANGO_SCRIPT_KHAROSHTHI */
+ {"DFLT"}, /* PANGO_SCRIPT_UNKNOWN */
+ {"bali"}, /* PANGO_SCRIPT_BALINESE */
+ {"xsux"}, /* PANGO_SCRIPT_CUNEIFORM */
+ {"phnx"}, /* PANGO_SCRIPT_PHOENICIAN */
+ {"phag"}, /* PANGO_SCRIPT_PHAGS_PA */
+ {"nko "} /* PANGO_SCRIPT_NKO */
+};
+
+/**
+ * pango_ot_tag_from_script:
+ * @script: A #PangoScript
+ *
+ * Finds the OpenType script tag corresponding to @script.
+ *
+ * The %PANGO_SCRIPT_COMMON, %PANGO_SCRIPT_INHERITED, and
+ * %PANGO_SCRIPT_UNKNOWN scripts are mapped to the OpenType
+ * 'DFLT' script tag that is also defined as
+ * %PANGO_OT_TAG_DEFAULT_SCRIPT.
+ *
+ * Note that multiple #PangoScript values may map to the same
+ * OpenType script tag. In particular, %PANGO_SCRIPT_HIRAGANA
+ * and %PANGO_SCRIPT_KATAKANA both map to the OT tag 'kana'.
+ *
+ * Return value: #PangoOTTag corresponding to @script or
+ * %PANGO_OT_TAG_DEFAULT_SCRIPT if none found.
+ *
+ * Since: 1.18
+ **/
+PangoOTTag
+pango_ot_tag_from_script (PangoScript script)
+{
+ g_return_val_if_fail (script >= 0 && (guint)script < G_N_ELEMENTS (ot_scripts), PANGO_OT_TAG_DEFAULT_SCRIPT);
+
+ return GUINT32_FROM_BE (ot_scripts[script].integer);
+}
+
+/**
+ * pango_ot_tag_to_script:
+ * @script_tag: A #PangoOTTag OpenType script tag
+ *
+ * Finds the #PangoScript corresponding to @script_tag.
+ *
+ * The 'DFLT' script tag is mapped to %PANGO_SCRIPT_COMMON.
+ *
+ * Note that an OpenType script tag may correspond to multiple
+ * #PangoScript values. In such cases, the #PangoScript value
+ * with the smallest value is returned.
+ * In particular, %PANGO_SCRIPT_HIRAGANA
+ * and %PANGO_SCRIPT_KATAKANA both map to the OT tag 'kana'.
+ * This function will return %PANGO_SCRIPT_HIRAGANA for
+ * 'kana'.
+ *
+ * Return value: #PangoScript corresponding to @script_tag or
+ * %PANGO_SCRIPT_UNKNOWN if none found.
+ *
+ * Since: 1.18
+ **/
+PangoScript
+pango_ot_tag_to_script (PangoOTTag script_tag)
+{
+ PangoScript i;
+ guint32 be_tag = GUINT32_TO_BE (script_tag);
+
+ for (i = 0; i < (PangoScript) G_N_ELEMENTS (ot_scripts); i++)
+ {
+ guint32 tag = ot_scripts[i].integer;
+
+ if (tag == be_tag)
+ return i;
+ }
+
+ return PANGO_SCRIPT_UNKNOWN;
+}
+
+
+typedef struct {
+ char language[6];
+ Tag tag;
+} LangTag;
+
+/*
+ * complete list at:
+ * http://www.microsoft.com/OpenType/OTSpec/languagetags.htm
+ *
+ * Generated by intersecting the above list with the ISO 639-2 codes
+ * and then adjusting manually. A lot of items missing still, feel
+ * free to add. Keep sorted for bsearch purpose.
+ */
+static const LangTag ot_languages[] = {
+ {"aa", {"AFR "}},
+ {"ab", {"ABK "}},
+ {"ady", {"ADY "}},
+ {"af", {"AFK "}},
+ {"am", {"AMH "}},
+ {"ar", {"ARA "}},
+ {"as", {"ASM "}},
+ {"awa", {"AWA "}},
+ {"ay", {"AYM "}},
+ {"az", {"AZE "}},
+ {"ba", {"BSH "}},
+ {"bal", {"BLI "}},
+ {"bem", {"BEM "}},
+ {"ber", {"BBR "}},
+ {"bg", {"BGR "}},
+ {"bho", {"BHO "}},
+ {"bik", {"BIK "}},
+ {"bin", {"EDO "}},
+ {"bm", {"BMB "}},
+ {"bn", {"BEN "}},
+ {"bo", {"TIB "}},
+ {"br", {"BRE "}},
+ {"brh", {"BRH "}},
+ {"ca", {"CAT "}},
+ {"ce", {"CHE "}},
+ {"ceb", {"CEB "}},
+ {"chp", {"CHP "}},
+ {"chr", {"CHR "}},
+ {"cop", {"COP "}},
+ {"cr", {"CRE "}},
+ {"crh", {"CRT "}},
+ {"cs", {"CSY "}},
+ {"cu", {"CSL "}},
+ {"cv", {"CHU "}},
+ {"cy", {"WEL "}},
+ {"da", {"DAN "}},
+ {"dar", {"DAR "}},
+ {"de", {"DEU "}},
+ {"din", {"DNK "}},
+ {"doi", {"DGR "}},
+ {"dsb", {"LSB "}},
+ {"dv", {"DHV "}},
+ {"dz", {"DZN "}},
+ {"ee", {"EWE "}},
+ {"efi", {"EFI "}},
+ {"el", {"ELL "}},
+ {"en", {"ENG "}},
+ {"eo", {"NTO "}},
+ {"es", {"ESP "}},
+ {"et", {"ETI "}},
+ {"eu", {"EUQ "}},
+ {"fa", {"FAR "}},
+ {"ff", {"FUL "}},
+ {"fi", {"FIN "}},
+ {"fil", {"PIL "}},
+ {"fj", {"FJI "}},
+ {"fo", {"FOS "}},
+ {"fon", {"FON "}},
+ {"fr", {"FRA "}},
+ {"fur", {"FRL "}},
+ {"fy", {"FRI "}},
+ {"ga", {"IRI "}},
+ {"gaa", {"GAD "}},
+ {"gd", {"GAE "}},
+ {"gl", {"GAL "}},
+ {"gn", {"GUA "}},
+ {"gon", {"GON "}},
+ {"gu", {"GUJ "}},
+ {"ha", {"HAU "}},
+ {"he", {"IWR "}},
+ {"hi", {"HIN "}},
+ {"hil", {"HIL "}},
+ {"hr", {"HRV "}},
+ {"hsb", {"USB "}},
+ {"ht", {"HAI "}},
+ {"hu", {"HUN "}},
+ {"hy", {"HYE "}},
+ {"id", {"IND "}},
+ {"ig", {"IBO "}},
+ {"inc", {"SRK "}},
+ {"ine", {"KHW "}},
+ {"inh", {"ING "}},
+ {"is", {"ISL "}},
+ {"it", {"ITA "}},
+ {"iu", {"INU "}},
+ {"ja", {"JAN "}},
+ {"jv", {"JAV "}},
+ {"ka", {"KAT "}},
+ {"kam", {"KMB "}},
+ {"kbd", {"KAB "}},
+ {"kha", {"KSI "}},
+ {"ki", {"KIK "}},
+ {"kk", {"KAZ "}},
+ {"kl", {"GRN "}},
+ {"km", {"KHM "}},
+ {"kn", {"KAN "}},
+ {"ko", {"KOR "}},
+ {"kok", {"KOK "}},
+ {"kpe", {"KPL "}},
+ {"kr", {"KNR "}},
+ {"krl", {"KRL "}},
+ {"kru", {"KUU "}},
+ {"ks", {"KSH "}},
+ {"ku", {"KUR "}},
+ {"kum", {"KUM "}},
+ {"ky", {"KIR "}},
+ {"la", {"LAT "}},
+ {"lad", {"JUD "}},
+ {"lbj", {"LDK "}},
+ {"ln", {"LIN "}},
+ {"lo", {"LAO "}},
+ {"lt", {"LTH "}},
+ {"lv", {"LVI "}},
+ {"mai", {"MTH "}},
+ {"mdf", {"MOK "}},
+ {"men", {"MDE "}},
+ {"mg", {"MLG "}},
+ {"mi", {"MRI "}},
+ {"mkh", {"KUY "}},
+ {"ml", {"MLR "}},
+ {"mnc", {"MCH "}},
+ {"mni", {"MNI "}},
+ {"mnk", {"MND "}},
+ {"mo", {"MOL "}},
+ {"mr", {"MAR "}},
+ {"ms", {"MLY "}},
+ {"mt", {"MTS "}},
+ {"mwr", {"MAW "}},
+ {"my", {"BRM "}},
+ {"myv", {"ERZ "}},
+ {"ne", {"NEP "}},
+ {"nl", {"NLD "}},
+ {"no", {"NOR "}},
+ {"ny", {"CHI "}},
+ {"oc", {"PRO "}},
+ {"om", {"ORO "}},
+ {"or", {"ORI "}},
+ {"os", {"OSS "}},
+ {"pa", {"PAN "}},
+ {"pi", {"PAL "}},
+ {"pl", {"PLK "}},
+ {"ps", {"PAS "}},
+ {"pt", {"PTG "}},
+ {"ro", {"ROM "}},
+ {"rom", {"ROY "}},
+ {"ru", {"RUS "}},
+ {"sa", {"SAN "}},
+ {"sat", {"SAT "}},
+ {"sd", {"SND "}},
+ {"sel", {"SEL "}},
+ {"sg", {"SGO "}},
+ {"shn", {"SHN "}},
+ {"si", {"SNH "}},
+ {"sid", {"SID "}},
+ {"sk", {"SKY "}},
+ {"sl", {"SLV "}},
+ {"sm", {"SMO "}},
+ {"smj", {"LSM "}},
+ {"smn", {"ISM "}},
+ {"sms", {"SKS "}},
+ {"snk", {"SNK "}},
+ {"so", {"SML "}},
+ {"sq", {"SQI "}},
+ {"sr", {"SRB "}},
+ {"srr", {"SRR "}},
+ {"sv", {"SVE "}},
+ {"sw", {"SWK "}},
+ {"syr", {"SYR "}},
+ {"ta", {"TAM "}},
+ {"te", {"TEL "}},
+ {"tg", {"TAJ "}},
+ {"th", {"THA "}},
+ {"ti", {"TGY "}},
+ {"tig", {"TGR "}},
+ {"tk", {"TKM "}},
+ {"tn", {"TNA "}},
+ {"tr", {"TRK "}},
+ {"ts", {"TSG "}},
+ {"tw", {"TWI "}},
+ {"udm", {"UDM "}},
+ {"ug", {"UYG "}},
+ {"uk", {"UKR "}},
+ {"ur", {"URD "}},
+ {"uz", {"UZB "}},
+ {"ve", {"VEN "}},
+ {"vi", {"VIT "}},
+ {"wo", {"WLF "}},
+ {"xal", {"KLM "}},
+ {"xh", {"XHS "}},
+ {"yi", {"JII "}},
+ {"yo", {"YBA "}},
+ {"zh-cn", {"ZHS "}},
+ {"zh-hk", {"ZHH "}},
+ {"zh-mo", {"ZHT "}},
+ {"zh-sg", {"ZHS "}},
+ {"zh-tw", {"ZHT "}},
+ {"zu", {"ZUL "}}
+};
+
+static int
+lang_compare_first_component (gconstpointer pa,
+ gconstpointer pb)
+{
+ const char *a = pa, *b = pb;
+ unsigned int da, db;
+ const char *p;
+
+ p = strstr (a, "-");
+ da = p ? (unsigned int) (p - a) : strlen (a);
+
+ p = strstr (b, "-");
+ db = p ? (unsigned int) (p - b) : strlen (b);
+
+ return strncmp (a, b, MAX (da, db));
+}
+
+/**
+ * pango_ot_tag_from_language:
+ * @language: A #PangoLanguage, or %NULL
+ *
+ * Finds the OpenType language-system tag best describing @language.
+ *
+ * Return value: #PangoOTTag best matching @language or
+ * %PANGO_OT_TAG_DEFAULT_LANGUAGE if none found or if @language
+ * is %NULL.
+ *
+ * Since: 1.18
+ **/
+PangoOTTag
+pango_ot_tag_from_language (PangoLanguage *language)
+{
+ const char *lang_str;
+ LangTag *lang_tag;
+
+ if (language == NULL)
+ return PANGO_OT_TAG_DEFAULT_LANGUAGE;
+
+ lang_str = pango_language_to_string (language);
+
+ /* find a language matching in the first component */
+ lang_tag = bsearch (lang_str, ot_languages,
+ G_N_ELEMENTS (ot_languages), sizeof (LangTag),
+ lang_compare_first_component);
+
+ /* we now need to find the best language matching */
+ if (lang_tag)
+ {
+ gboolean found = FALSE;
+
+ /* go to the final one matching in the first component */
+ while (lang_tag + 1 < ot_languages + G_N_ELEMENTS (ot_languages) &&
+ lang_compare_first_component (lang_str, lang_tag + 1) == 0)
+ lang_tag++;
+
+ /* go back, find which one matches completely */
+ while (lang_tag >= ot_languages &&
+ lang_compare_first_component (lang_str, lang_tag) == 0)
+ {
+ if (pango_language_matches (language, lang_tag->language))
+ {
+ found = TRUE;
+ break;
+ }
+
+ lang_tag--;
+ }
+
+ if (!found)
+ lang_tag = NULL;
+ }
+
+ if (lang_tag)
+ return GUINT32_FROM_BE (lang_tag->tag.integer);
+
+ return PANGO_OT_TAG_DEFAULT_LANGUAGE;
+}
+
+/**
+ * pango_ot_tag_to_language:
+ * @language_tag: A #PangoOTTag OpenType language-system tag
+ *
+ * Finds a #PangoLanguage corresponding to @language_tag.
+ *
+ * Return value: #PangoLanguage best matching @language_tag or
+ * #PangoLanguage corresponding to the string "xx" if none found.
+ *
+ * Since: 1.18
+ **/
+PangoLanguage *
+pango_ot_tag_to_language (PangoOTTag language_tag)
+{
+ int i;
+ guint32 be_tag = GUINT32_TO_BE (language_tag);
+
+ for (i = 0; i < (int) G_N_ELEMENTS (ot_languages); i++)
+ {
+ guint32 tag = ot_languages[i].tag.integer;
+
+ if (tag == be_tag)
+ return pango_language_from_string (ot_languages[i].language);
+ }
+
+ return pango_language_from_string ("xx");
+}
diff --git a/trunk/pango/pango-ot.h b/trunk/pango/pango-ot.h
new file mode 100644
index 00000000..1b3b8b7e
--- /dev/null
+++ b/trunk/pango/pango-ot.h
@@ -0,0 +1,185 @@
+/* Pango
+ * pango-ot.h:
+ *
+ * Copyright (C) 2000,2007 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_OT_H__
+#define __PANGO_OT_H__
+
+#include <pango/pangofc-font.h>
+#include <pango/pango-glyph.h>
+#include <pango/pango-font.h>
+#include <pango/pango-script.h>
+#include <pango/pango-language.h>
+
+G_BEGIN_DECLS
+
+#ifdef PANGO_ENABLE_ENGINE
+
+typedef guint32 PangoOTTag;
+
+#define PANGO_OT_TAG_MAKE(c1,c2,c3,c4) ((PangoOTTag) FT_MAKE_TAG (c1, c2, c3, c4))
+#define PANGO_OT_TAG_MAKE_FROM_STRING(s) (PANGO_OT_TAG_MAKE(((const char *) s)[0], \
+ ((const char *) s)[1], \
+ ((const char *) s)[2], \
+ ((const char *) s)[3]))
+
+typedef struct _PangoOTInfo PangoOTInfo;
+typedef struct _PangoOTBuffer PangoOTBuffer;
+typedef struct _PangoOTGlyph PangoOTGlyph;
+typedef struct _PangoOTRuleset PangoOTRuleset;
+typedef struct _PangoOTFeatureMap PangoOTFeatureMap;
+typedef struct _PangoOTRulesetDescription PangoOTRulesetDescription;
+
+typedef enum
+{
+ PANGO_OT_TABLE_GSUB,
+ PANGO_OT_TABLE_GPOS
+} PangoOTTableType;
+
+#define PANGO_OT_ALL_GLYPHS ((guint) 0xFFFF)
+#define PANGO_OT_NO_FEATURE ((guint) 0xFFFF)
+#define PANGO_OT_NO_SCRIPT ((guint) 0xFFFF)
+#define PANGO_OT_DEFAULT_LANGUAGE ((guint) 0xFFFF)
+
+#define PANGO_OT_TAG_DEFAULT_SCRIPT PANGO_OT_TAG_MAKE ('D', 'F', 'L', 'T')
+#define PANGO_OT_TAG_DEFAULT_LANGUAGE PANGO_OT_TAG_MAKE ('d', 'f', 'l', 't')
+
+/* Note that this must match HB_GlyphItem */
+struct _PangoOTGlyph
+{
+ guint glyph;
+ guint properties;
+ guint cluster;
+ gushort component;
+ gushort ligID;
+ gushort property_cache; /* Internal */
+};
+
+struct _PangoOTFeatureMap
+{
+ char feature_name[5];
+ gulong property_bit;
+};
+
+struct _PangoOTRulesetDescription {
+ PangoScript script;
+ PangoLanguage *language;
+ const PangoOTFeatureMap *static_gsub_features;
+ guint n_static_gsub_features;
+ const PangoOTFeatureMap *static_gpos_features;
+ guint n_static_gpos_features;
+ const PangoOTFeatureMap *other_features;
+ guint n_other_features;
+};
+
+
+PangoOTInfo *pango_ot_info_get (FT_Face face);
+
+gboolean pango_ot_info_find_script (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ PangoOTTag script_tag,
+ guint *script_index);
+gboolean pango_ot_info_find_language (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ guint script_index,
+ PangoOTTag language_tag,
+ guint *language_index,
+ guint *required_feature_index);
+gboolean pango_ot_info_find_feature (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ PangoOTTag feature_tag,
+ guint script_index,
+ guint language_index,
+ guint *feature_index);
+
+PangoOTTag *pango_ot_info_list_scripts (PangoOTInfo *info,
+ PangoOTTableType table_type);
+PangoOTTag *pango_ot_info_list_languages (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ guint script_index,
+ PangoOTTag language_tag);
+PangoOTTag *pango_ot_info_list_features (PangoOTInfo *info,
+ PangoOTTableType table_type,
+ PangoOTTag tag,
+ guint script_index,
+ guint language_index);
+
+PangoOTBuffer *pango_ot_buffer_new (PangoFcFont *font);
+void pango_ot_buffer_destroy (PangoOTBuffer *buffer);
+void pango_ot_buffer_clear (PangoOTBuffer *buffer);
+void pango_ot_buffer_set_rtl (PangoOTBuffer *buffer,
+ gboolean rtl);
+void pango_ot_buffer_add_glyph (PangoOTBuffer *buffer,
+ guint glyph,
+ guint properties,
+ guint cluster);
+void pango_ot_buffer_get_glyphs (const PangoOTBuffer *buffer,
+ PangoOTGlyph **glyphs,
+ int *n_glyphs);
+void pango_ot_buffer_output (const PangoOTBuffer *buffer,
+ PangoGlyphString *glyphs);
+
+void pango_ot_buffer_set_zero_width_marks (PangoOTBuffer *buffer,
+ gboolean zero_width_marks);
+
+const PangoOTRuleset *pango_ot_ruleset_get_for_description (PangoOTInfo *info,
+ const PangoOTRulesetDescription *desc);
+PangoOTRuleset *pango_ot_ruleset_new (PangoOTInfo *info);
+PangoOTRuleset *pango_ot_ruleset_new_for (PangoOTInfo *info,
+ PangoScript script,
+ PangoLanguage *language);
+PangoOTRuleset *pango_ot_ruleset_new_from_description (PangoOTInfo *info,
+ const PangoOTRulesetDescription *desc);
+void pango_ot_ruleset_add_feature (PangoOTRuleset *ruleset,
+ PangoOTTableType table_type,
+ guint feature_index,
+ gulong property_bit);
+gboolean pango_ot_ruleset_maybe_add_feature (PangoOTRuleset *ruleset,
+ PangoOTTableType table_type,
+ PangoOTTag feature_tag,
+ gulong property_bit);
+guint pango_ot_ruleset_maybe_add_features (PangoOTRuleset *ruleset,
+ PangoOTTableType table_type,
+ const PangoOTFeatureMap *features,
+ guint n_features);
+guint pango_ot_ruleset_get_feature_count (const PangoOTRuleset *ruleset,
+ guint *n_gsub_features,
+ guint *n_gpos_features);
+void pango_ot_ruleset_substitute (const PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer);
+void pango_ot_ruleset_position (const PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer);
+PangoScript pango_ot_tag_to_script (PangoOTTag script_tag) G_GNUC_CONST;
+PangoOTTag pango_ot_tag_from_script (PangoScript script) G_GNUC_CONST;
+PangoLanguage *pango_ot_tag_to_language (PangoOTTag language_tag) G_GNUC_CONST;
+PangoOTTag pango_ot_tag_from_language (PangoLanguage *language) G_GNUC_CONST;
+
+guint pango_ot_ruleset_description_hash (const PangoOTRulesetDescription *desc) G_GNUC_PURE;
+gboolean pango_ot_ruleset_description_equal (const PangoOTRulesetDescription *desc1,
+ const PangoOTRulesetDescription *desc2) G_GNUC_PURE;
+PangoOTRulesetDescription *pango_ot_ruleset_description_copy (const PangoOTRulesetDescription *desc);
+void pango_ot_ruleset_description_free (PangoOTRulesetDescription *desc);
+
+
+#endif /* PANGO_ENABLE_ENGINE */
+
+G_END_DECLS
+
+#endif /* __PANGO_OT_H__ */
diff --git a/trunk/pango/pango-renderer.c b/trunk/pango/pango-renderer.c
new file mode 100644
index 00000000..9dc1198f
--- /dev/null
+++ b/trunk/pango/pango-renderer.c
@@ -0,0 +1,1275 @@
+/* Pango
+ * pango-renderer.h: Base class for rendering
+ *
+ * Copyright (C) 2004 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+
+#include "pango-renderer.h"
+
+#define N_RENDER_PARTS 4
+
+#define PANGO_IS_RENDERER_FAST(renderer) (renderer != NULL)
+#define IS_VALID_PART(part) ((guint)part < N_RENDER_PARTS)
+
+typedef struct _LineState LineState;
+typedef struct _Point Point;
+
+struct _Point
+{
+ double x, y;
+};
+
+struct _LineState
+{
+ PangoUnderline underline;
+ PangoRectangle underline_rect;
+
+ gboolean strikethrough;
+ PangoRectangle strikethrough_rect;
+
+ int logical_rect_end;
+};
+
+struct _PangoRendererPrivate
+{
+ PangoColor color[N_RENDER_PARTS];
+ gboolean color_set[N_RENDER_PARTS];
+
+ LineState *line_state;
+};
+
+static void pango_renderer_finalize (GObject *gobject);
+static void pango_renderer_default_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+static void pango_renderer_default_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height);
+static void pango_renderer_default_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height);
+static void pango_renderer_default_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run);
+
+static void pango_renderer_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run);
+
+static void
+to_device (PangoMatrix *matrix,
+ double x,
+ double y,
+ Point *result)
+{
+ if (matrix)
+ {
+ result->x = (x * matrix->xx + y * matrix->xy) / PANGO_SCALE + matrix->x0;
+ result->y = (x * matrix->yx + y * matrix->yy) / PANGO_SCALE + matrix->y0;
+ }
+ else
+ {
+ result->x = x / PANGO_SCALE;
+ result->y = y / PANGO_SCALE;
+ }
+}
+
+G_DEFINE_ABSTRACT_TYPE (PangoRenderer, pango_renderer, G_TYPE_OBJECT)
+
+static void
+pango_renderer_class_init (PangoRendererClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ klass->draw_glyphs = pango_renderer_default_draw_glyphs;
+ klass->draw_rectangle = pango_renderer_default_draw_rectangle;
+ klass->draw_error_underline = pango_renderer_default_draw_error_underline;
+ klass->prepare_run = pango_renderer_default_prepare_run;
+
+ gobject_class->finalize = pango_renderer_finalize;
+
+ g_type_class_add_private (gobject_class, sizeof (PangoRendererPrivate));
+}
+
+static void
+pango_renderer_init (PangoRenderer *renderer)
+{
+ renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer,
+ PANGO_TYPE_RENDERER,
+ PangoRendererPrivate);
+ renderer->matrix = NULL;
+}
+
+static void
+pango_renderer_finalize (GObject *gobject)
+{
+ PangoRenderer *renderer = PANGO_RENDERER (gobject);
+
+ if (renderer->matrix)
+ pango_matrix_free (renderer->matrix);
+}
+
+/**
+ * pango_renderer_draw_layout:
+ * @renderer: a #PangoRenderer
+ * @layout: a #PangoLayout
+ * @x: X position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ * @y: Y position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ *
+ * Draws @layout with the specified #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_layout (PangoRenderer *renderer,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ PangoLayoutIter *iter;
+
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ /* We only change the matrix if the renderer isn't already
+ * active.
+ */
+ if (!renderer->active_count)
+ {
+ PangoContext *context = pango_layout_get_context (layout);
+ pango_renderer_set_matrix (renderer,
+ pango_context_get_matrix (context));
+ }
+
+ pango_renderer_activate (renderer);
+
+ iter = pango_layout_get_iter (layout);
+
+ do
+ {
+ PangoRectangle logical_rect;
+ PangoLayoutLine *line;
+ int baseline;
+
+ line = pango_layout_iter_get_line_readonly (iter);
+
+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+ baseline = pango_layout_iter_get_baseline (iter);
+
+ pango_renderer_draw_layout_line (renderer,
+ line,
+ x + logical_rect.x,
+ y + baseline);
+ }
+ while (pango_layout_iter_next_line (iter));
+
+ pango_layout_iter_free (iter);
+
+ pango_renderer_deactivate (renderer);
+}
+
+static void
+draw_underline (PangoRenderer *renderer,
+ LineState *state)
+{
+ PangoRectangle *rect = &state->underline_rect;
+ PangoUnderline underline = state->underline;
+
+ state->underline = PANGO_UNDERLINE_NONE;
+
+ switch (underline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_UNDERLINE,
+ rect->x,
+ rect->y + 2 * rect->height,
+ rect->width,
+ rect->height);
+ /* Fall through */
+ case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_LOW:
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_UNDERLINE,
+ rect->x,
+ rect->y,
+ rect->width,
+ rect->height);
+ break;
+ case PANGO_UNDERLINE_ERROR:
+ pango_renderer_draw_error_underline (renderer,
+ rect->x,
+ rect->y,
+ rect->width,
+ 3 * rect->height);
+ break;
+ }
+}
+
+static void
+draw_strikethrough (PangoRenderer *renderer,
+ LineState *state)
+{
+ PangoRectangle *rect = &state->strikethrough_rect;
+ gboolean strikethrough = state->strikethrough;
+
+ state->strikethrough = FALSE;
+
+ if (strikethrough)
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_STRIKETHROUGH,
+ rect->x,
+ rect->y,
+ rect->width,
+ rect->height);
+}
+
+static void
+handle_line_state_change (PangoRenderer *renderer,
+ PangoRenderPart part)
+{
+ LineState *state = renderer->priv->line_state;
+ if (!state)
+ return;
+
+ if (part == PANGO_RENDER_PART_UNDERLINE &&
+ state->underline != PANGO_UNDERLINE_NONE)
+ {
+ PangoRectangle *rect = &state->underline_rect;
+
+ rect->width = state->logical_rect_end - rect->x;
+ draw_underline (renderer, state);
+ state->underline = renderer->underline;
+ rect->x = state->logical_rect_end;
+ rect->width = 0;
+ }
+
+ if (part == PANGO_RENDER_PART_STRIKETHROUGH &&
+ state->strikethrough)
+ {
+ PangoRectangle *rect = &state->strikethrough_rect;
+
+ rect->width = state->logical_rect_end - rect->x;
+ draw_strikethrough (renderer, state);
+ state->strikethrough = renderer->strikethrough;
+ rect->x = state->logical_rect_end;
+ rect->width = 0;
+ }
+}
+
+static void
+add_underline (PangoRenderer *renderer,
+ LineState *state,
+ PangoFontMetrics *metrics,
+ int base_x,
+ int base_y,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoRectangle *current_rect = &state->underline_rect;
+ PangoRectangle new_rect;
+
+ int underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
+ int underline_position = pango_font_metrics_get_underline_position (metrics);
+
+ new_rect.x = base_x + logical_rect->x;
+ new_rect.width = logical_rect->width;
+ new_rect.height = underline_thickness;
+ new_rect.y = base_y;
+
+ switch (renderer->underline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ g_assert_not_reached ();
+ break;
+ case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_DOUBLE:
+ case PANGO_UNDERLINE_ERROR:
+ new_rect.y -= underline_position;
+ break;
+ case PANGO_UNDERLINE_LOW:
+ new_rect.y += ink_rect->y + ink_rect->height + underline_thickness;
+ break;
+ }
+
+ if (renderer->underline == state->underline &&
+ new_rect.y == current_rect->y &&
+ new_rect.height == current_rect->height)
+ {
+ current_rect->width = new_rect.x + new_rect.width - current_rect->x;
+ }
+ else
+ {
+ draw_underline (renderer, state);
+
+ *current_rect = new_rect;
+ state->underline = renderer->underline;
+ }
+}
+
+static void
+add_strikethrough (PangoRenderer *renderer,
+ LineState *state,
+ PangoFontMetrics *metrics,
+ int base_x,
+ int base_y,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoRectangle *current_rect = &state->strikethrough_rect;
+ PangoRectangle new_rect;
+
+ int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics);
+ int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics);
+
+ new_rect.x = base_x + logical_rect->x;
+ new_rect.width = logical_rect->width;
+ new_rect.y = base_y - strikethrough_position;
+ new_rect.height = strikethrough_thickness;
+
+ if (state->strikethrough &&
+ new_rect.y == current_rect->y &&
+ new_rect.height == current_rect->height)
+ {
+ current_rect->width = new_rect.x + new_rect.width - current_rect->x;
+ }
+ else
+ {
+ draw_strikethrough (renderer, state);
+
+ *current_rect = new_rect;
+ state->strikethrough = TRUE;
+ }
+}
+
+static void
+get_item_properties (PangoItem *item,
+ gint *rise,
+ PangoAttrShape **shape_attr)
+{
+ GSList *l;
+
+ if (rise)
+ *rise = 0;
+
+ if (shape_attr)
+ *shape_attr = NULL;
+
+ for (l = item->analysis.extra_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_SHAPE:
+ if (shape_attr)
+ *shape_attr = (PangoAttrShape *)attr;
+ break;
+
+ case PANGO_ATTR_RISE:
+ if (rise)
+ *rise = ((PangoAttrInt *)attr)->value;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+static void
+draw_shaped_glyphs (PangoRenderer *renderer,
+ PangoGlyphString *glyphs,
+ PangoAttrShape *attr,
+ int x,
+ int y)
+{
+ PangoRendererClass *class = PANGO_RENDERER_GET_CLASS (renderer);
+ int i;
+
+ if (!class->draw_shape)
+ return;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+
+ class->draw_shape (renderer, attr, x, y);
+
+ x += gi->geometry.width;
+ }
+}
+
+/**
+ * pango_renderer_draw_layout_line:
+ * @renderer: a #PangoRenderer
+ * @line: a #PangoLayoutLine
+ * @x: X position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ * @y: Y position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ *
+ * Draws @line with the specified #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_layout_line (PangoRenderer *renderer,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ int x_off = 0;
+ int glyph_string_width;
+ LineState state;
+ GSList *l;
+ gboolean got_overall = FALSE;
+ PangoRectangle overall_rect;
+
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+ /* We only change the matrix if the renderer isn't already
+ * active.
+ */
+ if (!renderer->active_count)
+ {
+ PangoContext *context = pango_layout_get_context (line->layout);
+ pango_renderer_set_matrix (renderer,
+ pango_context_get_matrix (context));
+ }
+
+ pango_renderer_activate (renderer);
+
+ renderer->priv->line_state = &state;
+
+ state.underline = PANGO_UNDERLINE_NONE;
+ state.strikethrough = FALSE;
+
+ for (l = line->runs; l; l = l->next)
+ {
+ PangoFontMetrics *metrics;
+ gint rise;
+ PangoLayoutRun *run = l->data;
+ PangoAttrShape *shape_attr;
+ PangoRectangle ink_rect, *ink = NULL;
+ PangoRectangle logical_rect, *logical = NULL;
+
+ if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ logical = &logical_rect;
+
+ pango_renderer_prepare_run (renderer, run);
+
+ get_item_properties (run->item, &rise, &shape_attr);
+
+ if (shape_attr)
+ {
+ ink_rect = shape_attr->ink_rect;
+ logical_rect = shape_attr->logical_rect;
+ ink = &ink_rect;
+ logical = &logical_rect;
+ glyph_string_width = shape_attr->logical_rect.width;
+ }
+ else
+ {
+ if (renderer->underline != PANGO_UNDERLINE_NONE ||
+ renderer->strikethrough)
+ {
+ ink = &ink_rect;
+ logical = &logical_rect;
+ }
+ if (G_UNLIKELY (ink || logical))
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ ink, logical);
+ if (logical)
+ glyph_string_width = logical_rect.width;
+ else
+ glyph_string_width = pango_glyph_string_get_width (run->glyphs);
+ }
+
+ state.logical_rect_end = x + x_off + glyph_string_width;
+
+ if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ {
+ gboolean is_hinted = ((logical_rect.y | logical_rect.height) & (PANGO_SCALE - 1)) == 0;
+ int adjustment = logical_rect.y + logical_rect.height / 2;
+
+ if (is_hinted)
+ adjustment = PANGO_UNITS_ROUND (adjustment);
+
+ rise += adjustment;
+ }
+
+
+ if (renderer->priv->color_set[PANGO_RENDER_PART_BACKGROUND])
+ {
+ if (!got_overall)
+ {
+ pango_layout_line_get_extents (line, NULL, &overall_rect);
+ got_overall = TRUE;
+ }
+
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_BACKGROUND,
+ x + x_off,
+ y + overall_rect.y,
+ glyph_string_width,
+ overall_rect.height);
+ }
+
+ if (shape_attr)
+ {
+ draw_shaped_glyphs (renderer, run->glyphs, shape_attr, x + x_off, y - rise);
+ }
+ else
+ {
+ pango_renderer_draw_glyphs (renderer,
+ run->item->analysis.font, run->glyphs,
+ x + x_off, y - rise);
+ }
+
+ if (renderer->underline != PANGO_UNDERLINE_NONE ||
+ renderer->strikethrough)
+ {
+ metrics = pango_font_get_metrics (run->item->analysis.font,
+ run->item->analysis.language);
+
+ if (renderer->underline != PANGO_UNDERLINE_NONE)
+ add_underline (renderer, &state,metrics,
+ x + x_off, y - rise,
+ ink, logical);
+
+ if (renderer->strikethrough)
+ add_strikethrough (renderer, &state, metrics,
+ x + x_off, y - rise,
+ ink, logical);
+
+ pango_font_metrics_unref (metrics);
+ }
+
+ if (renderer->underline == PANGO_UNDERLINE_NONE &&
+ state.underline != PANGO_UNDERLINE_NONE)
+ draw_underline (renderer, &state);
+
+ if (!renderer->strikethrough && state.strikethrough)
+ draw_strikethrough (renderer, &state);
+
+ x_off += glyph_string_width;
+ }
+
+ /* Finish off any remaining underlines
+ */
+ draw_underline (renderer, &state);
+ draw_strikethrough (renderer, &state);
+
+ renderer->priv->line_state = NULL;
+
+ pango_renderer_deactivate (renderer);
+}
+
+/**
+ * pango_renderer_draw_glyphs:
+ * @renderer: a #PangoRenderer
+ * @font: a #PangoFont
+ * @glyphs: a #PangoGlyphString
+ * @x: X position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ * @y: Y position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ *
+ * Draws the glyphs in @glyphs with the specified #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+ pango_renderer_activate (renderer);
+
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_glyphs (renderer, font, glyphs, x, y);
+
+ pango_renderer_deactivate (renderer);
+}
+
+static void
+pango_renderer_default_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ int i;
+ int x_position = 0;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+ Point p;
+
+ to_device (renderer->matrix,
+ x + x_position + gi->geometry.x_offset,
+ y + gi->geometry.y_offset,
+ &p);
+
+ pango_renderer_draw_glyph (renderer, font, gi->glyph, p.x, p.y);
+
+ x_position += gi->geometry.width;
+ }
+}
+
+/**
+ * pango_renderer_draw_rectangle:
+ * @renderer: a #PangoRenderer
+ * @part: type of object this rectangle is part of
+ * @x: X position at which to draw rectangle, in user space coordinates in Pango units
+ * @y: Y position at which to draw rectangle, in user space coordinates in Pango units
+ * @width: width of rectangle in Pango units in user space coordinates
+ * @height: height of rectangle in Pango units in user space coordinates
+ *
+ * Draws an axis-aligned rectangle in user space coordinates with the
+ * specified #PangoRenderer.
+ *
+ * This should be called while @renderer is already active. Use
+ * pango_renderer_activate() to activate a renderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+ g_return_if_fail (IS_VALID_PART (part));
+ g_return_if_fail (renderer->active_count > 0);
+
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_rectangle (renderer, part, x, y, width, height);
+}
+
+static int
+compare_points (const void *a,
+ const void *b)
+{
+ const Point *pa = a;
+ const Point *pb = b;
+
+ if (pa->y < pb->y)
+ return -1;
+ else if (pa->y > pb->y)
+ return 1;
+ else if (pa->x < pb->x)
+ return -1;
+ else if (pa->x > pb->x)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+draw_rectangle (PangoRenderer *renderer,
+ PangoMatrix *matrix,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ Point points[4];
+
+ /* Convert the points to device coordinates, and sort
+ * in ascending Y order. (Ordering by X for ties)
+ */
+ to_device (matrix, x, y, &points[0]);
+ to_device (matrix, x + width, y, &points[1]);
+ to_device (matrix, x, y + height, &points[2]);
+ to_device (matrix, x + width, y + height, &points[3]);
+
+ qsort (points, 4, sizeof (Point), compare_points);
+
+ /* There are essentially three cases. (There is a fourth
+ * case where trapezoid B is degenerate and we just have
+ * two triangles, but we don't need to handle it separately.)
+ *
+ * 1 2 3
+ *
+ * ______ /\ /\
+ * / / /A \ /A \
+ * / B / /____\ /____\
+ * /_____/ / B / \ B \
+ * /_____/ \_____\
+ * \ C / \ C /
+ * \ / \ /
+ * \/ \/
+ */
+ if (points[0].y == points[1].y)
+ {
+ /* Case 1 (pure shear) */
+ pango_renderer_draw_trapezoid (renderer, part, /* B */
+ points[0].y, points[0].x, points[1].x,
+ points[2].y, points[2].x, points[3].x);
+ }
+ else if (points[1].x < points[2].x)
+ {
+ /* Case 2 */
+ double tmp_width = ((points[2].x - points[0].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y);
+ double base_width = tmp_width + points[0].x - points[1].x;
+
+ pango_renderer_draw_trapezoid (renderer, part, /* A */
+ points[0].y, points[0].x, points[0].x,
+ points[1].y, points[1].x, points[1].x + base_width);
+ pango_renderer_draw_trapezoid (renderer, part, /* B */
+ points[1].y, points[1].x, points[1].x + base_width,
+ points[2].y, points[2].x - base_width, points[2].x);
+ pango_renderer_draw_trapezoid (renderer, part, /* C */
+ points[2].y, points[2].x - base_width, points[2].x,
+ points[3].y, points[3].x, points[3].x);
+ }
+ else
+ {
+ /* case 3 */
+ double tmp_width = ((points[0].x - points[2].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y);
+ double base_width = tmp_width + points[1].x - points[0].x;
+
+ pango_renderer_draw_trapezoid (renderer, part, /* A */
+ points[0].y, points[0].x, points[0].x,
+ points[1].y, points[1].x - base_width, points[1].x);
+ pango_renderer_draw_trapezoid (renderer, part, /* B */
+ points[1].y, points[1].x - base_width, points[1].x,
+ points[2].y, points[2].x, points[2].x + base_width);
+ pango_renderer_draw_trapezoid (renderer, part, /* C */
+ points[2].y, points[2].x, points[2].x + base_width,
+ points[3].y, points[3].x, points[3].x);
+ }
+}
+
+static void
+pango_renderer_default_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ draw_rectangle (renderer, renderer->matrix, part, x, y, width, height);
+}
+
+/**
+ * pango_renderer_draw_error_underline:
+ * @renderer: a #PangoRenderer
+ * @x: X coordinate of underline, in Pango units in user coordinate system
+ * @y: Y coordinate of underline, in Pango units in user coordinate system
+ * @width: width of underline, in Pango units in user coordinate system
+ * @height: height of underline, in Pango units in user coordinate system
+ *
+ * Draw a squiggly line that approximately covers the given rectangle
+ * in the style of an underline used to indicate a spelling error.
+ * (The width of the underline is rounded to an integer number
+ * of up/down segments and the resulting rectangle is centered
+ * in the original rectangle)
+ *
+ * This should be called while @renderer is already active. Use
+ * pango_renderer_activate() to activate a renderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+ g_return_if_fail (renderer->active_count > 0);
+
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_error_underline (renderer, x, y, width, height);
+}
+
+/* We are drawing an error underline that looks like one of:
+ *
+ * /\ /\ /\ /\ /\ -
+ * / \ / \ / \ / \ / \ |
+ * \ \ /\ \ / / \ \ /\ \ |
+ * \ \/B \ \/ C / \ \/B \ \ | height = HEIGHT_SQUARES * square
+ * \ A \ /\ A \ / \ A \ /\ A \ |
+ * \ \/ \ \/ \ \/ \ \ |
+ * \ / \ / \ / \ / |
+ * \/ \/ \/ \/ -
+ * |---|
+ * unit_width = (HEIGHT_SQUARES - 1) * square
+ *
+ * To do this conveniently, we work in a coordinate system where A,B,C
+ * are axis aligned rectangles. (If fonts were square, the diagrams
+ * would be clearer)
+ *
+ * (0,0)
+ * /\ /\
+ * / \ / \
+ * /\ /\ /\ /
+ * / \/ \/ \/
+ * / \ /\ /
+ * Y axis \/ \/
+ * \ /\
+ * \/ \
+ * \ X axis
+ *
+ * Note that the long side in this coordinate system is HEIGHT_SQUARES + 1
+ * units long
+ *
+ * The diagrams above are shown with HEIGHT_SQUARES an integer, but
+ * that is actually incidental; the value 2.5 below seems better than
+ * either HEIGHT_SQUARES=3 (a little long and skinny) or
+ * HEIGHT_SQUARES=2 (a bit short and stubby)
+ */
+
+#define HEIGHT_SQUARES 2.5
+
+static void
+get_total_matrix (PangoMatrix *total,
+ const PangoMatrix *global,
+ int x,
+ int y,
+ int square)
+{
+ PangoMatrix local;
+ gdouble scale = 0.5 * square;
+
+ /* The local matrix translates from the axis aligned coordinate system
+ * to the original user space coordinate system.
+ */
+ local.xx = scale;
+ local.xy = - scale;
+ local.yx = scale;
+ local.yy = scale;
+ local.x0 = 0;
+ local.y0 = 0;
+
+ *total = *global;
+ pango_matrix_concat (total, &local);
+
+ total->x0 = (global->xx * x + global->xy * y) / PANGO_SCALE + global->x0;
+ total->y0 = (global->yx * x + global->yy * y) / PANGO_SCALE + global->y0;
+}
+
+static void
+pango_renderer_default_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ int square = height / HEIGHT_SQUARES;
+ int unit_width = (HEIGHT_SQUARES - 1) * square;
+ int width_units = (width + unit_width / 2) / unit_width;
+ static const PangoMatrix identity = PANGO_MATRIX_INIT;
+ const PangoMatrix *matrix;
+
+ x += (width - width_units * unit_width) / 2;
+ width = width_units * unit_width;
+
+ if (renderer->matrix)
+ matrix = renderer->matrix;
+ else
+ matrix = &identity;
+
+ while (TRUE)
+ {
+ PangoMatrix total;
+ get_total_matrix (&total, matrix, x, y, square);
+
+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* A */
+ 0, 0,
+ HEIGHT_SQUARES * 2 - 1, 1);
+
+ if (width_units > 2)
+ {
+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* B */
+ HEIGHT_SQUARES * 2 - 2, - (HEIGHT_SQUARES * 2 - 3),
+ 1, HEIGHT_SQUARES * 2 - 3);
+ width_units -= 2;
+ x += unit_width * 2;
+ }
+ else if (width_units == 2)
+ {
+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* C */
+ HEIGHT_SQUARES * 2 - 2, - (HEIGHT_SQUARES * 2 - 2),
+ 1, HEIGHT_SQUARES * 2 - 2);
+ break;
+ }
+ else
+ break;
+ }
+}
+
+/**
+ * pango_renderer_draw_trapezoid:
+ * @renderer: a #PangoRenderer
+ * @part: type of object this trapezoid is part of
+ * @y1_: Y coordinate of top of trapezoid
+ * @x11: X coordinate of left end of top of trapezoid
+ * @x21: X coordinate of right end of top of trapezoid
+ * @y2: Y coordinate of bottom of trapezoid
+ * @x12: X coordinate of left end of bottom of trapezoid
+ * @x22: X coordinate of right end of bottom of trapezoid
+ *
+ * Draws a trapezoid with the parallel sides aligned with the X axis
+ * using the given #PangoRenderer; coordinates are in device space.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1_,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+ g_return_if_fail (renderer->active_count > 0);
+
+ if (PANGO_RENDERER_GET_CLASS (renderer)->draw_trapezoid)
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_trapezoid (renderer, part,
+ y1_, x11, x21,
+ y2, x12, x22);
+}
+
+/**
+ * pango_renderer_draw_glyph:
+ * @renderer: a #PangoRenderer
+ * @font: a #PangoFont
+ * @glyph: the glyph index of a single glyph
+ * @x: X coordinate of left edge of baseline of glyph
+ * @y: Y coordinate of left edge of baseline of glyph
+ *
+ * Draws a single glyph with coordinates in device space.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+ g_return_if_fail (renderer->active_count > 0);
+
+ if (glyph == PANGO_GLYPH_EMPTY) /* glyph PANGO_GLYPH_EMPTY never renders */
+ return;
+
+ if (PANGO_RENDERER_GET_CLASS (renderer)->draw_glyph)
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_glyph (renderer, font, glyph, x, y);
+}
+
+/**
+ * pango_renderer_activate:
+ * @renderer: a #PangoRenderer
+ *
+ * Does initial setup before rendering operations on @renderer.
+ * pango_renderer_deactivate() should be called when done drawing.
+ * Calls such as pango_renderer_draw_layout() automatically
+ * activate the layout before drawing on it. Calls to
+ * pango_renderer_activate() and pango_renderer_deactivate() can
+ * be nested and the renderer will only be initialized and
+ * deinitialized once.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_activate (PangoRenderer *renderer)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+ renderer->active_count++;
+ if (renderer->active_count == 1)
+ {
+ if (PANGO_RENDERER_GET_CLASS (renderer)->begin)
+ PANGO_RENDERER_GET_CLASS (renderer)->begin (renderer);
+ }
+}
+
+/**
+ * pango_renderer_deactivate:
+ * @renderer: a #PangoRenderer
+ *
+ * Cleans up after rendering operations on @renderer. See
+ * docs for pango_renderer_activate().
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_deactivate (PangoRenderer *renderer)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+ g_return_if_fail (renderer->active_count > 0);
+
+ if (renderer->active_count == 1)
+ {
+ if (PANGO_RENDERER_GET_CLASS (renderer)->end)
+ PANGO_RENDERER_GET_CLASS (renderer)->end (renderer);
+ }
+ renderer->active_count--;
+}
+
+/**
+ * pango_renderer_set_color:
+ * @renderer: a #PangoRenderer
+ * @part: the part to change the color of
+ * @color: the new color or %NULL to unset the current color
+ *
+ * Sets the color for part of the rendering.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_set_color (PangoRenderer *renderer,
+ PangoRenderPart part,
+ const PangoColor *color)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+ g_return_if_fail (IS_VALID_PART (part));
+
+ if ((!color && !renderer->priv->color_set[part]) ||
+ (color && renderer->priv->color_set[part] &&
+ renderer->priv->color[part].red == color->red &&
+ renderer->priv->color[part].green == color->green &&
+ renderer->priv->color[part].blue == color->blue))
+ return;
+
+ pango_renderer_part_changed (renderer, part);
+
+ if (color)
+ {
+ renderer->priv->color_set[part] = TRUE;
+ renderer->priv->color[part] = *color;
+ }
+ else
+ {
+ renderer->priv->color_set[part] = FALSE;
+ }
+}
+
+/**
+ * pango_renderer_get_color:
+ * @renderer: a #PangoRenderer
+ * @part: the part to get the color for
+ *
+ * Gets the current rendering color for the specified part.
+ *
+ * Return value: the color for the specified part, or %NULL
+ * if it hasn't been set and should be inherited from the
+ * environment.
+ *
+ * Since: 1.8
+ **/
+PangoColor *
+pango_renderer_get_color (PangoRenderer *renderer,
+ PangoRenderPart part)
+{
+ g_return_val_if_fail (PANGO_IS_RENDERER_FAST (renderer), NULL);
+ g_return_val_if_fail (IS_VALID_PART (part), NULL);
+
+ if (renderer->priv->color_set[part])
+ return &renderer->priv->color[part];
+ else
+ return NULL;
+}
+
+/**
+ * pango_renderer_part_changed:
+ * @renderer: a #PangoRenderer
+ * @part: the part for which rendering has changed.
+ *
+ * Informs Pango that the way that the rendering is done
+ * for @part has changed in a way that would prevent multiple
+ * pieces being joined together into one drawing call. For
+ * instance, if a subclass of #PangoRenderer was to add a stipple
+ * option for drawing underlines, it needs to call
+ *
+ * <informalexample><programlisting>
+ * pango_renderer_part_changed (render, PANGO_RENDER_PART_UNDERLINE);
+ * </programlisting></informalexample>
+ *
+ * When the stipple changes or underlines with different stipples
+ * might be joined together. Pango automatically calls this for
+ * changes to colors. (See pango_renderer_set_color())
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_part_changed (PangoRenderer *renderer,
+ PangoRenderPart part)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+ g_return_if_fail (IS_VALID_PART (part));
+ g_return_if_fail (renderer->active_count > 0);
+
+ handle_line_state_change (renderer, part);
+
+ if (PANGO_RENDERER_GET_CLASS (renderer)->part_changed)
+ PANGO_RENDERER_GET_CLASS (renderer)->part_changed (renderer, part);
+}
+
+/**
+ * pango_renderer_prepare_run:
+ * @renderer: a #PangoRenderer
+ * @run: a #PangoLayoutRun
+ *
+ * Set up the state of the #PangoRenderer for rendering @run.
+ *
+ * Since: 1.8
+ **/
+static void
+pango_renderer_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+ PANGO_RENDERER_GET_CLASS (renderer)->prepare_run (renderer, run);
+}
+
+static void
+pango_renderer_default_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run)
+{
+ PangoColor *fg_color = NULL;
+ PangoColor *bg_color = NULL;
+ PangoColor *underline_color = NULL;
+ PangoColor *strikethrough_color = NULL;
+ GSList *l;
+
+ renderer->underline = PANGO_UNDERLINE_NONE;
+ renderer->strikethrough = FALSE;
+
+ for (l = run->item->analysis.extra_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_UNDERLINE:
+ renderer->underline = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_STRIKETHROUGH:
+ renderer->strikethrough = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_FOREGROUND:
+ fg_color = &((PangoAttrColor *)attr)->color;
+ break;
+
+ case PANGO_ATTR_BACKGROUND:
+ bg_color = &((PangoAttrColor *)attr)->color;
+ break;
+
+ case PANGO_ATTR_UNDERLINE_COLOR:
+ underline_color = &((PangoAttrColor *)attr)->color;
+ break;
+
+ case PANGO_ATTR_STRIKETHROUGH_COLOR:
+ strikethrough_color = &((PangoAttrColor *)attr)->color;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (!underline_color)
+ underline_color = fg_color;
+
+ if (!strikethrough_color)
+ strikethrough_color = fg_color;
+
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_FOREGROUND, fg_color);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_BACKGROUND, bg_color);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_UNDERLINE, underline_color);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_STRIKETHROUGH, strikethrough_color);
+}
+
+/**
+ * pango_renderer_set_matrix:
+ * @renderer: a #PangoRenderer
+ * @matrix: a #PangoMatrix, or %NULL to unset any existing matrix.
+ * (No matrix set is the same as setting the identity matrix.)
+ *
+ * Sets the transformation matrix that will be applied when rendering.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_set_matrix (PangoRenderer *renderer,
+ const PangoMatrix *matrix)
+{
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+ if (renderer->matrix)
+ pango_matrix_free (renderer->matrix);
+ if (matrix)
+ renderer->matrix = pango_matrix_copy (matrix);
+ else
+ renderer->matrix = NULL;
+
+}
+
+/**
+ * pango_renderer_get_matrix:
+ * @renderer: a #PangoRenderer
+ *
+ * Gets the transformation matrix that will be applied when
+ * rendering. See pango_renderer_set_matrix().
+ *
+ * Return value: the matrix, or %NULL if no matrix has been set
+ * (which is the same as the identity matrix). The returned
+ * matrix is owned by Pango and must not be modified or
+ * freed.
+ *
+ * Since: 1.8
+ **/
+G_CONST_RETURN PangoMatrix *
+pango_renderer_get_matrix (PangoRenderer *renderer)
+{
+ g_return_val_if_fail (PANGO_IS_RENDERER (renderer), NULL);
+
+ return renderer->matrix;
+}
diff --git a/trunk/pango/pango-renderer.h b/trunk/pango/pango-renderer.h
new file mode 100644
index 00000000..47fbb017
--- /dev/null
+++ b/trunk/pango/pango-renderer.h
@@ -0,0 +1,243 @@
+/* Pango
+ * pango-renderer.h: Base class for rendering
+ *
+ * Copyright (C) 2004, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __PANGO_RENDERER_H_
+#define __PANGO_RENDERER_H_
+
+#include <pango/pango-layout.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_RENDERER (pango_renderer_get_type())
+#define PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_RENDERER, PangoRenderer))
+#define PANGO_IS_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_RENDERER))
+#define PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_RENDERER, PangoRendererClass))
+#define PANGO_IS_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_RENDERER))
+#define PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_RENDERER, PangoRendererClass))
+
+typedef struct _PangoRenderer PangoRenderer;
+typedef struct _PangoRendererClass PangoRendererClass;
+typedef struct _PangoRendererPrivate PangoRendererPrivate;
+
+/**
+ * PangoRenderPart:
+ * @PANGO_RENDER_PART_FOREGROUND: the text itself
+ * @PANGO_RENDER_PART_BACKGROUND: the area behind the text
+ * @PANGO_RENDER_PART_UNDERLINE: underlines
+ * @PANGO_RENDER_PART_STRIKETHROUGH: strikethrough lines
+ *
+ * #PangoRenderPart defines different items to render for such
+ * purposes as setting colors.
+ *
+ * Since: 1.8
+ **/
+/* When extending, note N_RENDER_PARTS #define in pango-renderer.c */
+typedef enum
+{
+ PANGO_RENDER_PART_FOREGROUND,
+ PANGO_RENDER_PART_BACKGROUND,
+ PANGO_RENDER_PART_UNDERLINE,
+ PANGO_RENDER_PART_STRIKETHROUGH
+} PangoRenderPart;
+
+/**
+ * PangoRenderer:
+ * @matrix: the current transformation matrix for the Renderer; may
+ * be %NULL, which should be treated the same as the identity matrix.
+ *
+ * #PangoRenderer is a base class for objects that are used to
+ * render Pango objects such as #PangoGlyphString and
+ * #PangoLayout.
+ *
+ * Since: 1.8
+ **/
+struct _PangoRenderer
+{
+ /*< private >*/
+ GObject parent_instance;
+
+ PangoUnderline underline;
+ gboolean strikethrough;
+ int active_count;
+
+ /*< public >*/
+ PangoMatrix *matrix; /* May be NULL */
+
+ /*< private >*/
+ PangoRendererPrivate *priv;
+};
+
+/**
+ * PangoRendererClass:
+ * @draw_glyphs: draws a #PangoGlyphString
+ * @draw_rectangle: draws a rectangle
+ * @draw_error_underline: draws a squiggly line that approximately
+ * covers the given rectangle in the style of an underline used to
+ * indicate a spelling error.
+ * @draw_shape: draw content for a glyph shaped with #PangoAttrShape.
+ * @x, @y are the coordinates of the left edge of the baseline,
+ * in user coordinates.
+ * @draw_trapezoid: draws a trapezoidal filled area
+ * @draw_glyph: draws a single glyph
+ * @part_changed: do renderer specific processing when rendering
+ * attributes change
+ * @begin: Do renderer-specific initialization before drawing
+ * @end: Do renderer-specific cleanup after drawing
+ * @prepare_run: updates the renderer for a new run
+ *
+ * Class structure for #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+struct _PangoRendererClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ /* vtable - not signals */
+ /*< public >*/
+
+ /* All of the following have default implementations
+ * and take as coordinates user coordinates in Pango units
+ */
+ void (*draw_glyphs) (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+ void (*draw_rectangle) (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height);
+ void (*draw_error_underline) (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height);
+
+ /* Nothing is drawn for shaped glyphs unless this is implemented */
+ void (*draw_shape) (PangoRenderer *renderer,
+ PangoAttrShape *attr,
+ int x,
+ int y);
+
+ /* These two must be implemented and take coordinates in
+ * device space as doubles.
+ */
+ void (*draw_trapezoid) (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1_,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22);
+ void (*draw_glyph) (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y);
+
+ /* Notification of change in rendering attributes
+ */
+ void (*part_changed) (PangoRenderer *renderer,
+ PangoRenderPart part);
+
+ /* Paired around drawing operations
+ */
+ void (*begin) (PangoRenderer *renderer);
+ void (*end) (PangoRenderer *renderer);
+
+ /* Hooks into the details of layout rendering
+ */
+ void (*prepare_run) (PangoRenderer *renderer,
+ PangoLayoutRun *run);
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+GType pango_renderer_get_type (void) G_GNUC_CONST;
+
+void pango_renderer_draw_layout (PangoRenderer *renderer,
+ PangoLayout *layout,
+ int x,
+ int y);
+void pango_renderer_draw_layout_line (PangoRenderer *renderer,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+void pango_renderer_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height);
+void pango_renderer_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height);
+void pango_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1_,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22);
+void pango_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y);
+
+void pango_renderer_activate (PangoRenderer *renderer);
+void pango_renderer_deactivate (PangoRenderer *renderer);
+
+void pango_renderer_part_changed (PangoRenderer *renderer,
+ PangoRenderPart part);
+
+void pango_renderer_set_color (PangoRenderer *renderer,
+ PangoRenderPart part,
+ const PangoColor *color);
+PangoColor *pango_renderer_get_color (PangoRenderer *renderer,
+ PangoRenderPart part);
+
+void pango_renderer_set_matrix (PangoRenderer *renderer,
+ const PangoMatrix *matrix);
+G_CONST_RETURN PangoMatrix *pango_renderer_get_matrix (PangoRenderer *renderer);
+
+G_END_DECLS
+
+#endif /* __PANGO_RENDERER_H_ */
+
diff --git a/trunk/pango/pango-script-lang-table.h b/trunk/pango/pango-script-lang-table.h
new file mode 100644
index 00000000..1817271b
--- /dev/null
+++ b/trunk/pango/pango-script-lang-table.h
@@ -0,0 +1,199 @@
+/* pango-script-lang-table.h: Generated by gen-script-for-lang.c
+ *
+ * Date: 9 May 2007
+ * Source: fontconfig-2.4.2
+ *
+ * Do not edit.
+ */
+typedef struct {
+ const char lang[6];
+ PangoScript scripts[3];
+} PangoScriptForLang;
+
+static const PangoScriptForLang pango_script_for_lang[] = {
+ { "aa", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ab", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "af", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "am", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ar", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "as", { PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ast", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ava", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ay", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "az", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE } },
+ { "az-ir", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ba", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bam", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "be", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bg", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bh", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bho", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bin", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bn", { PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bo", { PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "br", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bs", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bua", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ca", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ce", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ch", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "chm", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "chr", { PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "co", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "cs", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "cu", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "cv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE } },
+ { "cy", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "da", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "de", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "dz", { PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "el", { PANGO_SCRIPT_GREEK, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "en", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "eo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "es", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "et", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "eu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fa", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fj", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ful", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fur", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fy", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ga", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gd", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gez", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gu", { PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ha", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "haw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "he", { PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "hi", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ho", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "hr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "hu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "hy", { PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ia", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ibo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "id", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ie", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ik", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "io", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "is", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "it", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "iu", { PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ja", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_HIRAGANA, PANGO_SCRIPT_KATAKANA } },
+ { "ka", { PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kaa", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ki", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "km", { PANGO_SCRIPT_KHMER, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kn", { PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ko", { PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kok", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ks", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ku", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE } },
+ { "ku-ir", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kum", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ky", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "la", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lb", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lez", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ln", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lo", { PANGO_SCRIPT_LAO, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mg", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mh", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ml", { PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mn", { PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE } },
+ { "mr", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "my", { PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "nb", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "nds", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ne", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "nl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "nn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "no", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ny", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "oc", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "om", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "or", { PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "os", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "pa", { PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "pl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ps-af", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ps-pk", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "pt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "rm", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ro", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ru", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sa", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sah", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sco", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "se", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sel", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sh", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "si", { PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sk", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sm", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sma", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "smj", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "smn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sms", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "so", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sq", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sr", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "syr", { PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ta", { PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "te", { PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tg", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "th", { PANGO_SCRIPT_THAI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ti-er", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ti-et", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tig", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tl", { PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "to", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ts", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tt", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tyv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ug", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "uk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ur", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "uz", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ven", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "vi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "vo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "vot", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "wa", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "wen", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "wo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "xh", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "yap", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "yi", { PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "yo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-cn", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-hk", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-mo", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-sg", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-tw", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+};
diff --git a/trunk/pango/pango-script-table.h b/trunk/pango/pango-script-table.h
new file mode 100644
index 00000000..cfc796e1
--- /dev/null
+++ b/trunk/pango/pango-script-table.h
@@ -0,0 +1,2981 @@
+/* pango-script-table.h: Generated by gen-script-table.pl
+ *
+ * Date: Mon Sep 18 21:07:42 2006
+ * Source: Scripts-5.0.0.txt
+ *
+ * Do not edit.
+ */
+
+static const guchar pango_script_easy_table[8192] = {
+
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC,
+ PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC,
+ PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC,
+ PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC,
+ PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC, PANGO_SCRIPT_COPTIC,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_ARMENIAN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_HEBREW,
+ PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_SYRIAC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_ARABIC,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA,
+ PANGO_SCRIPT_THAANA, PANGO_SCRIPT_THAANA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO, PANGO_SCRIPT_NKO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI,
+ PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI,
+ PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_GURMUKHI,
+ PANGO_SCRIPT_GURMUKHI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GUJARATI,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA,
+ PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_TAMIL,
+ PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_TELUGU,
+ PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_KANNADA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM,
+ PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_SINHALA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI, PANGO_SCRIPT_THAI,
+ PANGO_SCRIPT_THAI, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_LAO, PANGO_SCRIPT_LAO, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_TIBETAN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_MYANMAR,
+ PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_GEORGIAN,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HANGUL,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC,
+ PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_CHEROKEE,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_CANADIAN_ABORIGINAL,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM,
+ PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_OGHAM, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_RUNIC,
+ PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_RUNIC, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAGALOG,
+ PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG,
+ PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG,
+ PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG,
+ PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG,
+ PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG,
+ PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO,
+ PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO,
+ PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO,
+ PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO,
+ PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO,
+ PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO,
+ PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_HANUNOO,
+ PANGO_SCRIPT_HANUNOO, PANGO_SCRIPT_COMMON, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID,
+ PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID,
+ PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID,
+ PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID,
+ PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID,
+ PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID,
+ PANGO_SCRIPT_BUHID, PANGO_SCRIPT_BUHID, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAGBANWA,
+ PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA,
+ PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA,
+ PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA,
+ PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_TAGBANWA,
+ PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAGBANWA,
+ PANGO_SCRIPT_TAGBANWA, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_COMMON, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_COMMON,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN,
+ PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU, PANGO_SCRIPT_LIMBU,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_TAI_LE,
+ PANGO_SCRIPT_TAI_LE, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_NEW_TAI_LUE, PANGO_SCRIPT_NEW_TAI_LUE,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER,
+ PANGO_SCRIPT_KHMER, PANGO_SCRIPT_KHMER, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BUGINESE,
+ PANGO_SCRIPT_BUGINESE, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE,
+ PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_BALINESE, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_CYRILLIC,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_INHERITED, PANGO_SCRIPT_INHERITED,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_LATIN,
+ PANGO_SCRIPT_LATIN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_UNKNOWN,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_UNKNOWN, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK, PANGO_SCRIPT_GREEK,
+ PANGO_SCRIPT_GREEK, PANGO_SCRIPT_UNKNOWN,
+};
+
+static const struct {
+ gunichar start;
+ guint16 chars;
+ guint16 script;
+} pango_script_table[] = {
+ { 0x2000, 12, PANGO_SCRIPT_COMMON },
+ { 0x200c, 2, PANGO_SCRIPT_INHERITED },
+ { 0x200e, 86, PANGO_SCRIPT_COMMON },
+ { 0x206a, 7, PANGO_SCRIPT_COMMON },
+ { 0x2071, 1, PANGO_SCRIPT_LATIN },
+ { 0x2074, 11, PANGO_SCRIPT_COMMON },
+ { 0x207f, 1, PANGO_SCRIPT_LATIN },
+ { 0x2080, 15, PANGO_SCRIPT_COMMON },
+ { 0x2090, 5, PANGO_SCRIPT_LATIN },
+ { 0x20a0, 22, PANGO_SCRIPT_COMMON },
+ { 0x20d0, 32, PANGO_SCRIPT_INHERITED },
+ { 0x2100, 38, PANGO_SCRIPT_COMMON },
+ { 0x2126, 1, PANGO_SCRIPT_GREEK },
+ { 0x2127, 3, PANGO_SCRIPT_COMMON },
+ { 0x212a, 2, PANGO_SCRIPT_LATIN },
+ { 0x212c, 6, PANGO_SCRIPT_COMMON },
+ { 0x2132, 1, PANGO_SCRIPT_LATIN },
+ { 0x2133, 27, PANGO_SCRIPT_COMMON },
+ { 0x214e, 1, PANGO_SCRIPT_LATIN },
+ { 0x2153, 49, PANGO_SCRIPT_COMMON },
+ { 0x2184, 1, PANGO_SCRIPT_LATIN },
+ { 0x2190, 600, PANGO_SCRIPT_COMMON },
+ { 0x2400, 39, PANGO_SCRIPT_COMMON },
+ { 0x2440, 11, PANGO_SCRIPT_COMMON },
+ { 0x2460, 573, PANGO_SCRIPT_COMMON },
+ { 0x26a0, 19, PANGO_SCRIPT_COMMON },
+ { 0x2701, 4, PANGO_SCRIPT_COMMON },
+ { 0x2706, 4, PANGO_SCRIPT_COMMON },
+ { 0x270c, 28, PANGO_SCRIPT_COMMON },
+ { 0x2729, 35, PANGO_SCRIPT_COMMON },
+ { 0x274d, 1, PANGO_SCRIPT_COMMON },
+ { 0x274f, 4, PANGO_SCRIPT_COMMON },
+ { 0x2756, 1, PANGO_SCRIPT_COMMON },
+ { 0x2758, 7, PANGO_SCRIPT_COMMON },
+ { 0x2761, 52, PANGO_SCRIPT_COMMON },
+ { 0x2798, 24, PANGO_SCRIPT_COMMON },
+ { 0x27b1, 14, PANGO_SCRIPT_COMMON },
+ { 0x27c0, 11, PANGO_SCRIPT_COMMON },
+ { 0x27d0, 28, PANGO_SCRIPT_COMMON },
+ { 0x27f0, 16, PANGO_SCRIPT_COMMON },
+ { 0x2800, 256, PANGO_SCRIPT_BRAILLE },
+ { 0x2900, 539, PANGO_SCRIPT_COMMON },
+ { 0x2b20, 4, PANGO_SCRIPT_COMMON },
+ { 0x2c00, 47, PANGO_SCRIPT_GLAGOLITIC },
+ { 0x2c30, 47, PANGO_SCRIPT_GLAGOLITIC },
+ { 0x2c60, 13, PANGO_SCRIPT_LATIN },
+ { 0x2c74, 4, PANGO_SCRIPT_LATIN },
+ { 0x2c80, 107, PANGO_SCRIPT_COPTIC },
+ { 0x2cf9, 7, PANGO_SCRIPT_COPTIC },
+ { 0x2d00, 38, PANGO_SCRIPT_GEORGIAN },
+ { 0x2d30, 54, PANGO_SCRIPT_TIFINAGH },
+ { 0x2d6f, 1, PANGO_SCRIPT_TIFINAGH },
+ { 0x2d80, 23, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2da0, 7, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2da8, 7, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2db0, 7, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2db8, 7, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2dc0, 7, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2dc8, 7, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2dd0, 7, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2dd8, 7, PANGO_SCRIPT_ETHIOPIC },
+ { 0x2e00, 24, PANGO_SCRIPT_COMMON },
+ { 0x2e1c, 2, PANGO_SCRIPT_COMMON },
+ { 0x2e80, 26, PANGO_SCRIPT_HAN },
+ { 0x2e9b, 89, PANGO_SCRIPT_HAN },
+ { 0x2f00, 214, PANGO_SCRIPT_HAN },
+ { 0x2ff0, 12, PANGO_SCRIPT_COMMON },
+ { 0x3000, 5, PANGO_SCRIPT_COMMON },
+ { 0x3005, 1, PANGO_SCRIPT_HAN },
+ { 0x3006, 1, PANGO_SCRIPT_COMMON },
+ { 0x3007, 1, PANGO_SCRIPT_HAN },
+ { 0x3008, 25, PANGO_SCRIPT_COMMON },
+ { 0x3021, 9, PANGO_SCRIPT_HAN },
+ { 0x302a, 6, PANGO_SCRIPT_INHERITED },
+ { 0x3030, 8, PANGO_SCRIPT_COMMON },
+ { 0x3038, 4, PANGO_SCRIPT_HAN },
+ { 0x303c, 4, PANGO_SCRIPT_COMMON },
+ { 0x3041, 86, PANGO_SCRIPT_HIRAGANA },
+ { 0x3099, 2, PANGO_SCRIPT_INHERITED },
+ { 0x309b, 2, PANGO_SCRIPT_COMMON },
+ { 0x309d, 3, PANGO_SCRIPT_HIRAGANA },
+ { 0x30a0, 1, PANGO_SCRIPT_COMMON },
+ { 0x30a1, 90, PANGO_SCRIPT_KATAKANA },
+ { 0x30fb, 2, PANGO_SCRIPT_COMMON },
+ { 0x30fd, 3, PANGO_SCRIPT_KATAKANA },
+ { 0x3105, 40, PANGO_SCRIPT_BOPOMOFO },
+ { 0x3131, 94, PANGO_SCRIPT_HANGUL },
+ { 0x3190, 16, PANGO_SCRIPT_COMMON },
+ { 0x31a0, 24, PANGO_SCRIPT_BOPOMOFO },
+ { 0x31c0, 16, PANGO_SCRIPT_COMMON },
+ { 0x31f0, 16, PANGO_SCRIPT_KATAKANA },
+ { 0x3200, 31, PANGO_SCRIPT_HANGUL },
+ { 0x3220, 36, PANGO_SCRIPT_COMMON },
+ { 0x3250, 16, PANGO_SCRIPT_COMMON },
+ { 0x3260, 30, PANGO_SCRIPT_HANGUL },
+ { 0x327e, 129, PANGO_SCRIPT_COMMON },
+ { 0x3300, 256, PANGO_SCRIPT_COMMON },
+ { 0x3400, 6582, PANGO_SCRIPT_HAN },
+ { 0x4dc0, 64, PANGO_SCRIPT_COMMON },
+ { 0x4e00, 20924, PANGO_SCRIPT_HAN },
+ { 0xa000, 1165, PANGO_SCRIPT_YI },
+ { 0xa490, 55, PANGO_SCRIPT_YI },
+ { 0xa700, 27, PANGO_SCRIPT_COMMON },
+ { 0xa720, 2, PANGO_SCRIPT_COMMON },
+ { 0xa800, 44, PANGO_SCRIPT_SYLOTI_NAGRI },
+ { 0xa840, 56, PANGO_SCRIPT_PHAGS_PA },
+ { 0xac00, 11172, PANGO_SCRIPT_HANGUL },
+ { 0xf900, 302, PANGO_SCRIPT_HAN },
+ { 0xfa30, 59, PANGO_SCRIPT_HAN },
+ { 0xfa70, 106, PANGO_SCRIPT_HAN },
+ { 0xfb00, 7, PANGO_SCRIPT_LATIN },
+ { 0xfb13, 5, PANGO_SCRIPT_ARMENIAN },
+ { 0xfb1d, 26, PANGO_SCRIPT_HEBREW },
+ { 0xfb38, 5, PANGO_SCRIPT_HEBREW },
+ { 0xfb3e, 1, PANGO_SCRIPT_HEBREW },
+ { 0xfb40, 2, PANGO_SCRIPT_HEBREW },
+ { 0xfb43, 2, PANGO_SCRIPT_HEBREW },
+ { 0xfb46, 10, PANGO_SCRIPT_HEBREW },
+ { 0xfb50, 98, PANGO_SCRIPT_ARABIC },
+ { 0xfbd3, 363, PANGO_SCRIPT_ARABIC },
+ { 0xfd3e, 2, PANGO_SCRIPT_COMMON },
+ { 0xfd50, 64, PANGO_SCRIPT_ARABIC },
+ { 0xfd92, 54, PANGO_SCRIPT_ARABIC },
+ { 0xfdf0, 13, PANGO_SCRIPT_ARABIC },
+ { 0xfdfd, 1, PANGO_SCRIPT_COMMON },
+ { 0xfe00, 16, PANGO_SCRIPT_INHERITED },
+ { 0xfe10, 10, PANGO_SCRIPT_COMMON },
+ { 0xfe20, 4, PANGO_SCRIPT_INHERITED },
+ { 0xfe30, 35, PANGO_SCRIPT_COMMON },
+ { 0xfe54, 19, PANGO_SCRIPT_COMMON },
+ { 0xfe68, 4, PANGO_SCRIPT_COMMON },
+ { 0xfe70, 5, PANGO_SCRIPT_ARABIC },
+ { 0xfe76, 135, PANGO_SCRIPT_ARABIC },
+ { 0xfeff, 1, PANGO_SCRIPT_COMMON },
+ { 0xff01, 32, PANGO_SCRIPT_COMMON },
+ { 0xff21, 26, PANGO_SCRIPT_LATIN },
+ { 0xff3b, 6, PANGO_SCRIPT_COMMON },
+ { 0xff41, 26, PANGO_SCRIPT_LATIN },
+ { 0xff5b, 11, PANGO_SCRIPT_COMMON },
+ { 0xff66, 10, PANGO_SCRIPT_KATAKANA },
+ { 0xff70, 1, PANGO_SCRIPT_COMMON },
+ { 0xff71, 45, PANGO_SCRIPT_KATAKANA },
+ { 0xff9e, 2, PANGO_SCRIPT_COMMON },
+ { 0xffa0, 31, PANGO_SCRIPT_HANGUL },
+ { 0xffc2, 6, PANGO_SCRIPT_HANGUL },
+ { 0xffca, 6, PANGO_SCRIPT_HANGUL },
+ { 0xffd2, 6, PANGO_SCRIPT_HANGUL },
+ { 0xffda, 3, PANGO_SCRIPT_HANGUL },
+ { 0xffe0, 7, PANGO_SCRIPT_COMMON },
+ { 0xffe8, 7, PANGO_SCRIPT_COMMON },
+ { 0xfff9, 5, PANGO_SCRIPT_COMMON },
+ { 0x10000, 12, PANGO_SCRIPT_LINEAR_B },
+ { 0x1000d, 26, PANGO_SCRIPT_LINEAR_B },
+ { 0x10028, 19, PANGO_SCRIPT_LINEAR_B },
+ { 0x1003c, 2, PANGO_SCRIPT_LINEAR_B },
+ { 0x1003f, 15, PANGO_SCRIPT_LINEAR_B },
+ { 0x10050, 14, PANGO_SCRIPT_LINEAR_B },
+ { 0x10080, 123, PANGO_SCRIPT_LINEAR_B },
+ { 0x10100, 3, PANGO_SCRIPT_COMMON },
+ { 0x10107, 45, PANGO_SCRIPT_COMMON },
+ { 0x10137, 9, PANGO_SCRIPT_COMMON },
+ { 0x10140, 75, PANGO_SCRIPT_GREEK },
+ { 0x10300, 31, PANGO_SCRIPT_OLD_ITALIC },
+ { 0x10320, 4, PANGO_SCRIPT_OLD_ITALIC },
+ { 0x10330, 27, PANGO_SCRIPT_GOTHIC },
+ { 0x10380, 30, PANGO_SCRIPT_UGARITIC },
+ { 0x1039f, 1, PANGO_SCRIPT_UGARITIC },
+ { 0x103a0, 36, PANGO_SCRIPT_OLD_PERSIAN },
+ { 0x103c8, 14, PANGO_SCRIPT_OLD_PERSIAN },
+ { 0x10400, 80, PANGO_SCRIPT_DESERET },
+ { 0x10450, 48, PANGO_SCRIPT_SHAVIAN },
+ { 0x10480, 30, PANGO_SCRIPT_OSMANYA },
+ { 0x104a0, 10, PANGO_SCRIPT_OSMANYA },
+ { 0x10800, 6, PANGO_SCRIPT_CYPRIOT },
+ { 0x10808, 1, PANGO_SCRIPT_CYPRIOT },
+ { 0x1080a, 44, PANGO_SCRIPT_CYPRIOT },
+ { 0x10837, 2, PANGO_SCRIPT_CYPRIOT },
+ { 0x1083c, 1, PANGO_SCRIPT_CYPRIOT },
+ { 0x1083f, 1, PANGO_SCRIPT_CYPRIOT },
+ { 0x10900, 26, PANGO_SCRIPT_PHOENICIAN },
+ { 0x1091f, 1, PANGO_SCRIPT_PHOENICIAN },
+ { 0x10a00, 4, PANGO_SCRIPT_KHAROSHTHI },
+ { 0x10a05, 2, PANGO_SCRIPT_KHAROSHTHI },
+ { 0x10a0c, 8, PANGO_SCRIPT_KHAROSHTHI },
+ { 0x10a15, 3, PANGO_SCRIPT_KHAROSHTHI },
+ { 0x10a19, 27, PANGO_SCRIPT_KHAROSHTHI },
+ { 0x10a38, 3, PANGO_SCRIPT_KHAROSHTHI },
+ { 0x10a3f, 9, PANGO_SCRIPT_KHAROSHTHI },
+ { 0x10a50, 9, PANGO_SCRIPT_KHAROSHTHI },
+ { 0x12000, 879, PANGO_SCRIPT_CUNEIFORM },
+ { 0x12400, 99, PANGO_SCRIPT_CUNEIFORM },
+ { 0x12470, 4, PANGO_SCRIPT_CUNEIFORM },
+ { 0x1d000, 246, PANGO_SCRIPT_COMMON },
+ { 0x1d100, 39, PANGO_SCRIPT_COMMON },
+ { 0x1d12a, 61, PANGO_SCRIPT_COMMON },
+ { 0x1d167, 3, PANGO_SCRIPT_INHERITED },
+ { 0x1d16a, 17, PANGO_SCRIPT_COMMON },
+ { 0x1d17b, 8, PANGO_SCRIPT_INHERITED },
+ { 0x1d183, 2, PANGO_SCRIPT_COMMON },
+ { 0x1d185, 7, PANGO_SCRIPT_INHERITED },
+ { 0x1d18c, 30, PANGO_SCRIPT_COMMON },
+ { 0x1d1aa, 4, PANGO_SCRIPT_INHERITED },
+ { 0x1d1ae, 48, PANGO_SCRIPT_COMMON },
+ { 0x1d200, 70, PANGO_SCRIPT_GREEK },
+ { 0x1d300, 87, PANGO_SCRIPT_COMMON },
+ { 0x1d360, 18, PANGO_SCRIPT_COMMON },
+ { 0x1d400, 85, PANGO_SCRIPT_COMMON },
+ { 0x1d456, 71, PANGO_SCRIPT_COMMON },
+ { 0x1d49e, 2, PANGO_SCRIPT_COMMON },
+ { 0x1d4a2, 1, PANGO_SCRIPT_COMMON },
+ { 0x1d4a5, 2, PANGO_SCRIPT_COMMON },
+ { 0x1d4a9, 4, PANGO_SCRIPT_COMMON },
+ { 0x1d4ae, 12, PANGO_SCRIPT_COMMON },
+ { 0x1d4bb, 1, PANGO_SCRIPT_COMMON },
+ { 0x1d4bd, 7, PANGO_SCRIPT_COMMON },
+ { 0x1d4c5, 65, PANGO_SCRIPT_COMMON },
+ { 0x1d507, 4, PANGO_SCRIPT_COMMON },
+ { 0x1d50d, 8, PANGO_SCRIPT_COMMON },
+ { 0x1d516, 7, PANGO_SCRIPT_COMMON },
+ { 0x1d51e, 28, PANGO_SCRIPT_COMMON },
+ { 0x1d53b, 4, PANGO_SCRIPT_COMMON },
+ { 0x1d540, 5, PANGO_SCRIPT_COMMON },
+ { 0x1d546, 1, PANGO_SCRIPT_COMMON },
+ { 0x1d54a, 7, PANGO_SCRIPT_COMMON },
+ { 0x1d552, 340, PANGO_SCRIPT_COMMON },
+ { 0x1d6a8, 292, PANGO_SCRIPT_COMMON },
+ { 0x1d7ce, 50, PANGO_SCRIPT_COMMON },
+ { 0x20000, 42711, PANGO_SCRIPT_HAN },
+ { 0x2f800, 542, PANGO_SCRIPT_HAN },
+ { 0xe0001, 1, PANGO_SCRIPT_COMMON },
+ { 0xe0020, 96, PANGO_SCRIPT_COMMON },
+ { 0xe0100, 240, PANGO_SCRIPT_INHERITED },
+};
diff --git a/trunk/pango/pango-script.c b/trunk/pango/pango-script.c
new file mode 100644
index 00000000..3f8dadb7
--- /dev/null
+++ b/trunk/pango/pango-script.c
@@ -0,0 +1,381 @@
+/* Pango
+ * pango-script.c: Script tag handling
+ *
+ * Copyright (C) 2002 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Implementation of pango_script_iter is derived from ICU:
+ *
+ * icu/sources/common/usc_impl.c
+ *
+ **********************************************************************
+ * Copyright (C) 1999-2002, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ **********************************************************************
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pango-script.h"
+#include "pango-script-table.h"
+
+#define PAREN_STACK_DEPTH 128
+
+typedef struct _ParenStackEntry ParenStackEntry;
+
+struct _ParenStackEntry
+{
+ int pair_index;
+ PangoScript script_code;
+};
+
+struct _PangoScriptIter
+{
+ const gchar *text_start;
+ const gchar *text_end;
+
+ const gchar *script_start;
+ const gchar *script_end;
+ PangoScript script_code;
+
+ ParenStackEntry paren_stack[PAREN_STACK_DEPTH];
+ int paren_sp;
+};
+
+#define PANGO_SCRIPT_TABLE_MIDPOINT (G_N_ELEMENTS (pango_script_table) / 2)
+
+static inline PangoScript
+pango_script_for_unichar_bsearch (gunichar ch)
+{
+ int lower = 0;
+ int upper = G_N_ELEMENTS (pango_script_table) - 1;
+ static int saved_mid = PANGO_SCRIPT_TABLE_MIDPOINT;
+ int mid = saved_mid;
+
+
+ do
+ {
+ if (ch < pango_script_table[mid].start)
+ upper = mid - 1;
+ else if (ch >= pango_script_table[mid].start + pango_script_table[mid].chars)
+ lower = mid + 1;
+ else
+ return pango_script_table[saved_mid = mid].script;
+
+ mid = (lower + upper) / 2;
+ }
+ while (lower <= upper);
+
+ return PANGO_SCRIPT_UNKNOWN;
+}
+
+/**
+ * pango_script_for_unichar:
+ * @ch: a Unicode character
+ *
+ * Looks up the #PangoScript for a particular character (as defined by
+ * Unicode Standard Annex #24). No check is made for @ch being a
+ * valid Unicode character; if you pass in invalid character, the
+ * result is undefined.
+ *
+ * Return value: the #PangoScript for the character.
+ *
+ * Since: 1.4
+ **/
+PangoScript
+pango_script_for_unichar (gunichar ch)
+{
+ if (ch < G_N_ELEMENTS (pango_script_easy_table))
+ return pango_script_easy_table[ch];
+ else
+ return pango_script_for_unichar_bsearch (ch);
+}
+
+/**********************************************************************/
+
+/**
+ * pango_script_iter_new:
+ * @text: a UTF-8 string
+ * @length: length of @text, or -1 if @text is nul-terminated.
+ *
+ * Create a new #PangoScriptIter, used to break a string of
+ * Unicode into runs by text. No copy is made of @text, so
+ * the caller needs to make sure it remains valid until
+ * the iterator is freed with pango_script_iter_free ().x
+ *
+ * Return value: the new script iterator, initialized
+ * to point at the first range in the text, which should be
+ * freed with pango_script_iter_free(). If the string is
+ * empty, it will point at an empty range.
+ *
+ * Since: 1.4
+ **/
+PangoScriptIter *
+pango_script_iter_new (const char *text,
+ int length)
+{
+ PangoScriptIter *iter = g_slice_new (PangoScriptIter);
+
+ iter->text_start = text;
+ if (length >= 0)
+ iter->text_end = text + length;
+ else
+ iter->text_end = text + strlen (text);
+
+ iter->script_start = text;
+ iter->script_end = text;
+ iter->script_code = PANGO_SCRIPT_COMMON;
+
+ iter->paren_sp = -1;
+
+ pango_script_iter_next (iter);
+
+ return iter;
+}
+
+/**
+ * pango_script_iter_free:
+ * @iter: a #PangoScriptIter
+ *
+ * Frees a #PangoScriptIter created with pango_script_iter_new().
+ *
+ * Since: 1.4
+ **/
+void
+pango_script_iter_free (PangoScriptIter *iter)
+{
+ g_slice_free (PangoScriptIter, iter);
+}
+
+/**
+ * pango_script_iter_get_range:
+ * @iter: a #PangoScriptIter
+ * @start: location to store start position of the range, or %NULL
+ * @end: location to store end position of the range, or %NULL
+ * @script: location to store script for range, or %NULL
+ *
+ * Gets information about the range to which @iter currently points.
+ * The range is the set of locations p where *start <= p < *end.
+ * (That is, it doesn't include the character stored at *end)
+ *
+ * Since: 1.4
+ **/
+void
+pango_script_iter_get_range (PangoScriptIter *iter,
+ G_CONST_RETURN char **start,
+ G_CONST_RETURN char **end,
+ PangoScript *script)
+{
+ if (start)
+ *start = iter->script_start;
+ if (end)
+ *end = iter->script_end;
+ if (script)
+ *script = iter->script_code;
+}
+
+static const gunichar paired_chars[] = {
+ 0x0028, 0x0029, /* ascii paired punctuation */
+ 0x003c, 0x003e,
+ 0x005b, 0x005d,
+ 0x007b, 0x007d,
+ 0x00ab, 0x00bb, /* guillemets */
+ 0x2018, 0x2019, /* general punctuation */
+ 0x201c, 0x201d,
+ 0x2039, 0x203a,
+ 0x3008, 0x3009, /* chinese paired punctuation */
+ 0x300a, 0x300b,
+ 0x300c, 0x300d,
+ 0x300e, 0x300f,
+ 0x3010, 0x3011,
+ 0x3014, 0x3015,
+ 0x3016, 0x3017,
+ 0x3018, 0x3019,
+ 0x301a, 0x301b
+};
+
+static int
+get_pair_index (gunichar ch)
+{
+ int lower = 0;
+ int upper = G_N_ELEMENTS (paired_chars) - 1;
+
+ while (lower <= upper)
+ {
+ int mid = (lower + upper) / 2;
+
+ if (ch < paired_chars[mid])
+ upper = mid - 1;
+ else if (ch > paired_chars[mid])
+ lower = mid + 1;
+ else
+ return mid;
+ }
+
+ return -1;
+}
+
+#define REAL_SCRIPT(script) \
+ ((script) > PANGO_SCRIPT_INHERITED && (script) != PANGO_SCRIPT_UNKNOWN)
+
+#define SAME_SCRIPT(script1, script2) \
+ (!REAL_SCRIPT (script1) || !REAL_SCRIPT (script2) || (script1) == (script2))
+
+#define IS_OPEN(pair_index) (((pair_index) & 1) == 0)
+
+/**
+ * pango_script_iter_next:
+ * @iter: a #PangoScriptIter
+ *
+ * Advances a #PangoScriptIter to the next range. If @iter
+ * is already at the end, it is left unchanged and %FALSE
+ * is returned.
+ *
+ * Return value: %TRUE if @iter was successfully advanced.
+ *
+ * Since: 1.4
+ **/
+gboolean
+pango_script_iter_next (PangoScriptIter *iter)
+{
+ int start_sp;
+
+ if (iter->script_end == iter->text_end)
+ return FALSE;
+
+ start_sp = iter->paren_sp;
+ iter->script_code = PANGO_SCRIPT_COMMON;
+ iter->script_start = iter->script_end;
+
+ for (; iter->script_end < iter->text_end; iter->script_end = g_utf8_next_char (iter->script_end))
+ {
+ gunichar ch = g_utf8_get_char (iter->script_end);
+ PangoScript sc;
+ int pair_index;
+
+ sc = pango_script_for_unichar (ch);
+ if (sc != PANGO_SCRIPT_COMMON)
+ pair_index = -1;
+ else
+ pair_index = get_pair_index (ch);
+
+ /*
+ * Paired character handling:
+ *
+ * if it's an open character, push it onto the stack.
+ * if it's a close character, find the matching open on the
+ * stack, and use that script code. Any non-matching open
+ * characters above it on the stack will be poped.
+ */
+ if (pair_index >= 0)
+ {
+ if (IS_OPEN (pair_index))
+ {
+ /*
+ * If the paren stack is full, empty it. This
+ * means that deeply nested paired punctuation
+ * characters will be ignored, but that's an unusual
+ * case, and it's better to ignore them than to
+ * write off the end of the stack...
+ */
+ if (++iter->paren_sp >= PAREN_STACK_DEPTH)
+ iter->paren_sp = 0;
+
+ iter->paren_stack[iter->paren_sp].pair_index = pair_index;
+ iter->paren_stack[iter->paren_sp].script_code = iter->script_code;
+ }
+ else if (iter->paren_sp >= 0)
+ {
+ int pi = pair_index & ~1;
+
+ while (iter->paren_sp >= 0 && iter->paren_stack[iter->paren_sp].pair_index != pi)
+ iter->paren_sp--;
+
+ if (iter->paren_sp < start_sp)
+ start_sp = iter->paren_sp;
+
+ if (iter->paren_sp >= 0)
+ sc = iter->paren_stack[iter->paren_sp].script_code;
+ }
+ }
+
+ if (SAME_SCRIPT (iter->script_code, sc))
+ {
+ if (!REAL_SCRIPT (iter->script_code) && REAL_SCRIPT (sc))
+ {
+ iter->script_code = sc;
+
+ /*
+ * now that we have a final script code, fix any open
+ * characters we pushed before we knew the script code.
+ */
+ while (start_sp < iter->paren_sp)
+ iter->paren_stack[++start_sp].script_code = iter->script_code;
+ }
+
+ /*
+ * if this character is a close paired character,
+ * pop it from the stack
+ */
+ if (pair_index >= 0 && !IS_OPEN (pair_index) && iter->paren_sp >= 0)
+ {
+ iter->paren_sp--;
+
+ if (iter->paren_sp < start_sp)
+ start_sp = iter->paren_sp;
+ }
+ }
+ else
+ {
+ /* Different script, we're done */
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/**********************************************************
+ * End of code from ICU
+ **********************************************************/
diff --git a/trunk/pango/pango-script.h b/trunk/pango/pango-script.h
new file mode 100644
index 00000000..6aa2a937
--- /dev/null
+++ b/trunk/pango/pango-script.h
@@ -0,0 +1,133 @@
+/* Pango
+ * pango-script.h: Script tag handling
+ *
+ * Copyright (C) 2002 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_SCRIPT_H__
+#define __PANGO_SCRIPT_H__
+
+#include <glib.h>
+
+#include <pango/pango-language.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PangoScriptIter:
+ *
+ * A #PangoScriptIter is used to iterate through a string
+ * and identify ranges in different scripts.
+ **/
+typedef struct _PangoScriptIter PangoScriptIter;
+
+typedef enum { /* ISO 15924 code */
+ PANGO_SCRIPT_INVALID_CODE = -1,
+ PANGO_SCRIPT_COMMON = 0, /* Zyyy */
+ PANGO_SCRIPT_INHERITED, /* Qaai */
+ PANGO_SCRIPT_ARABIC, /* Arab */
+ PANGO_SCRIPT_ARMENIAN, /* Armn */
+ PANGO_SCRIPT_BENGALI, /* Beng */
+ PANGO_SCRIPT_BOPOMOFO, /* Bopo */
+ PANGO_SCRIPT_CHEROKEE, /* Cher */
+ PANGO_SCRIPT_COPTIC, /* Qaac */
+ PANGO_SCRIPT_CYRILLIC, /* Cyrl (Cyrs) */
+ PANGO_SCRIPT_DESERET, /* Dsrt */
+ PANGO_SCRIPT_DEVANAGARI, /* Deva */
+ PANGO_SCRIPT_ETHIOPIC, /* Ethi */
+ PANGO_SCRIPT_GEORGIAN, /* Geor (Geon, Geoa) */
+ PANGO_SCRIPT_GOTHIC, /* Goth */
+ PANGO_SCRIPT_GREEK, /* Grek */
+ PANGO_SCRIPT_GUJARATI, /* Gujr */
+ PANGO_SCRIPT_GURMUKHI, /* Guru */
+ PANGO_SCRIPT_HAN, /* Hani */
+ PANGO_SCRIPT_HANGUL, /* Hang */
+ PANGO_SCRIPT_HEBREW, /* Hebr */
+ PANGO_SCRIPT_HIRAGANA, /* Hira */
+ PANGO_SCRIPT_KANNADA, /* Knda */
+ PANGO_SCRIPT_KATAKANA, /* Kana */
+ PANGO_SCRIPT_KHMER, /* Khmr */
+ PANGO_SCRIPT_LAO, /* Laoo */
+ PANGO_SCRIPT_LATIN, /* Latn (Latf, Latg) */
+ PANGO_SCRIPT_MALAYALAM, /* Mlym */
+ PANGO_SCRIPT_MONGOLIAN, /* Mong */
+ PANGO_SCRIPT_MYANMAR, /* Mymr */
+ PANGO_SCRIPT_OGHAM, /* Ogam */
+ PANGO_SCRIPT_OLD_ITALIC, /* Ital */
+ PANGO_SCRIPT_ORIYA, /* Orya */
+ PANGO_SCRIPT_RUNIC, /* Runr */
+ PANGO_SCRIPT_SINHALA, /* Sinh */
+ PANGO_SCRIPT_SYRIAC, /* Syrc (Syrj, Syrn, Syre) */
+ PANGO_SCRIPT_TAMIL, /* Taml */
+ PANGO_SCRIPT_TELUGU, /* Telu */
+ PANGO_SCRIPT_THAANA, /* Thaa */
+ PANGO_SCRIPT_THAI, /* Thai */
+ PANGO_SCRIPT_TIBETAN, /* Tibt */
+ PANGO_SCRIPT_CANADIAN_ABORIGINAL, /* Cans */
+ PANGO_SCRIPT_YI, /* Yiii */
+ PANGO_SCRIPT_TAGALOG, /* Tglg */
+ PANGO_SCRIPT_HANUNOO, /* Hano */
+ PANGO_SCRIPT_BUHID, /* Buhd */
+ PANGO_SCRIPT_TAGBANWA, /* Tagb */
+
+ /* Unicode-4.0 additions */
+ PANGO_SCRIPT_BRAILLE, /* Brai */
+ PANGO_SCRIPT_CYPRIOT, /* Cprt */
+ PANGO_SCRIPT_LIMBU, /* Limb */
+ PANGO_SCRIPT_OSMANYA, /* Osma */
+ PANGO_SCRIPT_SHAVIAN, /* Shaw */
+ PANGO_SCRIPT_LINEAR_B, /* Linb */
+ PANGO_SCRIPT_TAI_LE, /* Tale */
+ PANGO_SCRIPT_UGARITIC, /* Ugar */
+
+ /* Unicode-4.1 additions */
+ PANGO_SCRIPT_NEW_TAI_LUE, /* Talu */
+ PANGO_SCRIPT_BUGINESE, /* Bugi */
+ PANGO_SCRIPT_GLAGOLITIC, /* Glag */
+ PANGO_SCRIPT_TIFINAGH, /* Tfng */
+ PANGO_SCRIPT_SYLOTI_NAGRI, /* Sylo */
+ PANGO_SCRIPT_OLD_PERSIAN, /* Xpeo */
+ PANGO_SCRIPT_KHAROSHTHI, /* Khar */
+
+ /* Unicode-5.0 additions */
+ PANGO_SCRIPT_UNKNOWN, /* Zzzz */
+ PANGO_SCRIPT_BALINESE, /* Bali */
+ PANGO_SCRIPT_CUNEIFORM, /* Xsux */
+ PANGO_SCRIPT_PHOENICIAN, /* Phnx */
+ PANGO_SCRIPT_PHAGS_PA, /* Phag */
+ PANGO_SCRIPT_NKO /* Nkoo */
+} PangoScript;
+
+PangoScript pango_script_for_unichar (gunichar ch);
+
+PangoScriptIter *pango_script_iter_new (const char *text,
+ int length);
+void pango_script_iter_get_range (PangoScriptIter *iter,
+ G_CONST_RETURN char **start,
+ G_CONST_RETURN char **end,
+ PangoScript *script);
+gboolean pango_script_iter_next (PangoScriptIter *iter);
+void pango_script_iter_free (PangoScriptIter *iter);
+
+PangoLanguage *pango_script_get_sample_language (PangoScript script) G_GNUC_PURE;
+gboolean pango_language_includes_script (PangoLanguage *language,
+ PangoScript script) G_GNUC_PURE;
+
+G_END_DECLS
+
+#endif /* __PANGO_SCRIPT_H__ */
diff --git a/trunk/pango/pango-tabs.c b/trunk/pango/pango-tabs.c
new file mode 100644
index 00000000..df283a21
--- /dev/null
+++ b/trunk/pango/pango-tabs.c
@@ -0,0 +1,370 @@
+/* Pango
+ * pango-tabs.c: Tab-related stuff
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "pango-tabs.h"
+#include "pango-impl-utils.h"
+#include <string.h>
+
+typedef struct _PangoTab PangoTab;
+
+struct _PangoTab
+{
+ gint location; /* Offset in pixels of this tab stop
+ * from the left margin of the text.
+ */
+ PangoTabAlign alignment; /* Where the tab stop appears relative
+ * to the text.
+ */
+};
+
+struct _PangoTabArray
+{
+ gint size;
+ gint allocated;
+ gboolean positions_in_pixels;
+ PangoTab *tabs;
+};
+
+static void
+init_tabs (PangoTabArray *array, gint start, gint end)
+{
+ while (start < end)
+ {
+ array->tabs[start].location = 0;
+ array->tabs[start].alignment = PANGO_TAB_LEFT;
+ ++start;
+ }
+}
+
+/**
+ * pango_tab_array_new:
+ * @initial_size: Initial number of tab stops to allocate, can be 0
+ * @positions_in_pixels: whether positions are in pixel units
+ *
+ * Creates an array of @initial_size tab stops. Tab stops are specified in
+ * pixel units if @positions_in_pixels is %TRUE, otherwise in Pango
+ * units. All stops are initially at position 0.
+ *
+ * Return value: the newly allocated #PangoTabArray, which should
+ * be freed with pango_tab_array_free().
+ **/
+PangoTabArray*
+pango_tab_array_new (gint initial_size,
+ gboolean positions_in_pixels)
+{
+ PangoTabArray *array;
+
+ g_return_val_if_fail (initial_size >= 0, NULL);
+
+ /* alloc enough to treat array->tabs as an array of length
+ * size, though it's declared as an array of length 1.
+ * If we allowed tab array resizing we'd need to drop this
+ * optimization.
+ */
+ array = g_slice_new (PangoTabArray);
+ array->size = initial_size;
+ array->allocated = initial_size;
+
+ if (array->allocated > 0)
+ {
+ array->tabs = g_new (PangoTab, array->allocated);
+ init_tabs (array, 0, array->allocated);
+ }
+ else
+ array->tabs = NULL;
+
+ array->positions_in_pixels = positions_in_pixels;
+
+ return array;
+}
+
+/**
+ * pango_tab_array_new_with_positions:
+ * @size: number of tab stops in the array
+ * @positions_in_pixels: whether positions are in pixel units
+ * @first_alignment: alignment of first tab stop
+ * @first_position: position of first tab stop
+ * @varargs: additional alignment/position pairs
+ *
+ * This is a convenience function that creates a #PangoTabArray
+ * and allows you to specify the alignment and position of each
+ * tab stop. You <emphasis>must</emphasis> provide an alignment
+ * and position for @size tab stops.
+ *
+ * Return value: the newly allocated #PangoTabArray, which should
+ * be freed with pango_tab_array_free().
+ **/
+PangoTabArray *
+pango_tab_array_new_with_positions (gint size,
+ gboolean positions_in_pixels,
+ PangoTabAlign first_alignment,
+ gint first_position,
+ ...)
+{
+ PangoTabArray *array;
+ va_list args;
+ int i;
+
+ g_return_val_if_fail (size >= 0, NULL);
+
+ array = pango_tab_array_new (size, positions_in_pixels);
+
+ if (size == 0)
+ return array;
+
+ array->tabs[0].alignment = first_alignment;
+ array->tabs[0].location = first_position;
+
+ if (size == 1)
+ return array;
+
+ va_start (args, first_position);
+
+ i = 1;
+ while (i < size)
+ {
+ PangoTabAlign align = va_arg (args, PangoTabAlign);
+ int pos = va_arg (args, int);
+
+ array->tabs[i].alignment = align;
+ array->tabs[i].location = pos;
+
+ ++i;
+ }
+
+ va_end (args);
+
+ return array;
+}
+
+GType
+pango_tab_array_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (I_("PangoTabArray"),
+ (GBoxedCopyFunc)pango_tab_array_copy,
+ (GBoxedFreeFunc)pango_tab_array_free);
+ return our_type;
+}
+
+/**
+ * pango_tab_array_copy:
+ * @src: #PangoTabArray to copy
+ *
+ * Copies a #PangoTabArray
+ *
+ * Return value: the newly allocated #PangoTabArray, which should
+ * be freed with pango_tab_array_free().
+ **/
+PangoTabArray*
+pango_tab_array_copy (PangoTabArray *src)
+{
+ PangoTabArray *copy;
+
+ g_return_val_if_fail (src != NULL, NULL);
+
+ copy = pango_tab_array_new (src->size, src->positions_in_pixels);
+
+ memcpy (copy->tabs, src->tabs, sizeof(PangoTab)*src->size);
+
+ return copy;
+}
+
+/**
+ * pango_tab_array_free:
+ * @tab_array: a #PangoTabArray
+ *
+ * Frees a tab array and associated resources.
+ *
+ **/
+void
+pango_tab_array_free (PangoTabArray *tab_array)
+{
+ g_return_if_fail (tab_array != NULL);
+
+ g_free (tab_array->tabs);
+
+ g_slice_free (PangoTabArray, tab_array);
+}
+
+/**
+ * pango_tab_array_get_size:
+ * @tab_array: a #PangoTabArray
+ *
+ * Gets the number of tab stops in @tab_array.
+ *
+ * Return value: the number of tab stops in the array.
+ **/
+gint
+pango_tab_array_get_size (PangoTabArray *tab_array)
+{
+ g_return_val_if_fail (tab_array != NULL, 0);
+
+ return tab_array->size;
+}
+
+/**
+ * pango_tab_array_resize:
+ * @tab_array: a #PangoTabArray
+ * @new_size: new size of the array
+ *
+ * Resizes a tab array. You must subsequently initialize any tabs that
+ * were added as a result of growing the array.
+ *
+ **/
+void
+pango_tab_array_resize (PangoTabArray *tab_array,
+ gint new_size)
+{
+ if (new_size > tab_array->allocated)
+ {
+ gint current_end = tab_array->allocated;
+
+ /* Ratchet allocated size up above the index. */
+ if (tab_array->allocated == 0)
+ tab_array->allocated = 2;
+
+ while (new_size > tab_array->allocated)
+ tab_array->allocated = tab_array->allocated * 2;
+
+ tab_array->tabs = g_renew (PangoTab, tab_array->tabs,
+ tab_array->allocated);
+
+ init_tabs (tab_array, current_end, tab_array->allocated);
+ }
+
+ tab_array->size = new_size;
+}
+
+/**
+ * pango_tab_array_set_tab:
+ * @tab_array: a #PangoTabArray
+ * @tab_index: the index of a tab stop
+ * @alignment: tab alignment
+ * @location: tab location in Pango units
+ *
+ * Sets the alignment and location of a tab stop.
+ * @alignment must always be #PANGO_TAB_LEFT in the current
+ * implementation.
+ *
+ **/
+void
+pango_tab_array_set_tab (PangoTabArray *tab_array,
+ gint tab_index,
+ PangoTabAlign alignment,
+ gint location)
+{
+ g_return_if_fail (tab_array != NULL);
+ g_return_if_fail (tab_index >= 0);
+ g_return_if_fail (alignment == PANGO_TAB_LEFT);
+ g_return_if_fail (location >= 0);
+
+ if (tab_index >= tab_array->size)
+ pango_tab_array_resize (tab_array, tab_index + 1);
+
+ tab_array->tabs[tab_index].alignment = alignment;
+ tab_array->tabs[tab_index].location = location;
+}
+
+/**
+ * pango_tab_array_get_tab:
+ * @tab_array: a #PangoTabArray
+ * @tab_index: tab stop index
+ * @alignment: location to store alignment, or %NULL
+ * @location: location to store tab position, or %NULL
+ *
+ * Gets the alignment and position of a tab stop.
+ *
+ **/
+void
+pango_tab_array_get_tab (PangoTabArray *tab_array,
+ gint tab_index,
+ PangoTabAlign *alignment,
+ gint *location)
+{
+ g_return_if_fail (tab_array != NULL);
+ g_return_if_fail (tab_index < tab_array->size);
+ g_return_if_fail (tab_index >= 0);
+
+ if (alignment)
+ *alignment = tab_array->tabs[tab_index].alignment;
+
+ if (location)
+ *location = tab_array->tabs[tab_index].location;
+}
+
+/**
+ * pango_tab_array_get_tabs:
+ * @tab_array: a #PangoTabArray
+ * @alignments: location to store an array of tab stop alignments, or %NULL
+ * @locations: location to store an array of tab positions, or %NULL
+ *
+ * If non-%NULL, @alignments and @locations are filled with allocated
+ * arrays of length pango_tab_array_get_size(). You must free the
+ * returned array.
+ *
+ **/
+void
+pango_tab_array_get_tabs (PangoTabArray *tab_array,
+ PangoTabAlign **alignments,
+ gint **locations)
+{
+ gint i;
+
+ g_return_if_fail (tab_array != NULL);
+
+ if (alignments)
+ *alignments = g_new (PangoTabAlign, tab_array->size);
+
+ if (locations)
+ *locations = g_new (gint, tab_array->size);
+
+ i = 0;
+ while (i < tab_array->size)
+ {
+ if (alignments)
+ (*alignments)[i] = tab_array->tabs[i].alignment;
+ if (locations)
+ (*locations)[i] = tab_array->tabs[i].location;
+
+ ++i;
+ }
+}
+
+/**
+ * pango_tab_array_get_positions_in_pixels:
+ * @tab_array: a #PangoTabArray
+ *
+ * Returns %TRUE if the tab positions are in pixels, %FALSE if they are
+ * in Pango units.
+ *
+ * Return value: whether positions are in pixels.
+ **/
+gboolean
+pango_tab_array_get_positions_in_pixels (PangoTabArray *tab_array)
+{
+ g_return_val_if_fail (tab_array != NULL, FALSE);
+
+ return tab_array->positions_in_pixels;
+}
diff --git a/trunk/pango/pango-tabs.h b/trunk/pango/pango-tabs.h
new file mode 100644
index 00000000..7f52d1d0
--- /dev/null
+++ b/trunk/pango/pango-tabs.h
@@ -0,0 +1,76 @@
+/* Pango
+ * pango-tabs.h: Tab-related stuff
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_TABS_H__
+#define __PANGO_TABS_H__
+
+#include <pango/pango-types.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoTabArray PangoTabArray;
+
+typedef enum
+{
+ PANGO_TAB_LEFT
+
+ /* These are not supported now, but may be in the
+ * future.
+ *
+ * PANGO_TAB_RIGHT,
+ * PANGO_TAB_CENTER,
+ * PANGO_TAB_NUMERIC
+ */
+} PangoTabAlign;
+
+#define PANGO_TYPE_TAB_ARRAY (pango_tab_array_get_type ())
+
+PangoTabArray *pango_tab_array_new (gint initial_size,
+ gboolean positions_in_pixels);
+PangoTabArray *pango_tab_array_new_with_positions (gint size,
+ gboolean positions_in_pixels,
+ PangoTabAlign first_alignment,
+ gint first_position,
+ ...);
+GType pango_tab_array_get_type (void) G_GNUC_CONST;
+PangoTabArray *pango_tab_array_copy (PangoTabArray *src);
+void pango_tab_array_free (PangoTabArray *tab_array);
+gint pango_tab_array_get_size (PangoTabArray *tab_array);
+void pango_tab_array_resize (PangoTabArray *tab_array,
+ gint new_size);
+void pango_tab_array_set_tab (PangoTabArray *tab_array,
+ gint tab_index,
+ PangoTabAlign alignment,
+ gint location);
+void pango_tab_array_get_tab (PangoTabArray *tab_array,
+ gint tab_index,
+ PangoTabAlign *alignment,
+ gint *location);
+void pango_tab_array_get_tabs (PangoTabArray *tab_array,
+ PangoTabAlign **alignments,
+ gint **locations);
+
+gboolean pango_tab_array_get_positions_in_pixels (PangoTabArray *tab_array);
+
+
+G_END_DECLS
+
+#endif /* __PANGO_TABS_H__ */
diff --git a/trunk/pango/pango-types.h b/trunk/pango/pango-types.h
new file mode 100644
index 00000000..642a06c6
--- /dev/null
+++ b/trunk/pango/pango-types.h
@@ -0,0 +1,146 @@
+/* Pango
+ * pango-types.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_TYPES_H__
+#define __PANGO_TYPES_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoLogAttr PangoLogAttr;
+
+typedef struct _PangoEngineLang PangoEngineLang;
+typedef struct _PangoEngineShape PangoEngineShape;
+
+typedef struct _PangoFont PangoFont;
+typedef struct _PangoFontMap PangoFontMap;
+
+typedef struct _PangoRectangle PangoRectangle;
+
+
+
+/* A index of a glyph into a font. Rendering system dependent */
+typedef guint32 PangoGlyph;
+
+
+
+#define PANGO_SCALE 1024
+#define PANGO_PIXELS(d) (((int)(d) + 512) >> 10)
+#define PANGO_PIXELS_FLOOR(d) (((int)(d)) >> 10)
+#define PANGO_PIXELS_CEIL(d) (((int)(d) + 1023) >> 10)
+/* The above expressions are just slightly wrong for floating point d;
+ * For example we'd expect PANGO_PIXELS(-512.5) => -1 but instead we get 0.
+ * That's unlikely to matter for practical use and the expression is much
+ * more compact and faster than alternatives that work exactly for both
+ * integers and floating point.
+ *
+ * PANGO_PIXELS also behaves differently for +512 and -512.
+ */
+
+#define PANGO_UNITS_ROUND(d) \
+ (((d) + (PANGO_SCALE >> 1)) & ~(PANGO_SCALE - 1))
+
+
+int pango_units_from_double (double d) G_GNUC_CONST;
+double pango_units_to_double (int i) G_GNUC_CONST;
+
+
+
+/* A rectangle. Used to store logical and physical extents of glyphs,
+ * runs, strings, etc.
+ */
+struct _PangoRectangle
+{
+ int x;
+ int y;
+ int width;
+ int height;
+};
+
+/* Macros to translate from extents rectangles to ascent/descent/lbearing/rbearing
+ */
+#define PANGO_ASCENT(rect) (-(rect).y)
+#define PANGO_DESCENT(rect) ((rect).y + (rect).height)
+#define PANGO_LBEARING(rect) ((rect).x)
+#define PANGO_RBEARING(rect) ((rect).x + (rect).width)
+
+void pango_extents_to_pixels (PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+/**
+ * PangoDirection:
+ * @PANGO_DIRECTION_LTR: A strong left-to-right direction
+ * @PANGO_DIRECTION_RTL: A strong right-to-left direction
+ * @PANGO_DIRECTION_TTB_LTR: Deprecated value; treated the
+ * same as %PANGO_DIRECTION_RTL.
+ * @PANGO_DIRECTION_TTB_RTL: Deprecated value; treated the
+ * same as %PANGO_DIRECTION_LTR
+ * @PANGO_DIRECTION_WEAK_LTR: A weak left-to-right direction
+ * @PANGO_DIRECTION_WEAK_RTL: A weak right-to-left direction
+ * @PANGO_DIRECTION_NEUTRAL: No direction specified
+ *
+ * The #PangoDirection type represents a direction in the
+ * Unicode bidirectional algorithm; not every value in this
+ * enumeration makes sense for every usage of #PangoDirection;
+ * for example, the return value of pango_unichar_direction()
+ * and pango_find_base_dir() cannot be %PANGO_DIRECTION_WEAK_LTR
+ * or %PANGO_DIRECTION_WEAK_RTL, since every character is either
+ * neutral or has a strong direction; on the other hand
+ * %PANGO_DIRECTION_NEUTRAL doesn't make sense to pass
+ * to pango_itemize_with_base_dir().
+ *
+ * The %PANGO_DIRECTION_TTB_LTR, %PANGO_DIRECTION_TTB_RTL
+ * values come from an earlier interpretation of this
+ * enumeration as the writing direction of a block of
+ * text and are no longer used; See #PangoGravity for how
+ * vertical text is handled in Pango.
+ **/
+typedef enum {
+ PANGO_DIRECTION_LTR,
+ PANGO_DIRECTION_RTL,
+ PANGO_DIRECTION_TTB_LTR,
+ PANGO_DIRECTION_TTB_RTL,
+ PANGO_DIRECTION_WEAK_LTR,
+ PANGO_DIRECTION_WEAK_RTL,
+ PANGO_DIRECTION_NEUTRAL
+} PangoDirection;
+
+PangoDirection pango_unichar_direction (gunichar ch) G_GNUC_CONST;
+PangoDirection pango_find_base_dir (const gchar *text,
+ gint length);
+
+#ifndef PANGO_DISABLE_DEPRECATED
+gboolean pango_get_mirror_char (gunichar ch,
+ gunichar *mirrored_ch);
+#endif
+
+
+#include <pango/pango-gravity.h>
+#include <pango/pango-language.h>
+#include <pango/pango-matrix.h>
+#include <pango/pango-script.h>
+
+
+G_END_DECLS
+
+#endif /* __PANGO_TYPES_H__ */
diff --git a/trunk/pango/pango-utils.c b/trunk/pango/pango-utils.c
new file mode 100644
index 00000000..39ade732
--- /dev/null
+++ b/trunk/pango/pango-utils.c
@@ -0,0 +1,1643 @@
+/* Pango
+ * pango-utils.c: Utilities for internal functions and modules
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <locale.h>
+
+#include "pango-font.h"
+#include "pango-features.h"
+#include "pango-impl-utils.h"
+
+#include <glib/gstdio.h>
+
+#include "mini-fribidi/fribidi.h"
+
+#ifndef HAVE_FLOCKFILE
+# define flockfile(f) (void)1
+# define funlockfile(f) (void)1
+# define getc_unlocked(f) getc(f)
+#endif /* !HAVE_FLOCKFILE */
+
+#ifdef G_OS_WIN32
+
+#include <sys/types.h>
+
+#define STRICT
+#include <windows.h>
+
+#endif
+
+struct PangoAlias
+{
+ char *alias;
+ int n_families;
+ char **families;
+ gboolean visible; /* Do we want/need this? */
+};
+
+static GHashTable *pango_aliases_ht = NULL;
+
+PangoWarningHistory _pango_warning_history = { FALSE, FALSE, FALSE };
+
+/**
+ * pango_version:
+ *
+ * This is similar to the macro %PANGO_VERSION except that
+ * it returns the encoded version of Pango available at run-time,
+ * as opposed to the version available at compile-time.
+ *
+ * A version number can be encoded into an integer using
+ * PANGO_VERSION_ENCODE().
+ *
+ * Returns value: The encoded version of Pango library
+ * available at run time.
+ *
+ * Since: 1.16
+ **/
+int
+pango_version (void)
+{
+ return PANGO_VERSION;
+}
+
+/**
+ * pango_version_string:
+ *
+ * This is similar to the macro %PANGO_VERSION_STRING except that
+ * it returns the version of Pango available at run-time, as opposed to
+ * the version available at compile-time.
+ *
+ * Returns value: A string containing the version of Pango library
+ * available at run time.
+ * The returned string is owned by Pango and should not be modified
+ * or freed.
+ *
+ * Since: 1.16
+ **/
+const char *
+pango_version_string (void)
+{
+ return PANGO_VERSION_STRING;
+}
+
+/**
+ * pango_version_check:
+ * @required_major: the required major version.
+ * @required_minor: the required minor version.
+ * @required_micro: the required major version.
+ *
+ * Checks that the Pango library in use is compatible with the
+ * given version. Generally you would pass in the constants
+ * %PANGO_VERSION_MAJOR, %PANGO_VERSION_MINOR, %PANGO_VERSION_MICRO
+ * as the three arguments to this function; that produces
+ * a check that the library in use at run-time is compatible with
+ * the version of Pango the application or module was compiled against.
+ *
+ * Compatibility is defined by two things: first the version
+ * of the running library is newer than the version
+ * @required_major.required_minor.@required_micro. Second
+ * the running library must be binary compatible with the
+ * version @required_major.required_minor.@required_micro
+ * (same major version.)
+ *
+ * For compile-time version checking use PANGO_VERSION_CHECK().
+ *
+ * Return value: %NULL if the Pango library is compatible with the
+ * given version, or a string describing the version mismatch.
+ * The returned string is owned by Pango and should not be modified
+ * or freed.
+ *
+ * Since: 1.16
+ **/
+const gchar*
+pango_version_check (int required_major,
+ int required_minor,
+ int required_micro)
+{
+ gint pango_effective_micro = 100 * PANGO_VERSION_MINOR + PANGO_VERSION_MICRO;
+ gint required_effective_micro = 100 * required_minor + required_micro;
+
+ if (required_major < PANGO_VERSION_MAJOR)
+ return "Pango version too new (major mismatch)";
+ if (required_effective_micro < pango_effective_micro - PANGO_BINARY_AGE)
+ return "Pango version too new (micro mismatch)";
+ if (required_effective_micro > pango_effective_micro)
+ return "Pango version too old (micro mismatch)";
+ return NULL;
+}
+
+/**
+ * pango_trim_string:
+ * @str: a string
+ *
+ * Trims leading and trailing whitespace from a string.
+ *
+ * Return value: A newly-allocated string that must be freed with g_free()
+ **/
+char *
+pango_trim_string (const char *str)
+{
+ int len;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ while (*str && g_ascii_isspace (*str))
+ str++;
+
+ len = strlen (str);
+ while (len > 0 && g_ascii_isspace (str[len-1]))
+ len--;
+
+ return g_strndup (str, len);
+}
+
+/**
+ * pango_split_file_list:
+ * @str: a %G_SEARCHPATH_SEPARATOR separated list of filenames
+ *
+ * Splits a %G_SEARCHPATH_SEPARATOR-separated list of files, stripping
+ * white space and substituting ~/ with $HOME/.
+ *
+ * Return value: a list of strings to be freed with g_strfreev()
+ **/
+char **
+pango_split_file_list (const char *str)
+{
+ int i = 0;
+ int j;
+ char **files;
+
+ files = g_strsplit (str, G_SEARCHPATH_SEPARATOR_S, -1);
+
+ while (files[i])
+ {
+ char *file = pango_trim_string (files[i]);
+
+ /* If the resulting file is empty, skip it */
+ if (file[0] == '\0')
+ {
+ g_free(file);
+ g_free (files[i]);
+
+ for (j = i + 1; files[j]; j++)
+ files[j - 1] = files[j];
+
+ files[j - 1] = NULL;
+
+ continue;
+ }
+#ifndef G_OS_WIN32
+ /* '~' is a quite normal and common character in file names on
+ * Windows, especially in the 8.3 versions of long file names, which
+ * still occur now and then. Also, few Windows user are aware of the
+ * Unix shell convention that '~' stands for the home directory,
+ * even if they happen to have a home directory.
+ */
+ if (file[0] == '~' && file[1] == G_DIR_SEPARATOR)
+ {
+ char *tmp = g_strconcat (g_get_home_dir(), file + 1, NULL);
+ g_free (file);
+ file = tmp;
+ }
+ else if (file[0] == '~' && file[1] == '\0')
+ {
+ g_free (file);
+ file = g_strdup (g_get_home_dir());
+ }
+#endif
+ g_free (files[i]);
+ files[i] = file;
+
+ i++;
+ }
+
+ return files;
+}
+
+/**
+ * pango_read_line:
+ * @stream: a stdio stream
+ * @str: #GString buffer into which to write the result
+ *
+ * Reads an entire line from a file into a buffer. Lines may
+ * be delimited with '\n', '\r', '\n\r', or '\r\n'. The delimiter
+ * is not written into the buffer. Text after a '#' character is treated as
+ * a comment and skipped. '\' can be used to escape a # character.
+ * '\' proceeding a line delimiter combines adjacent lines. A '\' proceeding
+ * any other character is ignored and written into the output buffer
+ * unmodified.
+ *
+ * Return value: 0 if the stream was already at an %EOF character, otherwise
+ * the number of lines read (this is useful for maintaining
+ * a line number counter which doesn't combine lines with '\')
+ **/
+gint
+pango_read_line (FILE *stream, GString *str)
+{
+ gboolean quoted = FALSE;
+ gboolean comment = FALSE;
+ int n_read = 0;
+ int lines = 1;
+
+ flockfile (stream);
+
+ g_string_truncate (str, 0);
+
+ while (1)
+ {
+ int c;
+
+ c = getc_unlocked (stream);
+
+ if (c == EOF)
+ {
+ if (quoted)
+ g_string_append_c (str, '\\');
+
+ goto done;
+ }
+ else
+ n_read++;
+
+ if (quoted)
+ {
+ quoted = FALSE;
+
+ switch (c)
+ {
+ case '#':
+ g_string_append_c (str, '#');
+ break;
+ case '\r':
+ case '\n':
+ {
+ int next_c = getc_unlocked (stream);
+
+ if (!(next_c == EOF ||
+ (c == '\r' && next_c == '\n') ||
+ (c == '\n' && next_c == '\r')))
+ ungetc (next_c, stream);
+
+ lines++;
+
+ break;
+ }
+ default:
+ g_string_append_c (str, '\\');
+ g_string_append_c (str, c);
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case '#':
+ comment = TRUE;
+ break;
+ case '\\':
+ if (!comment)
+ quoted = TRUE;
+ break;
+ case '\n':
+ {
+ int next_c = getc_unlocked (stream);
+
+ if (!(c == EOF ||
+ (c == '\r' && next_c == '\n') ||
+ (c == '\n' && next_c == '\r')))
+ ungetc (next_c, stream);
+
+ goto done;
+ }
+ default:
+ if (!comment)
+ g_string_append_c (str, c);
+ }
+ }
+ }
+
+ done:
+
+ funlockfile (stream);
+
+ return (n_read > 0) ? lines : 0;
+}
+
+/**
+ * pango_skip_space:
+ * @pos: in/out string position
+ *
+ * Skips 0 or more characters of white space.
+ *
+ * Return value: %FALSE if skipping the white space leaves
+ * the position at a '\0' character.
+ **/
+gboolean
+pango_skip_space (const char **pos)
+{
+ const char *p = *pos;
+
+ while (g_ascii_isspace (*p))
+ p++;
+
+ *pos = p;
+
+ return !(*p == '\0');
+}
+
+/**
+ * pango_scan_word:
+ * @pos: in/out string position
+ * @out: a #GString into which to write the result
+ *
+ * Scans a word into a #GString buffer. A word consists
+ * of [A-Za-z_] followed by zero or more [A-Za-z_0-9]
+ * Leading white space is skipped.
+ *
+ * Return value: %FALSE if a parse error occurred.
+ **/
+gboolean
+pango_scan_word (const char **pos, GString *out)
+{
+ const char *p = *pos;
+
+ while (g_ascii_isspace (*p))
+ p++;
+
+ if (!((*p >= 'A' && *p <= 'Z') ||
+ (*p >= 'a' && *p <= 'z') ||
+ *p == '_'))
+ return FALSE;
+
+ g_string_truncate (out, 0);
+ g_string_append_c (out, *p);
+ p++;
+
+ while ((*p >= 'A' && *p <= 'Z') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= '0' && *p <= '9') ||
+ *p == '_')
+ {
+ g_string_append_c (out, *p);
+ p++;
+ }
+
+ *pos = p;
+
+ return TRUE;
+}
+
+/**
+ * pango_scan_string:
+ * @pos: in/out string position
+ * @out: a #GString into which to write the result
+ *
+ * Scans a string into a #GString buffer. The string may either
+ * be a sequence of non-white-space characters, or a quoted
+ * string with '"'. Instead a quoted string, '\"' represents
+ * a literal quote. Leading white space outside of quotes is skipped.
+ *
+ * Return value: %FALSE if a parse error occurred.
+ **/
+gboolean
+pango_scan_string (const char **pos, GString *out)
+{
+ const char *p = *pos;
+
+ while (g_ascii_isspace (*p))
+ p++;
+
+ if (!*p)
+ return FALSE;
+ else if (*p == '"')
+ {
+ gboolean quoted = FALSE;
+ g_string_truncate (out, 0);
+
+ p++;
+
+ while (TRUE)
+ {
+ if (quoted)
+ {
+ int c = *p;
+
+ switch (c)
+ {
+ case '\0':
+ return FALSE;
+ case 'n':
+ c = '\n';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ default:
+ break;
+ }
+
+ quoted = FALSE;
+ g_string_append_c (out, c);
+ }
+ else
+ {
+ switch (*p)
+ {
+ case '\0':
+ return FALSE;
+ case '\\':
+ quoted = TRUE;
+ break;
+ case '"':
+ p++;
+ goto done;
+ default:
+ g_string_append_c (out, *p);
+ break;
+ }
+ }
+ p++;
+ }
+ done:
+ ;
+ }
+ else
+ {
+ g_string_truncate (out, 0);
+
+ while (*p && !g_ascii_isspace (*p))
+ {
+ g_string_append_c (out, *p);
+ p++;
+ }
+ }
+
+ *pos = p;
+
+ return TRUE;
+}
+
+/**
+ * pango_scan_int:
+ * @pos: in/out string position
+ * @out: an int into which to write the result
+ *
+ * Scans an integer.
+ * Leading white space is skipped.
+ *
+ * Return value: %FALSE if a parse error occurred.
+ **/
+gboolean
+pango_scan_int (const char **pos, int *out)
+{
+ unsigned int i = 0;
+ char *end;
+ long temp;
+
+ errno = 0;
+ temp = strtol (*pos, &end, 10);
+ if (errno == ERANGE)
+ {
+ errno = 0;
+ return FALSE;
+ }
+
+ *out = (int)temp;
+ if ((long)(*out) != temp)
+ {
+ return FALSE;
+ }
+
+ *pos = end;
+
+ return TRUE;
+}
+
+static GHashTable *config_hash = NULL;
+
+static void
+read_config_file (const char *filename, gboolean enoent_error)
+{
+ GKeyFile *key_file = g_key_file_new();
+ GError *key_file_error = NULL;
+ gchar **groups;
+ gsize groups_count = 0;
+ guint group_index;
+
+ if (!g_key_file_load_from_file(key_file,filename, 0, &key_file_error))
+ {
+ if (key_file_error)
+ {
+ if (key_file_error->domain != G_FILE_ERROR || key_file_error->code != G_FILE_ERROR_NOENT || enoent_error)
+ {
+ g_warning ("error opening config file '%s': %s\n",
+ filename, key_file_error->message);
+ }
+ g_error_free(key_file_error);
+ }
+ g_key_file_free(key_file);
+ return;
+ }
+
+ groups = g_key_file_get_groups (key_file, &groups_count);
+ for (group_index = 0; group_index < groups_count; group_index++)
+ {
+ gsize keys_count = 0;
+ const gchar *group = groups[group_index];
+ GError *keys_error = NULL;
+ gchar **keys;
+
+ keys = g_key_file_get_keys(key_file, group, &keys_count, &keys_error);
+
+ if (keys)
+ {
+ guint key_index;
+
+ for (key_index = 0; key_index < keys_count; key_index++)
+ {
+ const gchar *key = keys[key_index];
+ GError *key_error = NULL;
+ gchar *value = g_key_file_get_value(key_file, group, key, &key_error);
+ if (value != NULL)
+ {
+ g_hash_table_insert (config_hash,
+ g_strdup_printf ("%s/%s", group, key),
+ value);
+ }
+ if (key_error)
+ {
+ g_warning ("error getting key '%s/%s' in config file '%s'\n",
+ group, key, filename);
+ g_error_free(key_error);
+ }
+ }
+ g_strfreev(keys);
+ }
+
+ if (keys_error)
+ {
+ g_warning ("error getting keys in group '%s' of config file '%s'\n",
+ filename, group);
+ g_error_free(keys_error);
+ }
+ }
+ g_strfreev(groups);
+ g_key_file_free(key_file);
+}
+
+static void
+read_config (void)
+{
+ if (!config_hash)
+ {
+ char *filename;
+ const char *home;
+ const char *envvar;
+
+ config_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)g_free);
+ filename = g_build_filename (pango_get_sysconf_subdirectory (),
+ "pangorc",
+ NULL);
+ read_config_file (filename, FALSE);
+ g_free (filename);
+
+ home = g_get_home_dir ();
+ if (home && *home)
+ {
+ filename = g_build_filename (home, ".pangorc", NULL);
+ read_config_file (filename, FALSE);
+ g_free (filename);
+ }
+
+ envvar = g_getenv ("PANGO_RC_FILE");
+ if (envvar)
+ read_config_file (envvar, TRUE);
+ }
+}
+
+/**
+ * pango_config_key_get:
+ * @key: Key to look up, in the form "SECTION/KEY".
+ *
+ * Looks up a key in the Pango config database
+ * (pseudo-win.ini style, read from $sysconfdir/pango/pangorc,
+ * ~/.pangorc, and getenv (PANGO_RC_FILE).)
+ *
+ * Return value: the value, if found, otherwise %NULL. The value is a
+ * newly-allocated string and must be freed with g_free().
+ **/
+char *
+pango_config_key_get (const char *key)
+{
+ g_return_val_if_fail (key != NULL, NULL);
+
+ read_config ();
+
+ return g_strdup (g_hash_table_lookup (config_hash, key));
+}
+
+#ifdef G_OS_WIN32
+
+/* DllMain function needed to tuck away the DLL name */
+
+G_WIN32_DLLMAIN_FOR_DLL_NAME(static, dll_name)
+#endif
+
+/**
+ * pango_get_sysconf_subdirectory:
+ *
+ * On Unix, returns the name of the "pango" subdirectory of SYSCONFDIR
+ * (which is set at compile time). On Win32, returns a subdirectory of
+ * the Pango installation directory (which is deduced at run time from
+ * the DLL's location, or stored in the Registry).
+ *
+ * Return value: the Pango sysconf directory. The returned string should
+ * not be freed.
+ */
+G_CONST_RETURN char *
+pango_get_sysconf_subdirectory (void)
+{
+#ifdef G_OS_WIN32
+ static gchar *result = NULL;
+
+ if (result == NULL)
+ result = g_win32_get_package_installation_subdirectory
+ (PACKAGE " " VERSION, dll_name, "etc\\pango");
+
+ return result;
+#else
+ return SYSCONFDIR "/pango";
+#endif
+}
+
+/**
+ * pango_get_lib_subdirectory:
+ *
+ * On Unix, returns the name of the "pango" subdirectory of LIBDIR
+ * (which is set at compile time). On Win32, returns the Pango
+ * installation directory (which is deduced at run time from the DLL's
+ * location, or stored in the Registry). The returned string should
+ * not be freed.
+ *
+ * Return value: the Pango lib directory. The returned string should
+ * not be freed.
+ */
+G_CONST_RETURN char *
+pango_get_lib_subdirectory (void)
+{
+#ifdef G_OS_WIN32
+ static gchar *result = NULL;
+
+ if (result == NULL)
+ result = g_win32_get_package_installation_subdirectory
+ (PACKAGE " " VERSION, dll_name, "lib\\pango");
+
+ return result;
+#else
+ return LIBDIR "/pango";
+#endif
+}
+
+
+/**
+ * pango_parse_enum:
+ * @type: enum type to parse, eg. %PANGO_TYPE_ELLIPSIZE_MODE.
+ * @str: string to parse. May be %NULL.
+ * @value: integer to store the result in, or %NULL.
+ * @warn: if %TRUE, issue a g_warning() on bad input.
+ * @possible_values: place to store list of possible values on failure, or %NULL.
+ *
+ * Parses an enum type and stored the result in @value.
+ *
+ * If @str does not match the nick name of any of the possible values for the
+ * enum, %FALSE is returned, a warning is issued if @warn is %TRUE, and a
+ * string representing the list of possible values is stored in
+ * @possible_values. The list is slash-separated, eg.
+ * "none/start/middle/end". If failed and @possible_values is not %NULL,
+ * returned string should be freed using g_free().
+ *
+ * Return value: %TRUE if @str was successfully parsed.
+ *
+ * Since: 1.16
+ **/
+gboolean
+pango_parse_enum (GType type,
+ const char *str,
+ int *value,
+ gboolean warn,
+ char **possible_values)
+{
+ GEnumClass *class = NULL;
+ gboolean ret = TRUE;
+ GEnumValue *v = NULL;
+
+ class = g_type_class_ref (type);
+
+ if (G_LIKELY (str))
+ v = g_enum_get_value_by_nick (class, str);
+
+ if (v)
+ {
+ if (G_LIKELY (value))
+ *value = v->value;
+ }
+ else
+ {
+ ret = FALSE;
+ if (warn || possible_values)
+ {
+ int i;
+ GString *s = g_string_new (NULL);
+
+ for (i = 0, v = g_enum_get_value (class, i); v;
+ i++ , v = g_enum_get_value (class, i))
+ {
+ if (i)
+ g_string_append_c (s, '/');
+ g_string_append (s, v->value_nick);
+ }
+
+ if (warn)
+ g_warning ("%s must be one of %s",
+ G_ENUM_CLASS_TYPE_NAME(class),
+ s->str);
+
+ if (possible_values)
+ *possible_values = s->str;
+
+ g_string_free (s, possible_values ? FALSE : TRUE);
+ }
+ }
+
+ g_type_class_unref (class);
+
+ return ret;
+}
+
+/**
+ * pango_parse_style:
+ * @str: a string to parse.
+ * @style: a #PangoStyle to store the result in.
+ * @warn: if %TRUE, issue a g_warning() on bad input.
+ *
+ * Parses a font style. The allowed values are "normal",
+ * "italic" and "oblique", case variations being
+ * ignored.
+ *
+ * Return value: %TRUE if @str was successfully parsed.
+ **/
+gboolean
+pango_parse_style (const char *str,
+ PangoStyle *style,
+ gboolean warn)
+{
+ if (*str == '\0')
+ return FALSE;
+
+ switch (str[0])
+ {
+ case 'n':
+ case 'N':
+ if (g_ascii_strcasecmp (str, "normal") == 0)
+ {
+ *style = PANGO_STYLE_NORMAL;
+ return TRUE;
+ }
+ break;
+ case 'i':
+ case 'I':
+ if (g_ascii_strcasecmp (str, "italic") == 0)
+ {
+ *style = PANGO_STYLE_ITALIC;
+ return TRUE;
+ }
+ break;
+ case 'o':
+ case 'O':
+ if (g_ascii_strcasecmp (str, "oblique") == 0)
+ {
+ *style = PANGO_STYLE_OBLIQUE;
+ return TRUE;
+ }
+ break;
+ }
+ if (warn)
+ g_warning ("style must be normal, italic, or oblique");
+
+ return FALSE;
+}
+
+/**
+ * pango_parse_variant:
+ * @str: a string to parse.
+ * @variant: a #PangoVariant to store the result in.
+ * @warn: if %TRUE, issue a g_warning() on bad input.
+ *
+ * Parses a font variant. The allowed values are "normal"
+ * and "smallcaps" or "small_caps", case variations being
+ * ignored.
+ *
+ * Return value: %TRUE if @str was successfully parsed.
+ **/
+gboolean
+pango_parse_variant (const char *str,
+ PangoVariant *variant,
+ gboolean warn)
+{
+ if (*str == '\0')
+ return FALSE;
+
+ switch (str[0])
+ {
+ case 'n':
+ case 'N':
+ if (g_ascii_strcasecmp (str, "normal") == 0)
+ {
+ *variant = PANGO_VARIANT_NORMAL;
+ return TRUE;
+ }
+ break;
+ case 's':
+ case 'S':
+ if (g_ascii_strcasecmp (str, "small_caps") == 0 ||
+ g_ascii_strcasecmp (str, "smallcaps") == 0)
+ {
+ *variant = PANGO_VARIANT_SMALL_CAPS;
+ return TRUE;
+ }
+ break;
+ }
+
+ if (warn)
+ g_warning ("variant must be normal or small_caps");
+ return FALSE;
+}
+
+/**
+ * pango_parse_weight:
+ * @str: a string to parse.
+ * @weight: a #PangoWeight to store the result in.
+ * @warn: if %TRUE, issue a g_warning() on bad input.
+ *
+ * Parses a font weight. The allowed values are "heavy",
+ * "ultrabold", "bold", "normal", "light", "ultraleight"
+ * and integers. Case variations are ignored.
+ *
+ * Return value: %TRUE if @str was successfully parsed.
+ **/
+gboolean
+pango_parse_weight (const char *str,
+ PangoWeight *weight,
+ gboolean warn)
+{
+ if (*str == '\0')
+ return FALSE;
+
+ switch (str[0])
+ {
+ case 'b':
+ case 'B':
+ if (g_ascii_strcasecmp (str, "bold") == 0)
+ {
+ *weight = PANGO_WEIGHT_BOLD;
+ return TRUE;
+ }
+ break;
+ case 'h':
+ case 'H':
+ if (g_ascii_strcasecmp (str, "heavy") == 0)
+ {
+ *weight = PANGO_WEIGHT_HEAVY;
+ return TRUE;
+ }
+ break;
+ case 'l':
+ case 'L':
+ if (g_ascii_strcasecmp (str, "light") == 0)
+ {
+ *weight = PANGO_WEIGHT_LIGHT;
+ return TRUE;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (g_ascii_strcasecmp (str, "normal") == 0)
+ {
+ *weight = PANGO_WEIGHT_NORMAL;
+ return TRUE;
+ }
+ break;
+ case 'u':
+ case 'U':
+ if (g_ascii_strcasecmp (str, "ultralight") == 0)
+ {
+ *weight = PANGO_WEIGHT_ULTRALIGHT;
+ return TRUE;
+ }
+ else if (g_ascii_strcasecmp (str, "ultrabold") == 0)
+ {
+ *weight = PANGO_WEIGHT_ULTRABOLD;
+ return TRUE;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ char *end;
+
+ *weight = strtol (str, &end, 10);
+ if (*end != '\0')
+ {
+ if (warn)
+ g_warning ("failed parsing numerical weight '%s'", str);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+
+ if (warn)
+ g_warning ("weight must be ultralight, light, normal, bold, ultrabold, heavy, or an integer");
+ return FALSE;
+}
+
+/**
+ * pango_parse_stretch:
+ * @str: a string to parse.
+ * @stretch: a #PangoStretch to store the result in.
+ * @warn: if %TRUE, issue a g_warning() on bad input.
+ *
+ * Parses a font stretch. The allowed values are
+ * "ultra_condensed", "extra_condensed", "condensed",
+ * "semi_condensed", "normal", "semi_expanded", "expanded",
+ * "extra_expanded" and "ultra_expanded". Case variations are
+ * ignored and the '_' characters may be omitted.
+ *
+ * Return value: %TRUE if @str was successfully parsed.
+ **/
+gboolean
+pango_parse_stretch (const char *str,
+ PangoStretch *stretch,
+ gboolean warn)
+{
+ if (*str == '\0')
+ return FALSE;
+
+ switch (str[0])
+ {
+ case 'c':
+ case 'C':
+ if (g_ascii_strcasecmp (str, "condensed") == 0)
+ {
+ *stretch = PANGO_STRETCH_CONDENSED;
+ return TRUE;
+ }
+ break;
+ case 'e':
+ case 'E':
+ if (g_ascii_strcasecmp (str, "extra_condensed") == 0 ||
+ g_ascii_strcasecmp (str, "extracondensed") == 0)
+ {
+ *stretch = PANGO_STRETCH_EXTRA_CONDENSED;
+ return TRUE;
+ }
+ if (g_ascii_strcasecmp (str, "extra_expanded") == 0 ||
+ g_ascii_strcasecmp (str, "extraexpanded") == 0)
+ {
+ *stretch = PANGO_STRETCH_EXTRA_EXPANDED;
+ return TRUE;
+ }
+ if (g_ascii_strcasecmp (str, "expanded") == 0)
+ {
+ *stretch = PANGO_STRETCH_EXPANDED;
+ return TRUE;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (g_ascii_strcasecmp (str, "normal") == 0)
+ {
+ *stretch = PANGO_STRETCH_NORMAL;
+ return TRUE;
+ }
+ break;
+ case 's':
+ case 'S':
+ if (g_ascii_strcasecmp (str, "semi_condensed") == 0 ||
+ g_ascii_strcasecmp (str, "semicondensed") == 0)
+ {
+ *stretch = PANGO_STRETCH_SEMI_CONDENSED;
+ return TRUE;
+ }
+ if (g_ascii_strcasecmp (str, "semi_expanded") == 0 ||
+ g_ascii_strcasecmp (str, "semiexpanded") == 0)
+ {
+ *stretch = PANGO_STRETCH_SEMI_EXPANDED;
+ return TRUE;
+ }
+ break;
+ case 'u':
+ case 'U':
+ if (g_ascii_strcasecmp (str, "ultra_condensed") == 0 ||
+ g_ascii_strcasecmp (str, "ultracondensed") == 0)
+ {
+ *stretch = PANGO_STRETCH_ULTRA_CONDENSED;
+ return TRUE;
+ }
+ if (g_ascii_strcasecmp (str, "ultra_expanded") == 0 ||
+ g_ascii_strcasecmp (str, "ultraexpanded") == 0)
+ {
+ *stretch = PANGO_STRETCH_ULTRA_EXPANDED;
+ return TRUE;
+ }
+ break;
+ }
+
+ if (warn)
+ g_warning ("stretch must be ultra_condensed, extra_condensed, condensed, semi_condensed, normal, semi_expanded, expanded, extra_expanded, or ultra_expanded");
+ return FALSE;
+}
+
+/**
+ * pango_log2vis_get_embedding_levels:
+ * @text: the text to itemize.
+ * @length: the number of bytes (not characters) to process, or -1
+ * if @text is nul-terminated and the length should be calculated.
+ * @pbase_dir: input base direction, and output resolved direction.
+ *
+ * This will return the bidirectional embedding levels of the input paragraph
+ * as defined by the Unicode Bidirectional Algorithm available at:
+ *
+ * http://www.unicode.org/reports/tr9/
+ *
+ * If the input base direction is a weak direction, the direction of the
+ * characters in the text will determine the final resolved direction.
+ *
+ * Return value: a newly allocated array of embedding levels, one item per
+ * character (not byte), that should be freed using g_free.
+ *
+ * Since: 1.4
+ */
+guint8 *
+pango_log2vis_get_embedding_levels (const gchar *text,
+ int length,
+ PangoDirection *pbase_dir)
+{
+ FriBidiCharType fribidi_base_dir;
+ guint8 *embedding_levels_list;
+
+ switch (*pbase_dir)
+ {
+ case PANGO_DIRECTION_LTR:
+ case PANGO_DIRECTION_TTB_RTL:
+ fribidi_base_dir = FRIBIDI_TYPE_L;
+ break;
+ case PANGO_DIRECTION_RTL:
+ case PANGO_DIRECTION_TTB_LTR:
+ fribidi_base_dir = FRIBIDI_TYPE_R;
+ break;
+ case PANGO_DIRECTION_WEAK_RTL:
+ fribidi_base_dir = FRIBIDI_TYPE_WR;
+ break;
+ /*
+ case PANGO_DIRECTION_WEAK_LTR:
+ case PANGO_DIRECTION_NEUTRAL:
+ */
+ default:
+ fribidi_base_dir = FRIBIDI_TYPE_WL;
+ break;
+ }
+
+#ifdef FRIBIDI_HAVE_UTF8
+ {
+ if (length < 0)
+ length = strlen (text);
+ embedding_levels_list = fribidi_log2vis_get_embedding_levels_new_utf8 (text, length, &fribidi_base_dir);
+ }
+#else
+ {
+ gunichar *text_ucs4;
+ int n_chars;
+ text_ucs4 = g_utf8_to_ucs4_fast (text, length, &n_chars);
+ embedding_levels_list = g_new (guint8, n_chars);
+ fribidi_log2vis_get_embedding_levels ((FriBidiChar*)text_ucs4, n_chars,
+ &fribidi_base_dir,
+ (FriBidiLevel*)embedding_levels_list);
+ g_free (text_ucs4);
+ }
+#endif
+
+ *pbase_dir = (fribidi_base_dir == FRIBIDI_TYPE_L) ? PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL;
+
+ return embedding_levels_list;
+}
+
+/**
+ * pango_unichar_direction:
+ * @ch: a Unicode character
+ *
+ * Determines the direction of a character; either
+ * %PANGO_DIRECTION_LTR, %PANGO_DIRECTION_RTL, or
+ * %PANGO_DIRECTION_NEUTRAL.
+ *
+ * Return value: the direction of the character, as used in the
+ * Unicode bidirectional algorithm.
+ */
+PangoDirection
+pango_unichar_direction (gunichar ch)
+{
+ FriBidiCharType fribidi_ch_type = fribidi_get_type (ch);
+
+ if (!FRIBIDI_IS_LETTER (fribidi_ch_type))
+ return PANGO_DIRECTION_NEUTRAL;
+ else if (FRIBIDI_IS_RTL (fribidi_ch_type))
+ return PANGO_DIRECTION_RTL;
+ else
+ return PANGO_DIRECTION_LTR;
+}
+
+/**
+ * pango_get_mirror_char:
+ * @ch: a Unicode character
+ * @mirrored_ch: location to store the mirrored character
+ *
+ * If @ch has the Unicode mirrored property and there is another Unicode
+ * character that typically has a glyph that is the mirror image of @ch's
+ * glyph, puts that character in the address pointed to by @mirrored_ch.
+ *
+ * Use g_unichar_get_mirror_char() instead; the docs for that function
+ * provide full details.
+ *
+ * Return value: %TRUE if @ch has a mirrored character and @mirrored_ch is
+ * filled in, %FALSE otherwise
+ **/
+gboolean
+pango_get_mirror_char (gunichar ch,
+ gunichar *mirrored_ch)
+{
+ return g_unichar_get_mirror_char (ch, mirrored_ch);
+}
+
+
+static guint
+alias_hash (struct PangoAlias *alias)
+{
+ return g_str_hash (alias->alias);
+}
+
+static gboolean
+alias_equal (struct PangoAlias *alias1,
+ struct PangoAlias *alias2)
+{
+ return g_str_equal (alias1->alias,
+ alias2->alias);
+}
+
+
+static void
+alias_free (struct PangoAlias *alias)
+{
+ int i;
+ g_free (alias->alias);
+
+ for (i = 0; i < alias->n_families; i++)
+ g_free (alias->families[i]);
+
+ g_free (alias->families);
+
+ g_slice_free (struct PangoAlias, alias);
+}
+
+static void
+read_alias_file (const char *filename)
+{
+ FILE *file;
+
+ GString *line_buffer;
+ GString *tmp_buffer1;
+ GString *tmp_buffer2;
+ char *errstring = NULL;
+ const char *pos;
+ int line = 0;
+ struct PangoAlias alias_key;
+ struct PangoAlias *alias;
+ char **new_families;
+ int n_new;
+ int i;
+
+ file = g_fopen (filename, "r");
+ if (!file)
+ return;
+
+ line_buffer = g_string_new (NULL);
+ tmp_buffer1 = g_string_new (NULL);
+ tmp_buffer2 = g_string_new (NULL);
+
+ while (pango_read_line (file, line_buffer))
+ {
+ gboolean append = FALSE;
+ line++;
+
+ pos = line_buffer->str;
+ if (!pango_skip_space (&pos))
+ continue;
+
+ if (!pango_scan_word (&pos, tmp_buffer1) ||
+ !pango_skip_space (&pos))
+ {
+ errstring = g_strdup ("Line is not of the form KEY=VALUE or KEY+=VALUE");
+ goto error;
+ }
+
+ if (*pos == '+')
+ {
+ append = TRUE;
+ pos++;
+ }
+
+ if (*(pos++) != '=')
+ {
+ errstring = g_strdup ("Line is not of the form KEY=VALUE or KEY+=VALUE");
+ goto error;
+ }
+
+ if (!pango_scan_string (&pos, tmp_buffer2))
+ {
+ errstring = g_strdup ("Error parsing value string");
+ goto error;
+ }
+ if (pango_skip_space (&pos))
+ {
+ errstring = g_strdup ("Junk after value string");
+ goto error;
+ }
+
+ alias_key.alias = g_ascii_strdown (tmp_buffer1->str, -1);
+
+ /* Remove any existing values */
+ alias = g_hash_table_lookup (pango_aliases_ht, &alias_key);
+
+ if (!alias)
+ {
+ alias = g_slice_new0 (struct PangoAlias);
+ alias->alias = alias_key.alias;
+
+ g_hash_table_insert (pango_aliases_ht,
+ alias, alias);
+ }
+ else
+ g_free (alias_key.alias);
+
+ new_families = g_strsplit (tmp_buffer2->str, ",", -1);
+
+ n_new = 0;
+ while (new_families[n_new])
+ n_new++;
+
+ if (alias->families && append)
+ {
+ alias->families = g_realloc (alias->families,
+ sizeof (char *) *(n_new + alias->n_families));
+ for (i = 0; i < n_new; i++)
+ alias->families[alias->n_families + i] = new_families[i];
+ g_free (new_families);
+ alias->n_families += n_new;
+ }
+ else
+ {
+ for (i = 0; i < alias->n_families; i++)
+ g_free (alias->families[i]);
+ g_free (alias->families);
+
+ alias->families = new_families;
+ alias->n_families = n_new;
+ }
+ }
+
+ if (ferror (file))
+ errstring = g_strdup (g_strerror(errno));
+
+ error:
+
+ if (errstring)
+ {
+ g_warning ("error reading alias file: %s:%d: %s\n", filename, line, errstring);
+ g_free (errstring);
+ }
+
+ g_string_free (line_buffer, TRUE);
+ g_string_free (tmp_buffer1, TRUE);
+ g_string_free (tmp_buffer2, TRUE);
+
+ fclose (file);
+}
+
+static void
+pango_load_aliases (void)
+{
+ char *filename;
+ const char *home;
+
+ pango_aliases_ht = g_hash_table_new_full ((GHashFunc)alias_hash,
+ (GEqualFunc)alias_equal,
+ (GDestroyNotify)alias_free,
+ NULL);
+
+
+ filename = g_strconcat (pango_get_sysconf_subdirectory (),
+ G_DIR_SEPARATOR_S "pango.aliases",
+ NULL);
+ read_alias_file (filename);
+ g_free (filename);
+
+ home = g_get_home_dir ();
+ if (home && *home)
+ {
+ filename = g_strconcat (home,
+ G_DIR_SEPARATOR_S ".pango.aliases",
+ NULL);
+ read_alias_file (filename);
+ g_free (filename);
+ }
+}
+
+
+/**
+ * pango_lookup_aliases:
+ * @fontname: an ascii string
+ * @families: will be set to an array of font family names.
+ * this array is owned by pango and should not be freed.
+ * @n_families: will be set to the length of the @families array.
+ *
+ * Look up all user defined aliases for the alias @fontname.
+ * The resulting font family names will be stored in @families,
+ * and the number of families in @n_families.
+ **/
+void
+pango_lookup_aliases (const char *fontname,
+ char ***families,
+ int *n_families)
+{
+ struct PangoAlias alias_key;
+ struct PangoAlias *alias;
+
+ if (pango_aliases_ht == NULL)
+ pango_load_aliases ();
+
+ alias_key.alias = g_ascii_strdown (fontname, -1);
+ alias = g_hash_table_lookup (pango_aliases_ht, &alias_key);
+ g_free (alias_key.alias);
+
+ if (alias)
+ {
+ *families = alias->families;
+ *n_families = alias->n_families;
+ }
+ else
+ {
+ *families = NULL;
+ *n_families = 0;
+ }
+}
+
+/**
+ * pango_find_base_dir:
+ * @text: the text to process
+ * @length: length of @text in bytes (may be -1 if @text is nul-terminated)
+ *
+ * Searches a string the first character that has a strong
+ * direction, according to the Unicode bidirectional algorithm.
+ *
+ * Return value: The direction corresponding to the first strong character.
+ * If no such character is found, then %PANGO_DIRECTION_NEUTRAL is returned.
+ *
+ * Since: 1.4
+ */
+PangoDirection
+pango_find_base_dir (const gchar *text,
+ gint length)
+{
+ PangoDirection dir = PANGO_DIRECTION_NEUTRAL;
+ const gchar *p;
+
+ g_return_val_if_fail (text != NULL || length == 0, PANGO_DIRECTION_NEUTRAL);
+
+ p = text;
+ while ((length < 0 || p < text + length) && *p)
+ {
+ gunichar wc = g_utf8_get_char (p);
+
+ dir = pango_unichar_direction (wc);
+
+ if (dir != PANGO_DIRECTION_NEUTRAL)
+ break;
+
+ p = g_utf8_next_char (p);
+ }
+
+ return dir;
+}
+
+/**
+ * pango_is_zero_width:
+ * @ch: a Unicode character
+ *
+ * Checks @ch to see if it is a character that should not be
+ * normally rendered on the screen. This includes all Unicode characters
+ * with "ZERO WIDTH" in their name, as well as <firstterm>bidi</firstterm> formatting characters, and
+ * a few other ones. This is totally different from g_unichar_iszerowidth()
+ * and is at best misnamed.
+ *
+ * Return value: %TRUE if @ch is a zero-width character, %FALSE otherwise
+ *
+ * Since: 1.10
+ */
+gboolean
+pango_is_zero_width (gunichar ch)
+{
+/* Zero Width characters:
+ *
+ * 00AD SOFT HYPHEN
+ * 034F COMBINING GRAPHEME JOINER
+ *
+ * 200B ZERO WIDTH SPACE
+ * 200C ZERO WIDTH NON-JOINER
+ * 200D ZERO WIDTH JOINER
+ * 200E LEFT-TO-RIGHT MARK
+ * 200F RIGHT-TO-LEFT MARK
+ *
+ * 2028 LINE SEPARATOR
+ *
+ * 202A LEFT-TO-RIGHT EMBEDDING
+ * 202B RIGHT-TO-LEFT EMBEDDING
+ * 202C POP DIRECTIONAL FORMATTING
+ * 202D LEFT-TO-RIGHT OVERRIDE
+ * 202E RIGHT-TO-LEFT OVERRIDE
+ *
+ * 2060 WORD JOINER
+ * 2061 FUNCTION APPLICATION
+ * 2062 INVISIBLE TIMES
+ * 2063 INVISIBLE SEPARATOR
+ *
+ * FEFF ZERO WIDTH NO-BREAK SPACE
+ */
+ return ((ch & ~(gunichar)0x007F) == 0x2000 && (
+ (ch >= 0x200B && ch <= 0x200F) ||
+ (ch >= 0x202A && ch <= 0x202E) ||
+ (ch >= 0x2060 && ch <= 0x2063) ||
+ (ch == 0x2028)
+ )) || G_UNLIKELY (ch == 0x00AD
+ || ch == 0x034F
+ || ch == 0xFEFF);
+}
+
+/**
+ * pango_quantize_line_geometry:
+ * @thickness: pointer to the thickness of a line, in Pango scaled units
+ * @position: corresponding position
+ *
+ * Quantizes the thickness and position of a line, typically an
+ * underline or strikethrough, to whole device pixels, that is integer
+ * multiples of %PANGO_SCALE. The purpose of this function is to avoid
+ * such lines looking blurry.
+ *
+ * Since: 1.12
+ */
+void
+pango_quantize_line_geometry (int *thickness,
+ int *position)
+{
+ int thickness_pixels = (*thickness + PANGO_SCALE / 2) / PANGO_SCALE;
+ if (thickness_pixels == 0)
+ thickness_pixels = 1;
+
+ if (thickness_pixels & 1)
+ {
+ int new_center = ((*position - *thickness / 2) & ~(PANGO_SCALE - 1)) + PANGO_SCALE / 2;
+ *position = new_center + (PANGO_SCALE * thickness_pixels) / 2;
+ }
+ else
+ {
+ int new_center = ((*position - *thickness / 2 + PANGO_SCALE / 2) & ~(PANGO_SCALE - 1));
+ *position = new_center + (PANGO_SCALE * thickness_pixels) / 2;
+ }
+
+ *thickness = thickness_pixels * PANGO_SCALE;
+}
+
+/**
+ * pango_units_from_double:
+ * @d: double floating-point value
+ *
+ * Converts a floating-point number to Pango units: multiplies
+ * it by %PANGO_SCALE and rounds to nearest integer.
+ *
+ * Return value: the value in Pango units.
+ *
+ * Since: 1.16
+ */
+int
+pango_units_from_double (double d)
+{
+ return (int)floor (d * PANGO_SCALE + 0.5);
+}
+
+/**
+ * pango_units_to_double:
+ * @i: value in Pango units
+ *
+ * Converts a number in Pango units to floating-point: divides
+ * it by %PANGO_SCALE.
+ *
+ * Return value: the double value.
+ *
+ * Since: 1.16
+ */
+double
+pango_units_to_double (int i)
+{
+ return (double)i / PANGO_SCALE;
+}
+
+/**
+ * pango_extents_to_pixels:
+ * @ink_rect: ink rectangle to convert, or %NULL.
+ * @logical_rect: logical rectangle to convert, or %NULL.
+ *
+ * Converts extents from Pango units to device units, dividing by the
+ * %PANGO_SCALE factor and performing rounding.
+ *
+ * The ink rectangle is converted by flooring the x/y coordinates and extending
+ * width/height, such that the final rectangle completely includes the original
+ * rectangle.
+ *
+ * The logical rectangle is converted by rounding the coordinates
+ * of the rectangle to the nearest device unit.
+ *
+ * Note that in certain situations you may want pass a logical extents
+ * rectangle to this function as @ink_rect. The rule is: if you want the
+ * resulting device-space rectangle to completely contain the original
+ * rectangle, pass it in as @ink_rect.
+ *
+ * Since: 1.16
+ **/
+void
+pango_extents_to_pixels (PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ if (ink_rect)
+ {
+ int orig_x = ink_rect->x;
+ int orig_y = ink_rect->y;
+
+ ink_rect->x = PANGO_PIXELS_FLOOR (ink_rect->x);
+ ink_rect->y = PANGO_PIXELS_FLOOR (ink_rect->y);
+
+ ink_rect->width = PANGO_PIXELS_CEIL (orig_x + ink_rect->width ) - ink_rect->x;
+ ink_rect->height = PANGO_PIXELS_CEIL (orig_y + ink_rect->height) - ink_rect->y;
+ }
+
+ if (logical_rect)
+ {
+ int orig_x = logical_rect->x;
+ int orig_y = logical_rect->y;
+
+ logical_rect->x = PANGO_PIXELS (logical_rect->x);
+ logical_rect->y = PANGO_PIXELS (logical_rect->y);
+
+ logical_rect->width = PANGO_PIXELS (orig_x + logical_rect->width ) - logical_rect->x;
+ logical_rect->height = PANGO_PIXELS (orig_y + logical_rect->height) - logical_rect->y;
+ }
+}
diff --git a/trunk/pango/pango-utils.h b/trunk/pango/pango-utils.h
new file mode 100644
index 00000000..41a8bbb0
--- /dev/null
+++ b/trunk/pango/pango-utils.h
@@ -0,0 +1,143 @@
+/* Pango
+ * pango-utils.c: Utilities for internal functions and modules
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_UTILS_H__
+#define __PANGO_UTILS_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include <pango/pango-font.h>
+
+G_BEGIN_DECLS
+
+char ** pango_split_file_list (const char *str);
+
+char *pango_trim_string (const char *str);
+gint pango_read_line (FILE *stream,
+ GString *str);
+gboolean pango_skip_space (const char **pos);
+gboolean pango_scan_word (const char **pos,
+ GString *out);
+gboolean pango_scan_string (const char **pos,
+ GString *out);
+gboolean pango_scan_int (const char **pos,
+ int *out);
+
+#ifdef PANGO_ENABLE_BACKEND
+char * pango_config_key_get (const char *key);
+void pango_lookup_aliases (const char *fontname,
+ char ***families,
+ int *n_families);
+#endif /* PANGO_ENABLE_BACKEND */
+
+gboolean pango_parse_enum (GType type,
+ const char *str,
+ int *value,
+ gboolean warn,
+ char **possible_values);
+
+/* Functions for parsing textual representations
+ * of PangoFontDescription fields. They return TRUE if the input string
+ * contains a valid value, which then has been assigned to the corresponding
+ * field in the PangoFontDescription. If the warn parameter is TRUE,
+ * a warning is printed (with g_warning) if the string does not
+ * contain a valid value.
+ */
+gboolean pango_parse_style (const char *str,
+ PangoStyle *style,
+ gboolean warn);
+gboolean pango_parse_variant (const char *str,
+ PangoVariant *variant,
+ gboolean warn);
+gboolean pango_parse_weight (const char *str,
+ PangoWeight *weight,
+ gboolean warn);
+gboolean pango_parse_stretch (const char *str,
+ PangoStretch *stretch,
+ gboolean warn);
+
+#ifdef PANGO_ENABLE_BACKEND
+
+/* On Unix, return the name of the "pango" subdirectory of SYSCONFDIR
+ * (which is set at compile time). On Win32, return the Pango
+ * installation directory (which is set at installation time, and
+ * stored in the registry). The returned string should not be
+ * g_free'd.
+ */
+G_CONST_RETURN char * pango_get_sysconf_subdirectory (void) G_GNUC_PURE;
+
+/* Ditto for LIBDIR/pango. On Win32, use the same Pango
+ * installation directory. This returned string should not be
+ * g_free'd either.
+ */
+G_CONST_RETURN char * pango_get_lib_subdirectory (void) G_GNUC_PURE;
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+/* Hint line position and thickness.
+ */
+void pango_quantize_line_geometry (int *thickness,
+ int *position);
+
+/* A routine from fribidi that we either wrap or provide ourselves.
+ */
+guint8 * pango_log2vis_get_embedding_levels (const gchar *text,
+ int length,
+ PangoDirection *pbase_dir);
+
+/* Unicode characters that are zero-width and should not be rendered
+ * normally.
+ */
+gboolean pango_is_zero_width (gunichar ch) G_GNUC_CONST;
+
+/* Pango version checking */
+
+/* Encode a Pango version as an integer */
+#define PANGO_VERSION_ENCODE(major, minor, micro) ( \
+ ((major) * 10000) \
+ + ((minor) * 100) \
+ + ((micro) * 1))
+
+/* Encoded version of Pango at compile-time */
+#define PANGO_VERSION PANGO_VERSION_ENCODE( \
+ PANGO_VERSION_MAJOR, \
+ PANGO_VERSION_MINOR, \
+ PANGO_VERSION_MICRO)
+
+/* Check that compile-time Pango is as new as required */
+#define PANGO_VERSION_CHECK(major,minor,micro) \
+ (PANGO_VERSION >= PANGO_VERSION_ENCODE(major,minor,micro))
+
+
+/* Return encoded version of Pango at run-time */
+int pango_version (void) G_GNUC_CONST;
+
+/* Return run-time Pango version as an string */
+G_CONST_RETURN char * pango_version_string (void) G_GNUC_CONST;
+
+/* Check that run-time Pango is as new as required */
+G_CONST_RETURN char * pango_version_check (int required_major,
+ int required_minor,
+ int required_micro) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __PANGO_UTILS_H__ */
diff --git a/trunk/pango/pango.def b/trunk/pango/pango.def
new file mode 100644
index 00000000..1d74ac84
--- /dev/null
+++ b/trunk/pango/pango.def
@@ -0,0 +1,369 @@
+EXPORTS
+ pango_alignment_get_type
+ pango_attr_background_new
+ pango_attr_fallback_new
+ pango_attr_family_new
+ pango_attr_font_desc_new
+ pango_attr_foreground_new
+ pango_attr_gravity_hint_new
+ pango_attr_gravity_new
+ pango_attr_iterator_copy
+ pango_attr_iterator_destroy
+ pango_attr_iterator_get
+ pango_attr_iterator_get_attrs
+ pango_attr_iterator_get_font
+ pango_attr_iterator_next
+ pango_attr_iterator_range
+ pango_attr_language_new
+ pango_attr_letter_spacing_new
+ pango_attr_list_change
+ pango_attr_list_copy
+ pango_attr_list_filter
+ pango_attr_list_get_iterator
+ pango_attr_list_get_type
+ pango_attr_list_insert
+ pango_attr_list_insert_before
+ pango_attr_list_new
+ pango_attr_list_ref
+ pango_attr_list_splice
+ pango_attr_list_unref
+ pango_attr_rise_new
+ pango_attr_scale_new
+ pango_attr_shape_new
+ pango_attr_shape_new_with_data
+ pango_attr_size_new
+ pango_attr_size_new_absolute
+ pango_attr_stretch_new
+ pango_attr_strikethrough_color_new
+ pango_attr_strikethrough_new
+ pango_attr_style_new
+ pango_attr_type_get_type
+ pango_attr_type_register
+ pango_attr_underline_color_new
+ pango_attr_underline_new
+ pango_attr_variant_new
+ pango_attr_weight_new
+ pango_attribute_copy
+ pango_attribute_destroy
+ pango_attribute_equal
+ pango_break
+ pango_color_copy
+ pango_color_free
+ pango_color_get_type
+ pango_color_parse
+ pango_color_to_string
+ pango_config_key_get
+ pango_context_get_base_dir
+ pango_context_get_base_gravity
+ pango_context_get_font_description
+ pango_context_get_font_map
+ pango_context_get_gravity
+ pango_context_get_gravity_hint
+ pango_context_get_language
+ pango_context_get_matrix
+ pango_context_get_metrics
+ pango_context_get_type
+ pango_context_list_families
+ pango_context_load_font
+ pango_context_load_fontset
+ pango_context_new
+ pango_context_set_base_dir
+ pango_context_set_base_gravity
+ pango_context_set_font_description
+ pango_context_set_font_map
+ pango_context_set_gravity_hint
+ pango_context_set_language
+ pango_context_set_matrix
+ pango_coverage_copy
+ pango_coverage_from_bytes
+ pango_coverage_get
+ pango_coverage_level_get_type
+ pango_coverage_max
+ pango_coverage_new
+ pango_coverage_ref
+ pango_coverage_set
+ pango_coverage_to_bytes
+ pango_coverage_unref
+ pango_default_break
+ pango_direction_get_type
+ pango_ellipsize_mode_get_type
+ pango_engine_get_type
+ pango_engine_lang_get_type
+ pango_engine_shape_get_type
+ pango_extents_to_pixels
+ pango_find_base_dir
+ pango_find_map
+ pango_find_paragraph_boundary
+ pango_font_describe
+ pango_font_describe_with_absolute_size
+ pango_font_description_better_match
+ pango_font_description_copy
+ pango_font_description_copy_static
+ pango_font_description_equal
+ pango_font_description_free
+ pango_font_description_from_string
+ pango_font_description_get_family
+ pango_font_description_get_gravity
+ pango_font_description_get_set_fields
+ pango_font_description_get_size
+ pango_font_description_get_size_is_absolute
+ pango_font_description_get_stretch
+ pango_font_description_get_style
+ pango_font_description_get_type
+ pango_font_description_get_variant
+ pango_font_description_get_weight
+ pango_font_description_hash
+ pango_font_description_merge
+ pango_font_description_merge_static
+ pango_font_description_new
+ pango_font_description_set_absolute_size
+ pango_font_description_set_family
+ pango_font_description_set_family_static
+ pango_font_description_set_gravity
+ pango_font_description_set_size
+ pango_font_description_set_stretch
+ pango_font_description_set_style
+ pango_font_description_set_variant
+ pango_font_description_set_weight
+ pango_font_description_to_filename
+ pango_font_description_to_string
+ pango_font_description_unset_fields
+ pango_font_descriptions_free
+ pango_font_face_describe
+ pango_font_face_get_face_name
+ pango_font_face_get_type
+ pango_font_face_is_synthesized
+ pango_font_face_list_sizes
+ pango_font_family_get_name
+ pango_font_family_get_type
+ pango_font_family_is_monospace
+ pango_font_family_list_faces
+ pango_font_find_shaper
+ pango_font_get_coverage
+ pango_font_get_font_map
+ pango_font_get_glyph_extents
+ pango_font_get_metrics
+ pango_font_get_type
+ pango_font_map_get_shape_engine_type
+ pango_font_map_get_type
+ pango_font_map_list_families
+ pango_font_map_load_font
+ pango_font_map_load_fontset
+ pango_font_mask_get_type
+ pango_font_metrics_get_approximate_char_width
+ pango_font_metrics_get_approximate_digit_width
+ pango_font_metrics_get_ascent
+ pango_font_metrics_get_descent
+ pango_font_metrics_get_strikethrough_position
+ pango_font_metrics_get_strikethrough_thickness
+ pango_font_metrics_get_type
+ pango_font_metrics_get_underline_position
+ pango_font_metrics_get_underline_thickness
+ pango_font_metrics_new
+ pango_font_metrics_ref
+ pango_font_metrics_unref
+ pango_fontset_foreach
+ pango_fontset_get_font
+ pango_fontset_get_metrics
+ pango_fontset_get_type
+ pango_fontset_simple_append
+ pango_fontset_simple_get_type
+ pango_fontset_simple_new
+ pango_fontset_simple_size
+ pango_get_lib_subdirectory
+ pango_get_log_attrs
+ pango_get_mirror_char
+ pango_get_sysconf_subdirectory
+ pango_glyph_item_apply_attrs
+ pango_glyph_item_free
+ pango_glyph_item_letter_space
+ pango_glyph_item_split
+ pango_glyph_string_copy
+ pango_glyph_string_extents
+ pango_glyph_string_extents_range
+ pango_glyph_string_free
+ pango_glyph_string_get_logical_widths
+ pango_glyph_string_get_type
+ pango_glyph_string_get_width
+ pango_glyph_string_index_to_x
+ pango_glyph_string_new
+ pango_glyph_string_set_size
+ pango_glyph_string_x_to_index
+ pango_gravity_get_for_matrix
+ pango_gravity_get_for_script
+ pango_gravity_get_type
+ pango_gravity_hint_get_type
+ pango_gravity_to_rotation
+ pango_is_zero_width
+ pango_item_copy
+ pango_item_free
+ pango_item_get_type
+ pango_item_new
+ pango_item_split
+ pango_itemize
+ pango_itemize_with_base_dir
+ pango_language_from_string
+ pango_language_get_default
+ pango_language_get_sample_string
+ pango_language_get_type
+ pango_language_includes_script
+ pango_language_matches
+ pango_layout_context_changed
+ pango_layout_copy
+ pango_layout_get_alignment
+ pango_layout_get_attributes
+ pango_layout_get_auto_dir
+ pango_layout_get_context
+ pango_layout_get_cursor_pos
+ pango_layout_get_ellipsize
+ pango_layout_get_extents
+ pango_layout_get_font_description
+ pango_layout_get_indent
+ pango_layout_get_iter
+ pango_layout_get_justify
+ pango_layout_get_line
+ pango_layout_get_line_count
+ pango_layout_get_line_readonly
+ pango_layout_get_lines
+ pango_layout_get_lines_readonly
+ pango_layout_get_log_attrs
+ pango_layout_get_pixel_extents
+ pango_layout_get_pixel_size
+ pango_layout_get_single_paragraph_mode
+ pango_layout_get_size
+ pango_layout_get_spacing
+ pango_layout_get_tabs
+ pango_layout_get_text
+ pango_layout_get_type
+ pango_layout_get_unknown_glyphs_count
+ pango_layout_get_width
+ pango_layout_get_wrap
+ pango_layout_index_to_line_x
+ pango_layout_index_to_pos
+ pango_layout_is_ellipsized
+ pango_layout_is_wrapped
+ pango_layout_iter_at_last_line
+ pango_layout_iter_free
+ pango_layout_iter_get_baseline
+ pango_layout_iter_get_char_extents
+ pango_layout_iter_get_cluster_extents
+ pango_layout_iter_get_index
+ pango_layout_iter_get_layout_extents
+ pango_layout_iter_get_line
+ pango_layout_iter_get_line_extents
+ pango_layout_iter_get_line_readonly
+ pango_layout_iter_get_line_yrange
+ pango_layout_iter_get_run
+ pango_layout_iter_get_run_extents
+ pango_layout_iter_get_run_readonly
+ pango_layout_iter_get_type
+ pango_layout_iter_next_char
+ pango_layout_iter_next_cluster
+ pango_layout_iter_next_line
+ pango_layout_iter_next_run
+ pango_layout_line_get_extents
+ pango_layout_line_get_pixel_extents
+ pango_layout_line_get_type
+ pango_layout_line_get_x_ranges
+ pango_layout_line_index_to_x
+ pango_layout_line_ref
+ pango_layout_line_unref
+ pango_layout_line_x_to_index
+ pango_layout_move_cursor_visually
+ pango_layout_new
+ pango_layout_set_alignment
+ pango_layout_set_attributes
+ pango_layout_set_auto_dir
+ pango_layout_set_ellipsize
+ pango_layout_set_font_description
+ pango_layout_set_indent
+ pango_layout_set_justify
+ pango_layout_set_markup
+ pango_layout_set_markup_with_accel
+ pango_layout_set_single_paragraph_mode
+ pango_layout_set_spacing
+ pango_layout_set_tabs
+ pango_layout_set_text
+ pango_layout_set_width
+ pango_layout_set_wrap
+ pango_layout_xy_to_index
+ pango_log2vis_get_embedding_levels
+ pango_lookup_aliases
+ pango_map_get_engine
+ pango_map_get_engines
+ pango_matrix_concat
+ pango_matrix_copy
+ pango_matrix_free
+ pango_matrix_get_font_scale_factor
+ pango_matrix_get_type
+ pango_matrix_rotate
+ pango_matrix_scale
+ pango_matrix_transform_distance
+ pango_matrix_transform_pixel_rectangle
+ pango_matrix_transform_point
+ pango_matrix_transform_rectangle
+ pango_matrix_translate
+ pango_module_register
+ pango_parse_enum
+ pango_parse_markup
+ pango_parse_stretch
+ pango_parse_style
+ pango_parse_variant
+ pango_parse_weight
+ pango_quantize_line_geometry
+ pango_read_line
+ pango_render_part_get_type
+ pango_renderer_activate
+ pango_renderer_deactivate
+ pango_renderer_draw_error_underline
+ pango_renderer_draw_glyph
+ pango_renderer_draw_glyphs
+ pango_renderer_draw_layout
+ pango_renderer_draw_layout_line
+ pango_renderer_draw_rectangle
+ pango_renderer_draw_trapezoid
+ pango_renderer_get_color
+ pango_renderer_get_matrix
+ pango_renderer_get_type
+ pango_renderer_part_changed
+ pango_renderer_set_color
+ pango_renderer_set_matrix
+ pango_reorder_items
+ pango_scan_int
+ pango_scan_string
+ pango_scan_word
+ pango_script_for_unichar
+ pango_script_get_sample_language
+ pango_script_get_type
+ pango_script_iter_free
+ pango_script_iter_get_range
+ pango_script_iter_new
+ pango_script_iter_next
+ pango_shape
+ pango_skip_space
+ pango_split_file_list
+ pango_stretch_get_type
+ pango_style_get_type
+ pango_tab_align_get_type
+ pango_tab_array_copy
+ pango_tab_array_free
+ pango_tab_array_get_positions_in_pixels
+ pango_tab_array_get_size
+ pango_tab_array_get_tab
+ pango_tab_array_get_tabs
+ pango_tab_array_get_type
+ pango_tab_array_new
+ pango_tab_array_new_with_positions
+ pango_tab_array_resize
+ pango_tab_array_set_tab
+ pango_trim_string
+ pango_underline_get_type
+ pango_unichar_direction
+ pango_units_from_double
+ pango_units_to_double
+ pango_variant_get_type
+ pango_version
+ pango_version_check
+ pango_version_string
+ pango_weight_get_type
+ pango_wrap_mode_get_type
diff --git a/trunk/pango/pango.h b/trunk/pango/pango.h
new file mode 100644
index 00000000..5b5ef1e4
--- /dev/null
+++ b/trunk/pango/pango.h
@@ -0,0 +1,47 @@
+/* Pango
+ * pango.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_H__
+#define __PANGO_H__
+
+#include <pango/pango-attributes.h>
+#include <pango/pango-break.h>
+#include <pango/pango-context.h>
+#include <pango/pango-coverage.h>
+#include <pango/pango-engine.h>
+#include <pango/pango-enum-types.h>
+#include <pango/pango-features.h>
+#include <pango/pango-font.h>
+#include <pango/pango-fontmap.h>
+#include <pango/pango-fontset.h>
+#include <pango/pango-glyph.h>
+#include <pango/pango-glyph-item.h>
+#include <pango/pango-gravity.h>
+#include <pango/pango-item.h>
+#include <pango/pango-layout.h>
+#include <pango/pango-matrix.h>
+#include <pango/pango-renderer.h>
+#include <pango/pango-script.h>
+#include <pango/pango-tabs.h>
+#include <pango/pango-types.h>
+#include <pango/pango-utils.h>
+
+#endif /* __PANGO_H__ */
diff --git a/trunk/pango/pango.rc.in b/trunk/pango/pango.rc.in
new file mode 100644
index 00000000..a6cd2525
--- /dev/null
+++ b/trunk/pango/pango.rc.in
@@ -0,0 +1,30 @@
+#include <winver.h>
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @PANGO_VERSION_MAJOR@,@PANGO_VERSION_MINOR@,@PANGO_VERSION_MICRO@,0
+ PRODUCTVERSION @PANGO_VERSION_MAJOR@,@PANGO_VERSION_MINOR@,@PANGO_VERSION_MICRO@,0
+ FILEFLAGSMASK 0
+ FILEFLAGS 0
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Red Hat Software"
+ VALUE "FileDescription", "Pango"
+ VALUE "FileVersion", "@PANGO_VERSION_MAJOR@.@PANGO_VERSION_MINOR@.@PANGO_VERSION_MICRO@.0"
+ VALUE "InternalName", "pango-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@"
+ VALUE "LegalCopyright", "Copyright © 1999 Red Hat Software."
+ VALUE "OriginalFilename", "pango-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@.dll"
+ VALUE "ProductName", "Pango"
+ VALUE "ProductVersion", "@PANGO_VERSION_MAJOR@.@PANGO_VERSION_MINOR@.@PANGO_VERSION_MICRO@"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+ END
diff --git a/trunk/pango/pangoatsui-fontmap.c b/trunk/pango/pangoatsui-fontmap.c
new file mode 100644
index 00000000..f3d1ffd2
--- /dev/null
+++ b/trunk/pango/pangoatsui-fontmap.c
@@ -0,0 +1,825 @@
+/* Pango
+ * pangoatsui-fontmap.c
+ *
+ * Copyright (C) 2000-2003 Red Hat, Inc.
+ * Copyright (C) 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-fontmap.h"
+#include "pangoatsui-private.h"
+#include "pango-impl-utils.h"
+#include "modules.h"
+
+#import <Cocoa/Cocoa.h>
+
+typedef struct _FontHashKey FontHashKey;
+
+struct _PangoATSUIFamily
+{
+ PangoFontFamily parent_instance;
+
+ char *family_name;
+
+ PangoFontFace **faces;
+ gint n_faces;
+};
+
+#define PANGO_TYPE_ATSUI_FAMILY (pango_atsui_family_get_type ())
+#define PANGO_ATSUI_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_ATSUI_FAMILY, PangoATSUIFamily))
+#define PANGO_IS_ATSUI_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_ATSUI_FAMILY))
+
+#define PANGO_TYPE_ATSUI_FACE (pango_atsui_face_get_type ())
+#define PANGO_ATSUI_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_ATSUI_FACE, PangoATSUIFace))
+#define PANGO_IS_ATSUI_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_ATSUI_FACE))
+
+struct _PangoATSUIFace
+{
+ PangoFontFace parent_instance;
+
+ PangoATSUIFamily *family;
+
+ PangoCoverage *coverage;
+
+ char *postscript_name;
+ char *style_name;
+
+ int weight;
+ int traits;
+ guint synthetic_italic : 1;
+};
+
+static GType pango_atsui_family_get_type (void);
+static GType pango_atsui_face_get_type (void);
+
+static gpointer pango_atsui_family_parent_class;
+static gpointer pango_atsui_face_parent_class;
+
+static const char *
+get_real_family (const char *family_name)
+{
+ switch (family_name[0])
+ {
+ case 'm':
+ case 'M':
+ if (g_ascii_strcasecmp (family_name, "monospace") == 0)
+ return "Courier";
+ break;
+ case 's':
+ case 'S':
+ if (g_ascii_strcasecmp (family_name, "sans") == 0)
+ return "Helvetica";
+ else if (g_ascii_strcasecmp (family_name, "serif") == 0)
+ return "Times";
+ break;
+ }
+
+ return family_name;
+}
+
+static void
+pango_atsui_family_list_faces (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces)
+{
+ PangoATSUIFamily *atsuifamily = PANGO_ATSUI_FAMILY (family);
+
+ if (atsuifamily->n_faces < 0)
+ {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ const char *real_family = get_real_family (atsuifamily->family_name);
+ NSFontManager *manager = [NSFontManager sharedFontManager];
+ NSArray *members = [manager availableMembersOfFontFamily:[NSString stringWithUTF8String:real_family]];
+ int i, count;
+ GHashTable *hash_table;
+ GList *faces = NULL, *l;
+ GList *synthetic_faces = NULL;
+
+ /* The NSFontManager API returns italic faces for some families
+ * even if they don't exist. When using Cocoa to create
+ * instances of those fonts, Cocoa synthesizes italic versions
+ * by applying a shear transformation. We do that manually for
+ * those fonts in pangocairo-atsuifont.c. For many other fonts,
+ * there is no italic face at all, so we create synthesized
+ * versions of those like in the win32 and fontconfig backends.
+ */
+ hash_table = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ count = [members count];
+ for (i = 0; i < count; i++)
+ {
+ PangoATSUIFace *face = g_object_new (PANGO_TYPE_ATSUI_FACE, NULL);
+ NSArray *font_array = [members objectAtIndex:i];
+
+ face->family = atsuifamily;
+ face->postscript_name = g_strdup ([[font_array objectAtIndex:0] UTF8String]);
+ face->style_name = g_strdup ([[font_array objectAtIndex:1] UTF8String]);
+ face->weight = [[font_array objectAtIndex:2] intValue];
+ face->traits = [[font_array objectAtIndex:3] intValue];
+
+ faces = g_list_prepend (faces, face);
+
+ if (face->traits & NSItalicFontMask)
+ g_hash_table_insert (hash_table, GINT_TO_POINTER (face->weight), face);
+ }
+
+ for (l = faces; l; l = l->next)
+ {
+ PangoATSUIFace *face = l->data;
+
+ if (!g_hash_table_lookup (hash_table, GINT_TO_POINTER (face->weight)))
+ {
+ PangoATSUIFace *italic_face = g_object_new (PANGO_TYPE_ATSUI_FACE, NULL);
+
+ italic_face->family = atsuifamily;
+ italic_face->postscript_name = g_strdup (face->postscript_name);
+ italic_face->weight = face->weight;
+ italic_face->traits = face->traits | NSItalicFontMask;
+ italic_face->synthetic_italic = TRUE;
+
+ /* Try to create a sensible face name. */
+ if (strcasecmp (face->style_name, "regular") == 0)
+ italic_face->style_name = g_strdup ("Oblique");
+ else
+ italic_face->style_name = g_strdup_printf ("%s Oblique", face->style_name);
+
+ synthetic_faces = g_list_prepend (synthetic_faces, italic_face);
+ }
+ }
+
+ faces = g_list_concat (faces, synthetic_faces);
+
+ atsuifamily->n_faces = g_list_length (faces);
+ atsuifamily->faces = g_new (PangoFontFace *, atsuifamily->n_faces);
+
+ for (l = faces, i = 0; l; l = l->next, i++)
+ atsuifamily->faces[i] = l->data;
+
+ g_list_free (faces);
+ g_hash_table_destroy (hash_table);
+
+ [pool release];
+ }
+
+ if (n_faces)
+ *n_faces = atsuifamily->n_faces;
+
+ if (faces)
+ *faces = g_memdup (atsuifamily->faces, atsuifamily->n_faces * sizeof (PangoFontFace *));
+}
+
+static const char *
+pango_atsui_family_get_name (PangoFontFamily *family)
+{
+ PangoATSUIFamily *atsuifamily = PANGO_ATSUI_FAMILY (family);
+
+ return atsuifamily->family_name;
+}
+
+static gboolean
+pango_atsui_family_is_monospace (PangoFontFamily *family)
+{
+ /* Fixme: Implement */
+ return FALSE;
+}
+
+static void
+pango_atsui_family_finalize (GObject *object)
+{
+ PangoATSUIFamily *family = PANGO_ATSUI_FAMILY (object);
+ int i;
+
+ g_free (family->family_name);
+
+ if (family->n_faces != -1)
+ {
+ for (i = 0; i < family->n_faces; i++)
+ g_object_unref (family->faces[i]);
+
+ g_free (family->faces);
+ }
+
+ G_OBJECT_CLASS (pango_atsui_family_parent_class)->finalize (object);
+}
+
+static void
+pango_atsui_family_class_init (PangoFontFamilyClass *class)
+{
+ GObjectClass *object_class = (GObjectClass *)class;
+ int i;
+
+ pango_atsui_family_parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_atsui_family_finalize;
+
+ class->list_faces = pango_atsui_family_list_faces;
+ class->get_name = pango_atsui_family_get_name;
+ class->is_monospace = pango_atsui_family_is_monospace;
+
+ for (i = 0; _pango_included_atsui_modules[i].list; i++)
+ pango_module_register (&_pango_included_atsui_modules[i]);
+}
+
+static void
+pango_atsui_family_init (PangoATSUIFamily *family)
+{
+ family->n_faces = -1;
+}
+
+static GType
+pango_atsui_family_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFamilyClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_atsui_family_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoATSUIFamily),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_atsui_family_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
+ I_("PangoATSUIFamily"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static PangoFontDescription *
+pango_atsui_face_describe (PangoFontFace *face)
+{
+ PangoATSUIFace *atsuiface = PANGO_ATSUI_FACE (face);
+ PangoFontDescription *description;
+ PangoWeight pango_weight;
+ PangoStyle pango_style;
+ PangoVariant pango_variant;
+ int weight;
+
+ description = pango_font_description_new ();
+
+ pango_font_description_set_family (description, atsuiface->family->family_name);
+
+ weight = atsuiface->weight;
+
+ if (weight == 1 || weight == 2)
+ pango_weight = PANGO_WEIGHT_ULTRALIGHT;
+ else if (weight == 3 || weight == 4)
+ pango_weight = PANGO_WEIGHT_LIGHT;
+ else if (weight == 5 || weight == 6)
+ pango_weight = PANGO_WEIGHT_NORMAL;
+ else if (weight == 7 || weight == 8)
+ pango_weight = PANGO_WEIGHT_SEMIBOLD;
+ else if (weight == 9 || weight == 10)
+ pango_weight = PANGO_WEIGHT_BOLD;
+ else if (weight == 11 || weight == 12)
+ pango_weight = PANGO_WEIGHT_ULTRABOLD;
+ else if (weight == 13 || weight == 14)
+ pango_weight = PANGO_WEIGHT_HEAVY;
+ else
+ g_assert_not_reached ();
+
+ if (atsuiface->traits & NSItalicFontMask)
+ pango_style = PANGO_STYLE_ITALIC;
+ else
+ pango_style = PANGO_STYLE_NORMAL;
+
+ if (atsuiface->traits & NSSmallCapsFontMask)
+ pango_variant = PANGO_VARIANT_SMALL_CAPS;
+ else
+ pango_variant = PANGO_VARIANT_NORMAL;
+
+ pango_font_description_set_weight (description, pango_weight);
+ pango_font_description_set_style (description, pango_style);
+ pango_font_description_set_variant (description, pango_variant);
+
+ return description;
+}
+
+static const char *
+pango_atsui_face_get_face_name (PangoFontFace *face)
+{
+ PangoATSUIFace *atsuiface = PANGO_ATSUI_FACE (face);
+
+ return atsuiface->style_name;
+}
+
+static void
+pango_atsui_face_list_sizes (PangoFontFace *face,
+ int **sizes,
+ int *n_sizes)
+{
+ *n_sizes = 0;
+ *sizes = NULL;
+}
+
+static void
+pango_atsui_face_finalize (GObject *object)
+{
+ PangoATSUIFace *atsuiface = PANGO_ATSUI_FACE (object);
+
+ if (atsuiface->coverage)
+ pango_coverage_unref (atsuiface->coverage);
+
+ g_free (atsuiface->postscript_name);
+ g_free (atsuiface->style_name);
+
+ G_OBJECT_CLASS (pango_atsui_face_parent_class)->finalize (object);
+}
+
+static gboolean
+pango_atsui_face_is_synthesized (PangoFontFace *face)
+{
+ PangoATSUIFace *atsuiface = PANGO_ATSUI_FACE (face);
+
+ return atsuiface->synthetic_italic;
+}
+
+static void
+pango_atsui_face_class_init (PangoFontFaceClass *class)
+{
+ GObjectClass *object_class = (GObjectClass *)class;
+
+ pango_atsui_face_parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_atsui_face_finalize;
+
+ class->describe = pango_atsui_face_describe;
+ class->get_face_name = pango_atsui_face_get_face_name;
+ class->list_sizes = pango_atsui_face_list_sizes;
+ class->is_synthesized = pango_atsui_face_is_synthesized;
+}
+
+GType
+pango_atsui_face_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFaceClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_atsui_face_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoATSUIFace),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
+ I_("PangoATSUIFace"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+const char *
+_pango_atsui_face_get_postscript_name (PangoATSUIFace *face)
+{
+ return face->postscript_name;
+}
+
+gboolean
+_pango_atsui_face_get_synthetic_italic (PangoATSUIFace *face)
+{
+ return face->synthetic_italic;
+}
+
+PangoCoverage *
+_pango_atsui_face_get_coverage (PangoATSUIFace *face,
+ PangoLanguage *language)
+{
+ int i;
+
+ /* Note: We currently fake the coverage by reporting that the 255 first
+ * glyphs exist in all fonts, which is not true. It's unclear how to get
+ * this done correctly.
+ */
+
+ if (face->coverage)
+ return face->coverage;
+
+ face->coverage = pango_coverage_new ();
+
+ for (i = 0; i < 256; i++)
+ pango_coverage_set (face->coverage, i, PANGO_COVERAGE_EXACT);
+
+ return face->coverage;
+}
+
+static void pango_atsui_font_map_class_init (PangoATSUIFontMapClass *class);
+static void pango_atsui_font_map_init (PangoATSUIFontMap *atsuifontmap);
+
+static guint font_hash_key_hash (const FontHashKey *key);
+static gboolean font_hash_key_equal (const FontHashKey *key_a,
+ const FontHashKey *key_b);
+static void font_hash_key_free (FontHashKey *key);
+
+G_DEFINE_TYPE (PangoATSUIFontMap, pango_atsui_font_map, PANGO_TYPE_FONT_MAP);
+
+static void
+pango_atsui_font_map_finalize (GObject *object)
+{
+ PangoATSUIFontMap *fontmap = PANGO_ATSUI_FONT_MAP (object);
+
+ g_hash_table_destroy (fontmap->font_hash);
+ g_hash_table_destroy (fontmap->families);
+
+ G_OBJECT_CLASS (pango_atsui_font_map_parent_class)->finalize (object);
+}
+
+struct _FontHashKey {
+ PangoATSUIFontMap *fontmap;
+ PangoMatrix matrix;
+ PangoFontDescription *desc;
+ char *postscript_name;
+ gpointer context_key;
+};
+
+/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
+ *
+ * Not necessarily better than a lot of other hashes, but should be OK, and
+ * well tested with binary data.
+ */
+
+#define FNV_32_PRIME ((guint32)0x01000193)
+#define FNV1_32_INIT ((guint32)0x811c9dc5)
+
+static guint32
+hash_bytes_fnv (unsigned char *buffer,
+ int len,
+ guint32 hval)
+{
+ while (len--)
+ {
+ hval *= FNV_32_PRIME;
+ hval ^= *buffer++;
+ }
+
+ return hval;
+}
+
+static gboolean
+font_hash_key_equal (const FontHashKey *key_a,
+ const FontHashKey *key_b)
+{
+ if (key_a->matrix.xx == key_b->matrix.xx &&
+ key_a->matrix.xy == key_b->matrix.xy &&
+ key_a->matrix.yx == key_b->matrix.yx &&
+ key_a->matrix.yy == key_b->matrix.yy &&
+ pango_font_description_equal (key_a->desc, key_b->desc) &&
+ strcmp (key_a->postscript_name, key_b->postscript_name) == 0)
+ {
+ if (key_a->context_key)
+ return PANGO_ATSUI_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap,
+ key_a->context_key,
+ key_b->context_key);
+ else
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static guint
+font_hash_key_hash (const FontHashKey *key)
+{
+ guint32 hash = FNV1_32_INIT;
+
+ /* We do a bytewise hash on the context matrix */
+ hash = hash_bytes_fnv ((unsigned char *)(&key->matrix),
+ sizeof(double) * 4,
+ hash);
+
+ if (key->context_key)
+ hash ^= PANGO_ATSUI_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap,
+ key->context_key);
+
+ hash ^= g_str_hash (key->postscript_name);
+
+ return (hash ^ pango_font_description_hash (key->desc));
+}
+
+static void
+font_hash_key_free (FontHashKey *key)
+{
+ if (key->context_key)
+ PANGO_ATSUI_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap,
+ key->context_key);
+
+ g_slice_free (FontHashKey, key);
+}
+
+static FontHashKey *
+font_hash_key_copy (FontHashKey *old)
+{
+ FontHashKey *key = g_slice_new (FontHashKey);
+
+ key->fontmap = old->fontmap;
+ key->matrix = old->matrix;
+ key->desc = pango_font_description_copy (old->desc);
+ key->postscript_name = g_strdup (old->postscript_name);
+ if (old->context_key)
+ key->context_key = PANGO_ATSUI_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap,
+ old->context_key);
+ else
+ key->context_key = NULL;
+
+ return key;
+}
+
+
+static void
+get_context_matrix (PangoContext *context,
+ PangoMatrix *matrix)
+{
+ const PangoMatrix *set_matrix;
+ static const PangoMatrix identity = PANGO_MATRIX_INIT;
+
+ if (context)
+ set_matrix = pango_context_get_matrix (context);
+ else
+ set_matrix = NULL;
+
+ if (set_matrix)
+ *matrix = *set_matrix;
+ else
+ *matrix = identity;
+}
+
+static void
+font_hash_key_for_context (PangoATSUIFontMap *fcfontmap,
+ PangoContext *context,
+ FontHashKey *key)
+{
+ key->fontmap = fcfontmap;
+ get_context_matrix (context, &key->matrix);
+
+ if (PANGO_ATSUI_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get)
+ key->context_key = (gpointer)PANGO_ATSUI_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context);
+ else
+ key->context_key = NULL;
+}
+
+static void
+pango_atsui_font_map_add (PangoATSUIFontMap *atsuifontmap,
+ PangoContext *context,
+ PangoATSUIFont *atsuifont)
+{
+ FontHashKey key;
+ FontHashKey *key_copy;
+ PangoATSUIFace *face;
+
+ _pango_atsui_font_set_font_map (atsuifont, atsuifontmap);
+
+ font_hash_key_for_context (atsuifontmap, context, &key);
+ face = _pango_atsui_font_get_face (atsuifont);
+ key.postscript_name = (char *)_pango_atsui_face_get_postscript_name (face);
+ key.desc = _pango_atsui_font_get_font_description (atsuifont);
+
+ key_copy = font_hash_key_copy (&key);
+ _pango_atsui_font_set_context_key (atsuifont, key_copy->context_key);
+ g_hash_table_insert (atsuifontmap->font_hash, key_copy, g_object_ref (atsuifont));
+}
+
+static PangoATSUIFont *
+pango_atsui_font_map_lookup (PangoATSUIFontMap *atsuifontmap,
+ PangoContext *context,
+ PangoFontDescription *desc,
+ PangoATSUIFace *face)
+{
+ FontHashKey key;
+
+ font_hash_key_for_context (atsuifontmap, context, &key);
+ key.postscript_name = (char *)_pango_atsui_face_get_postscript_name (face);
+ key.desc = desc;
+
+ return g_hash_table_lookup (atsuifontmap->font_hash, &key);
+}
+
+static gboolean
+find_best_match (PangoATSUIFamily *font_family,
+ const PangoFontDescription *description,
+ PangoFontDescription **best_description,
+ PangoATSUIFace **best_face)
+{
+ PangoFontDescription *new_desc;
+ int i;
+
+ *best_description = NULL;
+ *best_face = NULL;
+
+ for (i = 0; i < font_family->n_faces; i++)
+ {
+ new_desc = pango_font_face_describe (font_family->faces[i]);
+
+ if (pango_font_description_better_match (description, *best_description, new_desc))
+ {
+ pango_font_description_free (*best_description);
+ *best_description = new_desc;
+ *best_face = (PangoATSUIFace *)font_family->faces[i];
+ }
+ else
+ pango_font_description_free (new_desc);
+ }
+
+ if (*best_description)
+ return TRUE;
+
+ return FALSE;
+}
+
+static PangoFont *
+pango_atsui_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description)
+{
+ PangoATSUIFontMap *atsuifontmap = (PangoATSUIFontMap *)fontmap;
+ PangoATSUIFamily *font_family;
+ gchar *name;
+ gint size;
+
+ size = pango_font_description_get_size (description);
+ if (size < 0)
+ return NULL;
+
+ name = g_utf8_casefold (pango_font_description_get_family (description), -1);
+ font_family = g_hash_table_lookup (atsuifontmap->families, name);
+ g_free (name);
+
+ if (font_family)
+ {
+ PangoFontDescription *best_description;
+ PangoATSUIFace *best_face;
+ PangoATSUIFont *best_font;
+
+ /* Force a listing of the available faces */
+ pango_font_family_list_faces ((PangoFontFamily *)font_family, NULL, NULL);
+
+ if (!find_best_match (font_family, description, &best_description, &best_face))
+ return NULL;
+
+ pango_font_description_set_size (best_description, size);
+
+ best_font = pango_atsui_font_map_lookup (atsuifontmap,
+ context,
+ best_description,
+ best_face);
+
+ if (best_font)
+ g_object_ref (best_font);
+ else
+ {
+ PangoATSUIFontMapClass *klass;
+
+ klass = PANGO_ATSUI_FONT_MAP_GET_CLASS (atsuifontmap);
+ best_font = klass->create_font (atsuifontmap, context,
+ best_face, best_description);
+
+ if (best_font)
+ pango_atsui_font_map_add (atsuifontmap, context, best_font);
+ /* TODO: Handle the else case here. */
+ }
+
+ pango_font_description_free (best_description);
+
+ return (PangoFont *)best_font;
+ }
+
+ return NULL;
+}
+
+static void
+list_families_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GSList **list = user_data;
+
+ *list = g_slist_prepend (*list, value);
+}
+
+static void
+pango_atsui_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families)
+{
+ GSList *family_list = NULL;
+ GSList *tmp_list;
+ PangoATSUIFontMap *atsuifontmap = (PangoATSUIFontMap *)fontmap;
+
+ if (!n_families)
+ return;
+
+ g_hash_table_foreach (atsuifontmap->families, list_families_foreach, &family_list);
+
+ *n_families = g_slist_length (family_list);
+
+ if (families)
+ {
+ int i = 0;
+
+ *families = g_new (PangoFontFamily *, *n_families);
+
+ tmp_list = family_list;
+ while (tmp_list)
+ {
+ (*families)[i] = tmp_list->data;
+ i++;
+ tmp_list = tmp_list->next;
+ }
+ }
+
+ g_slist_free (family_list);
+}
+
+static void
+pango_atsui_font_map_init (PangoATSUIFontMap *atsuifontmap)
+{
+ NSArray *family_array;
+ NSAutoreleasePool *pool;
+ PangoATSUIFamily *family;
+
+ int size, i;
+
+ atsuifontmap->families = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
+
+
+ atsuifontmap->font_hash = g_hash_table_new_full ((GHashFunc)font_hash_key_hash,
+ (GEqualFunc)font_hash_key_equal,
+ (GDestroyNotify)font_hash_key_free,
+ NULL);
+
+ pool = [[NSAutoreleasePool alloc] init];
+ family_array = [[NSFontManager sharedFontManager] availableFontFamilies];
+ size = [family_array count];
+
+ for (i = 0; i < size; i++) {
+ NSString *family_name = [family_array objectAtIndex:i];
+
+ family = g_object_new (PANGO_TYPE_ATSUI_FAMILY, NULL);
+ family->family_name = g_strdup ([family_name UTF8String]);
+
+ g_hash_table_insert (atsuifontmap->families, g_utf8_casefold (family->family_name, -1), family);
+ }
+
+ /* Insert aliases */
+ family = g_object_new (PANGO_TYPE_ATSUI_FAMILY, NULL);
+ family->family_name = g_strdup ("Sans");
+ g_hash_table_insert (atsuifontmap->families, g_utf8_casefold (family->family_name, -1), family);
+
+ family = g_object_new (PANGO_TYPE_ATSUI_FAMILY, NULL);
+ family->family_name = g_strdup ("Serif");
+ g_hash_table_insert (atsuifontmap->families, g_utf8_casefold (family->family_name, -1), family);
+
+ family = g_object_new (PANGO_TYPE_ATSUI_FAMILY, NULL);
+ family->family_name = g_strdup ("Monospace");
+ g_hash_table_insert (atsuifontmap->families, g_utf8_casefold (family->family_name, -1), family);
+
+ [pool release];
+}
+
+static void
+pango_atsui_font_map_class_init (PangoATSUIFontMapClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class);
+
+ object_class->finalize = pango_atsui_font_map_finalize;
+
+ fontmap_class->load_font = pango_atsui_font_map_load_font;
+ fontmap_class->list_families = pango_atsui_font_map_list_families;
+ fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_ATSUI;
+}
+
+
diff --git a/trunk/pango/pangoatsui-private.h b/trunk/pango/pangoatsui-private.h
new file mode 100644
index 00000000..f88f0060
--- /dev/null
+++ b/trunk/pango/pangoatsui-private.h
@@ -0,0 +1,101 @@
+/* Pango
+ * pangoatsui-private.h:
+ *
+ * Copyright (C) 2003 Red Hat Software
+ * Copyright (C) 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOATSUI_PRIVATE_H__
+#define __PANGOATSUI_PRIVATE_H__
+
+#include <pango/pango-fontmap.h>
+#include <pango/pango-context.h>
+#include "pangoatsui.h"
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_ATSUI_FONT_MAP (pango_atsui_font_map_get_type ())
+#define PANGO_ATSUI_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_ATSUI_FONT_MAP, PangoATSUIFontMap))
+#define PANGO_ATSUI_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_ATSUI_FONT_MAP))
+#define PANGO_ATSUI_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_ATSUI_FONT_MAP, PangoATSUIFontMapClass))
+#define PANGO_IS_ATSUI_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_ATSUI_FONT_MAP))
+#define PANGO_ATSUI_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_ATSUI_FONT_MAP, PangoATSUIFontMapClass))
+
+
+typedef struct _PangoATSUIFamily PangoATSUIFamily;
+typedef struct _PangoATSUIFace PangoATSUIFace;
+
+typedef struct _PangoATSUIFontMap PangoATSUIFontMap;
+typedef struct _PangoATSUIFontMapClass PangoATSUIFontMapClass;
+
+struct _PangoATSUIFontMap
+{
+ PangoFontMap parent_instance;
+
+ GHashTable *font_hash;
+
+ GHashTable *families;
+};
+
+struct _PangoATSUIFontMapClass
+{
+ PangoFontMapClass parent_class;
+
+ gconstpointer (*context_key_get) (PangoATSUIFontMap *atsuifontmap,
+ PangoContext *context);
+ gpointer (*context_key_copy) (PangoATSUIFontMap *atsuifontmap,
+ gconstpointer key);
+ void (*context_key_free) (PangoATSUIFontMap *atsuifontmap,
+ gpointer key);
+ guint32 (*context_key_hash) (PangoATSUIFontMap *atsuifontmap,
+ gconstpointer key);
+ gboolean (*context_key_equal) (PangoATSUIFontMap *atsuifontmap,
+ gconstpointer key_a,
+ gconstpointer key_b);
+
+ PangoATSUIFont * (* create_font) (PangoATSUIFontMap *fontmap,
+ PangoContext *context,
+ PangoATSUIFace *face,
+ const PangoFontDescription *desc);
+};
+
+
+GType pango_atsui_font_map_get_type (void) G_GNUC_CONST;
+
+const char * _pango_atsui_face_get_postscript_name (PangoATSUIFace *face);
+PangoCoverage * _pango_atsui_face_get_coverage (PangoATSUIFace *face,
+ PangoLanguage *language);
+gboolean _pango_atsui_face_get_synthetic_italic (PangoATSUIFace *face);
+
+void _pango_atsui_font_set_font_description (PangoATSUIFont *afont,
+ const PangoFontDescription *desc);
+PangoFontDescription *_pango_atsui_font_get_font_description (PangoATSUIFont *afont);
+void _pango_atsui_font_set_font_map (PangoATSUIFont *afont,
+ PangoATSUIFontMap *fontmap);
+void _pango_atsui_font_set_face (PangoATSUIFont *afont,
+ PangoATSUIFace *aface);
+PangoATSUIFace * _pango_atsui_font_get_face (PangoATSUIFont *font);
+gpointer _pango_atsui_font_get_context_key (PangoATSUIFont *afont);
+void _pango_atsui_font_set_context_key (PangoATSUIFont *afont,
+ gpointer context_key);
+void _pango_atsui_font_set_atsu_font_id (PangoATSUIFont *font,
+ ATSUFontID font_id);
+
+G_END_DECLS
+
+#endif /* __PANGOATSUI_H__ */
diff --git a/trunk/pango/pangoatsui.c b/trunk/pango/pangoatsui.c
new file mode 100644
index 00000000..2d5ee7fc
--- /dev/null
+++ b/trunk/pango/pangoatsui.c
@@ -0,0 +1,201 @@
+/* Pango
+ * pangatsui.c
+ *
+ * Copyright (C) 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pangoatsui.h"
+#include "pangoatsui-private.h"
+
+G_DEFINE_TYPE (PangoATSUIFont, pango_atsui_font, PANGO_TYPE_FONT);
+
+struct _PangoATSUIFontPrivate
+{
+ PangoATSUIFace *face;
+ PangoFontDescription *desc;
+ gpointer context_key;
+
+ ATSUFontID font_id;
+
+ PangoFontMap *fontmap;
+};
+
+static void
+pango_atsui_font_finalize (GObject *object)
+{
+ PangoATSUIFont *afont = (PangoATSUIFont *)object;
+ PangoATSUIFontPrivate *priv = afont->priv;
+
+ pango_font_description_free (priv->desc);
+
+ g_object_unref (priv->fontmap);
+
+ G_OBJECT_CLASS (pango_atsui_font_parent_class)->finalize (object);
+}
+
+static PangoFontDescription *
+pango_atsui_font_describe (PangoFont *font)
+{
+ PangoATSUIFont *afont = (PangoATSUIFont *)font;
+ PangoATSUIFontPrivate *priv = afont->priv;
+
+ return pango_font_description_copy (priv->desc);
+}
+
+static PangoCoverage *
+pango_atsui_font_get_coverage (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoATSUIFont *afont = (PangoATSUIFont *)font;
+ PangoATSUIFontPrivate *priv = afont->priv;
+
+ return pango_coverage_ref (_pango_atsui_face_get_coverage (priv->face,
+ language));
+}
+
+static PangoEngineShape *
+pango_atsui_font_find_shaper (PangoFont *font,
+ PangoLanguage *language,
+ guint32 ch)
+{
+ /* FIXME: Implement */
+ return NULL;
+}
+
+static PangoFontMap *
+pango_atsui_font_get_font_map (PangoFont *font)
+{
+ PangoATSUIFont *afont = (PangoATSUIFont *)font;
+
+ return afont->priv->fontmap;
+}
+
+static void
+pango_atsui_font_init (PangoATSUIFont *afont)
+{
+ afont->priv = G_TYPE_INSTANCE_GET_PRIVATE (afont,
+ PANGO_TYPE_ATSUI_FONT,
+ PangoATSUIFontPrivate);
+}
+
+static void
+pango_atsui_font_class_init (PangoATSUIFontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+
+ object_class->finalize = pango_atsui_font_finalize;
+
+ font_class->describe = pango_atsui_font_describe;
+ font_class->get_coverage = pango_atsui_font_get_coverage;
+ font_class->find_shaper = pango_atsui_font_find_shaper;
+ font_class->get_font_map = pango_atsui_font_get_font_map;
+
+ g_type_class_add_private (object_class, sizeof (PangoATSUIFontPrivate));
+}
+
+void
+_pango_atsui_font_set_font_description (PangoATSUIFont *font,
+ const PangoFontDescription *desc)
+{
+ PangoATSUIFontPrivate *priv = font->priv;
+
+ priv->desc = pango_font_description_copy (desc);
+}
+
+PangoFontDescription *
+_pango_atsui_font_get_font_description (PangoATSUIFont *font)
+{
+ PangoATSUIFontPrivate *priv = font->priv;
+
+ return priv->desc;
+}
+
+void
+_pango_atsui_font_set_font_map (PangoATSUIFont *font,
+ PangoATSUIFontMap *fontmap)
+{
+ PangoATSUIFontPrivate *priv = font->priv;
+
+ g_assert (priv->fontmap == NULL);
+
+ priv->fontmap = g_object_ref (fontmap);
+}
+
+void
+_pango_atsui_font_set_face (PangoATSUIFont *afont,
+ PangoATSUIFace *face)
+{
+ PangoATSUIFontPrivate *priv = afont->priv;
+
+ priv->face = face;
+}
+
+PangoATSUIFace *
+_pango_atsui_font_get_face (PangoATSUIFont *afont)
+{
+ PangoATSUIFontPrivate *priv = afont->priv;
+
+ return priv->face;
+}
+
+gpointer
+_pango_atsui_font_get_context_key (PangoATSUIFont *afont)
+{
+ PangoATSUIFontPrivate *priv = afont->priv;
+
+ return priv->context_key;
+}
+
+void
+_pango_atsui_font_set_context_key (PangoATSUIFont *afont,
+ gpointer context_key)
+{
+ PangoATSUIFontPrivate *priv = afont->priv;
+
+ priv->context_key = context_key;
+}
+
+void
+_pango_atsui_font_set_atsu_font_id (PangoATSUIFont *font,
+ ATSUFontID font_id)
+{
+ PangoATSUIFontPrivate *priv = font->priv;
+
+ priv->font_id = font_id;
+}
+
+/**
+ * pango_atsui_font_get_atsu_font_id:
+ * @font: A #PangoATSUIFont
+ *
+ * Returns the ATSUFontID of a font.
+ *
+ * Return value: the ATSUFontID associated to @font.
+ *
+ * Since: 1.18
+ */
+ATSUFontID
+pango_atsui_font_get_atsu_font_id (PangoATSUIFont *font)
+{
+ PangoATSUIFontPrivate *priv = font->priv;
+
+ return priv->font_id;
+}
diff --git a/trunk/pango/pangoatsui.h b/trunk/pango/pangoatsui.h
new file mode 100644
index 00000000..91cbdb14
--- /dev/null
+++ b/trunk/pango/pangoatsui.h
@@ -0,0 +1,79 @@
+/* Pango
+ * pangoatsui.h:
+ *
+ * Copyright (C) 2005 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOATSUI_H__
+#define __PANGOATSUI_H__
+
+#include <pango/pango-context.h>
+#include <pango/pango-font.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_ATSUI_FONT (pango_atsui_font_get_type ())
+#define PANGO_ATSUI_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_ATSUI_FONT, PangoATSUIFont))
+#define PANGO_IS_ATSUI_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_ATSUI_FONT))
+
+typedef struct _PangoATSUIFont PangoATSUIFont;
+typedef struct _PangoATSUIFontClass PangoATSUIFontClass;
+
+#if defined(PANGO_ENABLE_ENGINE) || defined(PANGO_ENABLE_BACKEND)
+
+#define PANGO_RENDER_TYPE_ATSUI "PangoRenderATSUI"
+
+#ifdef PANGO_ENABLE_BACKEND
+
+#define PANGO_ATSUI_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_ATSUI_FONT, PangoATSUIFontClass))
+#define PANGO_IS_ATSUI_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_ATSUI_FONT))
+#define PANGO_ATSUI_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_ATSUI_FONT, PangoATSUIFontClass))
+
+typedef struct _PangoATSUIFontPrivate PangoATSUIFontPrivate;
+
+struct _PangoATSUIFont
+{
+ PangoFont parent_instance;
+ PangoATSUIFontPrivate *priv;
+};
+
+struct _PangoATSUIFontClass
+{
+ PangoFontClass parent_class;
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+ATSUFontID pango_atsui_font_get_atsu_font_id (PangoATSUIFont *font);
+
+#endif /* PANGO_ENABLE_ENGINE || PANGO_ENABLE_BACKEND */
+
+GType pango_atsui_font_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __PANGOATSUI_H__ */
diff --git a/trunk/pango/pangocairo-atsui.h b/trunk/pango/pangocairo-atsui.h
new file mode 100644
index 00000000..25613a01
--- /dev/null
+++ b/trunk/pango/pangocairo-atsui.h
@@ -0,0 +1,57 @@
+/* Pango
+ * pangoatsui.h:
+ *
+ * Copyright (C) 2005 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOCAIRO_ATSUI_H__
+#define __PANGOCAIRO_ATSUI_H__
+
+#include "pangoatsui-private.h"
+#include <pango/pangocairo.h>
+#include <cairo-atsui.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_CAIRO_ATSUI_FONT_MAP (pango_cairo_atsui_font_map_get_type ())
+#define PANGO_CAIRO_ATSUI_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_ATSUI_FONT_MAP, PangoCairoATSUIFontMap))
+#define PANGO_IS_CAIRO_ATSUI_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_ATSUI_FONT_MAP))
+
+typedef struct _PangoCairoATSUIFontMap PangoCairoATSUIFontMap;
+
+struct _PangoCairoATSUIFontMap
+{
+ PangoATSUIFontMap parent_instance;
+
+ PangoRenderer *renderer;
+
+ gdouble dpi;
+};
+
+GType pango_cairo_atsui_font_map_get_type (void) G_GNUC_CONST;
+
+PangoATSUIFont *
+_pango_cairo_atsui_font_new (PangoCairoATSUIFontMap *cafontmap,
+ PangoContext *context,
+ PangoATSUIFace *face,
+ const PangoFontDescription *desc);
+
+G_END_DECLS
+
+#endif /* __PANGOCAIRO_ATSUI_H__ */
+
diff --git a/trunk/pango/pangocairo-atsuifont.c b/trunk/pango/pangocairo-atsuifont.c
new file mode 100644
index 00000000..ef7a4b46
--- /dev/null
+++ b/trunk/pango/pangocairo-atsuifont.c
@@ -0,0 +1,302 @@
+/* Pango
+ * pangocairo-atsuifont.c
+ *
+ * Copyright (C) 2000-2005 Red Hat Software
+ * Copyright (C) 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#import <Cocoa/Cocoa.h>
+
+#include "pangoatsui-private.h"
+#include "pangocairo.h"
+#include "pangocairo-private.h"
+#include "pangocairo-atsui.h"
+#include "pangocairo-atsuifont.h"
+
+struct _PangoCairoATSUIFont
+{
+ PangoATSUIFont font;
+ PangoCairoFontPrivate cf_priv;
+
+ double size;
+ int absolute_size;
+};
+
+struct _PangoCairoATSUIFontClass
+{
+ PangoATSUIFontClass parent_class;
+};
+
+
+
+static cairo_font_face_t *pango_cairo_atsui_font_create_font_face (PangoCairoFont *font);
+static PangoFontMetrics *pango_cairo_atsui_font_create_metrics_for_context (PangoCairoFont *font,
+ PangoContext *context);
+
+static void
+cairo_font_iface_init (PangoCairoFontIface *iface)
+{
+ iface->create_font_face = pango_cairo_atsui_font_create_font_face;
+ iface->create_metrics_for_context = pango_cairo_atsui_font_create_metrics_for_context;
+ iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoATSUIFont, cf_priv);
+}
+
+G_DEFINE_TYPE_WITH_CODE (PangoCairoATSUIFont, pango_cairo_atsui_font, PANGO_TYPE_ATSUI_FONT,
+ { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) });
+
+/* we want get_glyph_extents extremely fast, so we use a small wrapper here
+ * to avoid having to lookup the interface data like we do for get_metrics
+ * in _pango_cairo_font_get_metrics(). */
+static void
+pango_cairo_atsui_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoCairoATSUIFont *cafont = (PangoCairoATSUIFont *) (font);
+
+ _pango_cairo_font_private_get_glyph_extents (&cafont->cf_priv,
+ glyph,
+ ink_rect,
+ logical_rect);
+}
+
+static cairo_font_face_t *
+pango_cairo_atsui_font_create_font_face (PangoCairoFont *font)
+{
+ PangoATSUIFont *afont = (PangoATSUIFont *) (font);
+ ATSUFontID font_id;
+
+ font_id = pango_atsui_font_get_atsu_font_id (afont);
+ return cairo_atsui_font_face_create_for_atsu_font_id (font_id);
+}
+
+static int
+max_glyph_width (PangoLayout *layout)
+{
+ int max_width = 0;
+ GSList *l, *r;
+
+ for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
+ {
+ PangoLayoutLine *line = l->data;
+
+ for (r = line->runs; r; r = r->next)
+ {
+ PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ if (glyphs->glyphs[i].geometry.width > max_width)
+ max_width = glyphs->glyphs[i].geometry.width;
+ }
+ }
+
+ return max_width;
+}
+
+static PangoFontMetrics *
+pango_cairo_atsui_font_create_metrics_for_context (PangoCairoFont *font,
+ PangoContext *context)
+{
+ PangoCairoATSUIFont *cafont = (PangoCairoATSUIFont *) font;
+ PangoATSUIFont *afont = (PangoATSUIFont *) font;
+ ATSFontRef ats_font;
+ ATSFontMetrics ats_metrics;
+ PangoFontMetrics *metrics;
+ PangoFontDescription *font_desc;
+ PangoLayout *layout;
+ PangoRectangle extents;
+ PangoLanguage *language = pango_context_get_language (context);
+ const char *sample_str = pango_language_get_sample_string (language);
+
+ ats_font = FMGetATSFontRefFromFont (pango_atsui_font_get_atsu_font_id (afont));
+
+ ATSFontGetHorizontalMetrics (ats_font, kATSOptionFlagsDefault, &ats_metrics);
+
+ metrics = pango_font_metrics_new ();
+
+ metrics->ascent = ats_metrics.ascent * cafont->size * PANGO_SCALE;
+ metrics->descent = -ats_metrics.descent * cafont->size * PANGO_SCALE;
+
+ metrics->underline_position = ats_metrics.underlinePosition * cafont->size * PANGO_SCALE;
+ metrics->underline_thickness = ats_metrics.underlineThickness * cafont->size * PANGO_SCALE;
+
+ metrics->strikethrough_position = metrics->ascent / 3;
+ metrics->strikethrough_thickness = ats_metrics.underlineThickness * cafont->size * PANGO_SCALE;
+
+ layout = pango_layout_new (context);
+ font_desc = pango_font_describe_with_absolute_size ((PangoFont *) font);
+ pango_layout_set_font_description (layout, font_desc);
+ pango_layout_set_text (layout, sample_str, -1);
+ pango_layout_get_extents (layout, NULL, &extents);
+
+ metrics->approximate_char_width = extents.width / g_utf8_strlen (sample_str, -1);
+
+ pango_layout_set_text (layout, "0123456789", -1);
+ metrics->approximate_digit_width = max_glyph_width (layout);
+
+ pango_font_description_free (font_desc);
+ g_object_unref (layout);
+
+ return metrics;
+}
+
+static PangoFontDescription *
+pango_cairo_atsui_font_describe_absolute (PangoFont *font)
+{
+ PangoFontDescription *desc;
+ PangoCairoATSUIFont *cafont = (PangoCairoATSUIFont *) font;
+
+ desc = pango_font_describe (font);
+ pango_font_description_set_absolute_size (desc, cafont->absolute_size);
+
+ return desc;
+}
+
+static void
+pango_cairo_atsui_font_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (pango_cairo_atsui_font_parent_class)->finalize (object);
+}
+
+static void
+pango_cairo_atsui_font_class_init (PangoCairoATSUIFontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+
+ object_class->finalize = pango_cairo_atsui_font_finalize;
+
+ font_class->get_glyph_extents = pango_cairo_atsui_font_get_glyph_extents;
+ font_class->get_metrics = _pango_cairo_font_get_metrics;
+ font_class->describe_absolute = pango_cairo_atsui_font_describe_absolute;
+}
+
+static void
+pango_cairo_atsui_font_init (PangoCairoATSUIFont *cafont)
+{
+}
+
+PangoATSUIFont *
+_pango_cairo_atsui_font_new (PangoCairoATSUIFontMap *cafontmap,
+ PangoContext *context,
+ PangoATSUIFace *face,
+ const PangoFontDescription *desc)
+{
+ const char *postscript_name;
+ gboolean synthesize_italic = FALSE;
+ PangoCairoATSUIFont *cafont;
+ PangoATSUIFont *afont;
+ CFStringRef cfstr;
+ ATSFontRef font_ref;
+ ATSUFontID font_id;
+ double size;
+ double dpi;
+ cairo_matrix_t font_matrix;
+
+ postscript_name = _pango_atsui_face_get_postscript_name (face);
+
+ cfstr = CFStringCreateWithCString (NULL, postscript_name,
+ kCFStringEncodingUTF8);
+ font_ref = ATSFontFindFromPostScriptName (cfstr, kATSOptionFlagsDefault);
+ CFRelease (cfstr);
+
+ /* We synthesize italic in two cases. The first is when
+ * NSFontManager has handed out a face that it claims has italic but
+ * it doesn't. The other is when an italic face is requested that
+ * doesn't have a real version.
+ */
+ if (font_ref == kATSFontRefUnspecified &&
+ pango_font_description_get_style (desc) != PANGO_STYLE_NORMAL)
+ {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSString *nsname;
+ NSFont *nsfont, *converted_font;
+
+ size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
+
+ nsname = [NSString stringWithUTF8String:postscript_name];
+ nsfont = [NSFont fontWithName:nsname size:size];
+
+ converted_font = [[NSFontManager sharedFontManager] convertFont:nsfont
+ toHaveTrait:NSUnitalicFontMask];
+ font_ref = ATSFontFindFromPostScriptName ((CFStringRef) [converted_font fontName],
+ kATSOptionFlagsDefault);
+
+ [pool release];
+
+ synthesize_italic = TRUE;
+ }
+ else if (_pango_atsui_face_get_synthetic_italic (face))
+ synthesize_italic = TRUE;
+
+ if (font_ref == kATSFontRefUnspecified)
+ return NULL;
+
+ font_id = FMGetFontFromATSFontRef (font_ref);
+ if (!font_id)
+ return NULL;
+
+ cafont = g_object_new (PANGO_TYPE_CAIRO_ATSUI_FONT, NULL);
+ afont = PANGO_ATSUI_FONT (cafont);
+
+ _pango_atsui_font_set_font_description (afont, desc);
+ _pango_atsui_font_set_face (afont, face);
+
+ size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
+ _pango_atsui_font_set_atsu_font_id (afont, font_id);
+
+ if (context)
+ {
+ dpi = pango_cairo_context_get_resolution (context);
+
+ if (dpi <= 0)
+ dpi = cafontmap->dpi;
+ }
+ else
+ dpi = cafontmap->dpi;
+
+ cafont->absolute_size = pango_font_description_get_size (desc);
+
+ if (!pango_font_description_get_size_is_absolute (desc))
+ size *= dpi / 72.;
+
+ cafont->size = size;
+
+ /* If necessary, apply a shear matrix, matching what Cocoa does. */
+ if (synthesize_italic)
+ cairo_matrix_init (&font_matrix,
+ 1, 0,
+ 0.25, 1,
+ 0, 0);
+ else
+ cairo_matrix_init_identity (&font_matrix);
+
+ cairo_matrix_scale (&font_matrix, size, size);
+
+ _pango_cairo_font_private_initialize (&cafont->cf_priv,
+ (PangoCairoFont *) cafont,
+ context,
+ desc,
+ &font_matrix);
+
+ return afont;
+}
diff --git a/trunk/pango/pangocairo-atsuifont.h b/trunk/pango/pangocairo-atsuifont.h
new file mode 100644
index 00000000..fe692788
--- /dev/null
+++ b/trunk/pango/pangocairo-atsuifont.h
@@ -0,0 +1,36 @@
+/* Pango
+ * pangocairo-atsuifont.c
+ *
+ * Copyright (C) 2005 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOCAIRO_ATSUIFONT_H__
+#define __PANGOCAIRO_ATSUIFONT_H__
+
+#define PANGO_TYPE_CAIRO_ATSUI_FONT (pango_cairo_atsui_font_get_type ())
+#define PANGO_CAIRO_ATSUI_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_ATSUI_FONT, PangoCairoATSUIFont))
+#define PANGO_CAIRO_ATSUI_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_ATSUI_FONT, PangoCairoATSUIFontClass))
+#define PANGO_IS_CAIRO_ATSUI_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_ATSUI_FONT))
+#define PANGO_CAIRO_ATSUI_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_ATSUI_FONT, PangoCairoATSUIFontClass))
+
+typedef struct _PangoCairoATSUIFont PangoCairoATSUIFont;
+typedef struct _PangoCairoATSUIFontClass PangoCairoATSUIFontClass;
+
+GType pango_cairo_atsui_font_get_type (void) G_GNUC_CONST;
+
+#endif /* __PANGOCAIRO_ATSUIFONT_H__ */
diff --git a/trunk/pango/pangocairo-atsuifontmap.c b/trunk/pango/pangocairo-atsuifontmap.c
new file mode 100644
index 00000000..0c3e6390
--- /dev/null
+++ b/trunk/pango/pangocairo-atsuifontmap.c
@@ -0,0 +1,108 @@
+/* Pango
+ * pangocairo-atsuifontmap.c
+ *
+ * Copyright (C) 2005 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pangoatsui-private.h"
+#include "pangocairo.h"
+#include "pangocairo-private.h"
+#include "pangocairo-atsui.h"
+
+typedef struct _PangoCairoATSUIFontMapClass PangoCairoATSUIFontMapClass;
+
+struct _PangoCairoATSUIFontMapClass
+{
+ PangoATSUIFontMapClass parent_class;
+};
+
+static void
+pango_cairo_atsui_font_map_set_resolution (PangoCairoFontMap *cfontmap,
+ double dpi)
+{
+ PangoCairoATSUIFontMap *cafontmap = PANGO_CAIRO_ATSUI_FONT_MAP (cfontmap);
+
+ cafontmap->dpi = dpi;
+}
+
+static double
+pango_cairo_atsui_font_map_get_resolution (PangoCairoFontMap *cfontmap)
+{
+ PangoCairoATSUIFontMap *cafontmap = PANGO_CAIRO_ATSUI_FONT_MAP (cfontmap);
+
+ return cafontmap->dpi;
+}
+
+static cairo_font_type_t
+pango_cairo_atsui_font_map_get_font_type (PangoCairoFontMap *cfontmap)
+{
+ return CAIRO_FONT_TYPE_ATSUI;
+}
+
+static void
+cairo_font_map_iface_init (PangoCairoFontMapIface *iface)
+{
+ iface->set_resolution = pango_cairo_atsui_font_map_set_resolution;
+ iface->get_resolution = pango_cairo_atsui_font_map_get_resolution;
+ iface->get_font_type = pango_cairo_atsui_font_map_get_font_type;
+}
+
+G_DEFINE_TYPE_WITH_CODE (PangoCairoATSUIFontMap, pango_cairo_atsui_font_map, PANGO_TYPE_ATSUI_FONT_MAP,
+ { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT_MAP, cairo_font_map_iface_init) });
+
+
+static PangoATSUIFont *
+pango_cairo_atsui_font_map_create_font (PangoATSUIFontMap *fontmap,
+ PangoContext *context,
+ PangoATSUIFace *face,
+ const PangoFontDescription *desc)
+
+{
+ return _pango_cairo_atsui_font_new (PANGO_CAIRO_ATSUI_FONT_MAP (fontmap),
+ context, face, desc);
+}
+
+static void
+pango_cairo_atsui_font_map_finalize (GObject *object)
+{
+ PangoCairoATSUIFontMap *cafontmap = PANGO_CAIRO_ATSUI_FONT_MAP (object);
+
+ if (cafontmap->renderer)
+ g_object_unref (cafontmap->renderer);
+
+ G_OBJECT_CLASS (pango_cairo_atsui_font_map_parent_class)->finalize (object);
+}
+
+static void
+pango_cairo_atsui_font_map_class_init (PangoCairoATSUIFontMapClass *class)
+{
+ PangoATSUIFontMapClass *atsuifontmapclass = (PangoATSUIFontMapClass *)class;
+ GObjectClass *object_class = (GObjectClass *)class;
+
+ object_class->finalize = pango_cairo_atsui_font_map_finalize;
+
+ atsuifontmapclass->create_font = pango_cairo_atsui_font_map_create_font;
+}
+
+static void
+pango_cairo_atsui_font_map_init (PangoCairoATSUIFontMap *cafontmap)
+{
+ cafontmap->dpi = 72.;
+}
diff --git a/trunk/pango/pangocairo-context.c b/trunk/pango/pangocairo-context.c
new file mode 100644
index 00000000..98558f89
--- /dev/null
+++ b/trunk/pango/pangocairo-context.c
@@ -0,0 +1,438 @@
+/* Pango
+ * pangocairo-fontmap.c: Cairo font handling
+ *
+ * Copyright (C) 2000-2005 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pangocairo.h"
+#include "pangocairo-private.h"
+#include "pango-impl-utils.h"
+
+#include <string.h>
+
+typedef struct _PangoCairoContextInfo PangoCairoContextInfo;
+
+struct _PangoCairoContextInfo
+{
+ double dpi;
+
+ cairo_font_options_t *set_options;
+ cairo_font_options_t *surface_options;
+ cairo_font_options_t *merged_options;
+
+ PangoCairoShapeRendererFunc shape_renderer_func;
+ gpointer shape_renderer_data;
+ GDestroyNotify shape_renderer_notify;
+};
+
+static void
+free_context_info (PangoCairoContextInfo *info)
+{
+ if (info->set_options)
+ cairo_font_options_destroy (info->set_options);
+ if (info->surface_options)
+ cairo_font_options_destroy (info->surface_options);
+ if (info->merged_options)
+ cairo_font_options_destroy (info->merged_options);
+
+ if (info->shape_renderer_notify)
+ info->shape_renderer_notify (info->shape_renderer_data);
+
+ g_slice_free (PangoCairoContextInfo, info);
+}
+
+static PangoCairoContextInfo *
+get_context_info (PangoContext *context,
+ gboolean create)
+{
+ static GQuark context_info_quark;
+ PangoCairoContextInfo *info;
+
+ if (G_UNLIKELY (!context_info_quark))
+ context_info_quark = g_quark_from_static_string ("pango-cairo-context-info");
+
+ info = g_object_get_qdata (G_OBJECT (context), context_info_quark);
+
+ if (G_UNLIKELY (!info) && create)
+ {
+ info = g_slice_new0 (PangoCairoContextInfo);
+ info->dpi = -1.0;
+
+ g_object_set_qdata_full (G_OBJECT (context), context_info_quark,
+ info, (GDestroyNotify)free_context_info);
+ }
+
+ return info;
+}
+
+static gboolean
+_pango_cairo_update_context (cairo_t *cr,
+ PangoContext *context)
+{
+ PangoCairoContextInfo *info;
+ cairo_matrix_t cairo_matrix;
+ cairo_surface_t *target;
+ PangoMatrix pango_matrix;
+ const PangoMatrix *layout_matrix, identity_matrix = PANGO_MATRIX_INIT;
+ gboolean changed = FALSE;
+
+ info = get_context_info (context, TRUE);
+
+ cairo_get_matrix (cr, &cairo_matrix);
+ pango_matrix.xx = cairo_matrix.xx;
+ pango_matrix.yx = cairo_matrix.yx;
+ pango_matrix.xy = cairo_matrix.xy;
+ pango_matrix.yy = cairo_matrix.yy;
+ pango_matrix.x0 = cairo_matrix.x0;
+ pango_matrix.y0 = cairo_matrix.y0;
+
+ layout_matrix = pango_context_get_matrix (context);
+ if (!layout_matrix)
+ layout_matrix = &identity_matrix;
+
+ if (0 != memcmp (&pango_matrix, layout_matrix, sizeof (pango_matrix)))
+ changed = TRUE;
+
+ pango_context_set_matrix (context, &pango_matrix);
+
+
+ target = cairo_get_target (cr);
+
+ if (!info->surface_options) {
+ info->surface_options = cairo_font_options_create ();
+ changed = TRUE;
+ cairo_surface_get_font_options (target, info->surface_options);
+ } else {
+ cairo_font_options_t *surface_options = cairo_font_options_create ();
+ cairo_surface_get_font_options (target, surface_options);
+ if (!cairo_font_options_equal (surface_options, info->surface_options))
+ {
+ cairo_surface_get_font_options (target, info->surface_options);
+ changed = TRUE;
+ }
+ cairo_font_options_destroy (surface_options);
+ }
+
+ if (info->merged_options)
+ {
+ cairo_font_options_destroy (info->merged_options);
+ info->merged_options = NULL;
+ }
+
+ return changed;
+}
+
+/**
+ * pango_cairo_update_context:
+ * @cr: a Cairo context
+ * @context: a #PangoContext, from pango_cairo_font_map_create_context()
+ *
+ * Updates a #PangoContext previously created for use with Cairo to
+ * match the current transformation and target surface of a Cairo
+ * context. If any layouts have been created for the context,
+ * it's necessary to call pango_layout_context_changed() on those
+ * layouts.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_update_context (cairo_t *cr,
+ PangoContext *context)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (PANGO_IS_CONTEXT (context));
+
+ (void) _pango_cairo_update_context (cr, context);
+}
+
+/**
+ * pango_cairo_context_set_resolution:
+ * @context: a #PangoContext, from pango_cairo_font_map_create_context()
+ * @dpi: the resolution in "dots per inch". (Physical inches aren't actually
+ * involved; the terminology is conventional.) A 0 or negative value
+ * means to use the resolution from the font map.
+ *
+ * Sets the resolution for the context. This is a scale factor between
+ * points specified in a #PangoFontDescription and Cairo units. The
+ * default value is 96, meaning that a 10 point font will be 13
+ * units high. (10 * 96. / 72. = 13.3).
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_context_set_resolution (PangoContext *context,
+ double dpi)
+{
+ PangoCairoContextInfo *info = get_context_info (context, TRUE);
+ info->dpi = dpi;
+}
+
+/**
+ * pango_cairo_context_get_resolution:
+ * @context: a #PangoContext, from pango_cairo_font_map_create_context()
+ *
+ * Gets the resolution for the context. See pango_cairo_context_set_resolution()
+ *
+ * Return value: the resolution in "dots per inch". A negative value will
+ * be returned if no resolution has previously been set.
+ *
+ * Since: 1.10
+ **/
+double
+pango_cairo_context_get_resolution (PangoContext *context)
+{
+ PangoCairoContextInfo *info = get_context_info (context, FALSE);
+
+ if (info)
+ return info->dpi;
+ else
+ return -1.0;
+}
+
+/**
+ * pango_cairo_context_set_font_options:
+ * @context: a #PangoContext, from pango_cairo_font_map_create_context()
+ * @options: a #cairo_font_options_t, or %NULL to unset any previously set
+ * options. A copy is made.
+ *
+ * Sets the font options used when rendering text with this context.
+ * These options override any options that pango_cairo_update_context()
+ * derives from the target surface.
+ */
+void
+pango_cairo_context_set_font_options (PangoContext *context,
+ const cairo_font_options_t *options)
+{
+ PangoCairoContextInfo *info;
+
+ g_return_if_fail (PANGO_IS_CONTEXT (context));
+
+ info = get_context_info (context, TRUE);
+
+ if (info->set_options)
+ cairo_font_options_destroy (info->set_options);
+
+ if (options)
+ info->set_options = cairo_font_options_copy (options);
+ else
+ info->set_options = NULL;
+
+ if (info->merged_options)
+ {
+ cairo_font_options_destroy (info->merged_options);
+ info->merged_options = NULL;
+ }
+}
+
+/**
+ * pango_cairo_context_get_font_options:
+ * @context: a #PangoContext, from pango_cairo_font_map_create_context()
+ *
+ * Retrieves any font rendering options previously set with
+ * pango_cairo_font_map_set_font_options(). This functions not report options
+ * that are derived from the target surface by pango_cairo_update_context()
+ *
+ * Return value: the font options previously set on the context, or %NULL
+ * if no options have been set. This value is owned by the context
+ * and must not be modified or freed.
+ **/
+G_CONST_RETURN cairo_font_options_t *
+pango_cairo_context_get_font_options (PangoContext *context)
+{
+ PangoCairoContextInfo *info;
+
+ g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
+
+ info = get_context_info (context, FALSE);
+
+ if (info)
+ return info->set_options;
+ else
+ return NULL;
+}
+
+/**
+ * _pango_cairo_context_merge_font_options:
+ * @context: a #PangoContext
+ * @options: a #cairo_font_options_t
+ *
+ * Merge together options from the target surface and explicitly set
+ * on the context.
+ *
+ * Return value: the combined set of font options. This value is owned
+ * by the context and must not be modified or freed.
+ **/
+G_CONST_RETURN cairo_font_options_t *
+_pango_cairo_context_get_merged_font_options (PangoContext *context)
+{
+ PangoCairoContextInfo *info = get_context_info (context, TRUE);
+
+ if (!info->merged_options)
+ {
+ info->merged_options = cairo_font_options_create ();
+
+ if (info->surface_options)
+ cairo_font_options_merge (info->merged_options, info->surface_options);
+ if (info->set_options)
+ cairo_font_options_merge (info->merged_options, info->set_options);
+ }
+
+ return info->merged_options;
+}
+
+/**
+ * pango_cairo_context_set_shape_renderer:
+ * @context: a #PangoContext, from pango_cairo_font_map_create_context()
+ * @func: Callback function for rendering attributes of type
+ * %PANGO_ATTR_SHAPE, or %NULL to disable shape rendering.
+ * @data: User data that will be passed to @func.
+ * @dnotify: Callback that will be called when the
+ * context is freed to release @data, or %NULL.
+ *
+ * Sets callback function for context to use for rendering attributes
+ * of type %PANGO_ATTR_SHAPE. See #PangoCairoShapeRendererFunc for
+ * details.
+ *
+ * Since: 1.18
+ */
+void
+pango_cairo_context_set_shape_renderer (PangoContext *context,
+ PangoCairoShapeRendererFunc func,
+ gpointer data,
+ GDestroyNotify dnotify)
+{
+ PangoCairoContextInfo *info;
+
+ g_return_if_fail (PANGO_IS_CONTEXT (context));
+
+ info = get_context_info (context, TRUE);
+
+ if (info->shape_renderer_notify)
+ info->shape_renderer_notify (info->shape_renderer_data);
+
+ info->shape_renderer_func = func;
+ info->shape_renderer_data = data;
+ info->shape_renderer_notify = dnotify;
+}
+
+/**
+ * pango_cairo_context_get_shape_renderer:
+ * @context: a #PangoContext, from pango_cairo_font_map_create_context()
+ * @data: Pointer to #gpointer to return user data
+ *
+ * Sets callback function for context to use for rendering attributes
+ * of type %PANGO_ATTR_SHAPE. See #PangoCairoShapeRendererFunc for
+ * details.
+ *
+ * Retrieves callback function and associated user data for rendering
+ * attributes of type %PANGO_ATTR_SHAPE as set by
+ * pango_cairo_context_set_shape_renderer(), if any.
+ *
+ * Return value: the shape rendering callback previously set on the context, or %NULL
+ * if no shape rendering callback have been set.
+ *
+ * Since: 1.18
+ */
+PangoCairoShapeRendererFunc
+pango_cairo_context_get_shape_renderer (PangoContext *context,
+ gpointer *data)
+{
+ PangoCairoContextInfo *info;
+
+ g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
+
+ info = get_context_info (context, FALSE);
+
+ if (info)
+ {
+ if (data)
+ *data = info->shape_renderer_data;
+ return info->shape_renderer_func;
+ }
+ else
+ {
+ if (data)
+ *data = NULL;
+ return NULL;
+ }
+}
+
+/**
+ * pango_cairo_create_layout:
+ * @cr: a Cairo context
+ *
+ * Creates a layout object set up to match the current transformation
+ * and target surface of the Cairo context. This layout can then be
+ * used for text measurement with functions like
+ * pango_layout_get_size() or drawing with functions like
+ * pango_cairo_show_layout(). If you change the transformation
+ * or target surface for @cr, you need to call pango_cairo_update_layout()
+ *
+ * This function is the most convenient way to use Cairo with Pango,
+ * however it is slightly inefficient since it creates a separate
+ * #PangoContext object for each layout. This might matter in an
+ * application that was laying out large amounts of text.
+ *
+ * Return value: the newly created #PangoLayout. Free with
+ * g_object_unref().
+ *
+ * Since: 1.10
+ **/
+PangoLayout *
+pango_cairo_create_layout (cairo_t *cr)
+{
+ PangoFontMap *fontmap;
+ PangoContext *context;
+ PangoLayout *layout;
+
+ g_return_val_if_fail (cr != NULL, NULL);
+
+ fontmap = pango_cairo_font_map_get_default ();
+ context = pango_cairo_font_map_create_context ((PangoCairoFontMap *) (fontmap));
+ layout = pango_layout_new (context);
+
+ pango_cairo_update_context (cr, context);
+ g_object_unref (context);
+
+ return layout;
+}
+
+/**
+ * pango_cairo_update_layout:
+ * @cr: a Cairo context
+ * @layout: a #PangoLayout, from pango_cairo_create_layout()
+ *
+ * Updates the private #PangoContext of a #PangoLayout created with
+ * pango_cairo_create_layout() to match the current transformation
+ * and target surface of a Cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_update_layout (cairo_t *cr,
+ PangoLayout *layout)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ if (_pango_cairo_update_context (cr, pango_layout_get_context (layout)))
+ pango_layout_context_changed (layout);
+}
+
diff --git a/trunk/pango/pangocairo-fc.h b/trunk/pango/pangocairo-fc.h
new file mode 100644
index 00000000..82a6b7ec
--- /dev/null
+++ b/trunk/pango/pangocairo-fc.h
@@ -0,0 +1,57 @@
+/* Pango
+ * pangocairo-fc.h: Private header file for Cairo/fontconfig combination
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOCAIRO_FC_H__
+#define __PANGOCAIRO_FC_H__
+
+#include <pango/pangofc-fontmap.h>
+#include <pango/pangocairo.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_CAIRO_FC_FONT_MAP (pango_cairo_fc_font_map_get_type ())
+#define PANGO_CAIRO_FC_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT_MAP, PangoCairoFcFontMap))
+#define PANGO_IS_CAIRO_FC_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_FC_FONT_MAP))
+
+typedef struct _PangoCairoFcFontMap PangoCairoFcFontMap;
+
+struct _PangoCairoFcFontMap
+{
+ PangoFcFontMap parent_instance;
+
+ double dpi;
+
+ FT_Library library;
+ PangoRenderer *renderer;
+};
+
+GType pango_cairo_fc_font_map_get_type (void) G_GNUC_CONST;
+
+PangoFcFont *_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ FcPattern *pattern);
+FT_Library _pango_cairo_fc_font_map_get_library (PangoCairoFcFontMap *fontmap);
+
+G_END_DECLS
+
+#endif /* __PANGOCAIRO_FC_H__ */
+
diff --git a/trunk/pango/pangocairo-fcfont.c b/trunk/pango/pangocairo-fcfont.c
new file mode 100644
index 00000000..b671ebea
--- /dev/null
+++ b/trunk/pango/pangocairo-fcfont.c
@@ -0,0 +1,256 @@
+/* Pango
+ * pangocairofc-font.c: Cairo font handling, fontconfig backend
+ *
+ * Copyright (C) 2000-2005 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <cairo-ft.h>
+
+#include "pango-fontmap.h"
+#include "pangocairo-private.h"
+#include "pangocairo-fc.h"
+#include "pangofc-private.h"
+#include "pango-impl-utils.h"
+
+#define PANGO_TYPE_CAIRO_FC_FONT (pango_cairo_fc_font_get_type ())
+#define PANGO_CAIRO_FC_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFont))
+#define PANGO_CAIRO_FC_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFontClass))
+#define PANGO_CAIRO_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_FC_FONT))
+#define PANGO_CAIRO_FC_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFontClass))
+
+typedef struct _PangoCairoFcFont PangoCairoFcFont;
+typedef struct _PangoCairoFcFontClass PangoCairoFcFontClass;
+
+struct _PangoCairoFcFont
+{
+ PangoFcFont font;
+ PangoCairoFontPrivate cf_priv;
+
+ PangoGravity gravity;
+};
+
+struct _PangoCairoFcFontClass
+{
+ PangoFcFontClass parent_class;
+};
+
+GType pango_cairo_fc_font_get_type (void);
+
+/********************************
+ * Method implementations *
+ ********************************/
+
+static cairo_font_face_t *
+pango_cairo_fc_font_create_font_face (PangoCairoFont *cfont)
+{
+ PangoFcFont *fcfont = (PangoFcFont *) (cfont);
+
+ return cairo_ft_font_face_create_for_pattern (fcfont->font_pattern);
+}
+
+static PangoFontMetrics *
+pango_cairo_fc_font_create_metrics_for_context (PangoCairoFont *cfont,
+ PangoContext *context)
+{
+ PangoFcFont *fcfont = (PangoFcFont *) (cfont);
+
+ return pango_fc_font_create_metrics_for_context (fcfont, context);
+}
+
+static void
+cairo_font_iface_init (PangoCairoFontIface *iface)
+{
+ iface->create_font_face = pango_cairo_fc_font_create_font_face;
+ iface->create_metrics_for_context = pango_cairo_fc_font_create_metrics_for_context;
+ iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoFcFont, cf_priv);
+}
+
+G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFont, pango_cairo_fc_font, PANGO_TYPE_FC_FONT,
+ { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) })
+
+static void
+pango_cairo_fc_font_finalize (GObject *object)
+{
+ PangoCairoFcFont *cffont = (PangoCairoFcFont *) (object);
+
+ _pango_cairo_font_private_finalize (&cffont->cf_priv);
+
+ G_OBJECT_CLASS (pango_cairo_fc_font_parent_class)->finalize (object);
+}
+
+/* we want get_glyph_extents extremely fast, so we use a small wrapper here
+ * to avoid having to lookup the interface data like we do for get_metrics
+ * in _pango_cairo_font_get_metrics(). */
+static void
+pango_cairo_fc_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
+
+ _pango_cairo_font_private_get_glyph_extents (&cffont->cf_priv,
+ glyph,
+ ink_rect,
+ logical_rect);
+}
+
+static FT_Face
+pango_cairo_fc_font_lock_face (PangoFcFont *font)
+{
+ PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&cffont->cf_priv);
+
+ if (G_UNLIKELY (!scaled_font))
+ return NULL;
+
+ return cairo_ft_scaled_font_lock_face (scaled_font);
+}
+
+static void
+pango_cairo_fc_font_unlock_face (PangoFcFont *font)
+{
+ PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&cffont->cf_priv);
+
+ if (G_UNLIKELY (!scaled_font))
+ return;
+
+ cairo_ft_scaled_font_unlock_face (scaled_font);
+}
+
+static void
+pango_cairo_fc_font_shutdown (PangoFcFont *fcfont)
+{
+ PangoCairoFcFont *cffont = (PangoCairoFcFont *) (fcfont);
+
+ _pango_cairo_font_private_finalize (&cffont->cf_priv);
+}
+
+static void
+pango_cairo_fc_font_class_init (PangoCairoFcFontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+ PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class);
+
+ object_class->finalize = pango_cairo_fc_font_finalize;
+
+ font_class->get_glyph_extents = pango_cairo_fc_font_get_glyph_extents;
+ font_class->get_metrics = _pango_cairo_font_get_metrics;
+
+ fc_font_class->lock_face = pango_cairo_fc_font_lock_face;
+ fc_font_class->unlock_face = pango_cairo_fc_font_unlock_face;
+ fc_font_class->shutdown = pango_cairo_fc_font_shutdown;
+}
+
+static void
+pango_cairo_fc_font_init (PangoCairoFcFont *cffont)
+{
+}
+
+/********************
+ * Private API *
+ ********************/
+
+static double
+get_font_size (PangoCairoFcFontMap *cffontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ FcPattern *pattern)
+{
+ double size;
+
+ /* The reason why we read FC_PIXEL_SIZE here rather than just
+ * using the specified size is to support operations like clamping
+ * a font to a minimal readable size in fonts.conf. This is pretty weird,
+ * since it could mean that changing the Cairo CTM doesn't change the
+ * font size, but it's just a more radical version of the non-linear
+ * font scaling we already have due to hinting and due to bitmap
+ * fonts being only available at a few sizes.
+ *
+ * If honoring FC_PIXEL_SIZE gets in the way of more useful features
+ * it should be removed since it only matters in the unusual case
+ * of people doing exotic stuff in fonts.conf.
+ */
+
+ if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
+ return size * PANGO_SCALE / pango_matrix_get_font_scale_factor (pango_context_get_matrix (context));
+
+ /* Just in case FC_PIXEL_SIZE got unset between pango_fc_make_pattern()
+ * and here.
+ */
+ if (pango_font_description_get_size_is_absolute (desc))
+ return pango_font_description_get_size (desc);
+ else
+ {
+ double dpi = pango_cairo_context_get_resolution (context);
+
+ if (dpi <= 0)
+ dpi = cffontmap->dpi;
+
+ return dpi * pango_font_description_get_size (desc) / 72.;
+ }
+}
+
+PangoFcFont *
+_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ FcPattern *pattern)
+{
+ PangoCairoFcFont *cffont;
+ cairo_matrix_t font_matrix;
+ FcMatrix *fc_matrix;
+ double size;
+
+ g_return_val_if_fail (PANGO_IS_CAIRO_FC_FONT_MAP (cffontmap), NULL);
+ g_return_val_if_fail (pattern != NULL, NULL);
+
+ cffont = g_object_new (PANGO_TYPE_CAIRO_FC_FONT,
+ "pattern", pattern,
+ NULL);
+
+ size = get_font_size (cffontmap, context, desc, pattern);
+
+ if (FcPatternGetMatrix (pattern,
+ FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
+ cairo_matrix_init (&font_matrix,
+ fc_matrix->xx,
+ - fc_matrix->yx,
+ - fc_matrix->xy,
+ fc_matrix->yy,
+ 0., 0.);
+ else
+ cairo_matrix_init_identity (&font_matrix);
+
+ cairo_matrix_scale (&font_matrix,
+ size / PANGO_SCALE, size / PANGO_SCALE);
+
+ _pango_cairo_font_private_initialize (&cffont->cf_priv,
+ (PangoCairoFont *) cffont,
+ context,
+ desc,
+ &font_matrix);
+
+ ((PangoFcFont *)(cffont))->is_hinted = _pango_cairo_font_private_is_metrics_hinted (&cffont->cf_priv);
+
+ return (PangoFcFont *) cffont;
+}
diff --git a/trunk/pango/pangocairo-fcfontmap.c b/trunk/pango/pangocairo-fcfontmap.c
new file mode 100644
index 00000000..967ca8f4
--- /dev/null
+++ b/trunk/pango/pangocairo-fcfontmap.c
@@ -0,0 +1,206 @@
+/* Pango
+ * pangocairo-fontmap.c: Cairo font handling, fontconfig backend
+ *
+ * Copyright (C) 2000-2005 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#include <cairo-ft.h>
+
+#include "pangofc-fontmap.h"
+#include "pangocairo.h"
+#include "pangocairo-private.h"
+#include "pangocairo-fc.h"
+
+typedef struct _PangoCairoFcFontMapClass PangoCairoFcFontMapClass;
+
+struct _PangoCairoFcFontMapClass
+{
+ PangoFcFontMapClass parent_class;
+};
+
+static void
+pango_cairo_fc_font_map_set_resolution (PangoCairoFontMap *cfontmap,
+ double dpi)
+{
+ PangoCairoFcFontMap *cffontmap = (PangoCairoFcFontMap *) (cfontmap);
+
+ cffontmap->dpi = dpi;
+
+ pango_fc_font_map_cache_clear ((PangoFcFontMap *) (cfontmap));
+}
+
+static double
+pango_cairo_fc_font_map_get_resolution_cairo (PangoCairoFontMap *cfontmap)
+{
+ PangoCairoFcFontMap *cffontmap = (PangoCairoFcFontMap *) (cfontmap);
+
+ return cffontmap->dpi;
+}
+
+static cairo_font_type_t
+pango_cairo_fc_font_map_get_font_type (PangoCairoFontMap *cfontmap)
+{
+ return CAIRO_FONT_TYPE_FT;
+}
+
+static void
+cairo_font_map_iface_init (PangoCairoFontMapIface *iface)
+{
+ iface->set_resolution = pango_cairo_fc_font_map_set_resolution;
+ iface->get_resolution = pango_cairo_fc_font_map_get_resolution_cairo;
+ iface->get_font_type = pango_cairo_fc_font_map_get_font_type;
+}
+
+G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFontMap, pango_cairo_fc_font_map, PANGO_TYPE_FC_FONT_MAP,
+ { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT_MAP, cairo_font_map_iface_init) })
+
+static void
+pango_cairo_fc_font_map_finalize (GObject *object)
+{
+ PangoCairoFcFontMap *cffontmap = (PangoCairoFcFontMap *) (object);
+
+ if (cffontmap->renderer)
+ g_object_unref (cffontmap->renderer);
+
+ FT_Done_FreeType (cffontmap->library);
+
+ G_OBJECT_CLASS (pango_cairo_fc_font_map_parent_class)->finalize (object);
+}
+
+static void
+pango_cairo_fc_font_map_context_substitute (PangoFcFontMap *fcfontmap,
+ PangoContext *context,
+ FcPattern *pattern)
+{
+ FcConfigSubstitute (NULL, pattern, FcMatchPattern);
+
+ if (context)
+ cairo_ft_font_options_substitute (_pango_cairo_context_get_merged_font_options (context),
+ pattern);
+
+ FcDefaultSubstitute (pattern);
+}
+
+static double
+pango_cairo_fc_font_map_get_resolution_fc (PangoFcFontMap *fcfontmap,
+ PangoContext *context)
+{
+ PangoCairoFcFontMap *cffontmap = (PangoCairoFcFontMap *) (fcfontmap);
+ double dpi;
+
+ if (context)
+ {
+ dpi = pango_cairo_context_get_resolution (context);
+
+ if (dpi <= 0)
+ dpi = cffontmap->dpi;
+ }
+ else
+ dpi = cffontmap->dpi;
+
+ return dpi;
+}
+
+static gconstpointer
+pango_cairo_fc_font_map_context_key_get (PangoFcFontMap *fcfontmap,
+ PangoContext *context)
+{
+ return _pango_cairo_context_get_merged_font_options (context);
+}
+
+static gpointer
+pango_cairo_fc_font_map_context_key_copy (PangoFcFontMap *fcfontmap,
+ gconstpointer key)
+{
+ return cairo_font_options_copy (key);
+}
+
+static void
+pango_cairo_fc_font_map_context_key_free (PangoFcFontMap *fcfontmap,
+ gpointer key)
+{
+ cairo_font_options_destroy (key);
+}
+
+
+static guint32
+pango_cairo_fc_font_map_context_key_hash (PangoFcFontMap *fcfontmap,
+ gconstpointer key)
+{
+ return (guint32)cairo_font_options_hash (key);
+}
+
+static gboolean
+pango_cairo_fc_font_map_context_key_equal (PangoFcFontMap *fcfontmap,
+ gconstpointer key_a,
+ gconstpointer key_b)
+{
+ return cairo_font_options_equal (key_a, key_b);
+}
+
+static PangoFcFont *
+pango_cairo_fc_font_map_create_font (PangoFcFontMap *fcfontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ FcPattern *pattern)
+{
+ return _pango_cairo_fc_font_new ((PangoCairoFcFontMap *) (fcfontmap),
+ context, desc, pattern);
+}
+
+static void
+pango_cairo_fc_font_map_class_init (PangoCairoFcFontMapClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class);
+
+ gobject_class->finalize = pango_cairo_fc_font_map_finalize;
+
+ fcfontmap_class->context_substitute = pango_cairo_fc_font_map_context_substitute;
+ fcfontmap_class->get_resolution = pango_cairo_fc_font_map_get_resolution_fc;
+
+ fcfontmap_class->context_key_get = pango_cairo_fc_font_map_context_key_get;
+ fcfontmap_class->context_key_copy = pango_cairo_fc_font_map_context_key_copy;
+ fcfontmap_class->context_key_free = pango_cairo_fc_font_map_context_key_free;
+ fcfontmap_class->context_key_hash = pango_cairo_fc_font_map_context_key_hash;
+ fcfontmap_class->context_key_equal = pango_cairo_fc_font_map_context_key_equal;
+
+ fcfontmap_class->create_font = pango_cairo_fc_font_map_create_font;
+}
+
+static void
+pango_cairo_fc_font_map_init (PangoCairoFcFontMap *cffontmap)
+{
+ FT_Error error;
+
+ cffontmap->library = NULL;
+ error = FT_Init_FreeType (&cffontmap->library);
+ if (error != FT_Err_Ok)
+ g_critical ("pango_cairo_font_map_init: Could not initialize freetype");
+
+ cffontmap->dpi = 96.0;
+}
+
+FT_Library
+_pango_cairo_fc_font_map_get_library (PangoCairoFcFontMap *fontmap)
+{
+ g_return_val_if_fail (PANGO_IS_CAIRO_FC_FONT_MAP (fontmap), NULL);
+
+ return fontmap->library;
+}
+
diff --git a/trunk/pango/pangocairo-font.c b/trunk/pango/pangocairo-font.c
new file mode 100644
index 00000000..3ca4073e
--- /dev/null
+++ b/trunk/pango/pangocairo-font.c
@@ -0,0 +1,744 @@
+/* Pango
+ * pangocairo-font.c: Cairo font handling
+ *
+ * Copyright (C) 2000-2005 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <math.h>
+
+#include "pangocairo.h"
+#include "pangocairo-private.h"
+#include "pango-impl-utils.h"
+
+PangoCairoWarningHistory _pango_cairo_warning_history = { FALSE };
+
+#define PANGO_CAIRO_FONT_PRIVATE(font) \
+ ((PangoCairoFontPrivate *) \
+ (font == NULL ? NULL : \
+ G_STRUCT_MEMBER_P (font, \
+ PANGO_CAIRO_FONT_GET_IFACE(PANGO_CAIRO_FONT(font))->cf_priv_offset)))
+
+GType
+pango_cairo_font_get_type (void)
+{
+ static GType cairo_font_type = 0;
+
+ if (! cairo_font_type)
+ {
+ const GTypeInfo cairo_font_info =
+ {
+ sizeof (PangoCairoFontIface), /* class_size */
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0,
+ NULL,
+ NULL
+ };
+
+ cairo_font_type =
+ g_type_register_static (G_TYPE_INTERFACE, I_("PangoCairoFont"),
+ &cairo_font_info, 0);
+
+ g_type_interface_add_prerequisite (cairo_font_type, PANGO_TYPE_FONT);
+ }
+
+ return cairo_font_type;
+}
+
+static PangoCairoFontPrivateScaledFontData *
+_pango_cairo_font_private_scaled_font_data_create (void)
+{
+ return g_slice_new (PangoCairoFontPrivateScaledFontData);
+}
+
+static void
+_pango_cairo_font_private_scaled_font_data_destroy (PangoCairoFontPrivateScaledFontData *data)
+{
+ if (data)
+ {
+ cairo_font_options_destroy (data->options);
+ g_slice_free (PangoCairoFontPrivateScaledFontData, data);
+ }
+}
+
+cairo_scaled_font_t *
+_pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv)
+{
+ cairo_font_face_t *font_face;
+
+ if (G_LIKELY (cf_priv->scaled_font))
+ return cf_priv->scaled_font;
+
+ /* need to create it */
+
+ if (G_UNLIKELY (cf_priv->data == NULL))
+ {
+ /* we have tried to create and failed before */
+ return NULL;
+ }
+
+ font_face = (* PANGO_CAIRO_FONT_GET_IFACE (cf_priv->cfont)->create_font_face) (cf_priv->cfont);
+ if (G_UNLIKELY (font_face == NULL))
+ goto done;
+
+ cf_priv->scaled_font = cairo_scaled_font_create (font_face,
+ &cf_priv->data->font_matrix,
+ &cf_priv->data->ctm,
+ cf_priv->data->options);
+
+ cairo_font_face_destroy (font_face);
+
+done:
+ _pango_cairo_font_private_scaled_font_data_destroy (cf_priv->data);
+ cf_priv->data = NULL;
+
+ if (G_UNLIKELY (cf_priv->scaled_font == NULL || cairo_scaled_font_status (cf_priv->scaled_font) != CAIRO_STATUS_SUCCESS))
+ {
+ PangoFont *font = PANGO_FONT (cf_priv->cfont);
+ static GQuark warned_quark = 0;
+ if (!warned_quark)
+ warned_quark = g_quark_from_static_string ("pangocairo-scaledfont-warned");
+
+ if (!g_object_get_qdata (G_OBJECT (font), warned_quark))
+ {
+ PangoFontDescription *desc;
+ char *s;
+
+ desc = pango_font_describe (font);
+ s = pango_font_description_to_string (desc);
+ pango_font_description_free (desc);
+
+ g_warning ("failed to create cairo %s, expect ugly output. the offending font is '%s'",
+ font_face ? "scaled font" : "font face",
+ s);
+
+ g_free (s);
+
+ g_object_set_qdata_full (G_OBJECT (font), warned_quark,
+ GINT_TO_POINTER (1), NULL);
+ }
+ }
+
+ return cf_priv->scaled_font;
+}
+
+/**
+ * pango_cairo_font_get_scaled_font:
+ * @font: a #PangoFont from a #PangoCairoFontMap
+ *
+ * Gets the #cairo_scaled_font_t used by @font.
+ * The scaled font can be referenced and kept using
+ * cairo_scaled_font_reference().
+ *
+ * Return value: the #cairo_scaled_font_t used by @font
+ *
+ * Since: 1.18
+ **/
+cairo_scaled_font_t *
+pango_cairo_font_get_scaled_font (PangoCairoFont *cfont)
+{
+ PangoCairoFontPrivate *cf_priv;
+
+ if (G_UNLIKELY (!PANGO_IS_CAIRO_FONT (cfont)))
+ {
+ if (!_pango_cairo_warning_history.font_get_scaled_font)
+ {
+ _pango_cairo_warning_history.font_get_scaled_font = TRUE;
+ g_warning ("pango_cairo_font_get_scaled_font called with bad font, expect ugly output");
+ }
+ return NULL;
+ }
+
+ cf_priv = PANGO_CAIRO_FONT_PRIVATE (cfont);
+
+ return _pango_cairo_font_private_get_scaled_font (cf_priv);
+}
+
+/**
+ * _pango_cairo_font_install:
+ * @font: a #PangoCairoFont
+ * @cr: a #cairo_t
+ *
+ * Makes @font the current font for rendering in the specified
+ * Cairo context.
+ *
+ * Return value: %TRUE if font was installed successfully, %FALSE otherwise.
+ **/
+gboolean
+_pango_cairo_font_install (PangoFont *font,
+ cairo_t *cr)
+{
+ cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font (font);
+
+ if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
+ return FALSE;
+
+ cairo_set_scaled_font (cr, scaled_font);
+
+ return TRUE;
+}
+
+
+typedef struct _PangoCairoFontMetricsInfo
+{
+ const char *sample_str;
+ PangoFontMetrics *metrics;
+} PangoCairoFontMetricsInfo;
+
+PangoFontMetrics *
+_pango_cairo_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoCairoFont *cfont = (PangoCairoFont *) font;
+ PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (font);
+ PangoCairoFontMetricsInfo *info = NULL; /* Quiet gcc */
+ GSList *tmp_list;
+
+ const char *sample_str = pango_language_get_sample_string (language);
+
+ tmp_list = cf_priv->metrics_by_lang;
+ while (tmp_list)
+ {
+ info = tmp_list->data;
+
+ if (info->sample_str == sample_str) /* We _don't_ need strcmp */
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list)
+ {
+ PangoContext *context;
+ cairo_font_options_t *font_options;
+ int height, shift;
+
+ info = g_slice_new0 (PangoCairoFontMetricsInfo);
+
+ cf_priv->metrics_by_lang = g_slist_prepend (cf_priv->metrics_by_lang, info);
+
+ info->sample_str = sample_str;
+
+ context = pango_cairo_font_map_create_context ((PangoCairoFontMap *) pango_font_get_font_map (font));
+ pango_context_set_language (context, language);
+ font_options = cairo_font_options_create ();
+ cairo_scaled_font_get_font_options (_pango_cairo_font_private_get_scaled_font (cf_priv), font_options);
+ pango_cairo_context_set_font_options (context, font_options);
+ cairo_font_options_destroy (font_options);
+
+ info->metrics = (* PANGO_CAIRO_FONT_GET_IFACE (font)->create_metrics_for_context) (cfont, context);
+
+ /* We may actually reuse ascent/descent we got from cairo here. that's
+ * in cf_priv->font_extents.
+ */
+ height = info->metrics->ascent + info->metrics->descent;
+ switch (cf_priv->gravity)
+ {
+ default:
+ case PANGO_GRAVITY_AUTO:
+ case PANGO_GRAVITY_SOUTH:
+ break;
+ case PANGO_GRAVITY_NORTH:
+ info->metrics->ascent = info->metrics->descent;
+ break;
+ case PANGO_GRAVITY_EAST:
+ case PANGO_GRAVITY_WEST:
+ {
+ int ascent = height / 2;
+ if (cf_priv->is_hinted)
+ ascent = PANGO_UNITS_ROUND (ascent);
+ info->metrics->ascent = ascent;
+ }
+ }
+ shift = (height - info->metrics->ascent) - info->metrics->descent;
+ info->metrics->descent += shift;
+ info->metrics->underline_position -= shift;
+ info->metrics->strikethrough_position -= shift;
+ info->metrics->ascent = height - info->metrics->descent;
+
+ g_object_unref (context);
+ }
+
+ return pango_font_metrics_ref (info->metrics);
+}
+
+static PangoCairoFontHexBoxInfo *
+_pango_cairo_font_private_get_hex_box_info (PangoCairoFontPrivate *cf_priv)
+{
+ static const char hexdigits[] = "0123456789ABCDEF";
+ char c[2] = {0, 0};
+ PangoFont *mini_font;
+ PangoCairoFontHexBoxInfo *hbi;
+
+ /* for metrics hinting */
+ double scale_x = 1., scale_x_inv = 1., scale_y = 1., scale_y_inv = 1.;
+ gboolean is_hinted;
+
+ int i;
+ int rows;
+ double pad;
+ double width = 0;
+ double height = 0;
+ cairo_font_options_t *font_options;
+ cairo_font_extents_t font_extents;
+ double size, mini_size;
+ PangoFontDescription *desc;
+ cairo_scaled_font_t *scaled_font, *scaled_mini_font;
+ PangoMatrix pango_ctm;
+ cairo_matrix_t cairo_ctm;
+ PangoGravity gravity;
+
+ if (!cf_priv)
+ return NULL;
+
+ if (cf_priv->hbi)
+ return cf_priv->hbi;
+
+ scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv);
+ if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
+ return NULL;
+
+ is_hinted = cf_priv->is_hinted;
+
+ font_options = cairo_font_options_create ();
+ desc = pango_font_describe_with_absolute_size ((PangoFont *)cf_priv->cfont);
+ size = pango_font_description_get_size (desc) / (1.*PANGO_SCALE);
+ gravity = pango_font_description_get_gravity (desc);
+
+ cairo_scaled_font_get_ctm (scaled_font, &cairo_ctm);
+ /* I started adding support for vertical hexboxes here, but it's too much
+ * work. Easier to do with cairo user fonts and vertical writing mode
+ * support in cairo.
+ */
+ /*cairo_matrix_rotate (&cairo_ctm, pango_gravity_to_rotation (gravity));*/
+ pango_ctm.xx = cairo_ctm.xx;
+ pango_ctm.yx = cairo_ctm.yx;
+ pango_ctm.xy = cairo_ctm.xy;
+ pango_ctm.yy = cairo_ctm.yy;
+ pango_ctm.x0 = cairo_ctm.x0;
+ pango_ctm.y0 = cairo_ctm.y0;
+
+ if (is_hinted)
+ {
+ /* prepare for some hinting */
+ double x, y;
+
+ x = 1.; y = 0.;
+ cairo_matrix_transform_distance (&cairo_ctm, &x, &y);
+ scale_x = sqrt (x*x + y*y);
+ scale_x_inv = 1 / scale_x;
+
+ x = 0.; y = 1.;
+ cairo_matrix_transform_distance (&cairo_ctm, &x, &y);
+ scale_y = sqrt (x*x + y*y);
+ scale_y_inv = 1 / scale_y;
+ }
+
+/* we hint to the nearest device units */
+#define HINT(value, scale, scale_inv) (ceil ((value-1e-5) * scale) * scale_inv)
+#define HINT_X(value) HINT ((value), scale_x, scale_x_inv)
+#define HINT_Y(value) HINT ((value), scale_y, scale_y_inv)
+
+ /* create mini_font description */
+ {
+ PangoContext *context;
+ PangoFontMap *fontmap;
+
+ fontmap = pango_font_get_font_map ((PangoFont *)cf_priv->cfont);
+
+ /* we inherit most font properties for the mini font. just
+ * change family and size. means, you get bold hex digits
+ * in the hexbox for a bold font.
+ */
+
+ /* We should rotate the box, not glyphs */
+ pango_font_description_unset_fields (desc, PANGO_FONT_MASK_GRAVITY);
+
+ pango_font_description_set_family_static (desc, "monospace");
+
+ rows = 2;
+ mini_size = size / 2.4;
+ if (is_hinted)
+ {
+ mini_size = HINT_Y (mini_size);
+
+ if (mini_size < 5.0)
+ {
+ rows = 1;
+ mini_size = MIN (MAX (size - 1, 0), 5.0);
+ }
+ }
+
+ pango_font_description_set_absolute_size (desc, pango_units_from_double (mini_size));
+
+ /* load mini_font */
+
+ context = pango_cairo_font_map_create_context ((PangoCairoFontMap *) (fontmap));
+
+ pango_context_set_matrix (context, &pango_ctm);
+ pango_context_set_language (context, pango_script_get_sample_language (PANGO_SCRIPT_LATIN));
+ pango_cairo_context_set_font_options (context, font_options);
+ mini_font = pango_font_map_load_font (fontmap, context, desc);
+
+ g_object_unref (context);
+ }
+
+ cairo_font_options_destroy (font_options);
+
+
+ scaled_mini_font = pango_cairo_font_get_scaled_font (mini_font);
+
+ for (i = 0 ; i < 16 ; i++)
+ {
+ cairo_text_extents_t extents;
+
+ c[0] = hexdigits[i];
+ cairo_scaled_font_text_extents (scaled_mini_font, c, &extents);
+ width = MAX (width, extents.width);
+ height = MAX (height, extents.height);
+ }
+
+ cairo_scaled_font_extents (scaled_font, &font_extents);
+ if (font_extents.ascent + font_extents.descent <= 0)
+ {
+ font_extents.ascent = PANGO_UNKNOWN_GLYPH_HEIGHT;
+ font_extents.descent = 0;
+ }
+
+ pad = (font_extents.ascent + font_extents.descent) / 43;
+ pad = MIN (pad, mini_size);
+
+ hbi = g_slice_new (PangoCairoFontHexBoxInfo);
+ hbi->font = (PangoCairoFont *) mini_font;
+ hbi->rows = rows;
+
+ hbi->digit_width = width;
+ hbi->digit_height = height;
+
+ hbi->pad_x = pad;
+ hbi->pad_y = pad;
+
+ if (is_hinted)
+ {
+ hbi->digit_width = HINT_X (hbi->digit_width);
+ hbi->digit_height = HINT_Y (hbi->digit_height);
+ hbi->pad_x = HINT_X (hbi->pad_x);
+ hbi->pad_y = HINT_Y (hbi->pad_y);
+ }
+
+ hbi->line_width = MIN (hbi->pad_x, hbi->pad_y);
+
+ hbi->box_height = 3 * hbi->pad_y + rows * (hbi->pad_y + hbi->digit_height);
+
+ if (rows == 1 || hbi->box_height <= font_extents.ascent)
+ {
+ hbi->box_descent = 2 * hbi->pad_y;
+ }
+ else if (hbi->box_height <= font_extents.ascent + font_extents.descent - 2 * hbi->pad_y)
+ {
+ hbi->box_descent = 2 * hbi->pad_y + hbi->box_height - font_extents.ascent;
+ }
+ else
+ {
+ hbi->box_descent = font_extents.descent * hbi->box_height /
+ (font_extents.ascent + font_extents.descent);
+ }
+ if (is_hinted)
+ {
+ hbi->box_descent = HINT_Y (hbi->box_descent);
+ }
+
+ return hbi;
+}
+
+static void
+_pango_cairo_font_hex_box_info_destroy (PangoCairoFontHexBoxInfo *hbi)
+{
+ if (hbi)
+ {
+ g_object_unref (hbi->font);
+ g_slice_free (PangoCairoFontHexBoxInfo, hbi);
+ }
+}
+
+PangoCairoFontHexBoxInfo *
+_pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
+{
+ PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (cfont);
+
+ return _pango_cairo_font_private_get_hex_box_info (cf_priv);
+}
+
+void
+_pango_cairo_font_private_initialize (PangoCairoFontPrivate *cf_priv,
+ PangoCairoFont *cfont,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ const cairo_matrix_t *font_matrix)
+{
+ const cairo_font_options_t *font_options;
+ cairo_matrix_t gravity_matrix;
+ const PangoMatrix *pango_ctm;
+
+ cf_priv->cfont = cfont;
+ cf_priv->gravity = pango_font_description_get_gravity (desc);
+
+ cf_priv->data = _pango_cairo_font_private_scaled_font_data_create ();
+
+ /* first apply gravity rotation, then font_matrix, such that
+ * vertical italic text comes out "correct". we don't do anything
+ * like baseline adjustment etc though. should be specially
+ * handled when we support italic correction. */
+ cairo_matrix_init_rotate(&gravity_matrix,
+ pango_gravity_to_rotation (cf_priv->gravity));
+ cairo_matrix_multiply (&cf_priv->data->font_matrix,
+ font_matrix,
+ &gravity_matrix);
+
+ pango_ctm = pango_context_get_matrix (context);
+ if (pango_ctm)
+ cairo_matrix_init (&cf_priv->data->ctm,
+ pango_ctm->xx,
+ pango_ctm->yx,
+ pango_ctm->xy,
+ pango_ctm->yy,
+ 0., 0.);
+ else
+ cairo_matrix_init_identity (&cf_priv->data->ctm);
+
+ font_options = _pango_cairo_context_get_merged_font_options (context);
+ cf_priv->data->options = cairo_font_options_copy (font_options);
+ cf_priv->is_hinted = cairo_font_options_get_hint_metrics (font_options) != CAIRO_HINT_METRICS_OFF;
+
+ cf_priv->scaled_font = NULL;
+ cf_priv->hbi = NULL;
+ cf_priv->glyph_extents_cache = NULL;
+ cf_priv->metrics_by_lang = NULL;
+}
+
+static void
+free_metrics_info (PangoCairoFontMetricsInfo *info)
+{
+ pango_font_metrics_unref (info->metrics);
+ g_slice_free (PangoCairoFontMetricsInfo, info);
+}
+
+void
+_pango_cairo_font_private_finalize (PangoCairoFontPrivate *cf_priv)
+{
+ _pango_cairo_font_private_scaled_font_data_destroy (cf_priv->data);
+
+ if (cf_priv->scaled_font)
+ cairo_scaled_font_destroy (cf_priv->scaled_font);
+
+ _pango_cairo_font_hex_box_info_destroy (cf_priv->hbi);
+
+ if (cf_priv->glyph_extents_cache)
+ g_free (cf_priv->glyph_extents_cache);
+
+ g_slist_foreach (cf_priv->metrics_by_lang, (GFunc)free_metrics_info, NULL);
+ g_slist_free (cf_priv->metrics_by_lang);
+}
+
+gboolean
+_pango_cairo_font_private_is_metrics_hinted (PangoCairoFontPrivate *cf_priv)
+{
+ return cf_priv->is_hinted;
+}
+
+static void
+_pango_cairo_font_private_get_glyph_extents_missing (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoCairoFontHexBoxInfo *hbi;
+ gint rows, cols;
+
+ hbi = _pango_cairo_font_private_get_hex_box_info (cf_priv);
+ if (!hbi)
+ {
+ pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect);
+ return;
+ }
+
+ rows = hbi->rows;
+ cols = ((glyph & ~PANGO_GLYPH_UNKNOWN_FLAG) > 0xffff ? 6 : 4) / rows;
+
+ if (ink_rect)
+ {
+ ink_rect->x = PANGO_SCALE * hbi->pad_x;
+ ink_rect->y = PANGO_SCALE * (hbi->box_descent - hbi->box_height);
+ ink_rect->width = PANGO_SCALE * (3 * hbi->pad_x + cols * (hbi->digit_width + hbi->pad_x));
+ ink_rect->height = PANGO_SCALE * hbi->box_height;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = PANGO_SCALE * (hbi->box_descent - (hbi->box_height + hbi->pad_y));
+ logical_rect->width = PANGO_SCALE * (5 * hbi->pad_x + cols * (hbi->digit_width + hbi->pad_x));
+ logical_rect->height = PANGO_SCALE * (hbi->box_height + 2 * hbi->pad_y);
+ }
+}
+
+#define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */
+#define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1)
+/* An entry in the fixed-size cache for the glyph->extents mapping.
+ * The cache is indexed by the lower N bits of the glyph (see
+ * GLYPH_CACHE_NUM_ENTRIES). For scripts with few glyphs,
+ * this should provide pretty much instant lookups.
+ */
+struct _PangoCairoFontGlyphExtentsCacheEntry
+{
+ PangoGlyph glyph;
+ int width;
+ PangoRectangle ink_rect;
+};
+
+static gboolean
+_pango_cairo_font_private_glyph_extents_cache_init (PangoCairoFontPrivate *cf_priv)
+{
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv);
+ cairo_font_extents_t font_extents;
+
+ if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
+ return FALSE;
+
+ cairo_scaled_font_extents (scaled_font, &font_extents);
+
+ cf_priv->font_extents.x = 0;
+ cf_priv->font_extents.width = 0;
+ cf_priv->font_extents.height = pango_units_from_double (font_extents.ascent + font_extents.descent);
+ switch (cf_priv->gravity)
+ {
+ default:
+ case PANGO_GRAVITY_AUTO:
+ case PANGO_GRAVITY_SOUTH:
+ cf_priv->font_extents.y = - pango_units_from_double (font_extents.ascent);
+ break;
+ case PANGO_GRAVITY_NORTH:
+ cf_priv->font_extents.y = - pango_units_from_double (font_extents.descent);
+ break;
+ case PANGO_GRAVITY_EAST:
+ case PANGO_GRAVITY_WEST:
+ {
+ int ascent = pango_units_from_double (font_extents.ascent + font_extents.descent) / 2;
+ if (cf_priv->is_hinted)
+ ascent = PANGO_UNITS_ROUND (ascent);
+ cf_priv->font_extents.y = - ascent;
+ }
+ }
+
+ cf_priv->glyph_extents_cache = g_new0 (PangoCairoFontGlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES);
+ /* Make sure all cache entries are invalid initially */
+ cf_priv->glyph_extents_cache[0].glyph = 1; /* glyph 1 cannot happen in bucket 0 */
+
+ return TRUE;
+}
+
+/* Fills in the glyph extents cache entry
+ */
+static void
+compute_glyph_extents (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph,
+ PangoCairoFontGlyphExtentsCacheEntry *entry)
+{
+ cairo_text_extents_t extents;
+ cairo_glyph_t cairo_glyph;
+
+ cairo_glyph.index = glyph;
+ cairo_glyph.x = 0;
+ cairo_glyph.y = 0;
+
+ cairo_scaled_font_glyph_extents (_pango_cairo_font_private_get_scaled_font (cf_priv),
+ &cairo_glyph, 1, &extents);
+
+ entry->glyph = glyph;
+ entry->width = pango_units_from_double (extents.x_advance);
+ entry->ink_rect.x = pango_units_from_double (extents.x_bearing);
+ entry->ink_rect.y = pango_units_from_double (extents.y_bearing);
+ entry->ink_rect.width = pango_units_from_double (extents.width);
+ entry->ink_rect.height = pango_units_from_double (extents.height);
+}
+
+static PangoCairoFontGlyphExtentsCacheEntry *
+_pango_cairo_font_private_get_glyph_extents_cache_entry (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph)
+{
+ PangoCairoFontGlyphExtentsCacheEntry *entry;
+ guint idx;
+
+ idx = glyph & GLYPH_CACHE_MASK;
+ entry = cf_priv->glyph_extents_cache + idx;
+
+ if (entry->glyph != glyph)
+ {
+ compute_glyph_extents (cf_priv, glyph, entry);
+ }
+
+ return entry;
+}
+
+void
+_pango_cairo_font_private_get_glyph_extents (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoCairoFontGlyphExtentsCacheEntry *entry;
+
+ if (!cf_priv ||
+ (cf_priv->glyph_extents_cache == NULL &&
+ !_pango_cairo_font_private_glyph_extents_cache_init (cf_priv)))
+ {
+ /* Get generic unknown-glyph extents. */
+ pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect);
+ return;
+ }
+
+ if (glyph == PANGO_GLYPH_EMPTY)
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->y = ink_rect->width = ink_rect->height = 0;
+ if (logical_rect)
+ *logical_rect = cf_priv->font_extents;
+ return;
+ }
+ else if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ _pango_cairo_font_private_get_glyph_extents_missing(cf_priv, glyph, ink_rect, logical_rect);
+ return;
+ }
+
+ entry = _pango_cairo_font_private_get_glyph_extents_cache_entry (cf_priv, glyph);
+
+ if (ink_rect)
+ *ink_rect = entry->ink_rect;
+ if (logical_rect)
+ {
+ *logical_rect = cf_priv->font_extents;
+ logical_rect->width = entry->width;
+ }
+}
diff --git a/trunk/pango/pangocairo-fontmap.c b/trunk/pango/pangocairo-fontmap.c
new file mode 100644
index 00000000..d0fe716f
--- /dev/null
+++ b/trunk/pango/pangocairo-fontmap.c
@@ -0,0 +1,249 @@
+/* Pango
+ * pangocairo-fontmap.c: Cairo font handling
+ *
+ * Copyright (C) 2000-2005 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pangocairo.h"
+#include "pangocairo-private.h"
+#include "pango-impl-utils.h"
+
+#if defined (HAVE_CAIRO_ATSUI)
+# include "pangocairo-atsui.h"
+#endif
+#if defined (HAVE_CAIRO_WIN32)
+# include "pangocairo-win32.h"
+#endif
+#if defined (HAVE_CAIRO_FREETYPE)
+# include "pangocairo-fc.h"
+#endif
+
+GType
+pango_cairo_font_map_get_type (void)
+{
+ static GType cairo_font_map_type = 0;
+
+ if (! cairo_font_map_type)
+ {
+ const GTypeInfo cairo_font_map_info =
+ {
+ sizeof (PangoCairoFontMapIface), /* class_size */
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0,
+ NULL,
+ NULL
+ };
+
+ cairo_font_map_type =
+ g_type_register_static (G_TYPE_INTERFACE, I_("PangoCairoFontMap"),
+ &cairo_font_map_info, 0);
+
+ g_type_interface_add_prerequisite (cairo_font_map_type, PANGO_TYPE_FONT_MAP);
+ }
+
+ return cairo_font_map_type;
+}
+
+/**
+ * pango_cairo_font_map_new:
+ *
+ * Creates a new #PangoCairoFontMap object; a fontmap is used
+ * to cache information about available fonts, and holds
+ * certain global parameters such as the resolution.
+ * In most cases, you can use pango_cairo_font_map_get_default()
+ * instead.
+ *
+ * Note that the type of the returned object will depend
+ * on the particular font backend Cairo was compiled to use;
+ * You generally should only use the #PangoFontMap and
+ * #PangoCairoFontMap interfaces on the returned object.
+ *
+ * Return value: the newly allocated #PangoFontMap, which should
+ * be freed with g_object_unref().
+ *
+ * Since: 1.10
+ **/
+PangoFontMap *
+pango_cairo_font_map_new (void)
+{
+ /* Make sure that the type system is initialized */
+ g_type_init ();
+
+#if defined(HAVE_CAIRO_ATSUI)
+ return g_object_new (PANGO_TYPE_CAIRO_ATSUI_FONT_MAP, NULL);
+#elif defined(HAVE_CAIRO_WIN32)
+ return g_object_new (PANGO_TYPE_CAIRO_WIN32_FONT_MAP, NULL);
+#elif defined(HAVE_CAIRO_FREETYPE)
+ return g_object_new (PANGO_TYPE_CAIRO_FC_FONT_MAP, NULL);
+#else
+ g_assert_not_reached ();
+ return NULL;
+#endif
+}
+
+/**
+ * pango_cairo_font_map_new_for_font_type:
+ * @fonttype: desired #cairo_font_type_t
+ *
+ * Creates a new #PangoCairoFontMap object of the type suitable
+ * to be used with cairo font backend of type @fonttype.
+ *
+ * In most cases one should simply use @pango_cairo_font_map_new(),
+ * or in fact in most of those cases, just use
+ * @pango_cairo_font_map_get_default().
+ *
+ * Return value: the newly allocated #PangoFontMap of suitable type
+ * which should be freed with g_object_unref(),
+ * or %NULL if the requested cairo font backend is
+ * not supported.
+ *
+ * Since: 1.18
+ **/
+PangoFontMap *
+pango_cairo_font_map_new_for_font_type (cairo_font_type_t fonttype)
+{
+ /* Make sure that the type system is initialized */
+ g_type_init ();
+
+ switch (fonttype)
+ {
+#if defined(HAVE_CAIRO_ATSUI)
+ case CAIRO_FONT_TYPE_ATSUI:
+ return g_object_new (PANGO_TYPE_CAIRO_ATSUI_FONT_MAP, NULL);
+#endif
+#if defined(HAVE_CAIRO_WIN32)
+ case CAIRO_FONT_TYPE_WIN32:
+ return g_object_new (PANGO_TYPE_CAIRO_WIN32_FONT_MAP, NULL);
+#endif
+#if defined(HAVE_CAIRO_FREETYPE)
+ case CAIRO_FONT_TYPE_FT:
+ return g_object_new (PANGO_TYPE_CAIRO_FC_FONT_MAP, NULL);
+#endif
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_cairo_font_map_get_default:
+ *
+ * Gets a default font map to use with Cairo.
+ *
+ * Return value: the default Cairo fontmap for #Pango. This
+ * object is owned by Pango and must not be freed.
+ *
+ * Since: 1.10
+ **/
+PangoFontMap *
+pango_cairo_font_map_get_default (void)
+{
+ static PangoFontMap *default_font_map = NULL;
+
+ if (G_UNLIKELY (!default_font_map))
+ default_font_map = pango_cairo_font_map_new ();
+
+ return default_font_map;
+}
+
+/**
+ * pango_cairo_font_map_set_resolution:
+ * @fontmap: a #PangoCairoFontMap
+ * @dpi: the resolution in "dots per inch". (Physical inches aren't actually
+ * involved; the terminology is conventional.)
+ *
+ * Sets the resolution for the fontmap. This is a scale factor between
+ * points specified in a #PangoFontDescription and Cairo units. The
+ * default value is 96, meaning that a 10 point font will be 13
+ * units high. (10 * 96. / 72. = 13.3).
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_font_map_set_resolution (PangoCairoFontMap *fontmap,
+ double dpi)
+{
+ g_return_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap));
+
+ (* PANGO_CAIRO_FONT_MAP_GET_IFACE (fontmap)->set_resolution) (fontmap, dpi);
+}
+
+/**
+ * pango_cairo_font_map_get_resolution:
+ * @fontmap: a #PangoCairoFontMap
+ *
+ * Gets the resolution for the fontmap. See pango_cairo_font_map_set_resolution()
+ *
+ * Return value: the resolution in "dots per inch"
+ *
+ * Since: 1.10
+ **/
+double
+pango_cairo_font_map_get_resolution (PangoCairoFontMap *fontmap)
+{
+ g_return_val_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap), 96.);
+
+ return (* PANGO_CAIRO_FONT_MAP_GET_IFACE (fontmap)->get_resolution) (fontmap);
+}
+
+/**
+ * pango_cairo_font_map_create_context:
+ * @fontmap: a #PangoCairoFontMap
+ *
+ * Create a #PangoContext for the given fontmap.
+ *
+ * Return value: the newly created context; free with g_object_unref().
+ *
+ * Since: 1.10
+ **/
+PangoContext *
+pango_cairo_font_map_create_context (PangoCairoFontMap *fontmap)
+{
+ PangoContext *context;
+
+ g_return_val_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap), NULL);
+
+ context = pango_context_new ();
+ pango_context_set_font_map (context, PANGO_FONT_MAP (fontmap));
+
+ return context;
+}
+
+/**
+ * pango_cairo_font_map_get_font_type:
+ * @fontmap: a #PangoCairoFontMap
+ *
+ * Gets the type of Cairo font backend that @fontmap uses.
+ *
+ * Return value: the #cairo_font_type_t cairo font backend type
+ *
+ * Since: 1.18
+ **/
+cairo_font_type_t
+pango_cairo_font_map_get_font_type (PangoCairoFontMap *fontmap)
+{
+ g_return_val_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap), CAIRO_FONT_TYPE_TOY);
+
+ return (* PANGO_CAIRO_FONT_MAP_GET_IFACE (fontmap)->get_font_type) (fontmap);
+}
diff --git a/trunk/pango/pangocairo-private.h b/trunk/pango/pangocairo-private.h
new file mode 100644
index 00000000..05dbb5a2
--- /dev/null
+++ b/trunk/pango/pangocairo-private.h
@@ -0,0 +1,145 @@
+/* Pango
+ * pangocairo-private.h: private symbols for the Cairo backend
+ *
+ * Copyright (C) 2000,2004 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOCAIRO_PRIVATE_H__
+#define __PANGOCAIRO_PRIVATE_H__
+
+#include <pango/pangocairo.h>
+#include <pango/pango-renderer.h>
+
+G_BEGIN_DECLS
+
+
+#define PANGO_CAIRO_FONT_MAP_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PANGO_TYPE_CAIRO_FONT_MAP, PangoCairoFontMapIface))
+
+typedef struct _PangoCairoFontMapIface PangoCairoFontMapIface;
+
+struct _PangoCairoFontMapIface
+{
+ GTypeInterface g_iface;
+
+ void (*set_resolution) (PangoCairoFontMap *fontmap,
+ double dpi);
+ double (*get_resolution) (PangoCairoFontMap *fontmap);
+
+ cairo_font_type_t (*get_font_type) (PangoCairoFontMap *fontmap);
+};
+
+
+#define PANGO_CAIRO_FONT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PANGO_TYPE_CAIRO_FONT, PangoCairoFontIface))
+
+typedef struct _PangoCairoFontIface PangoCairoFontIface;
+typedef struct _PangoCairoFontPrivate PangoCairoFontPrivate;
+typedef struct _PangoCairoFontHexBoxInfo PangoCairoFontHexBoxInfo;
+typedef struct _PangoCairoFontPrivateScaledFontData PangoCairoFontPrivateScaledFontData;
+typedef struct _PangoCairoFontGlyphExtentsCacheEntry PangoCairoFontGlyphExtentsCacheEntry;
+
+struct _PangoCairoFontHexBoxInfo
+{
+ PangoCairoFont *font;
+ int rows;
+ double digit_width;
+ double digit_height;
+ double pad_x;
+ double pad_y;
+ double line_width;
+ double box_descent;
+ double box_height;
+};
+
+struct _PangoCairoFontPrivateScaledFontData
+{
+ cairo_matrix_t font_matrix;
+ cairo_matrix_t ctm;
+ cairo_font_options_t *options;
+};
+
+struct _PangoCairoFontPrivate
+{
+ PangoCairoFont *cfont;
+
+ PangoCairoFontPrivateScaledFontData *data;
+
+ cairo_scaled_font_t *scaled_font;
+ PangoCairoFontHexBoxInfo *hbi;
+
+ gboolean is_hinted;
+ PangoGravity gravity;
+
+ PangoRectangle font_extents;
+ PangoCairoFontGlyphExtentsCacheEntry *glyph_extents_cache;
+
+ GSList *metrics_by_lang;
+};
+
+struct _PangoCairoFontIface
+{
+ GTypeInterface g_iface;
+
+ cairo_font_face_t *(*create_font_face) (PangoCairoFont *cfont);
+ PangoFontMetrics *(*create_metrics_for_context) (PangoCairoFont *cfont,
+ PangoContext *context);
+
+ gssize cf_priv_offset;
+};
+
+gboolean _pango_cairo_font_install (PangoFont *font,
+ cairo_t *cr);
+PangoFontMetrics * _pango_cairo_font_get_metrics (PangoFont *font,
+ PangoLanguage *language);
+PangoCairoFontHexBoxInfo *_pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont);
+
+void _pango_cairo_font_private_initialize (PangoCairoFontPrivate *cf_priv,
+ PangoCairoFont *font,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ const cairo_matrix_t *font_matrix);
+void _pango_cairo_font_private_finalize (PangoCairoFontPrivate *cf_priv);
+cairo_scaled_font_t *_pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv);
+gboolean _pango_cairo_font_private_is_metrics_hinted (PangoCairoFontPrivate *cf_priv);
+void _pango_cairo_font_private_get_glyph_extents (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+#define PANGO_TYPE_CAIRO_RENDERER (pango_cairo_renderer_get_type())
+#define PANGO_CAIRO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRenderer))
+#define PANGO_IS_CAIRO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_RENDERER))
+
+typedef struct _PangoCairoRenderer PangoCairoRenderer;
+
+GType pango_cairo_renderer_get_type (void) G_GNUC_CONST;
+
+
+const cairo_font_options_t *_pango_cairo_context_get_merged_font_options (PangoContext *context);
+
+
+typedef struct _PangoCairoWarningHistory PangoCairoWarningHistory;
+
+struct _PangoCairoWarningHistory {
+ guint font_get_scaled_font : 1;
+};
+
+extern PangoCairoWarningHistory _pango_cairo_warning_history;
+
+G_END_DECLS
+
+#endif /* __PANGOCAIRO_PRIVATE_H__ */
diff --git a/trunk/pango/pangocairo-render.c b/trunk/pango/pangocairo-render.c
new file mode 100644
index 00000000..b0ef136d
--- /dev/null
+++ b/trunk/pango/pangocairo-render.c
@@ -0,0 +1,788 @@
+/* Pango
+ * pangocairo-render.c: Rendering routines to Cairo surfaces
+ *
+ * Copyright (C) 2004 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pangocairo-private.h"
+
+typedef struct _PangoCairoRendererClass PangoCairoRendererClass;
+
+#define PANGO_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRendererClass))
+#define PANGO_IS_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_RENDERER))
+#define PANGO_CAIRO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRendererClass))
+
+struct _PangoCairoRenderer
+{
+ PangoRenderer parent_instance;
+
+ cairo_t *cr;
+ gboolean do_path;
+ double x_offset, y_offset;
+ PangoCairoShapeRendererFunc shape_renderer;
+ gpointer shape_renderer_data;
+};
+
+struct _PangoCairoRendererClass
+{
+ PangoRendererClass parent_class;
+};
+
+G_DEFINE_TYPE (PangoCairoRenderer, pango_cairo_renderer, PANGO_TYPE_RENDERER)
+
+static void
+set_color (PangoCairoRenderer *crenderer,
+ PangoRenderPart part)
+{
+ PangoColor *color = pango_renderer_get_color ((PangoRenderer *) (crenderer), part);
+
+ if (color)
+ cairo_set_source_rgb (crenderer->cr,
+ color->red / 65535.,
+ color->green / 65535.,
+ color->blue / 65535.);
+}
+
+/* modifies cairo_set_line_width() without doing cairo_save/restore() */
+static void
+_pango_cairo_renderer_draw_frame (PangoCairoRenderer *crenderer,
+ double x,
+ double y,
+ double width,
+ double height,
+ double line_width)
+{
+ if (crenderer->do_path)
+ {
+ double d2 = line_width * .5, d = line_width;
+
+ /* we draw an outer box in one winding direction and an inner one in the
+ * opposite direction. This works for both cairo windings rules.
+ *
+ * what we really want is cairo_stroke_to_path().
+ */
+
+ /* outer */
+ cairo_rectangle (crenderer->cr, x-d2, y-d2, width+d, height+d);
+ /* inner */
+ cairo_rectangle (crenderer->cr, x+d2 + (width-d), y+d2, - (width-d), height-d);
+ }
+ else
+ {
+ cairo_rectangle (crenderer->cr, x, y, width, height);
+ cairo_set_line_width (crenderer->cr, line_width);
+ cairo_stroke (crenderer->cr);
+ }
+}
+
+static void
+_pango_cairo_renderer_draw_box_glyph (PangoCairoRenderer *crenderer,
+ PangoGlyphInfo *gi,
+ double cx,
+ double cy)
+{
+ double temp_x, temp_y;
+
+ cairo_save (crenderer->cr);
+ cairo_get_current_point (crenderer->cr, &temp_x, &temp_y);
+
+
+ _pango_cairo_renderer_draw_frame (crenderer,
+ cx + 1.5,
+ cy + 1.5 - PANGO_UNKNOWN_GLYPH_HEIGHT,
+ (double)gi->geometry.width / PANGO_SCALE - 3.0,
+ PANGO_UNKNOWN_GLYPH_HEIGHT - 3.0,
+ 1.0);
+
+ cairo_move_to (crenderer->cr, temp_x, temp_y);
+ cairo_restore (crenderer->cr);
+}
+
+static void
+_pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,
+ PangoFont *font,
+ PangoGlyphInfo *gi,
+ double cx,
+ double cy)
+{
+ char buf[7];
+ double x0, y0;
+ int row, col;
+ int rows, cols;
+ char hexbox_string[2] = {0, 0};
+ double temp_x, temp_y;
+ PangoCairoFontHexBoxInfo *hbi;
+ gunichar ch;
+
+ cairo_save (crenderer->cr);
+ cairo_get_current_point (crenderer->cr, &temp_x, &temp_y);
+
+ hbi = _pango_cairo_font_get_hex_box_info ((PangoCairoFont *)font);
+
+ if (!hbi || !_pango_cairo_font_install ((PangoFont *)(hbi->font), crenderer->cr))
+ {
+ _pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy);
+ goto done;
+ }
+
+ ch = gi->glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
+
+ rows = hbi->rows;
+ cols = (ch > 0xffff ? 6 : 4) / rows;
+ g_snprintf (buf, sizeof(buf), (ch > 0xffff) ? "%06X" : "%04X", ch);
+
+ _pango_cairo_renderer_draw_frame (crenderer,
+ cx + hbi->pad_x * 1.5,
+ cy + hbi->box_descent - hbi->box_height + hbi->pad_y * 0.5,
+ (double)gi->geometry.width / PANGO_SCALE - 3 * hbi->pad_x,
+ (hbi->box_height - hbi->pad_y),
+ hbi->line_width);
+
+ x0 = cx + hbi->pad_x * 3.0;
+ y0 = cy + hbi->box_descent - hbi->pad_y * 2;
+
+ for (row = 0; row < rows; row++)
+ {
+ double y = y0 - (rows - 1 - row) * (hbi->digit_height + hbi->pad_y);
+ for (col = 0; col < cols; col++)
+ {
+ double x = x0 + col * (hbi->digit_width + hbi->pad_x);
+
+ cairo_move_to (crenderer->cr, x, y);
+
+ hexbox_string[0] = buf[row * cols + col];
+
+ if (crenderer->do_path)
+ cairo_text_path (crenderer->cr, hexbox_string);
+ else
+ cairo_show_text (crenderer->cr, hexbox_string);
+ }
+ }
+
+done:
+ cairo_move_to (crenderer->cr, temp_x, temp_y);
+ cairo_restore (crenderer->cr);
+}
+
+static void
+pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer);
+
+ /* cairo_glyph_t is 24 bytes */
+#define MAX_STACK 40
+
+ int i, count;
+ int x_position = 0;
+ cairo_glyph_t *cairo_glyphs;
+ cairo_glyph_t stack_glyphs[MAX_STACK];
+ double base_x = crenderer->x_offset + (double)x / PANGO_SCALE;
+ double base_y = crenderer->y_offset + (double)y / PANGO_SCALE;
+
+ cairo_save (crenderer->cr);
+ if (!crenderer->do_path)
+ set_color (crenderer, PANGO_RENDER_PART_FOREGROUND);
+
+ if (!_pango_cairo_font_install (font, crenderer->cr))
+ {
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+
+ if (gi->glyph != PANGO_GLYPH_EMPTY)
+ {
+ double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
+ double cy = gi->geometry.y_offset == 0 ?
+ base_y :
+ base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
+
+ _pango_cairo_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);
+ }
+ x_position += gi->geometry.width;
+ }
+
+ goto done;
+ }
+
+ if (glyphs->num_glyphs > MAX_STACK)
+ cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs);
+ else
+ cairo_glyphs = stack_glyphs;
+
+ count = 0;
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+
+ if (gi->glyph != PANGO_GLYPH_EMPTY)
+ {
+ double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
+ double cy = gi->geometry.y_offset == 0 ?
+ base_y :
+ base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
+
+ if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ _pango_cairo_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);
+ else
+ {
+ cairo_glyphs[count].index = gi->glyph;
+ cairo_glyphs[count].x = cx;
+ cairo_glyphs[count].y = cy;
+ count++;
+ }
+ }
+ x_position += gi->geometry.width;
+ }
+
+ if (crenderer->do_path)
+ cairo_glyph_path (crenderer->cr, cairo_glyphs, count);
+ else
+ cairo_show_glyphs (crenderer->cr, cairo_glyphs, count);
+
+ if (glyphs->num_glyphs > MAX_STACK)
+ g_free (cairo_glyphs);
+
+done:
+ cairo_restore (crenderer->cr);
+
+#undef MAX_STACK
+}
+
+static void
+pango_cairo_renderer_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer);
+
+ if (!crenderer->do_path)
+ {
+ cairo_save (crenderer->cr);
+
+ set_color (crenderer, part);
+ }
+
+ cairo_rectangle (crenderer->cr,
+ crenderer->x_offset + (double)x / PANGO_SCALE,
+ crenderer->y_offset + (double)y / PANGO_SCALE,
+ (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+
+ if (!crenderer->do_path)
+ {
+ cairo_fill (crenderer->cr);
+
+ cairo_restore (crenderer->cr);
+ }
+}
+
+/* Draws an error underline that looks like one of:
+ * H E H
+ * /\ /\ /\ /\ /\ -
+ * A/ \ / \ / \ A/ \ / \ |
+ * \ \ / \ / /D \ \ / \ |
+ * \ \/ C \/ / \ \/ C \ | height = HEIGHT_SQUARES * square
+ * \ /\ F / \ F /\ \ |
+ * \ / \ / \ / \ \G |
+ * \ / \ / \ / \ / |
+ * \/ \/ \/ \/ -
+ * B B
+ * |---|
+ * unit_width = (HEIGHT_SQUARES - 1) * square
+ *
+ * The x, y, width, height passed in give the desired bounding box;
+ * x/width are adjusted to make the underline a integer number of units
+ * wide.
+ */
+#define HEIGHT_SQUARES 2.5
+
+static void
+draw_error_underline (cairo_t *cr,
+ double x,
+ double y,
+ double width,
+ double height)
+{
+ double square = height / HEIGHT_SQUARES;
+ double unit_width = (HEIGHT_SQUARES - 1) * square;
+ int width_units = (width + unit_width / 2) / unit_width;
+ double y_top, y_bottom;
+ int i;
+
+ x += (width - width_units * unit_width) / 2;
+ width = width_units * unit_width;
+
+ y_top = y;
+ y_bottom = y + height;
+
+ /* Bottom of squiggle */
+ cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */
+ for (i = 0; i < width_units; i += 2)
+ {
+ double x_middle = x + (i + 1) * unit_width;
+ double x_right = x + (i + 2) * unit_width;
+
+ cairo_line_to (cr, x_middle, y_bottom); /* B */
+
+ if (i + 1 == width_units)
+ /* Nothing */;
+ else if (i + 2 == width_units)
+ cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */
+ else
+ cairo_line_to (cr, x_right, y_top + square); /* C */
+ }
+
+ /* Top of squiggle */
+ for (i -= 2; i >= 0; i -= 2)
+ {
+ double x_left = x + i * unit_width;
+ double x_middle = x + (i + 1) * unit_width;
+ double x_right = x + (i + 2) * unit_width;
+
+ if (i + 1 == width_units)
+ cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */
+ else {
+ if (i + 2 == width_units)
+ cairo_line_to (cr, x_right, y_top); /* E */
+ cairo_line_to (cr, x_middle, y_bottom - square); /* F */
+ }
+
+ cairo_line_to (cr, x_left, y_top); /* H */
+ }
+}
+
+static void
+pango_cairo_renderer_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer);
+ cairo_t *cr = crenderer->cr;
+
+ if (!crenderer->do_path)
+ {
+ cairo_save (cr);
+
+ set_color (crenderer, PANGO_RENDER_PART_UNDERLINE);
+
+ cairo_new_path (cr);
+ }
+
+ draw_error_underline (cr,
+ crenderer->x_offset + (double)x / PANGO_SCALE,
+ crenderer->y_offset + (double)y / PANGO_SCALE,
+ (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+
+ if (!crenderer->do_path)
+ {
+ cairo_fill (cr);
+
+ cairo_restore (cr);
+ }
+}
+
+static void
+pango_cairo_renderer_draw_shape (PangoRenderer *renderer,
+ PangoAttrShape *attr,
+ int x,
+ int y)
+{
+ PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer);
+ cairo_t *cr = crenderer->cr;
+ double base_x = crenderer->x_offset + (double)x / PANGO_SCALE;
+ double base_y = crenderer->y_offset + (double)y / PANGO_SCALE;
+
+ if (!crenderer->shape_renderer)
+ return;
+
+ cairo_save (cr);
+ if (!crenderer->do_path)
+ set_color (crenderer, PANGO_RENDER_PART_FOREGROUND);
+
+ cairo_move_to (cr, base_x, base_y);
+
+ crenderer->shape_renderer (cr, attr, crenderer->do_path, crenderer->shape_renderer_data);
+
+ cairo_restore (cr);
+}
+
+static void
+pango_cairo_renderer_init (PangoCairoRenderer *renderer)
+{
+}
+
+static void
+pango_cairo_renderer_class_init (PangoCairoRendererClass *klass)
+{
+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
+
+ renderer_class->draw_glyphs = pango_cairo_renderer_draw_glyphs;
+ renderer_class->draw_rectangle = pango_cairo_renderer_draw_rectangle;
+ renderer_class->draw_error_underline = pango_cairo_renderer_draw_error_underline;
+ renderer_class->draw_shape = pango_cairo_renderer_draw_shape;
+}
+
+static PangoCairoRenderer *cached_renderer = NULL;
+G_LOCK_DEFINE_STATIC (cached_renderer);
+
+static PangoCairoRenderer *
+acquire_renderer (gboolean *free_renderer)
+{
+ PangoCairoRenderer *renderer;
+
+ if (G_LIKELY (G_TRYLOCK (cached_renderer)))
+ {
+ if (G_UNLIKELY (!cached_renderer))
+ cached_renderer = g_object_new (PANGO_TYPE_CAIRO_RENDERER, NULL);
+
+ renderer = cached_renderer;
+ *free_renderer = FALSE;
+ }
+ else
+ {
+ renderer = g_object_new (PANGO_TYPE_CAIRO_RENDERER, NULL);
+ *free_renderer = TRUE;
+ }
+
+ return renderer;
+}
+
+static void
+release_renderer (PangoCairoRenderer *renderer, gboolean free_renderer)
+{
+ if (G_LIKELY (!free_renderer))
+ {
+ renderer->cr = NULL;
+ renderer->do_path = FALSE;
+ renderer->shape_renderer = NULL;
+ renderer->shape_renderer_data = NULL;
+ renderer->x_offset = 0.;
+ renderer->y_offset = 0.;
+
+ G_UNLOCK (cached_renderer);
+ }
+ else
+ g_object_unref (renderer);
+}
+
+
+/* convenience wrappers using the default renderer */
+
+
+static void
+_pango_cairo_do_glyph_string (cairo_t *cr,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gboolean do_path)
+{
+ gboolean free_renderer;
+ PangoCairoRenderer *crenderer = acquire_renderer (&free_renderer);
+ PangoRenderer *renderer = (PangoRenderer *) crenderer;
+
+ crenderer->cr = cr;
+ crenderer->do_path = do_path;
+ cairo_get_current_point (cr, &crenderer->x_offset, &crenderer->y_offset);
+
+ if (!do_path)
+ {
+ /* unset all part colors, since when drawing just a glyph string,
+ * prepare_run() isn't called.
+ */
+
+ pango_renderer_activate (renderer);
+
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_FOREGROUND, NULL);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_BACKGROUND, NULL);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_UNDERLINE, NULL);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_STRIKETHROUGH, NULL);
+ }
+
+ pango_renderer_draw_glyphs (renderer, font, glyphs, 0, 0);
+
+ if (!do_path)
+ {
+ pango_renderer_deactivate (renderer);
+ }
+
+ release_renderer (crenderer, free_renderer);
+}
+
+static void
+_pango_cairo_do_layout_line (cairo_t *cr,
+ PangoLayoutLine *line,
+ gboolean do_path)
+{
+ gboolean free_renderer;
+ PangoCairoRenderer *crenderer = acquire_renderer (&free_renderer);
+ PangoRenderer *renderer = (PangoRenderer *) crenderer;
+
+ crenderer->cr = cr;
+ crenderer->do_path = do_path;
+ crenderer->shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (line->layout),
+ &crenderer->shape_renderer_data);
+ cairo_get_current_point (cr, &crenderer->x_offset, &crenderer->y_offset);
+
+ pango_renderer_draw_layout_line (renderer, line, 0, 0);
+
+ release_renderer (crenderer, free_renderer);
+}
+
+static void
+_pango_cairo_do_layout (cairo_t *cr,
+ PangoLayout *layout,
+ gboolean do_path)
+{
+ gboolean free_renderer;
+ PangoCairoRenderer *crenderer = acquire_renderer (&free_renderer);
+ PangoRenderer *renderer = (PangoRenderer *) crenderer;
+
+ crenderer->cr = cr;
+ crenderer->do_path = do_path;
+ crenderer->shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout),
+ &crenderer->shape_renderer_data);
+ cairo_get_current_point (cr, &crenderer->x_offset, &crenderer->y_offset);
+
+ pango_renderer_draw_layout (renderer, layout, 0, 0);
+
+ release_renderer (crenderer, free_renderer);
+}
+
+static void
+_pango_cairo_do_error_underline (cairo_t *cr,
+ double x,
+ double y,
+ double width,
+ double height,
+ gboolean do_path)
+{
+ /* We don't use a renderer here, for a simple reason:
+ * the only renderer we can get is the default renderer, that
+ * is all implemented here, so we shortcircuit and make our
+ * life way easier.
+ */
+
+ if (!do_path)
+ cairo_new_path (cr);
+
+ draw_error_underline (cr, x, y, width, height);
+
+ if (!do_path)
+ cairo_fill (cr);
+}
+
+
+/* public wrapper of above to show or append path */
+
+
+/**
+ * pango_cairo_show_glyph_string:
+ * @cr: a Cairo context
+ * @font: a #PangoFont from a #PangoCairoFontMap
+ * @glyphs: a #PangoGlyphString
+ *
+ * Draws the glyphs in @glyphs in the specified cairo context.
+ * The origin of the glyphs (the left edge of the baseline) will
+ * be drawn at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_show_glyph_string (cairo_t *cr,
+ PangoFont *font,
+ PangoGlyphString *glyphs)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (glyphs != NULL);
+
+ _pango_cairo_do_glyph_string (cr, font, glyphs, FALSE);
+}
+
+/**
+ * pango_cairo_show_layout_line:
+ * @cr: a Cairo context
+ * @line: a #PangoLayoutLine
+ *
+ * Draws a #PangoLayoutLine in the specified cairo context.
+ * The origin of the glyphs (the left edge of the line) will
+ * be drawn at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_show_layout_line (cairo_t *cr,
+ PangoLayoutLine *line)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (line != NULL);
+
+ _pango_cairo_do_layout_line (cr, line, FALSE);
+}
+
+/**
+ * pango_cairo_show_layout:
+ * @cr: a Cairo context
+ * @layout: a Pango layout
+ *
+ * Draws a #PangoLayoutLine in the specified cairo context.
+ * The top-left corner of the #PangoLayout will be drawn
+ * at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_show_layout (cairo_t *cr,
+ PangoLayout *layout)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ _pango_cairo_do_layout (cr, layout, FALSE);
+}
+
+/**
+ * pango_cairo_show_error_underline:
+ * @cr: a Cairo context
+ * @x: The X coordinate of one corner of the rectangle
+ * @y: The Y coordinate of one corner of the rectangle
+ * @width: Non-negative width of the rectangle
+ * @height: Non-negative height of the rectangle
+ *
+ * Draw a squiggly line in the specified cairo context that approximately
+ * covers the given rectangle in the style of an underline used to indicate a
+ * spelling error. (The width of the underline is rounded to an integer
+ * number of up/down segments and the resulting rectangle is centered in the
+ * original rectangle)
+ *
+ * Since: 1.14
+ **/
+void
+pango_cairo_show_error_underline (cairo_t *cr,
+ double x,
+ double y,
+ double width,
+ double height)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail ((width >= 0) && (height >= 0));
+
+ _pango_cairo_do_error_underline (cr, x, y, width, height, FALSE);
+}
+
+/**
+ * pango_cairo_glyph_string_path
+ * @cr: a Cairo context
+ * @font: a #PangoFont from a #PangoCairoFontMap
+ * @glyphs: a #PangoGlyphString
+ *
+ * Adds the glyphs in @glyphs to the current path in the specified
+ * cairo context. The origin of the glyphs (the left edge of the baseline)
+ * will be at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_glyph_string_path (cairo_t *cr,
+ PangoFont *font,
+ PangoGlyphString *glyphs)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (glyphs != NULL);
+
+ _pango_cairo_do_glyph_string (cr, font, glyphs, TRUE);
+}
+
+/**
+ * pango_cairo_layout_line_path:
+ * @cr: a Cairo context
+ * @line: a #PangoLayoutLine
+ *
+ * Adds the text in #PangoLayoutLine to the current path in the
+ * specified cairo context. The origin of the glyphs (the left edge
+ * of the line) will be at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_layout_line_path (cairo_t *cr,
+ PangoLayoutLine *line)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (line != NULL);
+
+ _pango_cairo_do_layout_line (cr, line, TRUE);
+}
+
+/**
+ * pango_cairo_layout_path:
+ * @cr: a Cairo context
+ * @layout: a Pango layout
+ *
+ * Adds the text in a #PangoLayout to the current path in the
+ * specified cairo context. The top-left corner of the #PangoLayout
+ * will be at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_layout_path (cairo_t *cr,
+ PangoLayout *layout)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ _pango_cairo_do_layout (cr, layout, TRUE);
+}
+
+/**
+ * pango_cairo_error_underline_path:
+ * @cr: a Cairo context
+ * @x: The X coordinate of one corner of the rectangle
+ * @y: The Y coordinate of one corner of the rectangle
+ * @width: Non-negative width of the rectangle
+ * @height: Non-negative height of the rectangle
+ *
+ * Add a squiggly line to the current path in the specified cairo context that
+ * approximately covers the given rectangle in the style of an underline used
+ * to indicate a spelling error. (The width of the underline is rounded to an
+ * integer number of up/down segments and the resulting rectangle is centered
+ * in the original rectangle)
+ *
+ * Since: 1.14
+ **/
+void
+pango_cairo_error_underline_path (cairo_t *cr,
+ double x,
+ double y,
+ double width,
+ double height)
+{
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail ((width >= 0) && (height >= 0));
+
+ _pango_cairo_do_error_underline (cr, x, y, width, height, TRUE);
+}
diff --git a/trunk/pango/pangocairo-win32.h b/trunk/pango/pangocairo-win32.h
new file mode 100644
index 00000000..f95f4fb9
--- /dev/null
+++ b/trunk/pango/pangocairo-win32.h
@@ -0,0 +1,55 @@
+/* Pango
+ * pangocairo-win32.h: Private header file for Cairo/Win32 combination
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOCAIRO_WIN32_H__
+#define __PANGOCAIRO_WIN32_H__
+
+#include <pango/pangowin32.h>
+#include "pangowin32-private.h"
+#include <pango/pangocairo.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_CAIRO_WIN32_FONT_MAP (pango_cairo_win32_font_map_get_type ())
+#define PANGO_CAIRO_WIN32_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_WIN32_FONT_MAP, PangoCairoWin32FontMap))
+#define PANGO_IS_CAIRO_WIN32_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_WIN32_FONT_MAP))
+
+typedef struct _PangoCairoWin32FontMap PangoCairoWin32FontMap;
+
+struct _PangoCairoWin32FontMap
+{
+ PangoWin32FontMap parent_instance;
+
+ double dpi;
+
+ PangoRenderer *renderer;
+};
+
+GType pango_cairo_win32_font_map_get_type (void) G_GNUC_CONST;
+
+PangoFont *_pango_cairo_win32_font_new (PangoCairoWin32FontMap *cwfontmap,
+ PangoContext *context,
+ PangoWin32Face *face,
+ const PangoFontDescription *desc);
+G_END_DECLS
+
+#endif /* __PANGOCAIRO_WIN32_H__ */
+
diff --git a/trunk/pango/pangocairo-win32font.c b/trunk/pango/pangocairo-win32font.c
new file mode 100644
index 00000000..af4e1d07
--- /dev/null
+++ b/trunk/pango/pangocairo-win32font.c
@@ -0,0 +1,318 @@
+/* Pango
+ * pangocairowin32-font.c: Cairo font handling, Win32 backend
+ *
+ * Copyright (C) 2000-2005 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pango-fontmap.h"
+#include "pango-impl-utils.h"
+#include "pangocairo-private.h"
+#include "pangocairo-win32.h"
+
+#include <cairo-win32.h>
+
+#define PANGO_TYPE_CAIRO_WIN32_FONT (pango_cairo_win32_font_get_type ())
+#define PANGO_CAIRO_WIN32_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_WIN32_FONT, PangoCairoWin32Font))
+#define PANGO_CAIRO_WIN32_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_WIN32_FONT, PangoCairoWin32FontClass))
+#define PANGO_CAIRO_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_WIN32_FONT))
+#define PANGO_CAIRO_WIN32_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_WIN32_FONT, PangoCairoWin32FontClass))
+
+typedef struct _PangoCairoWin32Font PangoCairoWin32Font;
+typedef struct _PangoCairoWin32FontClass PangoCairoWin32FontClass;
+
+struct _PangoCairoWin32Font
+{
+ PangoWin32Font font;
+ PangoCairoFontPrivate cf_priv;
+};
+
+struct _PangoCairoWin32FontClass
+{
+ PangoWin32FontClass parent_class;
+};
+
+GType pango_cairo_win32_font_get_type (void);
+
+static cairo_font_face_t *pango_cairo_win32_font_create_font_face (PangoCairoFont *font);
+static PangoFontMetrics *pango_cairo_win32_font_create_metrics_for_context (PangoCairoFont *font,
+ PangoContext *context);
+
+
+static void
+cairo_font_iface_init (PangoCairoFontIface *iface)
+{
+ iface->create_font_face = pango_cairo_win32_font_create_font_face;
+ iface->create_metrics_for_context = pango_cairo_win32_font_create_metrics_for_context;
+ iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoWin32Font, cf_priv);
+}
+
+G_DEFINE_TYPE_WITH_CODE (PangoCairoWin32Font, pango_cairo_win32_font, PANGO_TYPE_WIN32_FONT,
+ { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) });
+
+static cairo_font_face_t *
+pango_cairo_win32_font_create_font_face (PangoCairoFont *font)
+{
+ PangoCairoWin32Font *cwfont = PANGO_CAIRO_WIN32_FONT (font);
+ PangoWin32Font *win32font = &cwfont->font;
+
+ return cairo_win32_font_face_create_for_logfontw (&win32font->logfontw);
+}
+
+static int
+max_glyph_width (PangoLayout *layout)
+{
+ int max_width = 0;
+ GSList *l, *r;
+
+ for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
+ {
+ PangoLayoutLine *line = l->data;
+
+ for (r = line->runs; r; r = r->next)
+ {
+ PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ if (glyphs->glyphs[i].geometry.width > max_width)
+ max_width = glyphs->glyphs[i].geometry.width;
+ }
+ }
+
+ return max_width;
+}
+
+static PangoFontMetrics *
+pango_cairo_win32_font_create_metrics_for_context (PangoCairoFont *font,
+ PangoContext *context)
+{
+ PangoFontMetrics *metrics;
+ PangoFontDescription *font_desc;
+ PangoLayout *layout;
+ PangoRectangle extents;
+ PangoLanguage *language = pango_context_get_language (context);
+ const char *sample_str = pango_language_get_sample_string (language);
+ cairo_scaled_font_t *scaled_font;
+ cairo_font_extents_t font_extents;
+ double height;
+
+ metrics = pango_font_metrics_new ();
+
+ scaled_font = pango_cairo_font_get_scaled_font ((PangoFont *) font);
+
+ cairo_scaled_font_extents (scaled_font, &font_extents);
+ cairo_win32_scaled_font_done_font (scaled_font);
+
+ metrics->ascent = font_extents.ascent * PANGO_SCALE;
+ metrics->descent = font_extents.descent * PANGO_SCALE;
+
+ /* FIXME: Should get the real settings for these from the TrueType
+ * font file.
+ */
+ height = metrics->ascent + metrics->descent;
+ metrics->underline_thickness = height / 14;
+ metrics->underline_position = - metrics->underline_thickness;
+ metrics->strikethrough_thickness = metrics->underline_thickness;
+ metrics->strikethrough_position = height / 4;
+
+ pango_quantize_line_geometry (&metrics->underline_thickness,
+ &metrics->underline_position);
+ pango_quantize_line_geometry (&metrics->strikethrough_thickness,
+ &metrics->strikethrough_position);
+
+ layout = pango_layout_new (context);
+ font_desc = pango_font_describe_with_absolute_size ((PangoFont *) font);
+ pango_layout_set_font_description (layout, font_desc);
+ pango_layout_set_text (layout, sample_str, -1);
+ pango_layout_get_extents (layout, NULL, &extents);
+
+ metrics->approximate_char_width = extents.width / g_utf8_strlen (sample_str, -1);
+
+ pango_layout_set_text (layout, "0123456789", -1);
+ metrics->approximate_digit_width = max_glyph_width (layout);
+
+ pango_font_description_free (font_desc);
+ g_object_unref (layout);
+
+ return metrics;
+}
+
+static void
+pango_cairo_win32_font_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (pango_cairo_win32_font_parent_class)->finalize (object);
+}
+
+static void
+pango_cairo_win32_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoCairoWin32Font *cwfont = (PangoCairoWin32Font *) font;
+
+ _pango_cairo_font_private_get_glyph_extents (&cwfont->cf_priv,
+ glyph,
+ ink_rect,
+ logical_rect);
+}
+
+static gboolean
+pango_cairo_win32_font_select_font (PangoFont *font,
+ HDC hdc)
+{
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
+
+ return cairo_win32_scaled_font_select_font (scaled_font, hdc) == CAIRO_STATUS_SUCCESS;
+}
+
+static void
+pango_cairo_win32_font_done_font (PangoFont *font)
+{
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
+
+ cairo_win32_scaled_font_done_font (scaled_font);
+}
+
+static double
+pango_cairo_win32_font_get_metrics_factor (PangoFont *font)
+{
+ PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
+
+ return cairo_win32_scaled_font_get_metrics_factor (scaled_font) * win32font->size;
+}
+
+static void
+pango_cairo_win32_font_class_init (PangoCairoWin32FontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+ PangoWin32FontClass *win32_font_class = PANGO_WIN32_FONT_CLASS (class);
+
+ object_class->finalize = pango_cairo_win32_font_finalize;
+
+ font_class->get_glyph_extents = pango_cairo_win32_font_get_glyph_extents;
+ font_class->get_metrics = _pango_cairo_font_get_metrics;
+
+ win32_font_class->select_font = pango_cairo_win32_font_select_font;
+ win32_font_class->done_font = pango_cairo_win32_font_done_font;
+ win32_font_class->get_metrics_factor = pango_cairo_win32_font_get_metrics_factor;
+}
+
+static void
+pango_cairo_win32_font_init (PangoCairoWin32Font *cwfont)
+{
+}
+
+/********************
+ * Private API *
+ ********************/
+
+PangoFont *
+_pango_cairo_win32_font_new (PangoCairoWin32FontMap *cwfontmap,
+ PangoContext *context,
+ PangoWin32Face *face,
+ const PangoFontDescription *desc)
+{
+ PangoCairoWin32Font *cwfont;
+ PangoWin32Font *win32font;
+ double size;
+ double dpi;
+#define USE_FACE_CACHED_FONTS
+#ifdef USE_FACE_CACHED_FONTS
+ PangoWin32FontMap *win32fontmap;
+ GSList *tmp_list;
+#endif
+ cairo_matrix_t font_matrix;
+
+ g_return_val_if_fail (PANGO_IS_CAIRO_WIN32_FONT_MAP (cwfontmap), NULL);
+
+ size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
+
+ if (context)
+ {
+ dpi = pango_cairo_context_get_resolution (context);
+
+ if (dpi <= 0)
+ dpi = cwfontmap->dpi;
+ }
+ else
+ dpi = cwfontmap->dpi;
+
+ if (!pango_font_description_get_size_is_absolute (desc))
+ size *= dpi / 72.;
+
+#ifdef USE_FACE_CACHED_FONTS
+ win32fontmap = PANGO_WIN32_FONT_MAP (cwfontmap);
+
+ tmp_list = face->cached_fonts;
+ while (tmp_list)
+ {
+ win32font = tmp_list->data;
+ if (ABS (win32font->size - size * PANGO_SCALE) < 2)
+ {
+ g_object_ref (win32font);
+ if (win32font->in_cache)
+ _pango_win32_fontmap_cache_remove (PANGO_FONT_MAP (win32fontmap), win32font);
+
+ return PANGO_FONT (win32font);
+ }
+ tmp_list = tmp_list->next;
+ }
+#endif
+ cwfont = g_object_new (PANGO_TYPE_CAIRO_WIN32_FONT, NULL);
+ win32font = PANGO_WIN32_FONT (cwfont);
+
+ win32font->fontmap = PANGO_FONT_MAP (cwfontmap);
+ g_object_ref (cwfontmap);
+
+ win32font->win32face = face;
+
+#ifdef USE_FACE_CACHED_FONTS
+ face->cached_fonts = g_slist_prepend (face->cached_fonts, win32font);
+#endif
+
+ /* FIXME: This is a pixel size, so not really what we want for describe(),
+ * but it's what we need when computing the scale factor.
+ */
+ win32font->size = size * PANGO_SCALE;
+
+ _pango_win32_make_matching_logfontw (win32font->fontmap,
+ &face->logfontw,
+ win32font->size,
+ &win32font->logfontw);
+
+ cairo_matrix_init_identity (&font_matrix);
+
+ cairo_matrix_scale (&font_matrix, size, size);
+
+ _pango_cairo_font_private_initialize (&cwfont->cf_priv,
+ (PangoCairoFont *) cwfont,
+ context,
+ desc,
+ &font_matrix);
+
+ return PANGO_FONT (cwfont);
+}
diff --git a/trunk/pango/pangocairo-win32fontmap.c b/trunk/pango/pangocairo-win32fontmap.c
new file mode 100644
index 00000000..6d097df3
--- /dev/null
+++ b/trunk/pango/pangocairo-win32fontmap.c
@@ -0,0 +1,105 @@
+/* Pango
+ * pangocairo-win32fontmap.c: Cairo font handling, Win32 backend
+ *
+ * Copyright (C) 2000-2005 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pangowin32-private.h"
+#include "pangocairo.h"
+#include "pangocairo-private.h"
+#include "pangocairo-win32.h"
+
+typedef struct _PangoCairoWin32FontMapClass PangoCairoWin32FontMapClass;
+
+struct _PangoCairoWin32FontMapClass
+{
+ PangoWin32FontMapClass parent_class;
+};
+
+static void
+pango_cairo_win32_font_map_set_resolution (PangoCairoFontMap *cfontmap,
+ double dpi)
+{
+ PangoCairoWin32FontMap *cwfontmap = PANGO_CAIRO_WIN32_FONT_MAP (cfontmap);
+
+ cwfontmap->dpi = dpi;
+}
+
+static double
+pango_cairo_win32_font_map_get_resolution (PangoCairoFontMap *cfontmap)
+{
+ PangoCairoWin32FontMap *cwfontmap = PANGO_CAIRO_WIN32_FONT_MAP (cfontmap);
+
+ return cwfontmap->dpi;
+}
+
+static cairo_font_type_t
+pango_cairo_win32_font_map_get_font_type (PangoCairoFontMap *cfontmap)
+{
+ return CAIRO_FONT_TYPE_WIN32;
+}
+
+static void
+cairo_font_map_iface_init (PangoCairoFontMapIface *iface)
+{
+ iface->set_resolution = pango_cairo_win32_font_map_set_resolution;
+ iface->get_resolution = pango_cairo_win32_font_map_get_resolution;
+ iface->get_font_type = pango_cairo_win32_font_map_get_font_type;
+}
+
+G_DEFINE_TYPE_WITH_CODE (PangoCairoWin32FontMap, pango_cairo_win32_font_map, PANGO_TYPE_WIN32_FONT_MAP,
+ { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT_MAP, cairo_font_map_iface_init) });
+
+static void
+pango_cairo_win32_font_map_finalize (GObject *object)
+{
+ PangoCairoWin32FontMap *cwfontmap = PANGO_CAIRO_WIN32_FONT_MAP (object);
+
+ if (cwfontmap->renderer)
+ g_object_unref (cwfontmap->renderer);
+
+ G_OBJECT_CLASS (pango_cairo_win32_font_map_parent_class)->finalize (object);
+}
+
+static PangoFont *
+pango_cairo_win32_font_map_find_font (PangoWin32FontMap *fontmap,
+ PangoContext *context,
+ PangoWin32Face *face,
+ const PangoFontDescription *desc)
+{
+ return _pango_cairo_win32_font_new (PANGO_CAIRO_WIN32_FONT_MAP (fontmap),
+ context, face, desc);
+}
+
+static void
+pango_cairo_win32_font_map_class_init (PangoCairoWin32FontMapClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ PangoWin32FontMapClass *win32fontmap_class = PANGO_WIN32_FONT_MAP_CLASS (class);
+
+ gobject_class->finalize = pango_cairo_win32_font_map_finalize;
+ win32fontmap_class->find_font = pango_cairo_win32_font_map_find_font;
+}
+
+static void
+pango_cairo_win32_font_map_init (PangoCairoWin32FontMap *cwfontmap)
+{
+ cwfontmap->dpi = GetDeviceCaps (pango_win32_get_dc (), LOGPIXELSY);
+}
diff --git a/trunk/pango/pangocairo.def b/trunk/pango/pangocairo.def
new file mode 100644
index 00000000..b16c0f2a
--- /dev/null
+++ b/trunk/pango/pangocairo.def
@@ -0,0 +1,31 @@
+EXPORTS
+ pango_cairo_context_get_font_options
+ pango_cairo_context_get_resolution
+ pango_cairo_context_get_shape_renderer
+ pango_cairo_context_set_font_options
+ pango_cairo_context_set_resolution
+ pango_cairo_context_set_shape_renderer
+ pango_cairo_create_layout
+ pango_cairo_error_underline_path
+; pango_cairo_fc_font_get_type
+; pango_cairo_fc_font_map_get_type
+ pango_cairo_font_get_type
+ pango_cairo_font_get_scaled_font
+ pango_cairo_font_map_create_context
+ pango_cairo_font_map_get_default
+ pango_cairo_font_map_get_font_type
+ pango_cairo_font_map_get_resolution
+ pango_cairo_font_map_get_type
+ pango_cairo_font_map_new
+ pango_cairo_font_map_new_for_font_type
+ pango_cairo_font_map_set_resolution
+ pango_cairo_glyph_string_path
+ pango_cairo_layout_line_path
+ pango_cairo_layout_path
+ pango_cairo_renderer_get_type
+ pango_cairo_show_error_underline
+ pango_cairo_show_glyph_string
+ pango_cairo_show_layout
+ pango_cairo_show_layout_line
+ pango_cairo_update_context
+ pango_cairo_update_layout
diff --git a/trunk/pango/pangocairo.h b/trunk/pango/pangocairo.h
new file mode 100644
index 00000000..54fe031c
--- /dev/null
+++ b/trunk/pango/pangocairo.h
@@ -0,0 +1,149 @@
+/* Pango
+ * pangocairo.h:
+ *
+ * Copyright (C) 1999, 2004 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOCAIRO_H__
+#define __PANGOCAIRO_H__
+
+#include <pango/pango-context.h>
+#include <pango/pango-fontmap.h>
+#include <pango/pango-layout.h>
+#include <cairo.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PangoCairoFont:
+ *
+ * #PangoCairoFont is an interface exported by fonts for
+ * use with Cairo. The actual type of the font will depend
+ * on the particular font technology Cairo was compiled to use.
+ *
+ * Since: 1.18
+ **/
+typedef struct _PangoCairoFont PangoCairoFont;
+#define PANGO_TYPE_CAIRO_FONT (pango_cairo_font_get_type ())
+#define PANGO_CAIRO_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FONT, PangoCairoFont))
+#define PANGO_IS_CAIRO_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_FONT))
+
+/**
+ * PangoCairoFontMap:
+ *
+ * #PangoCairoFontMap is an interface exported by font maps for
+ * use with Cairo. The actual type of the font map will depend
+ * on the particular font technology Cairo was compiled to use.
+ *
+ * Since: 1.10
+ **/
+typedef struct _PangoCairoFontMap PangoCairoFontMap;
+#define PANGO_TYPE_CAIRO_FONT_MAP (pango_cairo_font_map_get_type ())
+#define PANGO_CAIRO_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FONT_MAP, PangoCairoFontMap))
+#define PANGO_IS_CAIRO_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_FONT_MAP))
+
+typedef void (* PangoCairoShapeRendererFunc) (cairo_t *cr,
+ PangoAttrShape *attr,
+ gboolean do_path,
+ gpointer data);
+
+/*
+ * PangoCairoFontMap
+ */
+GType pango_cairo_font_map_get_type (void) G_GNUC_CONST;
+
+PangoFontMap *pango_cairo_font_map_new (void);
+PangoFontMap *pango_cairo_font_map_new_for_font_type (cairo_font_type_t fonttype);
+PangoFontMap *pango_cairo_font_map_get_default (void);
+cairo_font_type_t pango_cairo_font_map_get_font_type (PangoCairoFontMap *fontmap);
+
+void pango_cairo_font_map_set_resolution (PangoCairoFontMap *fontmap,
+ double dpi);
+double pango_cairo_font_map_get_resolution (PangoCairoFontMap *fontmap);
+PangoContext *pango_cairo_font_map_create_context (PangoCairoFontMap *fontmap);
+
+/*
+ * PangoCairoFont
+ */
+GType pango_cairo_font_get_type (void) G_GNUC_CONST;
+
+cairo_scaled_font_t *pango_cairo_font_get_scaled_font (PangoCairoFont *font);
+
+/* Update a Pango context for the current state of a cairo context
+ */
+void pango_cairo_update_context (cairo_t *cr,
+ PangoContext *context);
+
+void pango_cairo_context_set_font_options (PangoContext *context,
+ const cairo_font_options_t *options);
+const cairo_font_options_t *pango_cairo_context_get_font_options (PangoContext *context);
+
+void pango_cairo_context_set_resolution (PangoContext *context,
+ double dpi);
+double pango_cairo_context_get_resolution (PangoContext *context);
+
+void pango_cairo_context_set_shape_renderer (PangoContext *context,
+ PangoCairoShapeRendererFunc func,
+ gpointer data,
+ GDestroyNotify dnotify);
+PangoCairoShapeRendererFunc pango_cairo_context_get_shape_renderer (PangoContext *context,
+ gpointer *data);
+
+/* Convenience
+ */
+PangoLayout *pango_cairo_create_layout (cairo_t *cr);
+void pango_cairo_update_layout (cairo_t *cr,
+ PangoLayout *layout);
+
+/*
+ * Rendering
+ */
+void pango_cairo_show_glyph_string (cairo_t *cr,
+ PangoFont *font,
+ PangoGlyphString *glyphs);
+void pango_cairo_show_layout_line (cairo_t *cr,
+ PangoLayoutLine *line);
+void pango_cairo_show_layout (cairo_t *cr,
+ PangoLayout *layout);
+
+void pango_cairo_show_error_underline (cairo_t *cr,
+ double x,
+ double y,
+ double width,
+ double height);
+
+/*
+ * Rendering to a path
+ */
+void pango_cairo_glyph_string_path (cairo_t *cr,
+ PangoFont *font,
+ PangoGlyphString *glyphs);
+void pango_cairo_layout_line_path (cairo_t *cr,
+ PangoLayoutLine *line);
+void pango_cairo_layout_path (cairo_t *cr,
+ PangoLayout *layout);
+
+void pango_cairo_error_underline_path (cairo_t *cr,
+ double x,
+ double y,
+ double width,
+ double height);
+
+G_END_DECLS
+
+#endif /* __PANGOCAIRO_H__ */
diff --git a/trunk/pango/pangofc-decoder.c b/trunk/pango/pangofc-decoder.c
new file mode 100644
index 00000000..1f985265
--- /dev/null
+++ b/trunk/pango/pangofc-decoder.c
@@ -0,0 +1,86 @@
+/* Pango
+ * pangofc-decoder.c: Custom font encoder/decoders
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "pangofc-decoder.h"
+
+G_DEFINE_ABSTRACT_TYPE (PangoFcDecoder, pango_fc_decoder, G_TYPE_OBJECT)
+
+static void
+pango_fc_decoder_init (PangoFcDecoder *decoder)
+{
+}
+
+static void
+pango_fc_decoder_class_init (PangoFcDecoderClass *klass)
+{
+}
+
+/**
+ * pango_fc_decoder_get_charset:
+ * @decoder: a #PangoFcDecoder
+ * @fcfont: the #PangoFcFont to query.
+ *
+ * Generates an #FcCharSet of supported characters for the fcfont
+ * given. The returned #FcCharSet will be a reference to an
+ * internal value stored by the #PangoFcDecoder and must not
+ * be modified or freed.
+ *
+ * Return value: the #FcCharset for @fcfont; must not be modified
+ * or freed.
+ *
+ * Since: 1.6
+ **/
+FcCharSet *
+pango_fc_decoder_get_charset (PangoFcDecoder *decoder,
+ PangoFcFont *fcfont)
+{
+ g_return_val_if_fail (PANGO_IS_FC_DECODER (decoder), NULL);
+
+ return PANGO_FC_DECODER_GET_CLASS (decoder)->get_charset (decoder, fcfont);
+}
+
+/**
+ * pango_fc_decoder_get_glyph:
+ * @decoder: a #PangoFcDecoder
+ * @fcfont: a #PangoFcFont to query.
+ * @wc: the Unicode code point to convert to a single #PangoGlyph.
+ *
+ * Generates a #PangoGlyph for the given Unicode point using the
+ * custom decoder. For complex scripts where there can be multiple
+ * glyphs for a single character, the decoder will return whatever
+ * glyph is most convenient for it. (Usually whatever glyph is directly
+ * in the fonts character map table.)
+ *
+ * Return value: the glyph index, or 0 if the glyph isn't
+ * covered by the font.
+ *
+ * Since: 1.6
+ **/
+PangoGlyph
+pango_fc_decoder_get_glyph (PangoFcDecoder *decoder,
+ PangoFcFont *fcfont,
+ guint32 wc)
+{
+ g_return_val_if_fail (PANGO_IS_FC_DECODER (decoder), 0);
+
+ return PANGO_FC_DECODER_GET_CLASS (decoder)->get_glyph (decoder, fcfont, wc);
+}
diff --git a/trunk/pango/pangofc-decoder.h b/trunk/pango/pangofc-decoder.h
new file mode 100644
index 00000000..8e341469
--- /dev/null
+++ b/trunk/pango/pangofc-decoder.h
@@ -0,0 +1,110 @@
+/* Pango
+ * pangofc-decoder.h: Custom encoders/decoders on a per-font basis.
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_DECODER_H_
+#define __PANGO_DECODER_H_
+
+#include <pango/pangofc-font.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_FC_DECODER (pango_fc_decoder_get_type())
+#define PANGO_FC_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FC_DECODER, PangoFcDecoder))
+#define PANGO_IS_FC_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FC_DECODER))
+
+typedef struct _PangoFcDecoder PangoFcDecoder;
+typedef struct _PangoFcDecoderClass PangoFcDecoderClass;
+
+#define PANGO_FC_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FC_DECODER, PangoFcDecoderClass))
+#define PANGO_IS_FC_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FC_DECODER))
+#define PANGO_FC_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FC_DECODER, PangoFcDecoderClass))
+
+/**
+ * PangoFcDecoder:
+ *
+ * #PangoFcDecoder is a virtual base class that implementations will
+ * inherit from. It's the interface that is used to define a custom
+ * encoding for a font. These objects are created in your code from a
+ * function callback that was originally registered with
+ * pango_fc_font_map_add_decoder_find_func(). Pango requires
+ * information about the supported charset for a font as well as the
+ * individual character to glyph conversions. Pango gets that
+ * information via the #get_charset and #get_glyph callbacks into your
+ * object implementation.
+ *
+ * Since: 1.6
+ **/
+struct _PangoFcDecoder
+{
+ /*< private >*/
+ GObject parent_instance;
+};
+
+/**
+ * PangoFcDecoderClass:
+ * @get_charset: This returns an #FcCharset given a #PangoFcFont that
+ * includes a list of supported characters in the font. The
+ * #FcCharSet that is returned should be an internal reference to your
+ * code. Pango will not free this structure. It is important that
+ * you make this callback fast because this callback is called
+ * separately for each character to determine Unicode coverage.
+ * @get_glyph: This returns a single #PangoGlyph for a given Unicode
+ * code point.
+ *
+ * Class structure for #PangoFcDecoder.
+ *
+ * Since: 1.6
+ **/
+struct _PangoFcDecoderClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ /* vtable - not signals */
+ /*< public >*/
+ FcCharSet *(*get_charset) (PangoFcDecoder *decoder,
+ PangoFcFont *fcfont);
+ PangoGlyph (*get_glyph) (PangoFcDecoder *decoder,
+ PangoFcFont *fcfont,
+ guint32 wc);
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+GType pango_fc_decoder_get_type (void) G_GNUC_CONST;
+
+FcCharSet *pango_fc_decoder_get_charset (PangoFcDecoder *decoder,
+ PangoFcFont *fcfont);
+
+PangoGlyph pango_fc_decoder_get_glyph (PangoFcDecoder *decoder,
+ PangoFcFont *fcfont,
+ guint32 wc);
+
+G_END_DECLS
+
+#endif /* __PANGO_DECODER_H_ */
+
diff --git a/trunk/pango/pangofc-font.c b/trunk/pango/pangofc-font.c
new file mode 100644
index 00000000..dec1f680
--- /dev/null
+++ b/trunk/pango/pangofc-font.c
@@ -0,0 +1,933 @@
+/* Pango
+ * pangofc-font.c: Shared interfaces for fontconfig-based backends
+ *
+ * Copyright (C) 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pangofc-font.h"
+#include "pangofc-fontmap.h"
+#include "pangofc-private.h"
+#include "pango-layout.h"
+#include "pango-modules.h"
+#include "pango-impl-utils.h"
+
+#include <fontconfig/fcfreetype.h>
+
+#include FT_TRUETYPE_TABLES_H
+
+enum {
+ PROP_0,
+ PROP_PATTERN
+};
+
+typedef struct _GUnicharToGlyphCacheEntry GUnicharToGlyphCacheEntry;
+
+/* An entry in the fixed-size cache for the gunichar -> glyph mapping.
+ * The cache is indexed by the lower N bits of the gunichar (see
+ * GLYPH_CACHE_NUM_ENTRIES). For scripts with few code points,
+ * this should provide pretty much instant lookups.
+ *
+ * The "ch" field is zero if that cache entry is invalid.
+ */
+struct _GUnicharToGlyphCacheEntry
+{
+ gunichar ch;
+ PangoGlyph glyph;
+};
+
+typedef struct _PangoFcFontPrivate PangoFcFontPrivate;
+
+struct _PangoFcFontPrivate
+{
+ PangoFcDecoder *decoder;
+ gpointer context_key;
+ GUnicharToGlyphCacheEntry *char_to_glyph_cache;
+};
+
+#define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */
+#define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1)
+
+static gboolean pango_fc_font_real_has_char (PangoFcFont *font,
+ gunichar wc);
+static guint pango_fc_font_real_get_glyph (PangoFcFont *font,
+ gunichar wc);
+
+static void pango_fc_font_finalize (GObject *object);
+static void pango_fc_font_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static PangoEngineShape * pango_fc_font_find_shaper (PangoFont *font,
+ PangoLanguage *language,
+ guint32 ch);
+static PangoCoverage * pango_fc_font_get_coverage (PangoFont *font,
+ PangoLanguage *language);
+static PangoFontMetrics * pango_fc_font_get_metrics (PangoFont *font,
+ PangoLanguage *language);
+static PangoFontMap * pango_fc_font_get_font_map (PangoFont *font);
+static PangoFontDescription *pango_fc_font_describe (PangoFont *font);
+static PangoFontDescription *pango_fc_font_describe_absolute (PangoFont *font);
+
+
+#define PANGO_FC_FONT_LOCK_FACE(font) (PANGO_FC_FONT_GET_CLASS (font)->lock_face (font))
+#define PANGO_FC_FONT_UNLOCK_FACE(font) (PANGO_FC_FONT_GET_CLASS (font)->unlock_face (font))
+
+G_DEFINE_TYPE (PangoFcFont, pango_fc_font, PANGO_TYPE_FONT)
+
+static void
+pango_fc_font_class_init (PangoFcFontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+
+ class->has_char = pango_fc_font_real_has_char;
+ class->get_glyph = pango_fc_font_real_get_glyph;
+ class->get_unknown_glyph = NULL;
+
+ object_class->finalize = pango_fc_font_finalize;
+ object_class->set_property = pango_fc_font_set_property;
+ font_class->describe = pango_fc_font_describe;
+ font_class->describe_absolute = pango_fc_font_describe_absolute;
+ font_class->find_shaper = pango_fc_font_find_shaper;
+ font_class->get_coverage = pango_fc_font_get_coverage;
+ font_class->get_metrics = pango_fc_font_get_metrics;
+ font_class->get_font_map = pango_fc_font_get_font_map;
+
+ g_object_class_install_property (object_class, PROP_PATTERN,
+ g_param_spec_pointer ("pattern",
+ "Pattern",
+ "The fontconfig pattern for this font",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (PangoFcFontPrivate));
+}
+
+static void
+pango_fc_font_init (PangoFcFont *fcfont)
+{
+ fcfont->priv = G_TYPE_INSTANCE_GET_PRIVATE (fcfont,
+ PANGO_TYPE_FC_FONT,
+ PangoFcFontPrivate);
+}
+
+static void
+free_metrics_info (PangoFcMetricsInfo *info)
+{
+ pango_font_metrics_unref (info->metrics);
+ g_slice_free (PangoFcMetricsInfo, info);
+}
+
+static void
+pango_fc_font_finalize (GObject *object)
+{
+ PangoFcFont *fcfont = PANGO_FC_FONT (object);
+ PangoFcFontPrivate *priv = fcfont->priv;
+
+ g_slist_foreach (fcfont->metrics_by_lang, (GFunc)free_metrics_info, NULL);
+ g_slist_free (fcfont->metrics_by_lang);
+
+ if (fcfont->fontmap)
+ _pango_fc_font_map_remove (PANGO_FC_FONT_MAP (fcfont->fontmap), fcfont);
+
+ FcPatternDestroy (fcfont->font_pattern);
+ pango_font_description_free (fcfont->description);
+
+ if (priv->decoder)
+ _pango_fc_font_set_decoder (fcfont, NULL);
+
+ g_free (priv->char_to_glyph_cache);
+
+ G_OBJECT_CLASS (pango_fc_font_parent_class)->finalize (object);
+}
+
+static gboolean
+pattern_is_hinted (FcPattern *pattern)
+{
+ FcBool hinting;
+
+ if (FcPatternGetBool (pattern,
+ FC_HINTING, 0, &hinting) != FcResultMatch)
+ hinting = FcTrue;
+
+ return hinting;
+}
+
+static gboolean
+pattern_is_transformed (FcPattern *pattern)
+{
+ FcMatrix *fc_matrix;
+
+ if (FcPatternGetMatrix (pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
+ {
+ FT_Matrix ft_matrix;
+
+ ft_matrix.xx = 0x10000L * fc_matrix->xx;
+ ft_matrix.yy = 0x10000L * fc_matrix->yy;
+ ft_matrix.xy = 0x10000L * fc_matrix->xy;
+ ft_matrix.yx = 0x10000L * fc_matrix->yx;
+
+ return ((ft_matrix.xy | ft_matrix.yx) != 0 ||
+ ft_matrix.xx != 0x10000L ||
+ ft_matrix.yy != 0x10000L);
+ }
+ else
+ return FALSE;
+}
+
+static void
+pango_fc_font_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_PATTERN:
+ {
+ PangoFcFont *fcfont = PANGO_FC_FONT (object);
+ FcPattern *pattern = g_value_get_pointer (value);
+
+ g_return_if_fail (pattern != NULL);
+ g_return_if_fail (fcfont->font_pattern == NULL);
+
+ FcPatternReference (pattern);
+ fcfont->font_pattern = pattern;
+ fcfont->description = pango_fc_font_description_from_pattern (pattern, TRUE);
+ fcfont->is_hinted = pattern_is_hinted (pattern);
+ fcfont->is_transformed = pattern_is_transformed (pattern);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static PangoFontDescription *
+pango_fc_font_describe (PangoFont *font)
+{
+ PangoFcFont *fcfont = (PangoFcFont *)font;
+
+ return pango_font_description_copy (fcfont->description);
+}
+
+static PangoFontDescription *
+pango_fc_font_describe_absolute (PangoFont *font)
+{
+ PangoFcFont *fcfont = (PangoFcFont *)font;
+ PangoFontDescription *desc = pango_font_description_copy (fcfont->description);
+ double size;
+
+ if (FcPatternGetDouble (fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
+ pango_font_description_set_absolute_size (desc, size * PANGO_SCALE);
+
+ return desc;
+}
+
+static PangoMap *
+pango_fc_get_shaper_map (PangoLanguage *language)
+{
+ static guint engine_type_id = 0;
+ static guint render_type_id = 0;
+
+ if (engine_type_id == 0)
+ {
+ engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_SHAPE);
+ render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_FC);
+ }
+
+ return pango_find_map (language, engine_type_id, render_type_id);
+}
+
+static PangoEngineShape *
+pango_fc_font_find_shaper (PangoFont *font,
+ PangoLanguage *language,
+ guint32 ch)
+{
+ PangoMap *shaper_map = NULL;
+ PangoScript script;
+
+ shaper_map = pango_fc_get_shaper_map (language);
+ script = pango_script_for_unichar (ch);
+ return (PangoEngineShape *)pango_map_get_engine (shaper_map, script);
+}
+
+static PangoCoverage *
+pango_fc_font_get_coverage (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoFcFont *fcfont = (PangoFcFont *)font;
+ PangoFcFontPrivate *priv = fcfont->priv;
+ FcCharSet *charset;
+
+ if (priv->decoder)
+ {
+ charset = pango_fc_decoder_get_charset (priv->decoder, fcfont);
+ return _pango_fc_font_map_fc_to_coverage (charset);
+ }
+
+ return _pango_fc_font_map_get_coverage (PANGO_FC_FONT_MAP (fcfont->fontmap),
+ fcfont);
+}
+
+/* For Xft, it would be slightly more efficient to simply to
+ * call Xft, and also more robust against changes in Xft.
+ * But for now, we simply use the same code for all backends.
+ *
+ * The code in this function is partly based on code from Xft,
+ * Copyright 2000 Keith Packard
+ */
+static void
+get_face_metrics (PangoFcFont *fcfont,
+ PangoFontMetrics *metrics)
+{
+ FT_Face face = PANGO_FC_FONT_LOCK_FACE (fcfont);
+ FcMatrix *fc_matrix;
+ FT_Matrix ft_matrix;
+ TT_OS2 *os2;
+ gboolean have_transform = FALSE;
+
+ if (!face)
+ {
+ metrics->descent = 0;
+ metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT;
+ metrics->underline_thickness = PANGO_SCALE;
+ metrics->underline_position = - PANGO_SCALE;
+ metrics->strikethrough_thickness = PANGO_SCALE;
+ metrics->strikethrough_position = PANGO_SCALE * (PANGO_UNKNOWN_GLYPH_HEIGHT/2);
+ return;
+ }
+
+ if (FcPatternGetMatrix (fcfont->font_pattern,
+ FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
+ {
+ ft_matrix.xx = 0x10000L * fc_matrix->xx;
+ ft_matrix.yy = 0x10000L * fc_matrix->yy;
+ ft_matrix.xy = 0x10000L * fc_matrix->xy;
+ ft_matrix.yx = 0x10000L * fc_matrix->yx;
+
+ have_transform = (ft_matrix.xx != 0x10000 || ft_matrix.xy != 0 ||
+ ft_matrix.yx != 0 || ft_matrix.yy != 0x10000);
+ }
+
+ if (have_transform)
+ {
+ FT_Vector vector;
+
+ vector.x = 0;
+ vector.y = face->size->metrics.descender;
+ FT_Vector_Transform (&vector, &ft_matrix);
+ metrics->descent = - PANGO_UNITS_26_6 (vector.y);
+
+ vector.x = 0;
+ vector.y = face->size->metrics.ascender;
+ FT_Vector_Transform (&vector, &ft_matrix);
+ metrics->ascent = PANGO_UNITS_26_6 (vector.y);
+ }
+ else if (fcfont->is_hinted ||
+ (face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
+ {
+ metrics->descent = - PANGO_UNITS_26_6 (face->size->metrics.descender);
+ metrics->ascent = PANGO_UNITS_26_6 (face->size->metrics.ascender);
+ }
+ else
+ {
+ FT_Fixed ascender, descender;
+
+ descender = FT_MulFix (face->descender, face->size->metrics.y_scale);
+ metrics->descent = - PANGO_UNITS_26_6 (descender);
+
+ ascender = FT_MulFix (face->ascender, face->size->metrics.y_scale);
+ metrics->ascent = PANGO_UNITS_26_6 (ascender);
+ }
+
+ /* Versions of FreeType < 2.1.8 get underline thickness wrong
+ * for Postscript fonts (always zero), so we need a fallback
+ */
+ if (face->underline_thickness == 0)
+ {
+ metrics->underline_thickness = (PANGO_SCALE * face->size->metrics.y_ppem) / 14;
+ metrics->underline_position = - metrics->underline_thickness;
+ }
+ else
+ {
+ FT_Fixed ft_thickness, ft_position;
+
+ ft_thickness = FT_MulFix (face->underline_thickness, face->size->metrics.y_scale);
+ metrics->underline_thickness = PANGO_UNITS_26_6 (ft_thickness);
+
+ ft_position = FT_MulFix (face->underline_position, face->size->metrics.y_scale);
+ metrics->underline_position = PANGO_UNITS_26_6 (ft_position);
+ }
+
+ os2 = FT_Get_Sfnt_Table (face, ft_sfnt_os2);
+ if (os2 && os2->version != 0xFFFF && os2->yStrikeoutSize != 0)
+ {
+ FT_Fixed ft_thickness, ft_position;
+
+ ft_thickness = FT_MulFix (os2->yStrikeoutSize, face->size->metrics.y_scale);
+ metrics->strikethrough_thickness = PANGO_UNITS_26_6 (ft_thickness);
+
+ ft_position = FT_MulFix (os2->yStrikeoutPosition, face->size->metrics.y_scale);
+ metrics->strikethrough_position = PANGO_UNITS_26_6 (ft_position);
+ }
+ else
+ {
+ metrics->strikethrough_thickness = metrics->underline_thickness;
+ metrics->strikethrough_position = (PANGO_SCALE * face->size->metrics.y_ppem) / 4;
+ }
+
+ /* If hinting is on for this font, quantize the underline and strikethrough position
+ * to integer values.
+ */
+ if (fcfont->is_hinted)
+ {
+ pango_quantize_line_geometry (&metrics->underline_thickness,
+ &metrics->underline_position);
+ pango_quantize_line_geometry (&metrics->strikethrough_thickness,
+ &metrics->strikethrough_position);
+ }
+
+ PANGO_FC_FONT_UNLOCK_FACE (fcfont);
+}
+
+static int
+max_glyph_width (PangoLayout *layout)
+{
+ int max_width = 0;
+ GSList *l, *r;
+
+ for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
+ {
+ PangoLayoutLine *line = l->data;
+
+ for (r = line->runs; r; r = r->next)
+ {
+ PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ if (glyphs->glyphs[i].geometry.width > max_width)
+ max_width = glyphs->glyphs[i].geometry.width;
+ }
+ }
+
+ return max_width;
+}
+
+PangoFontMetrics *
+pango_fc_font_create_metrics_for_context (PangoFcFont *fcfont,
+ PangoContext *context)
+{
+ PangoFontMetrics *metrics;
+ PangoLayout *layout;
+ PangoRectangle extents;
+ PangoLanguage *language = pango_context_get_language (context);
+ const char *sample_str = pango_language_get_sample_string (language);
+ PangoFontDescription *desc = pango_font_describe_with_absolute_size (fcfont);
+
+ metrics = pango_font_metrics_new ();
+
+ get_face_metrics (fcfont, metrics);
+
+ layout = pango_layout_new (context);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+
+ pango_layout_set_text (layout, sample_str, -1);
+ pango_layout_get_extents (layout, NULL, &extents);
+
+ metrics->approximate_char_width =
+ extents.width / g_utf8_strlen (sample_str, -1);
+
+ pango_layout_set_text (layout, "0123456789", -1);
+ metrics->approximate_digit_width = max_glyph_width (layout);
+
+ g_object_unref (layout);
+
+ return metrics;
+}
+
+/* This function is cut-and-pasted into pangocairo-fcfont.c - it might be
+ * better to add a virtual fcfont->create_context (font).
+ */
+static PangoFontMetrics *
+pango_fc_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoFcFont *fcfont = PANGO_FC_FONT (font);
+ PangoFcMetricsInfo *info = NULL; /* Quiet gcc */
+ GSList *tmp_list;
+
+ const char *sample_str = pango_language_get_sample_string (language);
+
+ tmp_list = fcfont->metrics_by_lang;
+ while (tmp_list)
+ {
+ info = tmp_list->data;
+
+ if (info->sample_str == sample_str) /* We _don't_ need strcmp */
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list)
+ {
+ PangoContext *context;
+
+ if (!fcfont->fontmap)
+ return pango_font_metrics_new ();
+
+ info = g_slice_new0 (PangoFcMetricsInfo);
+
+ fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang,
+ info);
+
+ info->sample_str = sample_str;
+
+ context = pango_fc_font_map_create_context (PANGO_FC_FONT_MAP (fcfont->fontmap));
+ pango_context_set_language (context, language);
+
+ info->metrics = pango_fc_font_create_metrics_for_context (fcfont, context);
+
+ g_object_unref (context);
+ }
+
+ return pango_font_metrics_ref (info->metrics);
+}
+
+static PangoFontMap *
+pango_fc_font_get_font_map (PangoFont *font)
+{
+ PangoFcFont *fcfont = PANGO_FC_FONT (font);
+
+ return fcfont->fontmap;
+}
+
+static gboolean
+pango_fc_font_real_has_char (PangoFcFont *font,
+ gunichar wc)
+{
+ FcCharSet *charset;
+
+ if (FcPatternGetCharSet (font->font_pattern,
+ FC_CHARSET, 0, &charset) != FcResultMatch)
+ return FALSE;
+
+ return FcCharSetHasChar (charset, wc);
+}
+
+static guint
+pango_fc_font_real_get_glyph (PangoFcFont *font,
+ gunichar wc)
+{
+ FT_Face face;
+ FT_UInt index;
+
+ guint idx;
+ GUnicharToGlyphCacheEntry *entry;
+
+ PangoFcFontPrivate *priv = font->priv;
+
+ if (G_UNLIKELY (priv->char_to_glyph_cache == NULL))
+ {
+ priv->char_to_glyph_cache = g_new0 (GUnicharToGlyphCacheEntry, GLYPH_CACHE_NUM_ENTRIES);
+ /* Make sure all cache entries are invalid initially */
+ priv->char_to_glyph_cache[0].ch = 1; /* char 1 cannot happen in bucket 0 */
+ }
+
+ idx = wc & GLYPH_CACHE_MASK;
+ entry = priv->char_to_glyph_cache + idx;
+
+ if (entry->ch != wc)
+ {
+ face = PANGO_FC_FONT_LOCK_FACE (font);
+ index = FcFreeTypeCharIndex (face, wc);
+ if (index > (FT_UInt)face->num_glyphs)
+ index = 0;
+
+ entry->ch = wc;
+ entry->glyph = index;
+
+ PANGO_FC_FONT_UNLOCK_FACE (font);
+ }
+
+ return entry->glyph;
+}
+
+/**
+ * pango_fc_font_lock_face:
+ * @font: a #PangoFcFont.
+ *
+ * Gets the FreeType <type>FT_Face</type> associated with a font,
+ * This face will be kept around until you call
+ * pango_fc_font_unlock_face().
+ *
+ * Return value: the FreeType <type>FT_Face</type> associated with @font.
+ *
+ * Since: 1.4
+ **/
+FT_Face
+pango_fc_font_lock_face (PangoFcFont *font)
+{
+ g_return_val_if_fail (PANGO_IS_FC_FONT (font), NULL);
+
+ return PANGO_FC_FONT_LOCK_FACE (font);
+}
+
+/**
+ * pango_fc_font_unlock_face:
+ * @font: a #PangoFcFont.
+ *
+ * Releases a font previously obtained with
+ * pango_fc_font_lock_face().
+ *
+ * Since: 1.4
+ **/
+void
+pango_fc_font_unlock_face (PangoFcFont *font)
+{
+ g_return_if_fail (PANGO_IS_FC_FONT (font));
+
+ PANGO_FC_FONT_UNLOCK_FACE (font);
+}
+
+/**
+ * pango_fc_font_has_char:
+ * @font: a #PangoFcFont
+ * @wc: Unicode codepoint to look up
+ *
+ * Determines whether @font has a glyph for the codepoint @wc.
+ *
+ * Return value: %TRUE if @font has the requested codepoint.
+ *
+ * Since: 1.4
+ **/
+gboolean
+pango_fc_font_has_char (PangoFcFont *font,
+ gunichar wc)
+{
+ PangoFcFontPrivate *priv = font->priv;
+ FcCharSet *charset;
+
+ g_return_val_if_fail (PANGO_IS_FC_FONT (font), FALSE);
+
+ if (priv->decoder)
+ {
+ charset = pango_fc_decoder_get_charset (priv->decoder, font);
+ return FcCharSetHasChar (charset, wc);
+ }
+
+ return PANGO_FC_FONT_GET_CLASS (font)->has_char (font, wc);
+}
+
+/**
+ * pango_fc_font_get_glyph:
+ * @font: a #PangoFcFont
+ * @wc: Unicode character to look up
+ *
+ * Gets the glyph index for a given Unicode character
+ * for @font. If you only want to determine
+ * whether the font has the glyph, use pango_fc_font_has_char().
+ *
+ * Return value: the glyph index, or 0, if the Unicode
+ * character doesn't exist in the font.
+ *
+ * Since: 1.4
+ **/
+PangoGlyph
+pango_fc_font_get_glyph (PangoFcFont *font,
+ gunichar wc)
+{
+ PangoFcFontPrivate *priv = font->priv;
+
+ /* Replace NBSP with a normal space; it should be invariant that
+ * they shape the same other than breaking properties.
+ */
+ if (wc == 0xA0)
+ wc = 0x20;
+
+ if (priv->decoder)
+ return pango_fc_decoder_get_glyph (priv->decoder, font, wc);
+
+ return PANGO_FC_FONT_GET_CLASS (font)->get_glyph (font, wc);
+}
+
+
+/**
+ * pango_fc_font_get_unknown_glyph:
+ * @font: a #PangoFcFont
+ * @wc: the Unicode character for which a glyph is needed.
+ *
+ * Returns the index of a glyph suitable for drawing @wc as an
+ * unknown character.
+ *
+ * Use PANGO_GET_UNKNOWN_GLYPH() instead.
+ *
+ * Return value: a glyph index into @font.
+ *
+ * Since: 1.4
+ **/
+PangoGlyph
+pango_fc_font_get_unknown_glyph (PangoFcFont *font,
+ gunichar wc)
+{
+ if (font && PANGO_FC_FONT_GET_CLASS (font)->get_unknown_glyph)
+ return PANGO_FC_FONT_GET_CLASS (font)->get_unknown_glyph (font, wc);
+
+ return PANGO_GET_UNKNOWN_GLYPH (wc);
+}
+
+void
+_pango_fc_font_shutdown (PangoFcFont *font)
+{
+ g_return_if_fail (PANGO_IS_FC_FONT (font));
+
+ if (PANGO_FC_FONT_GET_CLASS (font)->shutdown)
+ PANGO_FC_FONT_GET_CLASS (font)->shutdown (font);
+}
+
+/**
+ * pango_fc_font_kern_glyphs
+ * @font: a #PangoFcFont
+ * @glyphs: a #PangoGlyphString
+ *
+ * Adjust each adjacent pair of glyphs in @glyphs according to
+ * kerning information in @font.
+ *
+ * Since: 1.4
+ **/
+void
+pango_fc_font_kern_glyphs (PangoFcFont *font,
+ PangoGlyphString *glyphs)
+{
+ FT_Face face;
+ FT_Error error;
+ FT_Vector kerning;
+ int i;
+ gboolean hinting = font->is_hinted;
+
+ g_return_if_fail (PANGO_IS_FC_FONT (font));
+ g_return_if_fail (glyphs != NULL);
+
+ face = PANGO_FC_FONT_LOCK_FACE (font);
+ if (!face)
+ return;
+
+ if (!FT_HAS_KERNING (face))
+ {
+ PANGO_FC_FONT_UNLOCK_FACE (font);
+ return;
+ }
+
+ for (i = 1; i < glyphs->num_glyphs; ++i)
+ {
+ error = FT_Get_Kerning (face,
+ glyphs->glyphs[i-1].glyph,
+ glyphs->glyphs[i].glyph,
+ ft_kerning_default,
+ &kerning);
+
+ if (error == FT_Err_Ok) {
+ int adjustment = PANGO_UNITS_26_6 (kerning.x);
+
+ if (hinting)
+ adjustment = PANGO_UNITS_ROUND (adjustment);
+
+ glyphs->glyphs[i-1].geometry.width += adjustment;
+ }
+ }
+
+ PANGO_FC_FONT_UNLOCK_FACE (font);
+}
+
+/**
+ * _pango_fc_font_get_decoder
+ * @font: a #PangoFcFont
+ *
+ * This will return any custom decoder set on this font.
+ *
+ * Return value: The custom decoder
+ *
+ * Since: 1.6
+ **/
+
+PangoFcDecoder *
+_pango_fc_font_get_decoder (PangoFcFont *font)
+{
+ PangoFcFontPrivate *priv = font->priv;
+
+ return priv->decoder;
+}
+
+/**
+ * _pango_fc_font_set_decoder
+ * @font: a #PangoFcFont
+ * @decoder: a #PangoFcDecoder to set for this font
+ *
+ * This sets a custom decoder for this font. Any previous decoder
+ * will be released before this one is set.
+ *
+ * Since: 1.6
+ **/
+
+void
+_pango_fc_font_set_decoder (PangoFcFont *font,
+ PangoFcDecoder *decoder)
+{
+ PangoFcFontPrivate *priv = font->priv;
+
+ if (priv->decoder)
+ g_object_unref (priv->decoder);
+
+ priv->decoder = decoder;
+
+ if (priv->decoder)
+ g_object_ref (priv->decoder);
+}
+
+gpointer
+_pango_fc_font_get_context_key (PangoFcFont *fcfont)
+{
+ PangoFcFontPrivate *priv = fcfont->priv;
+
+ return priv->context_key;
+}
+
+void
+_pango_fc_font_set_context_key (PangoFcFont *fcfont,
+ gpointer context_key)
+{
+ PangoFcFontPrivate *priv = fcfont->priv;
+
+ priv->context_key = context_key;
+}
+
+static FT_Glyph_Metrics *
+get_per_char (FT_Face face,
+ FT_Int32 load_flags,
+ PangoGlyph glyph)
+{
+ FT_Error error;
+ FT_Glyph_Metrics *result;
+
+ error = FT_Load_Glyph (face, glyph, load_flags);
+ if (error == FT_Err_Ok)
+ result = &face->glyph->metrics;
+ else
+ result = NULL;
+
+ return result;
+}
+
+/**
+ * pango_fc_font_get_raw_extents:
+ * @fcfont: a #PangoFcFont
+ * @load_flags: flags to pass to FT_Load_Glyph()
+ * @glyph: the glyph index to load
+ * @ink_rect: location to store ink extents of the glyph, or %NULL
+ * @logical_rect: location to store logical extents of the glyph or %NULL
+ *
+ * Gets the extents of a single glyph from a font. The extents are in
+ * user space; that is, they are not transformed by any matrix in effect
+ * for the font.
+ *
+ * Long term, this functionality probably belongs in the default
+ * implementation of the get_glyph_extents() virtual function.
+ * The other possibility would be to to make it public in something
+ * like it's current form, and also expose glyph information
+ * caching functionality similar to pango_ft2_font_set_glyph_info().
+ *
+ * Since: 1.6
+ **/
+void
+pango_fc_font_get_raw_extents (PangoFcFont *fcfont,
+ FT_Int32 load_flags,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ FT_Glyph_Metrics *gm;
+ FT_Face face;
+
+ g_return_if_fail (PANGO_IS_FC_FONT (fcfont));
+
+ face = PANGO_FC_FONT_LOCK_FACE (fcfont);
+
+ if (glyph == PANGO_GLYPH_EMPTY)
+ gm = NULL;
+ else
+ gm = get_per_char (face, load_flags, glyph);
+
+ if (gm)
+ {
+ if (ink_rect)
+ {
+ ink_rect->x = PANGO_UNITS_26_6 (gm->horiBearingX);
+ ink_rect->width = PANGO_UNITS_26_6 (gm->width);
+ ink_rect->y = -PANGO_UNITS_26_6 (gm->horiBearingY);
+ ink_rect->height = PANGO_UNITS_26_6 (gm->height);
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->width = PANGO_UNITS_26_6 (gm->horiAdvance);
+ if (fcfont->is_hinted ||
+ (face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
+ {
+ logical_rect->y = - PANGO_UNITS_26_6 (face->size->metrics.ascender);
+ logical_rect->height = PANGO_UNITS_26_6 (face->size->metrics.ascender - face->size->metrics.descender);
+ }
+ else
+ {
+ FT_Fixed ascender, descender;
+
+ ascender = FT_MulFix (face->ascender, face->size->metrics.y_scale);
+ descender = FT_MulFix (face->descender, face->size->metrics.y_scale);
+
+ logical_rect->y = - PANGO_UNITS_26_6 (ascender);
+ logical_rect->height = PANGO_UNITS_26_6 (ascender - descender);
+ }
+ }
+ }
+ else
+ {
+ if (ink_rect)
+ {
+ ink_rect->x = 0;
+ ink_rect->width = 0;
+ ink_rect->y = 0;
+ ink_rect->height = 0;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->width = 0;
+ logical_rect->y = 0;
+ logical_rect->height = 0;
+ }
+ }
+
+ PANGO_FC_FONT_UNLOCK_FACE (fcfont);
+}
+
diff --git a/trunk/pango/pangofc-font.h b/trunk/pango/pangofc-font.h
new file mode 100644
index 00000000..ae16b168
--- /dev/null
+++ b/trunk/pango/pangofc-font.h
@@ -0,0 +1,151 @@
+/* Pango
+ * pangofc-font.h: Base fontmap type for fontconfig-based backends
+ *
+ * Copyright (C) 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_FC_FONT_H__
+#define __PANGO_FC_FONT_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <fontconfig/fontconfig.h>
+#include <pango/pango-font.h>
+#include <pango/pango-fontmap.h>
+#include <pango/pango-glyph.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_FC_FONT (pango_fc_font_get_type ())
+#define PANGO_FC_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FC_FONT, PangoFcFont))
+#define PANGO_IS_FC_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FC_FONT))
+
+typedef struct _PangoFcFont PangoFcFont;
+typedef struct _PangoFcFontClass PangoFcFontClass;
+
+#if defined(PANGO_ENABLE_ENGINE) || defined(PANGO_ENABLE_BACKEND)
+
+/**
+ * PANGO_RENDER_TYPE_FC:
+ *
+ * A string constant used to identify shape engines that work
+ * with the fontconfig based backends. See the @engine_type field
+ * of #PangoEngineInfo.
+ **/
+#define PANGO_RENDER_TYPE_FC "PangoRenderFc"
+
+#ifdef PANGO_ENABLE_BACKEND
+
+#define PANGO_FC_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FC_FONT, PangoFcFontClass))
+#define PANGO_IS_FC_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FC_FONT))
+#define PANGO_FC_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FC_FONT, PangoFcFontClass))
+
+/**
+ * PangoFcFont:
+ *
+ * #PangoFcFont is a base class for font implementations
+ * using the Fontconfig and FreeType libraries and is used in
+ * conjunction with #PangoFcFontMap. When deriving from this
+ * class, you need to implement all of its virtual functions
+ * other than shutdown() along with the get_glyph_extents()
+ * virtual function from #PangoFont.
+ **/
+struct _PangoFcFont
+{
+ PangoFont parent_instance;
+
+ FcPattern *font_pattern; /* fully resolved pattern */
+ PangoFontMap *fontmap; /* associated map */
+ gpointer priv; /* used internally */
+ PangoMatrix matrix; /* used internally */
+ PangoFontDescription *description;
+
+ GSList *metrics_by_lang;
+
+ guint is_hinted : 1;
+ guint is_transformed : 1;
+};
+
+/**
+ * PangoFcFontClass:
+ * @lock_face: Returns the FT_Face of the font and increases
+ * the reference count for the face by one.
+ * @unlock_face: Decreases the reference count for the
+ * FT_Face of the font by one. When the count is zero,
+ * the #PangoFcFont subclass is allowed to free the
+ * FT_Face.
+ * @has_char: Return %TRUE if the the font contains a glyph
+ * corresponding to the specified character.
+ * @get_glyph: Gets the glyph that corresponds to the given
+ * Unicode character.
+ * @get_unknown_glyph: Gets the glyph that should be used to
+ * display an unknown-glyph indication for the specified
+ * Unicode character.
+ * May be %NULL.
+ * @shutdown: Performs any font-specific shutdown code that
+ * needs to be done when pango_fc_font_map_shutdown is called.
+ * May be %NULL.
+ *
+ * Class structure for #PangoFcFont.
+ **/
+struct _PangoFcFontClass
+{
+ /*< private >*/
+ PangoFontClass parent_class;
+
+ /*< public >*/
+ FT_Face (*lock_face) (PangoFcFont *font);
+ void (*unlock_face) (PangoFcFont *font);
+ gboolean (*has_char) (PangoFcFont *font,
+ gunichar wc);
+ guint (*get_glyph) (PangoFcFont *font,
+ gunichar wc);
+ PangoGlyph (*get_unknown_glyph) (PangoFcFont *font,
+ gunichar wc);
+ void (*shutdown) (PangoFcFont *font);
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+gboolean pango_fc_font_has_char (PangoFcFont *font,
+ gunichar wc);
+guint pango_fc_font_get_glyph (PangoFcFont *font,
+ gunichar wc);
+#ifndef PANGO_DISABLE_DEPRECATED
+PangoGlyph pango_fc_font_get_unknown_glyph (PangoFcFont *font,
+ gunichar wc);
+#endif /* PANGO_DISABLE_DEPRECATED */
+void pango_fc_font_kern_glyphs (PangoFcFont *font,
+ PangoGlyphString *glyphs);
+
+#endif /* PANGO_ENABLE_ENGINE || PANGO_ENABLE_BACKEND */
+
+GType pango_fc_font_get_type (void) G_GNUC_CONST;
+
+FT_Face pango_fc_font_lock_face (PangoFcFont *font);
+void pango_fc_font_unlock_face (PangoFcFont *font);
+
+G_END_DECLS
+#endif /* __PANGO_FC_FONT_H__ */
diff --git a/trunk/pango/pangofc-fontmap.c b/trunk/pango/pangofc-fontmap.c
new file mode 100644
index 00000000..267dc483
--- /dev/null
+++ b/trunk/pango/pangofc-fontmap.c
@@ -0,0 +1,2055 @@
+/* Pango
+ * pangofc-fontmap.c: Base fontmap type for fontconfig-based backends
+ *
+ * Copyright (C) 2000-2003 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Size of fontset cache */
+#define FONTSET_CACHE_SIZE 64
+
+#include <config.h>
+#include <math.h>
+
+#include "pango-context.h"
+#include "pangofc-fontmap.h"
+#include "pangofc-private.h"
+#include "pango-impl-utils.h"
+#include "modules.h"
+#include "pango-enum-types.h"
+
+typedef struct _PangoFcCoverageKey PangoFcCoverageKey;
+typedef struct _PangoFcFace PangoFcFace;
+typedef struct _PangoFcFamily PangoFcFamily;
+typedef struct _PangoFcPatternSet PangoFcPatternSet;
+typedef struct _PangoFcFindFuncInfo PangoFcFindFuncInfo;
+typedef struct _FontsetHashKey FontsetHashKey;
+typedef struct _FontHashKey FontHashKey;
+
+#define PANGO_FC_TYPE_FAMILY (pango_fc_family_get_type ())
+#define PANGO_FC_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FAMILY, PangoFcFamily))
+#define PANGO_FC_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FAMILY))
+
+#define PANGO_FC_TYPE_FACE (pango_fc_face_get_type ())
+#define PANGO_FC_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FACE, PangoFcFace))
+#define PANGO_FC_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FACE))
+
+struct _PangoFcFontMapPrivate
+{
+ GHashTable *fontset_hash; /* Maps PangoFontDescription -> PangoFcPatternSet */
+
+ /* pattern_hash is used to make sure we only store one copy of
+ * each identical pattern. (Speeds up lookup).
+ */
+ GHashTable *pattern_hash;
+ GHashTable *coverage_hash; /* Maps font file name/id -> PangoCoverage */
+
+ GHashTable *font_hash; /* Maps FcPattern -> PangoFcFont */
+
+ GQueue *fontset_cache; /* Recently used fontsets */
+
+ /* List of all families availible */
+ PangoFcFamily **families;
+ int n_families; /* -1 == uninitialized */
+
+ double dpi;
+
+ /* Decoders */
+ GSList *findfuncs;
+
+ guint closed : 1;
+};
+
+struct _PangoFcCoverageKey
+{
+ char *filename;
+ int id; /* needed to handle TTC files with multiple faces */
+};
+
+struct _PangoFcFace
+{
+ PangoFontFace parent_instance;
+
+ PangoFcFamily *family;
+ char *style;
+
+ guint fake : 1;
+};
+
+struct _PangoFcFamily
+{
+ PangoFontFamily parent_instance;
+
+ PangoFcFontMap *fontmap;
+ char *family_name;
+
+ PangoFcFace **faces;
+ int n_faces; /* -1 == uninitialized */
+
+ int spacing; /* FC_SPACING */
+};
+
+struct _PangoFcPatternSet
+{
+ int n_patterns;
+ FcPattern **patterns;
+ PangoFontset *fontset;
+ GList *cache_link;
+
+ FontsetHashKey *key;
+};
+
+struct _PangoFcFindFuncInfo
+{
+ PangoFcDecoderFindFunc findfunc;
+ gpointer user_data;
+ GDestroyNotify dnotify;
+ gpointer ddata;
+};
+
+static GType pango_fc_family_get_type (void);
+static GType pango_fc_face_get_type (void);
+
+static void pango_fc_font_map_finalize (GObject *object);
+static PangoFont * pango_fc_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description);
+static PangoFontset *pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
+static void pango_fc_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families);
+
+static void pango_fc_font_map_cache_fontset (PangoFcFontMap *fcfontmap,
+ PangoFcPatternSet *patterns);
+
+static void pango_fc_pattern_set_free (PangoFcPatternSet *patterns);
+
+static guint pango_fc_pattern_hash (FcPattern *pattern);
+static gboolean pango_fc_pattern_equal (FcPattern *pattern1,
+ FcPattern *pattern2);
+static guint pango_fc_coverage_key_hash (PangoFcCoverageKey *key);
+static gboolean pango_fc_coverage_key_equal (PangoFcCoverageKey *key1,
+ PangoFcCoverageKey *key2);
+
+static guint font_hash_key_hash (const FontHashKey *key);
+static gboolean font_hash_key_equal (const FontHashKey *key_a,
+ const FontHashKey *key_b);
+static void font_hash_key_free (FontHashKey *key);
+
+static guint fontset_hash_key_hash (const FontsetHashKey *key);
+static gboolean fontset_hash_key_equal (const FontsetHashKey *key_a,
+ const FontsetHashKey *key_b);
+static void fontset_hash_key_free (FontsetHashKey *key);
+
+G_DEFINE_TYPE (PangoFcFontMap, pango_fc_font_map, PANGO_TYPE_FONT_MAP)
+
+static void
+pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
+{
+ static gboolean registered_modules = FALSE;
+ PangoFcFontMapPrivate *priv;
+
+ priv = fcfontmap->priv = G_TYPE_INSTANCE_GET_PRIVATE (fcfontmap,
+ PANGO_TYPE_FC_FONT_MAP,
+ PangoFcFontMapPrivate);
+
+ if (!registered_modules)
+ {
+ int i;
+
+ registered_modules = TRUE;
+
+ for (i = 0; _pango_included_fc_modules[i].list; i++)
+ pango_module_register (&_pango_included_fc_modules[i]);
+ }
+
+ priv->n_families = -1;
+
+ priv->font_hash = g_hash_table_new_full ((GHashFunc)font_hash_key_hash,
+ (GEqualFunc)font_hash_key_equal,
+ (GDestroyNotify)font_hash_key_free,
+ NULL);
+ priv->fontset_hash = g_hash_table_new_full ((GHashFunc)fontset_hash_key_hash,
+ (GEqualFunc)fontset_hash_key_equal,
+ (GDestroyNotify)fontset_hash_key_free,
+ (GDestroyNotify)pango_fc_pattern_set_free);
+
+ priv->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_fc_coverage_key_hash,
+ (GEqualFunc)pango_fc_coverage_key_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)pango_coverage_unref);
+ priv->fontset_cache = g_queue_new ();
+ priv->dpi = -1;
+}
+
+static void
+pango_fc_font_map_class_init (PangoFcFontMapClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class);
+
+ object_class->finalize = pango_fc_font_map_finalize;
+ fontmap_class->load_font = pango_fc_font_map_load_font;
+ fontmap_class->load_fontset = pango_fc_font_map_load_fontset;
+ fontmap_class->list_families = pango_fc_font_map_list_families;
+ fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_FC;
+
+ g_type_class_add_private (object_class, sizeof (PangoFcFontMapPrivate));
+}
+
+static gpointer
+get_gravity_class (void)
+{
+ static GEnumClass *class = NULL;
+
+ if (G_UNLIKELY (!class))
+ class = g_type_class_ref (PANGO_TYPE_GRAVITY);
+
+ return class;
+}
+
+static guint
+pango_fc_pattern_hash (FcPattern *pattern)
+{
+#if 1
+ return FcPatternHash (pattern);
+#else
+ /* Hashing only part of the pattern can improve speed a bit.
+ */
+ char *str;
+ int i;
+ double d;
+ guint hash = 0;
+
+ FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &str);
+ if (str)
+ hash = g_str_hash (str);
+
+ if (FcPatternGetInteger (pattern, FC_INDEX, 0, &i) == FcResultMatch)
+ hash ^= i;
+
+ if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
+ hash ^= (guint) (d*1000.0);
+
+ return hash;
+#endif
+}
+
+static gboolean
+pango_fc_pattern_equal (FcPattern *pattern1,
+ FcPattern *pattern2)
+{
+ if (pattern1 == pattern2)
+ return TRUE;
+ else
+ return FcPatternEqual (pattern1, pattern2);
+}
+
+static guint
+pango_fc_coverage_key_hash (PangoFcCoverageKey *key)
+{
+ return g_str_hash (key->filename) ^ key->id;
+}
+
+static gboolean
+pango_fc_coverage_key_equal (PangoFcCoverageKey *key1,
+ PangoFcCoverageKey *key2)
+{
+ return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0;
+}
+
+struct _FontsetHashKey {
+ PangoFcFontMap *fontmap;
+ PangoMatrix matrix;
+ PangoLanguage *language;
+ PangoFontDescription *desc;
+ int size; /* scaled via the current DPI */
+ gpointer context_key;
+};
+
+struct _FontHashKey {
+ PangoFcFontMap *fontmap;
+ PangoMatrix matrix;
+ FcPattern *pattern;
+ gpointer context_key;
+};
+
+/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
+ *
+ * Not necessarily better than a lot of other hashes, but should be OK, and
+ * well tested with binary data.
+ */
+
+#define FNV_32_PRIME ((guint32)0x01000193)
+#define FNV1_32_INIT ((guint32)0x811c9dc5)
+
+static guint32
+hash_bytes_fnv (unsigned char *buffer,
+ int len,
+ guint32 hval)
+{
+ while (len--)
+ {
+ hval *= FNV_32_PRIME;
+ hval ^= *buffer++;
+ }
+
+ return hval;
+}
+
+static gboolean
+fontset_hash_key_equal (const FontsetHashKey *key_a,
+ const FontsetHashKey *key_b)
+{
+ if (key_a->size == key_b->size &&
+ pango_font_description_equal (key_a->desc, key_b->desc) &&
+ key_a->language == key_b->language &&
+ key_a->matrix.xx == key_b->matrix.xx &&
+ key_a->matrix.xy == key_b->matrix.xy &&
+ key_a->matrix.yx == key_b->matrix.yx &&
+ key_a->matrix.yy == key_b->matrix.yy)
+ {
+ if (key_a->context_key)
+ return PANGO_FC_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap,
+ key_a->context_key,
+ key_b->context_key);
+ else
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static guint
+fontset_hash_key_hash (const FontsetHashKey *key)
+{
+ guint32 hash = FNV1_32_INIT;
+
+ /* We do a bytewise hash on the context matrix */
+ hash = hash_bytes_fnv ((unsigned char *)(&key->matrix),
+ sizeof(double) * 4,
+ hash);
+
+ if (key->context_key)
+ hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap,
+ key->context_key);
+
+ /* 1237 is just an abitrary prime */
+ return (hash ^
+ GPOINTER_TO_UINT (key->language) ^
+ (key->size * 1237) ^
+ pango_font_description_hash (key->desc));
+}
+
+static void
+fontset_hash_key_free (FontsetHashKey *key)
+{
+ pango_font_description_free (key->desc);
+
+ if (key->context_key)
+ PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap,
+ key->context_key);
+
+ g_slice_free (FontsetHashKey, key);
+}
+
+static FontsetHashKey *
+fontset_hash_key_copy (FontsetHashKey *old)
+{
+ FontsetHashKey *key = g_slice_new (FontsetHashKey);
+
+ key->fontmap = old->fontmap;
+ key->matrix = old->matrix;
+ key->language = old->language;
+ key->desc = pango_font_description_copy (old->desc);
+ key->size = old->size;
+ if (old->context_key)
+ key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap,
+ old->context_key);
+ else
+ key->context_key = NULL;
+
+ return key;
+}
+
+static gboolean
+font_hash_key_equal (const FontHashKey *key_a,
+ const FontHashKey *key_b)
+{
+ if (key_a->matrix.xx == key_b->matrix.xx &&
+ key_a->matrix.xy == key_b->matrix.xy &&
+ key_a->matrix.yx == key_b->matrix.yx &&
+ key_a->matrix.yy == key_b->matrix.yy &&
+ key_a->pattern == key_b->pattern)
+ {
+ if (key_a->context_key)
+ return PANGO_FC_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap,
+ key_a->context_key,
+ key_b->context_key);
+ else
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static guint
+font_hash_key_hash (const FontHashKey *key)
+{
+ guint32 hash = FNV1_32_INIT;
+
+ /* We do a bytewise hash on the context matrix */
+ hash = hash_bytes_fnv ((unsigned char *)(&key->matrix),
+ sizeof(double) * 4,
+ hash);
+
+ if (key->context_key)
+ hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap,
+ key->context_key);
+
+ return (hash ^ GPOINTER_TO_UINT (key->pattern));
+}
+
+static void
+font_hash_key_free (FontHashKey *key)
+{
+ if (key->context_key)
+ PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap,
+ key->context_key);
+
+ g_slice_free (FontHashKey, key);
+}
+
+static FontHashKey *
+font_hash_key_copy (FontHashKey *old)
+{
+ FontHashKey *key = g_slice_new (FontHashKey);
+
+ key->fontmap = old->fontmap;
+ key->matrix = old->matrix;
+ key->pattern = old->pattern;
+ if (old->context_key)
+ key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap,
+ old->context_key);
+ else
+ key->context_key = NULL;
+
+ return key;
+}
+
+/**
+ * pango_fc_font_map_add_decoder_find_func:
+ * @fcfontmap: The #PangoFcFontMap to add this method to.
+ * @findfunc: The #PangoFcDecoderFindFunc callback function
+ * @user_data: User data.
+ * @dnotify: A #GDestroyNotify callback that will be called when the
+ * fontmap is finalized and the decoder is released.
+ *
+ * This function saves a callback method in the #PangoFcFontMap that
+ * will be called whenever new fonts are created. If the
+ * function returns a #PangoFcDecoder, that decoder will be used to
+ * determine both coverage via a #FcCharSet and a one-to-one mapping of
+ * characters to glyphs. This will allow applications to have
+ * application-specific encodings for various fonts.
+ *
+ * Since: 1.6.
+ **/
+void
+pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap,
+ PangoFcDecoderFindFunc findfunc,
+ gpointer user_data,
+ GDestroyNotify dnotify)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ PangoFcFindFuncInfo *info;
+
+ info = g_slice_new (PangoFcFindFuncInfo);
+
+ info->findfunc = findfunc;
+ info->user_data = user_data;
+ info->dnotify = dnotify;
+
+ priv->findfuncs = g_slist_append (priv->findfuncs, info);
+}
+
+static void
+pango_fc_font_map_finalize (GObject *object)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (object);
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+
+ pango_fc_font_map_cache_clear (fcfontmap);
+ g_queue_free (priv->fontset_cache);
+ g_hash_table_destroy (priv->coverage_hash);
+
+ if (priv->fontset_hash)
+ g_hash_table_destroy (priv->fontset_hash);
+
+ if (priv->font_hash)
+ g_hash_table_destroy (priv->font_hash);
+
+ if (priv->pattern_hash)
+ g_hash_table_destroy (priv->pattern_hash);
+
+ while (priv->findfuncs)
+ {
+ PangoFcFindFuncInfo *info;
+ info = priv->findfuncs->data;
+ if (info->dnotify)
+ info->dnotify (info->user_data);
+
+ g_slice_free (PangoFcFindFuncInfo, info);
+ priv->findfuncs = g_slist_delete_link (priv->findfuncs, priv->findfuncs);
+ }
+
+ G_OBJECT_CLASS (pango_fc_font_map_parent_class)->finalize (object);
+}
+
+static void
+get_context_matrix (PangoContext *context,
+ PangoMatrix *matrix)
+{
+ const PangoMatrix *set_matrix;
+ static const PangoMatrix identity = PANGO_MATRIX_INIT;
+
+ if (context)
+ set_matrix = pango_context_get_matrix (context);
+ else
+ set_matrix = NULL;
+
+ if (set_matrix)
+ *matrix = *set_matrix;
+ else
+ *matrix = identity;
+}
+
+static void
+font_hash_key_for_context (PangoFcFontMap *fcfontmap,
+ PangoContext *context,
+ FontHashKey *key)
+{
+ key->fontmap = fcfontmap;
+ get_context_matrix (context, &key->matrix);
+
+ if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get)
+ key->context_key = (gpointer)PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context);
+ else
+ key->context_key = NULL;
+}
+
+/* Add a mapping from xfont->font_pattern to xfont */
+static void
+pango_fc_font_map_add (PangoFcFontMap *fcfontmap,
+ PangoContext *context,
+ PangoFcFont *fcfont)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ FontHashKey key;
+ FontHashKey *key_copy;
+
+ g_assert (fcfont->fontmap == NULL);
+
+ fcfont->fontmap = g_object_ref (fcfontmap);
+
+ font_hash_key_for_context (fcfontmap, context, &key);
+ key.pattern = fcfont->font_pattern;
+
+ key_copy = font_hash_key_copy (&key);
+ _pango_fc_font_set_context_key (fcfont, key_copy->context_key);
+ fcfont->matrix = key.matrix;
+
+ g_hash_table_insert (priv->font_hash, key_copy, fcfont);
+}
+
+static PangoFcFont *
+pango_fc_font_map_lookup (PangoFcFontMap *fcfontmap,
+ PangoContext *context,
+ FcPattern *pattern)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ FontHashKey key;
+
+ font_hash_key_for_context (fcfontmap, context, &key);
+ key.pattern = pattern;
+
+ return g_hash_table_lookup (priv->font_hash, &key);
+}
+
+/* Remove mapping from xfont->font_pattern to xfont */
+void
+_pango_fc_font_map_remove (PangoFcFontMap *fcfontmap,
+ PangoFcFont *fcfont)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ FontHashKey key;
+
+ key.fontmap = fcfontmap;
+ key.matrix = fcfont->matrix;
+ key.pattern = fcfont->font_pattern;
+ key.context_key = _pango_fc_font_get_context_key (fcfont);
+
+ g_hash_table_remove (priv->font_hash, &key);
+ fcfont->fontmap = NULL;
+ _pango_fc_font_set_context_key (fcfont, NULL);
+ g_object_unref (fcfontmap);
+}
+
+static PangoFcFamily *
+create_family (PangoFcFontMap *fcfontmap,
+ const char *family_name,
+ int spacing)
+{
+ PangoFcFamily *family = g_object_new (PANGO_FC_TYPE_FAMILY, NULL);
+ family->fontmap = fcfontmap;
+ family->family_name = g_strdup (family_name);
+ family->spacing = spacing;
+
+ return family;
+}
+
+static gboolean
+is_alias_family (const char *family_name)
+{
+ switch (family_name[0])
+ {
+ case 'm':
+ case 'M':
+ return (g_ascii_strcasecmp (family_name, "monospace") == 0);
+ case 's':
+ case 'S':
+ return (g_ascii_strcasecmp (family_name, "sans") == 0 ||
+ g_ascii_strcasecmp (family_name, "serif") == 0);
+ }
+
+ return FALSE;
+}
+
+static void
+pango_fc_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ FcFontSet *fontset;
+ int i;
+ int count;
+
+ if (priv->closed)
+ {
+ if (families)
+ *families = NULL;
+ if (n_families)
+ *n_families = 0;
+
+ return;
+ }
+
+ if (priv->n_families < 0)
+ {
+ FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_SPACING, NULL);
+ FcPattern *pat = FcPatternCreate ();
+ /* use hash table to avoid duplicate listings if different faces in
+ * the same family have different spacing values */
+ GHashTable *temp_family_hash;
+
+ fontset = FcFontList (NULL, pat, os);
+
+ FcPatternDestroy (pat);
+ FcObjectSetDestroy (os);
+
+ priv->families = g_new (PangoFcFamily *, fontset->nfont + 3); /* 3 standard aliases */
+ temp_family_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ count = 0;
+ for (i = 0; i < fontset->nfont; i++)
+ {
+ FcChar8 *s;
+ FcResult res;
+ int spacing;
+
+ res = FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **) &s);
+ g_assert (res == FcResultMatch);
+
+ res = FcPatternGetInteger (fontset->fonts[i], FC_SPACING, 0, &spacing);
+ g_assert (res == FcResultMatch || res == FcResultNoMatch);
+ if (res == FcResultNoMatch)
+ spacing = FC_PROPORTIONAL;
+
+ if (!is_alias_family (s) && !g_hash_table_lookup (temp_family_hash, s))
+ {
+ PangoFcFamily *temp_family = create_family (fcfontmap, (gchar *)s, spacing);
+ g_hash_table_insert (temp_family_hash, g_strdup (s), s);
+ priv->families[count++] = temp_family;
+ }
+ }
+
+ FcFontSetDestroy (fontset);
+ g_hash_table_destroy (temp_family_hash);
+
+ priv->families[count++] = create_family (fcfontmap, "Sans", FC_PROPORTIONAL);
+ priv->families[count++] = create_family (fcfontmap, "Serif", FC_PROPORTIONAL);
+ priv->families[count++] = create_family (fcfontmap, "Monospace", FC_MONO);
+
+ priv->n_families = count;
+ }
+
+ if (n_families)
+ *n_families = priv->n_families;
+
+ if (families)
+ *families = g_memdup (priv->families, priv->n_families * sizeof (PangoFontFamily *));
+}
+
+static int
+pango_fc_convert_weight_to_fc (PangoWeight pango_weight)
+{
+#ifdef FC_WEIGHT_ULTRABOLD
+ /* fontconfig 2.1 only had light/medium/demibold/bold/black */
+ if (pango_weight < (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2)
+ return FC_WEIGHT_ULTRALIGHT;
+ else if (pango_weight < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2)
+ return FC_WEIGHT_LIGHT;
+ else if (pango_weight < (PANGO_WEIGHT_NORMAL + 500 /* PANGO_WEIGHT_MEDIUM */) / 2)
+ return FC_WEIGHT_NORMAL;
+ else if (pango_weight < (500 /* PANGO_WEIGHT_MEDIUM */ + PANGO_WEIGHT_SEMIBOLD) / 2)
+ return FC_WEIGHT_MEDIUM;
+ else if (pango_weight < (PANGO_WEIGHT_SEMIBOLD + PANGO_WEIGHT_BOLD) / 2)
+ return FC_WEIGHT_DEMIBOLD;
+ else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
+ return FC_WEIGHT_BOLD;
+ else if (pango_weight < (PANGO_WEIGHT_ULTRABOLD + PANGO_WEIGHT_HEAVY) / 2)
+ return FC_WEIGHT_ULTRABOLD;
+ else
+ return FC_WEIGHT_BLACK;
+#else /* fontconfig < 2.2 */
+ if (pango_weight < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2)
+ return FC_WEIGHT_LIGHT;
+ else if (pango_weight < (500 /* PANGO_WEIGHT_MEDIUM */ + PANGO_WEIGHT_SEMIBOLD) / 2)
+ return FC_WEIGHT_MEDIUM;
+ else if (pango_weight < (PANGO_WEIGHT_SEMIBOLD + PANGO_WEIGHT_BOLD) / 2)
+ return FC_WEIGHT_DEMIBOLD;
+ else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
+ return FC_WEIGHT_BOLD;
+ else
+ return FC_WEIGHT_BLACK;
+#endif
+}
+
+static int
+pango_fc_convert_slant_to_fc (PangoStyle pango_style)
+{
+ switch (pango_style)
+ {
+ case PANGO_STYLE_NORMAL:
+ return FC_SLANT_ROMAN;
+ case PANGO_STYLE_ITALIC:
+ return FC_SLANT_ITALIC;
+ case PANGO_STYLE_OBLIQUE:
+ return FC_SLANT_OBLIQUE;
+ default:
+ return FC_SLANT_ROMAN;
+ }
+}
+
+#ifdef FC_WIDTH
+static int
+pango_fc_convert_width_to_fc (PangoStretch pango_stretch)
+{
+ switch (pango_stretch)
+ {
+ case PANGO_STRETCH_NORMAL:
+ return FC_WIDTH_NORMAL;
+ case PANGO_STRETCH_ULTRA_CONDENSED:
+ return FC_WIDTH_ULTRACONDENSED;
+ case PANGO_STRETCH_EXTRA_CONDENSED:
+ return FC_WIDTH_EXTRACONDENSED;
+ case PANGO_STRETCH_CONDENSED:
+ return FC_WIDTH_CONDENSED;
+ case PANGO_STRETCH_SEMI_CONDENSED:
+ return FC_WIDTH_SEMICONDENSED;
+ case PANGO_STRETCH_SEMI_EXPANDED:
+ return FC_WIDTH_SEMIEXPANDED;
+ case PANGO_STRETCH_EXPANDED:
+ return FC_WIDTH_EXPANDED;
+ case PANGO_STRETCH_EXTRA_EXPANDED:
+ return FC_WIDTH_EXTRAEXPANDED;
+ case PANGO_STRETCH_ULTRA_EXPANDED:
+ return FC_WIDTH_ULTRAEXPANDED;
+ default:
+ return FC_WIDTH_NORMAL;
+ }
+}
+#endif
+
+static FcPattern *
+pango_fc_make_pattern (const PangoFontDescription *description,
+ PangoLanguage *language,
+ double pixel_size,
+ double dpi)
+{
+ FcPattern *pattern;
+ int slant;
+ int weight;
+ PangoGravity gravity;
+ FcBool vertical;
+ char **families;
+ int i;
+#ifdef FC_WIDTH
+ int width;
+#endif
+
+ slant = pango_fc_convert_slant_to_fc (pango_font_description_get_style (description));
+ weight = pango_fc_convert_weight_to_fc (pango_font_description_get_weight (description));
+#ifdef FC_WIDTH
+ width = pango_fc_convert_width_to_fc (pango_font_description_get_stretch (description));
+#endif
+
+ gravity = pango_font_description_get_gravity (description);
+ vertical = PANGO_GRAVITY_IS_VERTICAL (gravity) ? FcTrue : FcFalse;
+
+ /* The reason for passing in FC_SIZE as well as FC_PIXEL_SIZE is
+ * to work around a bug in libgnomeprint where it doesn't look
+ * for FC_PIXEL_SIZE. See http://bugzilla.gnome.org/show_bug.cgi?id=169020
+ *
+ * Putting FC_SIZE in here slightly reduces the efficiency
+ * of caching of patterns and fonts when working with multiple different
+ * dpi values.
+ */
+ pattern = FcPatternBuild (NULL,
+ FC_WEIGHT, FcTypeInteger, weight,
+ FC_SLANT, FcTypeInteger, slant,
+#ifdef FC_WIDTH
+ FC_WIDTH, FcTypeInteger, width,
+#endif
+#ifdef FC_VERTICAL_LAYOUT
+ FC_VERTICAL_LAYOUT, FcTypeBool, vertical,
+#endif
+ FC_SIZE, FcTypeDouble, pixel_size * (72. / dpi),
+ FC_PIXEL_SIZE, FcTypeDouble, pixel_size,
+ NULL);
+
+ families = g_strsplit (pango_font_description_get_family (description), ",", -1);
+
+ for (i = 0; families[i]; i++)
+ FcPatternAddString (pattern, FC_FAMILY, families[i]);
+
+ g_strfreev (families);
+
+ if (language)
+ FcPatternAddString (pattern, FC_LANG, (FcChar8 *) pango_language_to_string (language));
+
+ if (gravity != PANGO_GRAVITY_SOUTH)
+ {
+ GEnumValue *value = g_enum_get_value (get_gravity_class (), gravity);
+ FcPatternAddString (pattern, PANGO_FC_GRAVITY, value->value_nick);
+ }
+
+ return pattern;
+}
+
+static PangoFont *
+pango_fc_font_map_new_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description,
+ FcPattern *match)
+{
+ PangoFcFontMapClass *class;
+ PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ FcPattern *pattern;
+ PangoFcFont *fcfont;
+ GSList *l;
+
+ if (priv->closed)
+ return NULL;
+
+ fcfont = pango_fc_font_map_lookup (fcfontmap, context, match);
+ if (fcfont)
+ return g_object_ref (fcfont);
+
+ class = PANGO_FC_FONT_MAP_GET_CLASS (fontmap);
+
+ if (class->create_font)
+ {
+ fcfont = PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->create_font (fcfontmap,
+ context,
+ description,
+ match);
+ }
+ else
+ {
+ const PangoMatrix *pango_matrix;
+
+ if (context)
+ pango_matrix = pango_context_get_matrix (context);
+ else
+ pango_matrix = NULL;
+
+ if (pango_matrix)
+ {
+ FcMatrix fc_matrix;
+
+ /* Fontconfig has the Y axis pointing up, Pango, down.
+ */
+ fc_matrix.xx = pango_matrix->xx;
+ fc_matrix.xy = - pango_matrix->xy;
+ fc_matrix.yx = - pango_matrix->yx;
+ fc_matrix.yy = pango_matrix->yy;
+
+ pattern = FcPatternDuplicate (match);
+ FcPatternAddMatrix (pattern, FC_MATRIX, &fc_matrix);
+ }
+ else
+ pattern = match;
+
+ fcfont = PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->new_font (fcfontmap, pattern);
+
+ if (pango_matrix)
+ FcPatternDestroy (pattern);
+ }
+
+ if (!fcfont)
+ return NULL;
+
+ pango_fc_font_map_add (fcfontmap, context, fcfont);
+
+ /*
+ * Give any custom decoders a crack at this font now that it's been
+ * created.
+ */
+ for (l = priv->findfuncs; l && l->data; l = l->next)
+ {
+ PangoFcFindFuncInfo *info = l->data;
+ PangoFcDecoder *decoder;
+
+ decoder = info->findfunc (match, info->user_data);
+ if (decoder)
+ {
+ _pango_fc_font_set_decoder (fcfont, decoder);
+ break;
+ }
+ }
+
+ return (PangoFont *)fcfont;
+}
+
+static FcPattern *
+uniquify_pattern (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ FcPattern *old_pattern;
+
+ if (!priv->pattern_hash)
+ priv->pattern_hash =
+ g_hash_table_new_full ((GHashFunc)pango_fc_pattern_hash,
+ (GEqualFunc)pango_fc_pattern_equal,
+ (GDestroyNotify)FcPatternDestroy, NULL);
+
+ old_pattern = g_hash_table_lookup (priv->pattern_hash, pattern);
+ if (old_pattern)
+ {
+ FcPatternDestroy (pattern);
+ FcPatternReference (old_pattern);
+ return old_pattern;
+ }
+ else
+ {
+ FcPatternReference (pattern);
+ g_hash_table_insert (priv->pattern_hash, pattern, pattern);
+ return pattern;
+ }
+}
+
+static void
+pango_fc_default_substitute (PangoFcFontMap *fontmap,
+ PangoContext *context,
+ FcPattern *pattern)
+{
+ if (PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->context_substitute)
+ PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->context_substitute (fontmap, context, pattern);
+ else if (PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->default_substitute)
+ PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->default_substitute (fontmap, pattern);
+}
+
+static gdouble
+pango_fc_font_map_get_resolution (PangoFcFontMap *fcfontmap,
+ PangoContext *context)
+{
+ if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_resolution)
+ return PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_resolution (fcfontmap, context);
+
+ if (fcfontmap->priv->dpi < 0)
+ {
+ FcResult result = FcResultNoMatch;
+ FcPattern *tmp = FcPatternBuild (NULL,
+ FC_FAMILY, FcTypeString, "Sans",
+ FC_SIZE, FcTypeDouble, 10.,
+ NULL);
+ if (tmp)
+ {
+ pango_fc_default_substitute (fcfontmap, NULL, tmp);
+ result = FcPatternGetDouble (tmp, FC_DPI, 0, &fcfontmap->priv->dpi);
+ FcPatternDestroy (tmp);
+ }
+
+ if (result != FcResultMatch)
+ {
+ g_warning ("Error getting DPI from fontconfig, using 72.0");
+ fcfontmap->priv->dpi = 72.0;
+ }
+ }
+
+ return fcfontmap->priv->dpi;
+}
+
+static int
+get_unscaled_size (PangoFcFontMap *fcfontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc)
+{
+ int size = pango_font_description_get_size (desc);
+
+ if (pango_font_description_get_size_is_absolute (desc))
+ return size;
+ else
+ {
+ double dpi = pango_fc_font_map_get_resolution (fcfontmap, context);
+
+ return (int)(0.5 + size * dpi / 72.);
+ }
+}
+
+static PangoFcPatternSet *
+pango_fc_font_map_get_patterns (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ FcPattern *pattern, *font_pattern;
+ FcResult res;
+ int f;
+ PangoFcPatternSet *patterns;
+ FcFontSet *font_patterns;
+ FontsetHashKey key;
+
+ if (!language && context)
+ language = pango_context_get_language (context);
+
+ key.fontmap = fcfontmap;
+ get_context_matrix (context, &key.matrix);
+ key.language = language;
+ key.desc = pango_font_description_copy_static (desc);
+ pango_font_description_unset_fields (key.desc, PANGO_FONT_MASK_SIZE);
+ key.size = get_unscaled_size (fcfontmap, context, desc);
+
+ if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get)
+ key.context_key = (gpointer)PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context);
+ else
+ key.context_key = NULL;
+
+ patterns = g_hash_table_lookup (priv->fontset_hash, &key);
+
+ if (patterns == NULL)
+ {
+ double scale_factor = pango_matrix_get_font_scale_factor (&key.matrix);
+ double scaled_size = key.size * scale_factor / PANGO_SCALE;
+ pattern = pango_fc_make_pattern (desc, language,
+ scaled_size,
+ pango_fc_font_map_get_resolution (fcfontmap, context));
+
+ pango_fc_default_substitute (fcfontmap, context, pattern);
+
+ font_patterns = FcFontSort (NULL, pattern, FcTrue, NULL, &res);
+
+ if (!font_patterns)
+ {
+ g_printerr ("No fonts found; this probably means that the fontconfig\n"
+ "library is not correctly configured. You may need to\n"
+ "edit the fonts.conf configuration file. More information\n"
+ "about fontconfig can be found in the fontconfig(3) manual\n"
+ "page and on http://fontconfig.org\n");
+
+ /* There is no point in proceeding; we'll just get a segfault later
+ * on, and a bunch more possibly confusing error messages in between.
+ */
+
+ /* return NULL; */
+ exit (1);
+ }
+
+ patterns = g_slice_new (PangoFcPatternSet);
+ patterns->patterns = g_new (FcPattern *, font_patterns->nfont);
+ patterns->n_patterns = 0;
+ patterns->fontset = NULL;
+ patterns->cache_link = NULL;
+
+ for (f = 0; f < font_patterns->nfont; f++)
+ {
+ font_pattern = FcFontRenderPrepare (NULL, pattern,
+ font_patterns->fonts[f]);
+
+ if (font_pattern)
+ {
+#ifdef FC_PATTERN
+ /* The FC_PATTERN element, which points back to our the original
+ * pattern defeats our hash tables.
+ */
+ FcPatternDel (font_pattern, FC_PATTERN);
+#endif /* FC_PATTERN */
+
+ patterns->patterns[patterns->n_patterns++] = uniquify_pattern (fcfontmap, font_pattern);
+ }
+ }
+
+ FcPatternDestroy (pattern);
+
+ FcFontSetSortDestroy (font_patterns);
+
+ patterns->key = fontset_hash_key_copy (&key);
+ g_hash_table_insert (priv->fontset_hash,
+ patterns->key,
+ patterns);
+ }
+
+ if ((!patterns->cache_link ||
+ patterns->cache_link != priv->fontset_cache->head))
+ pango_fc_font_map_cache_fontset (fcfontmap, patterns);
+
+ pango_font_description_free (key.desc);
+
+ return patterns;
+}
+
+static gboolean
+get_first_font (PangoFontset *fontset,
+ PangoFont *font,
+ gpointer data)
+{
+ *(PangoFont **)data = font;
+
+ return TRUE;
+}
+
+static PangoFont *
+pango_fc_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description)
+{
+ PangoLanguage *language;
+ PangoFontset *fontset;
+ PangoFont *font = NULL;
+
+ if (context)
+ language = pango_context_get_language (context);
+ else
+ language = NULL;
+
+ fontset = pango_font_map_load_fontset (fontmap, context, description, language);
+
+ if (fontset)
+ {
+ pango_fontset_foreach (fontset, get_first_font, &font);
+
+ if (font)
+ g_object_ref (font);
+
+ g_object_unref (fontset);
+ }
+
+ return font;
+}
+
+static void
+pango_fc_pattern_set_free (PangoFcPatternSet *patterns)
+{
+ int i;
+
+ if (patterns->fontset)
+ g_object_unref (patterns->fontset);
+
+ for (i = 0; i < patterns->n_patterns; i++)
+ FcPatternDestroy (patterns->patterns[i]);
+
+ g_free (patterns->patterns);
+ g_slice_free (PangoFcPatternSet, patterns);
+}
+
+static void
+pango_fc_font_map_cache_fontset (PangoFcFontMap *fcfontmap,
+ PangoFcPatternSet *patterns)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ GQueue *cache = priv->fontset_cache;
+
+ if (patterns->cache_link)
+ {
+ /* Already in cache, move to head
+ */
+ if (patterns->cache_link == cache->tail)
+ cache->tail = patterns->cache_link->prev;
+
+ cache->head = g_list_remove_link (cache->head, patterns->cache_link);
+ cache->length--;
+ }
+ else
+ {
+ /* Add to cache initially
+ */
+ if (cache->length == FONTSET_CACHE_SIZE)
+ {
+ PangoFcPatternSet *tmp_patterns = g_queue_pop_tail (cache);
+ tmp_patterns->cache_link = NULL;
+ g_hash_table_remove (priv->fontset_hash, tmp_patterns->key);
+ }
+
+ patterns->cache_link = g_list_prepend (NULL, patterns);
+ }
+
+ g_queue_push_head_link (cache, patterns->cache_link);
+}
+
+static PangoFontset *
+pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, desc, language);
+ PangoFontset *result;
+ int i;
+
+ if (!patterns)
+ return NULL;
+
+ if (!patterns->fontset)
+ {
+ PangoFontsetSimple *simple;
+ simple = pango_fontset_simple_new (language);
+ result = PANGO_FONTSET (simple);
+
+ for (i = 0; i < patterns->n_patterns; i++)
+ {
+ PangoFont *font;
+
+ font = pango_fc_font_map_new_font (fontmap, context, desc,
+ patterns->patterns[i]);
+ if (font)
+ pango_fontset_simple_append (simple, font);
+ }
+
+ patterns->fontset = PANGO_FONTSET (simple);
+ }
+
+ result = g_object_ref (patterns->fontset);
+
+ return result;
+}
+
+static void
+uncache_patterns (PangoFcPatternSet *patterns,
+ PangoFcFontMap *fcfontmap)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+
+ g_hash_table_remove (priv->fontset_hash, patterns->key);
+}
+
+static void
+pango_fc_font_map_clear_fontset_cache (PangoFcFontMap *fcfontmap)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ GQueue *cache = priv->fontset_cache;
+
+ g_list_foreach (cache->head, (GFunc)uncache_patterns, fcfontmap);
+ g_list_free (cache->head);
+ cache->head = NULL;
+ cache->tail = NULL;
+ cache->length = 0;
+}
+
+/**
+ * pango_fc_font_map_cache_clear:
+ * @fcfontmap: a #PangoFcFontmap
+ *
+ * Clear all cached information and fontsets for this font map;
+ * this should be called whenever there is a change in the
+ * output of the default_substitute() virtual function.
+ *
+ * This function is intended to be used only by backend implementations
+ * deriving from #PangoFcFontmap.
+ *
+ * Since: 1.4
+ **/
+void
+pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap)
+{
+ fcfontmap->priv->dpi = -1;
+
+ pango_fc_font_map_clear_fontset_cache (fcfontmap);
+}
+
+static void
+pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap,
+ PangoFcCoverageKey *key,
+ PangoCoverage *coverage)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ PangoFcCoverageKey *key_dup;
+
+ key_dup = g_malloc (sizeof (PangoFcCoverageKey) + strlen (key->filename) + 1);
+ key_dup->id = key->id;
+ key_dup->filename = (char *) (key_dup + 1);
+ strcpy (key_dup->filename, key->filename);
+
+ g_hash_table_insert (priv->coverage_hash,
+ key_dup, pango_coverage_ref (coverage));
+}
+
+PangoCoverage *
+_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap,
+ PangoFcFont *fcfont)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ PangoFcCoverageKey key;
+ PangoCoverage *coverage;
+ FcCharSet *charset;
+
+ /*
+ * Assume that coverage information is identified by
+ * a filename/index pair; there shouldn't be any reason
+ * this isn't true, but it's not specified anywhere
+ */
+ if (FcPatternGetString (fcfont->font_pattern, FC_FILE, 0, (FcChar8 **) &key.filename) != FcResultMatch)
+ return NULL;
+
+ if (FcPatternGetInteger (fcfont->font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
+ return NULL;
+
+ coverage = g_hash_table_lookup (priv->coverage_hash, &key);
+ if (coverage)
+ return pango_coverage_ref (coverage);
+
+ /*
+ * Pull the coverage out of the pattern, this
+ * doesn't require loading the font
+ */
+ if (FcPatternGetCharSet (fcfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
+ return NULL;
+
+ coverage = _pango_fc_font_map_fc_to_coverage (charset);
+
+ pango_fc_font_map_set_coverage (fcfontmap, &key, coverage);
+
+ return coverage;
+}
+
+/**
+ * _pango_fc_font_map_fc_to_coverage:
+ * @charset: #FcCharSet to convert to a #PangoCoverage object.
+ *
+ * Convert the given #FcCharSet into a new #PangoCoverage object. The
+ * caller is responsible for freeing the newly created object.
+ *
+ * Since: 1.6
+ **/
+
+PangoCoverage *
+_pango_fc_font_map_fc_to_coverage (FcCharSet *charset)
+{
+ PangoCoverage *coverage;
+ FcChar32 ucs4, pos;
+ FcChar32 map[FC_CHARSET_MAP_SIZE];
+ int i;
+
+ /*
+ * Convert an Fc CharSet into a pango coverage structure. Sure
+ * would be nice to just use the Fc structure in place...
+ */
+ coverage = pango_coverage_new ();
+ for (ucs4 = FcCharSetFirstPage (charset, map, &pos);
+ ucs4 != FC_CHARSET_DONE;
+ ucs4 = FcCharSetNextPage (charset, map, &pos))
+ {
+ for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
+ {
+ FcChar32 bits = map[i];
+ FcChar32 base = ucs4 + i * 32;
+ int b = 0;
+ bits = map[i];
+ while (bits)
+ {
+ if (bits & 1)
+ pango_coverage_set (coverage, base + b, PANGO_COVERAGE_EXACT);
+
+ bits >>= 1;
+ b++;
+ }
+ }
+ }
+
+ /* Awful hack so Hangul Tone marks get rendered with the same
+ * font and in the same run as other Hangul characters. If a font
+ * covers the first composed Hangul glyph, then it is declared to cover
+ * the Hangul tone marks. This hack probably needs to be formalized
+ * by choosing fonts for scripts rather than individual code points.
+ */
+ if (pango_coverage_get (coverage, 0xac00) == PANGO_COVERAGE_EXACT)
+ {
+ pango_coverage_set (coverage, 0x302e, PANGO_COVERAGE_EXACT);
+ pango_coverage_set (coverage, 0x302f, PANGO_COVERAGE_EXACT);
+ }
+
+ return coverage;
+}
+
+/**
+ * pango_fc_font_map_create_context:
+ * @fcfontmap: a #PangoFcFontMap
+ *
+ * Creates a new context for this fontmap. This function is intended
+ * only for backend implementations deriving from #PangoFcFontmap;
+ * it is possible that a backend will store additional information
+ * needed for correct operation on the #PangoContext after calling
+ * this function.
+ *
+ * Return value: a new #PangoContext
+ *
+ * Since: 1.4
+ **/
+PangoContext *
+pango_fc_font_map_create_context (PangoFcFontMap *fcfontmap)
+{
+ PangoContext *context = pango_context_new ();
+ pango_context_set_font_map (context, PANGO_FONT_MAP (fcfontmap));
+
+ return context;
+}
+
+static void
+cleanup_font (gpointer key,
+ PangoFcFont *fcfont)
+{
+ _pango_fc_font_shutdown (fcfont);
+
+ g_object_unref (fcfont->fontmap);
+ fcfont->fontmap = NULL;
+}
+
+/**
+ * pango_fc_font_map_shutdown:
+ * @fcfontmap: a #PangoFcFontmap
+ *
+ * Clears all cached information for the fontmap and marks
+ * all fonts open for the fontmap as dead. (See the shutdown()
+ * virtual function of #PangoFcFont.) This function might be used
+ * by a backend when the underlying windowing system for the font
+ * map exits. This function is only intended to be called from
+ * only for backend implementations deriving from #PangoFcFontmap.
+ *
+ * Since: 1.4
+ **/
+void
+pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap)
+{
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+
+ pango_fc_font_map_cache_clear (fcfontmap);
+ g_hash_table_destroy (priv->fontset_hash);
+ priv->fontset_hash = NULL;
+
+ g_hash_table_foreach (priv->font_hash, (GHFunc)cleanup_font, NULL);
+ g_hash_table_destroy (priv->font_hash);
+ priv->font_hash = NULL;
+ priv->closed = TRUE;
+}
+
+static PangoWeight
+pango_fc_convert_weight_to_pango (int fc_weight)
+{
+#ifdef FC_WEIGHT_ULTRABOLD
+ /* fontconfig 2.1 only had light/medium/demibold/bold/black */
+ if (fc_weight < (FC_WEIGHT_ULTRALIGHT + FC_WEIGHT_LIGHT) / 2)
+ return PANGO_WEIGHT_ULTRALIGHT;
+ else if (fc_weight < (FC_WEIGHT_LIGHT + FC_WEIGHT_REGULAR) / 2)
+ return PANGO_WEIGHT_LIGHT;
+ else if (fc_weight < (FC_WEIGHT_REGULAR + FC_WEIGHT_DEMIBOLD) / 2)
+ return PANGO_WEIGHT_NORMAL;
+ /* We group the 500/MEDIUM weight with normal to reduce confusion
+ *
+ * else if (fc_weight < (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
+ * return 500;
+ */
+ else if (fc_weight < (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
+ return PANGO_WEIGHT_SEMIBOLD;
+ else if (fc_weight < (FC_WEIGHT_BOLD + FC_WEIGHT_ULTRABOLD) / 2)
+ return PANGO_WEIGHT_BOLD;
+ else if (fc_weight < (FC_WEIGHT_ULTRABOLD + FC_WEIGHT_BLACK) / 2)
+ return PANGO_WEIGHT_ULTRABOLD;
+ else
+ return PANGO_WEIGHT_HEAVY;
+#else /* fontconfig < 2.2 */
+ if (fc_weight < (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
+ return PANGO_WEIGHT_LIGHT;
+ else if (fc_weight < (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
+ return PANGO_WEIGHT_NORMAL;
+ else if (fc_weight < (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
+ return PANGO_WEIGHT_SEMIBOLD;
+ else if (fc_weight < (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
+ return PANGO_WEIGHT_BOLD;
+ else
+ return PANGO_WEIGHT_ULTRABOLD;
+#endif
+}
+
+static PangoStyle
+pango_fc_convert_slant_to_pango (int fc_style)
+{
+ switch (fc_style)
+ {
+ case FC_SLANT_ROMAN:
+ return PANGO_STYLE_NORMAL;
+ case FC_SLANT_ITALIC:
+ return PANGO_STYLE_ITALIC;
+ case FC_SLANT_OBLIQUE:
+ return PANGO_STYLE_OBLIQUE;
+ default:
+ return PANGO_STYLE_NORMAL;
+ }
+}
+
+#ifdef FC_WIDTH
+static PangoStretch
+pango_fc_convert_width_to_pango (int fc_stretch)
+{
+ switch (fc_stretch)
+ {
+ case FC_WIDTH_NORMAL:
+ return PANGO_STRETCH_NORMAL;
+ case FC_WIDTH_ULTRACONDENSED:
+ return PANGO_STRETCH_ULTRA_CONDENSED;
+ case FC_WIDTH_EXTRACONDENSED:
+ return PANGO_STRETCH_EXTRA_CONDENSED;
+ case FC_WIDTH_CONDENSED:
+ return PANGO_STRETCH_CONDENSED;
+ case FC_WIDTH_SEMICONDENSED:
+ return PANGO_STRETCH_SEMI_CONDENSED;
+ case FC_WIDTH_SEMIEXPANDED:
+ return PANGO_STRETCH_SEMI_EXPANDED;
+ case FC_WIDTH_EXPANDED:
+ return PANGO_STRETCH_EXPANDED;
+ case FC_WIDTH_EXTRAEXPANDED:
+ return PANGO_STRETCH_EXTRA_EXPANDED;
+ case FC_WIDTH_ULTRAEXPANDED:
+ return PANGO_STRETCH_ULTRA_EXPANDED;
+ default:
+ return PANGO_STRETCH_NORMAL;
+ }
+}
+#endif
+
+/**
+ * pango_fc_font_description_from_pattern:
+ * @pattern: a #FcPattern
+ * @include_size: if %TRUE, the pattern will include the size from
+ * the @pattern; otherwise the resulting pattern will be unsized.
+ * (only %FC_SIZE is examined, not %FC_PIXEL_SIZE)
+ *
+ * Creates a #PangoFontDescription that matches the specified
+ * Fontconfig pattern as closely as possible. Many possible Fontconfig
+ * pattern values, such as %FC_RASTERIZER or %FC_DPI, don't make sense in
+ * the context of #PangoFontDescription, so will be ignored.
+ *
+ * Return value: a new #PangoFontDescription. Free with
+ * pango_font_description_free().
+ *
+ * Since: 1.4
+ **/
+PangoFontDescription *
+pango_fc_font_description_from_pattern (FcPattern *pattern, gboolean include_size)
+{
+ PangoFontDescription *desc;
+ PangoStyle style;
+ PangoWeight weight;
+ PangoStretch stretch;
+ double size;
+ PangoGravity gravity;
+
+ FcChar8 *s;
+ int i;
+ FcResult res;
+
+ desc = pango_font_description_new ();
+
+ res = FcPatternGetString (pattern, FC_FAMILY, 0, (FcChar8 **) &s);
+ g_assert (res == FcResultMatch);
+
+ pango_font_description_set_family (desc, (gchar *)s);
+
+ if (FcPatternGetInteger (pattern, FC_SLANT, 0, &i) == FcResultMatch)
+ style = pango_fc_convert_slant_to_pango (i);
+ else
+ style = PANGO_STYLE_NORMAL;
+
+ pango_font_description_set_style (desc, style);
+
+ if (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &i) == FcResultMatch)
+ weight = pango_fc_convert_weight_to_pango (i);
+ else
+ weight = PANGO_WEIGHT_NORMAL;
+
+ pango_font_description_set_weight (desc, weight);
+
+#ifdef FC_WIDTH
+ if (FcPatternGetInteger (pattern, FC_WIDTH, 0, &i) == FcResultMatch)
+ stretch = pango_fc_convert_width_to_pango (i);
+ else
+#endif
+ stretch = PANGO_STRETCH_NORMAL;
+
+ pango_font_description_set_stretch (desc, stretch);
+
+ pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
+
+ if (include_size && FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
+ pango_font_description_set_size (desc, size * PANGO_SCALE);
+
+ /* gravity is a bit different. we don't want to set it if it was not set on
+ * the pattern */
+ if (FcPatternGetString (pattern, PANGO_FC_GRAVITY, 0, (FcChar8 **)&s) == FcResultMatch)
+ {
+ GEnumValue *value = g_enum_get_value_by_nick (get_gravity_class (), s);
+ gravity = value->value;
+
+ pango_font_description_set_gravity (desc, gravity);
+ }
+
+ return desc;
+}
+
+/*
+ * PangoFcFace
+ */
+
+static PangoFontDescription *
+make_alias_description (PangoFcFamily *fcfamily,
+ gboolean bold,
+ gboolean italic)
+{
+ PangoFontDescription *desc = pango_font_description_new ();
+
+ pango_font_description_set_family (desc, fcfamily->family_name);
+ pango_font_description_set_style (desc, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight (desc, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
+
+ return desc;
+}
+
+static PangoFontDescription *
+pango_fc_face_describe (PangoFontFace *face)
+{
+ PangoFcFace *fcface = PANGO_FC_FACE (face);
+ PangoFcFamily *fcfamily = fcface->family;
+ PangoFontDescription *desc = NULL;
+ FcResult res;
+ FcPattern *match_pattern;
+ FcPattern *result_pattern;
+
+ if (fcface->fake)
+ {
+ if (strcmp (fcface->style, "Regular") == 0)
+ return make_alias_description (fcfamily, FALSE, FALSE);
+ else if (strcmp (fcface->style, "Bold") == 0)
+ return make_alias_description (fcfamily, TRUE, FALSE);
+ else if (strcmp (fcface->style, "Italic") == 0)
+ return make_alias_description (fcfamily, FALSE, TRUE);
+ else /* Bold Italic */
+ return make_alias_description (fcfamily, TRUE, TRUE);
+ }
+
+ match_pattern = FcPatternBuild (NULL,
+ FC_FAMILY, FcTypeString, fcfamily->family_name,
+ FC_STYLE, FcTypeString, fcface->style,
+ NULL);
+
+ g_assert (match_pattern);
+
+ FcConfigSubstitute (NULL, match_pattern, FcMatchPattern);
+ FcDefaultSubstitute (match_pattern);
+
+ result_pattern = FcFontMatch (NULL, match_pattern, &res);
+ if (result_pattern)
+ {
+ desc = pango_fc_font_description_from_pattern (result_pattern, FALSE);
+ FcPatternDestroy (result_pattern);
+ }
+
+ FcPatternDestroy (match_pattern);
+
+ return desc;
+}
+
+static const char *
+pango_fc_face_get_face_name (PangoFontFace *face)
+{
+ PangoFcFace *fcface = PANGO_FC_FACE (face);
+
+ return fcface->style;
+}
+
+static int
+compare_ints (gconstpointer ap,
+ gconstpointer bp)
+{
+ int a = *(int *)ap;
+ int b = *(int *)bp;
+
+ if (a == b)
+ return 0;
+ else if (a > b)
+ return 1;
+ else
+ return -1;
+}
+
+static void
+pango_fc_face_list_sizes (PangoFontFace *face,
+ int **sizes,
+ int *n_sizes)
+{
+ PangoFcFace *fcface = PANGO_FC_FACE (face);
+ FcPattern *pattern;
+ FcFontSet *fontset;
+ FcObjectSet *objectset;
+
+ pattern = FcPatternCreate ();
+ FcPatternAddString (pattern, FC_FAMILY, fcface->family->family_name);
+ FcPatternAddString (pattern, FC_STYLE, fcface->style);
+
+ objectset = FcObjectSetCreate ();
+ FcObjectSetAdd (objectset, FC_PIXEL_SIZE);
+
+ fontset = FcFontList (NULL, pattern, objectset);
+
+ if (fontset)
+ {
+ GArray *size_array;
+ double size, dpi = -1.0;
+ int i, size_i;
+
+ size_array = g_array_new (FALSE, FALSE, sizeof (int));
+
+ for (i = 0; i < fontset->nfont; i++)
+ {
+ if (FcPatternGetDouble (fontset->fonts[i], FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
+ {
+ if (dpi < 0)
+ dpi = pango_fc_font_map_get_resolution (fcface->family->fontmap, NULL);
+
+ size_i = (int) (PANGO_SCALE * size * 72.0 / dpi);
+ g_array_append_val (size_array, size_i);
+ }
+ }
+
+ g_array_sort (size_array, compare_ints);
+
+ if (size_array->len == 0)
+ {
+ *n_sizes = 0;
+ if (sizes)
+ *sizes = NULL;
+ g_array_free (size_array, TRUE);
+ }
+ else
+ {
+ *n_sizes = size_array->len;
+ if (sizes)
+ {
+ *sizes = (int *) size_array->data;
+ g_array_free (size_array, FALSE);
+ }
+ else
+ g_array_free (size_array, TRUE);
+ }
+
+ FcFontSetDestroy (fontset);
+ }
+ else
+ {
+ *n_sizes = 0;
+ if (sizes)
+ *sizes = NULL;
+ }
+
+ FcPatternDestroy (pattern);
+ FcObjectSetDestroy (objectset);
+}
+
+static gboolean
+pango_fc_face_is_synthesized (PangoFontFace *face)
+{
+ PangoFcFace *fcface = PANGO_FC_FACE (face);
+
+ return fcface->fake;
+}
+
+static void
+pango_fc_face_class_init (PangoFontFaceClass *class)
+{
+ class->describe = pango_fc_face_describe;
+ class->get_face_name = pango_fc_face_get_face_name;
+ class->list_sizes = pango_fc_face_list_sizes;
+ class->is_synthesized = pango_fc_face_is_synthesized;
+}
+
+static GType
+pango_fc_face_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFaceClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_fc_face_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFcFace),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
+ I_("PangoFcFace"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+/*
+ * PangoFcFamily
+ */
+static PangoFcFace *
+create_face (PangoFcFamily *fcfamily,
+ const char *style,
+ gboolean fake)
+{
+ PangoFcFace *face = g_object_new (PANGO_FC_TYPE_FACE, NULL);
+ face->style = g_strdup (style);
+ face->family = fcfamily;
+ face->fake = fake;
+
+ return face;
+}
+
+static void
+pango_fc_family_list_faces (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces)
+{
+ PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
+ PangoFcFontMap *fcfontmap = fcfamily->fontmap;
+ PangoFcFontMapPrivate *priv = fcfontmap->priv;
+
+ if (fcfamily->n_faces < 0)
+ {
+ FcFontSet *fontset;
+ int i;
+
+ if (is_alias_family (fcfamily->family_name) || priv->closed)
+ {
+ fcfamily->n_faces = 4;
+ fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces);
+
+ i = 0;
+ fcfamily->faces[i++] = create_face (fcfamily, "Regular", TRUE);
+ fcfamily->faces[i++] = create_face (fcfamily, "Bold", TRUE);
+ fcfamily->faces[i++] = create_face (fcfamily, "Italic", TRUE);
+ fcfamily->faces[i++] = create_face (fcfamily, "Bold Italic", TRUE);
+ }
+ else
+ {
+ FcObjectSet *os = FcObjectSetBuild (FC_STYLE, FC_WEIGHT, FC_SLANT, NULL);
+ FcPattern *pat = FcPatternBuild (NULL,
+ FC_FAMILY, FcTypeString, fcfamily->family_name,
+ NULL);
+
+ enum {
+ REGULAR,
+ ITALIC,
+ BOLD,
+ BOLD_ITALIC
+ };
+ /* Regular, Italic, Bold, Bold Italic */
+ gboolean has_face [4] = { FALSE, FALSE, FALSE, FALSE };
+ PangoFcFace **faces;
+ gint num = 0;
+
+ fontset = FcFontList (NULL, pat, os);
+
+ FcPatternDestroy (pat);
+ FcObjectSetDestroy (os);
+
+ /* at most we have 3 additional artifical faces */
+ faces = g_new (PangoFcFace *, fontset->nfont + 3);
+
+ for (i = 0; i < fontset->nfont; i++)
+ {
+ FcChar8 *style, *font_style = NULL;
+ int weight, slant;
+
+ if (FcPatternGetInteger(fontset->fonts[i], FC_WEIGHT, 0, &weight) != FcResultMatch)
+ weight = FC_WEIGHT_MEDIUM;
+
+ if (FcPatternGetInteger(fontset->fonts[i], FC_SLANT, 0, &slant) != FcResultMatch)
+ slant = FC_SLANT_ROMAN;
+
+ if (FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, &font_style) != FcResultMatch)
+ font_style = NULL;
+
+ if (weight <= FC_WEIGHT_MEDIUM)
+ {
+ if (slant == FC_SLANT_ROMAN)
+ {
+ has_face[REGULAR] = TRUE;
+ style = "Regular";
+ }
+ else
+ {
+ has_face[ITALIC] = TRUE;
+ style = "Italic";
+ }
+ }
+ else
+ {
+ if (slant == FC_SLANT_ROMAN)
+ {
+ has_face[BOLD] = TRUE;
+ style = "Bold";
+ }
+ else
+ {
+ has_face[BOLD_ITALIC] = TRUE;
+ style = "Bold Italic";
+ }
+ }
+
+ if (!font_style)
+ font_style = style;
+ faces[num++] = create_face (fcfamily, font_style, FALSE);
+ }
+
+ if (has_face[REGULAR])
+ {
+ if (!has_face[ITALIC])
+ faces[num++] = create_face (fcfamily, "Italic", TRUE);
+ if (!has_face[BOLD])
+ faces[num++] = create_face (fcfamily, "Bold", TRUE);
+
+ }
+ if ((has_face[REGULAR] || has_face[ITALIC] || has_face[BOLD]) && !has_face[BOLD_ITALIC])
+ faces[num++] = create_face (fcfamily, "Bold Italic", TRUE);
+
+ faces = g_renew (PangoFcFace *, faces, num);
+
+ fcfamily->n_faces = num;
+ fcfamily->faces = faces;
+
+ FcFontSetDestroy (fontset);
+ }
+ }
+
+ if (n_faces)
+ *n_faces = fcfamily->n_faces;
+
+ if (faces)
+ *faces = g_memdup (fcfamily->faces, fcfamily->n_faces * sizeof (PangoFontFace *));
+}
+
+static const char *
+pango_fc_family_get_name (PangoFontFamily *family)
+{
+ PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
+
+ return fcfamily->family_name;
+}
+
+static gboolean
+pango_fc_family_is_monospace (PangoFontFamily *family)
+{
+ PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
+
+ return fcfamily->spacing == FC_MONO ||
+#ifdef FC_DUAL
+ fcfamily->spacing == FC_DUAL ||
+#endif
+ fcfamily->spacing == FC_CHARCELL;
+}
+
+static void
+pango_fc_family_class_init (PangoFontFamilyClass *class)
+{
+ class->list_faces = pango_fc_family_list_faces;
+ class->get_name = pango_fc_family_get_name;
+ class->is_monospace = pango_fc_family_is_monospace;
+}
+
+static void
+pango_fc_family_init (PangoFcFamily *fcfamily)
+{
+ fcfamily->n_faces = -1;
+}
+
+static GType
+pango_fc_family_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFamilyClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_fc_family_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFcFamily),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_fc_family_init,
+ NULL /* value_table */
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
+ I_("PangoFcFamily"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
diff --git a/trunk/pango/pangofc-fontmap.h b/trunk/pango/pangofc-fontmap.h
new file mode 100644
index 00000000..5eaf9cc9
--- /dev/null
+++ b/trunk/pango/pangofc-fontmap.h
@@ -0,0 +1,177 @@
+/* Pango
+ * pangofc-fontmap.h: Base fontmap type for fontconfig-based backends
+ *
+ * Copyright (C) 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_FC_FONT_MAP_H__
+#define __PANGO_FC_FONT_MAP_H__
+
+#include <fontconfig/fontconfig.h>
+#include <pango/pango-fontmap.h>
+#include <pango/pangofc-decoder.h>
+#include <pango/pangofc-font.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_FC_FONT_MAP (pango_fc_font_map_get_type ())
+#define PANGO_FC_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FC_FONT_MAP, PangoFcFontMap))
+#define PANGO_IS_FC_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FC_FONT_MAP))
+
+typedef struct _PangoFcFontMap PangoFcFontMap;
+typedef struct _PangoFcFontMapClass PangoFcFontMapClass;
+typedef struct _PangoFcFontMapPrivate PangoFcFontMapPrivate;
+
+#ifdef PANGO_ENABLE_BACKEND
+
+#define PANGO_FC_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FC_FONT_MAP, PangoFcFontMapClass))
+#define PANGO_IS_FC_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FC_FONT_MAP))
+#define PANGO_FC_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FC_FONT_MAP, PangoFcFontMapClass))
+
+/**
+ * PangoFcFontMap:
+ *
+ * #PangoFcFontMap is a base class for font map implementations
+ * using the Fontconfig and FreeType libraries. To create a new
+ * backend using Fontconfig and FreeType, you derive from this class
+ * and implement a new_font() virtual function that creates an
+ * instance deriving from #PangoFcFont.
+ **/
+struct _PangoFcFontMap
+{
+ PangoFontMap parent_instance;
+
+ PangoFcFontMapPrivate *priv;
+};
+
+/**
+ * PangoFcFontMapClass:
+ * @default_substitute: Substitutes in default values for
+ * unspecified fields in a #FcPattern. This will be called
+ * prior to creating a font for the pattern. May be %NULL.
+ * Deprecated in favor of @context_substitute().
+ * @new_font: Creates a new #PangoFcFont for the specified
+ * pattern of the appropriate type for this font map. The
+ * @pattern argument must be passed to the "pattern" property
+ * of #PangoFcFont when you call g_object_new(). Deprecated
+ * in favor of @create_font().
+ * @get_resolution: Gets the resolution (the scale factor
+ * between logical and absolute font sizes) that the backend
+ * will use for a particular fontmap and context. @context
+ * may be null.
+ * @context_key_get: Gets an opaque key holding backend
+ * specific options for the context that will affect
+ * fonts created by create_font(). The result must point to
+ * persistant storage owned by the fontmap. This key
+ * is used to index hash tables used to look up fontsets
+ * and fonts.
+ * @context_key_copy: Copies a context key. Pango uses this
+ * to make a persistant copy of the value returned from
+ * @context_key_get.
+ * @context_key_free: Frees a context key copied with
+ * @context_key_copy.
+ * @context_key_hash: Gets a hash value for a context key
+ * @context_key_equal: Compares two context keys for equality.
+ * @create_font: Creates a new #PangoFcFont for the specified
+ * pattern of the appropriate type for this font map using
+ * information from the context that is passed in. The
+ * @pattern argument must be passed to the "pattern" property
+ * of #PangoFcFont when you call g_object_new(). Deprecated
+ * in favor of @create_font(). If %NULL, new_font() is used.
+ * @context_substitute: Substitutes in default values for
+ * unspecified fields in a #FcPattern. This will be called
+ * prior to creating a font for the pattern. May be %NULL.
+ *
+ * Class structure for #PangoFcFontMap.
+ **/
+struct _PangoFcFontMapClass
+{
+ /*< private >*/
+ PangoFontMapClass parent_class;
+
+ /*< public >*/
+ /* Deprecated in favor of context_substitute */
+ void (*default_substitute) (PangoFcFontMap *fontmap,
+ FcPattern *pattern);
+ /* Deprecated in favor of create_font */
+ PangoFcFont *(*new_font) (PangoFcFontMap *fontmap,
+ FcPattern *pattern);
+
+ double (*get_resolution) (PangoFcFontMap *fcfontmap,
+ PangoContext *context);
+
+ gconstpointer (*context_key_get) (PangoFcFontMap *fcfontmap,
+ PangoContext *context);
+ gpointer (*context_key_copy) (PangoFcFontMap *fcfontmap,
+ gconstpointer key);
+ void (*context_key_free) (PangoFcFontMap *fcfontmap,
+ gpointer key);
+ guint32 (*context_key_hash) (PangoFcFontMap *fcfontmap,
+ gconstpointer key);
+ gboolean (*context_key_equal) (PangoFcFontMap *fcfontmap,
+ gconstpointer key_a,
+ gconstpointer key_b);
+
+ void (*context_substitute) (PangoFcFontMap *fontmap,
+ PangoContext *context,
+ FcPattern *pattern);
+ PangoFcFont *(*create_font) (PangoFcFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ FcPattern *pattern);
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+PangoContext * pango_fc_font_map_create_context (PangoFcFontMap *fcfontmap);
+void pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap);
+void pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap);
+
+#endif
+
+GType pango_fc_font_map_get_type (void) G_GNUC_CONST;
+
+/**
+ * PangoFcDecoderFindFunc:
+ * @pattern: a fully resolved #FcPattern specifying the font on the system
+ * @user_data: user data passed to pango_fc_font_map_add_decoder_find_func()
+ *
+ * Callback function passed to pango_fc_font_map_add_decoder_find_func().
+ *
+ * Return value: a new reference to a custom decoder for this pattern,
+ * or %NULL if the default decoder handling should be used.
+ **/
+typedef PangoFcDecoder * (*PangoFcDecoderFindFunc) (FcPattern *pattern,
+ gpointer user_data);
+
+void pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap,
+ PangoFcDecoderFindFunc findfunc,
+ gpointer user_data,
+ GDestroyNotify dnotify);
+
+PangoFontDescription *pango_fc_font_description_from_pattern (FcPattern *pattern,
+ gboolean include_size);
+
+G_END_DECLS
+
+#endif /* __PANGO_FC_FONT_MAP_H__ */
diff --git a/trunk/pango/pangofc-private.h b/trunk/pango/pangofc-private.h
new file mode 100644
index 00000000..27ad5769
--- /dev/null
+++ b/trunk/pango/pangofc-private.h
@@ -0,0 +1,74 @@
+/* Pango
+ * pangofc-private.h: Private routines and declarations for generic
+ * fontconfig operation
+ *
+ * Copyright (C) 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOFC_PRIVATE_H__
+#define __PANGOFC_PRIVATE_H__
+
+#include <pangofc-fontmap.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoFcMetricsInfo PangoFcMetricsInfo;
+
+struct _PangoFcMetricsInfo
+{
+ const char *sample_str;
+ PangoFontMetrics *metrics;
+};
+
+#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6))
+#define PANGO_PIXELS_26_6(d) \
+ (((d) >= 0) ? \
+ ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 : \
+ ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6)
+#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d))
+
+#define PANGO_FC_GRAVITY "pangogravity"
+
+void _pango_fc_font_shutdown (PangoFcFont *fcfont);
+
+void _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap,
+ PangoFcFont *fcfont);
+PangoCoverage *_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap,
+ PangoFcFont *fcfont);
+PangoCoverage *_pango_fc_font_map_fc_to_coverage (FcCharSet *charset);
+
+PangoFcDecoder *_pango_fc_font_get_decoder (PangoFcFont *font);
+void _pango_fc_font_set_decoder (PangoFcFont *font,
+ PangoFcDecoder *decoder);
+
+gpointer _pango_fc_font_get_context_key (PangoFcFont *font);
+void _pango_fc_font_set_context_key (PangoFcFont *font,
+ gpointer context_key);
+
+void pango_fc_font_get_raw_extents (PangoFcFont *font,
+ FT_Int32 load_flags,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+PangoFontMetrics *pango_fc_font_create_metrics_for_context (PangoFcFont *font,
+ PangoContext *context);
+
+G_END_DECLS
+
+#endif /* __PANGOFC_PRIVATE_H__ */
diff --git a/trunk/pango/pangoft2-fontmap.c b/trunk/pango/pangoft2-fontmap.c
new file mode 100644
index 00000000..0feae27d
--- /dev/null
+++ b/trunk/pango/pangoft2-fontmap.c
@@ -0,0 +1,353 @@
+/* Pango
+ * pangoft2-fontmap.c:
+ *
+ * Copyright (C) 2000 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <fontconfig/fontconfig.h>
+
+#include "pango-impl-utils.h"
+#include "pangoft2-private.h"
+#include "pangofc-fontmap.h"
+
+typedef struct _PangoFT2Family PangoFT2Family;
+typedef struct _PangoFT2FontMapClass PangoFT2FontMapClass;
+
+struct _PangoFT2FontMap
+{
+ PangoFcFontMap parent_instance;
+
+ FT_Library library;
+
+ double dpi_x;
+ double dpi_y;
+
+ /* Function to call on prepared patterns to do final
+ * config tweaking.
+ */
+ PangoFT2SubstituteFunc substitute_func;
+ gpointer substitute_data;
+ GDestroyNotify substitute_destroy;
+
+ PangoRenderer *renderer;
+};
+
+struct _PangoFT2FontMapClass
+{
+ PangoFcFontMapClass parent_class;
+};
+
+static void pango_ft2_font_map_finalize (GObject *object);
+static PangoFcFont * pango_ft2_font_map_new_font (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern);
+static double pango_ft2_font_map_get_resolution (PangoFcFontMap *fcfontmap,
+ PangoContext *context);
+
+static PangoFT2FontMap *pango_ft2_global_fontmap = NULL;
+
+G_DEFINE_TYPE (PangoFT2FontMap, pango_ft2_font_map, PANGO_TYPE_FC_FONT_MAP)
+
+static void
+pango_ft2_font_map_class_init (PangoFT2FontMapClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class);
+
+ gobject_class->finalize = pango_ft2_font_map_finalize;
+ fcfontmap_class->default_substitute = _pango_ft2_font_map_default_substitute;
+ fcfontmap_class->new_font = pango_ft2_font_map_new_font;
+ fcfontmap_class->get_resolution = pango_ft2_font_map_get_resolution;
+}
+
+static void
+pango_ft2_font_map_init (PangoFT2FontMap *fontmap)
+{
+ fontmap->library = NULL;
+ fontmap->dpi_x = 72.0;
+ fontmap->dpi_y = 72.0;
+}
+
+static void
+pango_ft2_font_map_finalize (GObject *object)
+{
+ PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (object);
+
+ if (ft2fontmap->renderer)
+ g_object_unref (ft2fontmap->renderer);
+
+ if (ft2fontmap->substitute_destroy)
+ ft2fontmap->substitute_destroy (ft2fontmap->substitute_data);
+
+ FT_Done_FreeType (ft2fontmap->library);
+
+ G_OBJECT_CLASS (pango_ft2_font_map_parent_class)->finalize (object);
+}
+
+/**
+ * pango_ft2_font_map_new:
+ *
+ * Create a new #PangoFT2FontMap object; a fontmap is used
+ * to cache information about available fonts, and holds
+ * certain global parameters such as the resolution and
+ * the default substitute function (see
+ * pango_ft2_font_map_set_default_substitute()).
+ *
+ * Return value: the newly created fontmap object. Unref
+ * with g_object_unref() when you are finished with it.
+ *
+ * Since: 1.2
+ **/
+PangoFontMap *
+pango_ft2_font_map_new (void)
+{
+ PangoFT2FontMap *ft2fontmap;
+ FT_Error error;
+
+ /* Make sure that the type system is initialized */
+ g_type_init ();
+
+ ft2fontmap = g_object_new (PANGO_TYPE_FT2_FONT_MAP, NULL);
+
+ error = FT_Init_FreeType (&ft2fontmap->library);
+ if (error != FT_Err_Ok)
+ g_critical ("pango_ft2_font_map_new: Could not initialize freetype");
+
+ return (PangoFontMap *)ft2fontmap;
+}
+
+/**
+ * pango_ft2_font_map_set_default_substitute:
+ * @fontmap: a #PangoFT2FontMap
+ * @func: function to call to to do final config tweaking
+ * on #FcPattern objects.
+ * @data: data to pass to @func
+ * @notify: function to call when @data is no longer used.
+ *
+ * Sets a function that will be called to do final configuration
+ * substitution on a #FcPattern before it is used to load
+ * the font. This function can be used to do things like set
+ * hinting and antialiasing options.
+ *
+ * Since: 1.2
+ **/
+void
+pango_ft2_font_map_set_default_substitute (PangoFT2FontMap *fontmap,
+ PangoFT2SubstituteFunc func,
+ gpointer data,
+ GDestroyNotify notify)
+{
+ if (fontmap->substitute_destroy)
+ fontmap->substitute_destroy (fontmap->substitute_data);
+
+ fontmap->substitute_func = func;
+ fontmap->substitute_data = data;
+ fontmap->substitute_destroy = notify;
+
+ pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (fontmap));
+}
+
+/**
+ * pango_ft2_font_map_substitute_changed:
+ * @fontmap: a #PangoFT2Fontmap
+ *
+ * Call this function any time the results of the
+ * default substitution function set with
+ * pango_ft2_font_map_set_default_substitute() change.
+ * That is, if your substitution function will return different
+ * results for the same input pattern, you must call this function.
+ *
+ * Since: 1.2
+ **/
+void
+pango_ft2_font_map_substitute_changed (PangoFT2FontMap *fontmap)
+{
+ pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (fontmap));
+}
+
+/**
+ * pango_ft2_font_map_set_resolution:
+ * @fontmap: a #PangoFT2Fontmap
+ * @dpi_x: dots per inch in the X direction
+ * @dpi_y: dots per inch in the Y direction
+ *
+ * Sets the horizontal and vertical resolutions for the fontmap.
+ *
+ * Since: 1.2
+ **/
+void
+pango_ft2_font_map_set_resolution (PangoFT2FontMap *fontmap,
+ double dpi_x,
+ double dpi_y)
+{
+ g_return_if_fail (PANGO_FT2_IS_FONT_MAP (fontmap));
+
+ fontmap->dpi_x = dpi_x;
+ fontmap->dpi_y = dpi_y;
+
+ pango_ft2_font_map_substitute_changed (fontmap);
+}
+
+/**
+ * pango_ft2_font_map_create_context:
+ * @fontmap: a #PangoFT2Fontmap
+ *
+ * Create a #PangoContext for the given fontmap.
+ *
+ * Return value: the newly created context; free with g_object_unref().
+ *
+ * Since: 1.2
+ **/
+PangoContext *
+pango_ft2_font_map_create_context (PangoFT2FontMap *fontmap)
+{
+ g_return_val_if_fail (PANGO_FT2_IS_FONT_MAP (fontmap), NULL);
+
+ return pango_fc_font_map_create_context (PANGO_FC_FONT_MAP (fontmap));
+}
+
+/**
+ * pango_ft2_get_context:
+ * @dpi_x: the horizontal DPI of the target device
+ * @dpi_y: the vertical DPI of the target device
+ *
+ * Retrieves a #PangoContext for the default PangoFT2 fontmap
+ * (see pango_ft2_fontmap_get_for_display()) and sets the resolution
+ * for the default fontmap to @dpi_x by @dpi_y.
+ *
+ * Use of this function is deprecated; see pango_ft2_fontmap_create_context()
+ * instead.
+ *
+ * Return value: the new #PangoContext
+ **/
+PangoContext *
+pango_ft2_get_context (double dpi_x, double dpi_y)
+{
+ PangoFontMap *fontmap;
+
+ fontmap = pango_ft2_font_map_for_display ();
+ pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (fontmap), dpi_x, dpi_y);
+
+ return pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (fontmap));
+}
+
+/**
+ * pango_ft2_font_map_for_display:
+ *
+ * Returns a #PangoFT2FontMap. This font map is cached and should
+ * not be freed. If the font map is no longer needed, it can
+ * be released with pango_ft2_shutdown_display(). Use of the
+ * global PangoFT2 fontmap is deprecated; use pango_ft2_font_map_new()
+ * instead.
+ *
+ * Return value: a #PangoFT2FontMap.
+ **/
+PangoFontMap *
+pango_ft2_font_map_for_display (void)
+{
+ if (pango_ft2_global_fontmap != NULL)
+ return PANGO_FONT_MAP (pango_ft2_global_fontmap);
+
+ pango_ft2_global_fontmap = (PangoFT2FontMap *)pango_ft2_font_map_new ();
+
+ return PANGO_FONT_MAP (pango_ft2_global_fontmap);
+}
+
+/**
+ * pango_ft2_shutdown_display:
+ *
+ * Free the global fontmap. (See pango_ft2_font_map_for_display())
+ * Use of the global PangoFT2 fontmap is deprecated.
+ **/
+void
+pango_ft2_shutdown_display (void)
+{
+ if (pango_ft2_global_fontmap)
+ {
+ pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (pango_ft2_global_fontmap));
+
+ g_object_unref (pango_ft2_global_fontmap);
+
+ pango_ft2_global_fontmap = NULL;
+ }
+}
+
+FT_Library
+_pango_ft2_font_map_get_library (PangoFontMap *fontmap)
+{
+ PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+
+ return ft2fontmap->library;
+}
+
+
+/**
+ * _pango_ft2_font_map_get_renderer:
+ * @fontmap: a #PangoFT2Fontmap
+ *
+ * Gets the singleton PangoFT2Renderer for this fontmap.
+ *
+ * Return value:
+ **/
+PangoRenderer *
+_pango_ft2_font_map_get_renderer (PangoFT2FontMap *ft2fontmap)
+{
+ if (!ft2fontmap->renderer)
+ ft2fontmap->renderer = g_object_new (PANGO_TYPE_FT2_RENDERER, NULL);
+
+ return ft2fontmap->renderer;
+}
+
+void
+_pango_ft2_font_map_default_substitute (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern)
+{
+ PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fcfontmap);
+ FcValue v;
+
+ FcConfigSubstitute (NULL, pattern, FcMatchPattern);
+
+ if (ft2fontmap->substitute_func)
+ ft2fontmap->substitute_func (pattern, ft2fontmap->substitute_data);
+
+ if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch)
+ FcPatternAddDouble (pattern, FC_DPI, ft2fontmap->dpi_y);
+ FcDefaultSubstitute (pattern);
+}
+
+static double
+pango_ft2_font_map_get_resolution (PangoFcFontMap *fcfontmap,
+ PangoContext *context)
+{
+ return ((PangoFT2FontMap *)fcfontmap)->dpi_y;
+}
+
+static PangoFcFont *
+pango_ft2_font_map_new_font (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern)
+{
+ return (PangoFcFont *)_pango_ft2_font_new (PANGO_FT2_FONT_MAP (fcfontmap), pattern);
+}
diff --git a/trunk/pango/pangoft2-private.h b/trunk/pango/pangoft2-private.h
new file mode 100644
index 00000000..8388ec9f
--- /dev/null
+++ b/trunk/pango/pangoft2-private.h
@@ -0,0 +1,126 @@
+/* Pango
+ * pangoft2-private.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOFT2_PRIVATE_H__
+#define __PANGOFT2_PRIVATE_H__
+
+#include <pango/pangoft2.h>
+#include <pango/pangofc-fontmap.h>
+#include <pango/pango-renderer.h>
+#include <fontconfig/fontconfig.h>
+
+/* Debugging... */
+/*#define DEBUGGING 1*/
+
+#if defined(DEBUGGING) && DEBUGGING
+#ifdef __GNUC__
+#define PING(printlist) \
+(g_print ("%s:%d ", __PRETTY_FUNCTION__, __LINE__), \
+ g_print printlist, \
+ g_print ("\n"))
+#else
+#define PING(printlist) \
+(g_print ("%s:%d ", __FILE__, __LINE__), \
+ g_print printlist, \
+ g_print ("\n"))
+#endif
+#else /* !DEBUGGING */
+#define PING(printlist)
+#endif
+
+typedef struct _PangoFT2Font PangoFT2Font;
+typedef struct _PangoFT2GlyphInfo PangoFT2GlyphInfo;
+typedef struct _PangoFT2Renderer PangoFT2Renderer;
+
+struct _PangoFT2Font
+{
+ PangoFcFont font;
+
+ FT_Face face;
+ int load_flags;
+
+ int size;
+
+ GSList *metrics_by_lang;
+
+ GHashTable *glyph_info;
+ GDestroyNotify glyph_cache_destroy;
+};
+
+struct _PangoFT2GlyphInfo
+{
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+ void *cached_glyph;
+};
+
+#define PANGO_TYPE_FT2_FONT (pango_ft2_font_get_type ())
+#define PANGO_FT2_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT, PangoFT2Font))
+#define PANGO_FT2_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_FONT))
+
+GType pango_ft2_font_get_type (void) G_GNUC_CONST;
+
+PangoFT2Font * _pango_ft2_font_new (PangoFT2FontMap *ft2fontmap,
+ FcPattern *pattern);
+FT_Library _pango_ft2_font_map_get_library (PangoFontMap *fontmap);
+const char *_pango_ft2_ft_strerror (FT_Error error);
+void _pango_ft2_font_map_default_substitute (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern);
+
+void *_pango_ft2_font_get_cache_glyph_data (PangoFont *font,
+ int glyph_index);
+void _pango_ft2_font_set_cache_glyph_data (PangoFont *font,
+ int glyph_index,
+ void *cached_glyph);
+void _pango_ft2_font_set_glyph_cache_destroy (PangoFont *font,
+ GDestroyNotify destroy_notify);
+
+void _pango_ft2_draw_rect (FT_Bitmap *bitmap,
+ const PangoMatrix *matrix,
+ int x,
+ int y,
+ int width,
+ int height);
+void _pango_ft2_draw_error_underline (FT_Bitmap *bitmap,
+ const PangoMatrix *matrix,
+ int x,
+ int y,
+ int width,
+ int height);
+
+#define PANGO_TYPE_FT2_RENDERER (pango_ft2_renderer_get_type())
+#define PANGO_FT2_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_RENDERER, PangoFT2Renderer))
+#define PANGO_IS_FT2_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_RENDERER))
+
+GType pango_ft2_renderer_get_type (void) G_GNUC_CONST;
+
+PangoRenderer *_pango_ft2_font_map_get_renderer (PangoFT2FontMap *ft2fontmap);
+
+typedef struct _PangoFT2WarningHistory PangoFT2WarningHistory;
+
+struct _PangoFT2WarningHistory {
+ guint get_face : 1;
+};
+
+extern PangoFT2WarningHistory _pango_ft2_warning_history;
+
+#endif /* __PANGOFT2_PRIVATE_H__ */
diff --git a/trunk/pango/pangoft2-render.c b/trunk/pango/pangoft2-render.c
new file mode 100644
index 00000000..ef052efa
--- /dev/null
+++ b/trunk/pango/pangoft2-render.c
@@ -0,0 +1,710 @@
+/* Pango
+ * pangoft2-render.c: Rendering routines to FT_Bitmap objects
+ *
+ * Copyright (C) 2004 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <math.h>
+
+#include "pangoft2-private.h"
+
+/* for compatibility with older freetype versions */
+#ifndef FT_LOAD_TARGET_MONO
+#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
+#endif
+
+typedef struct _PangoFT2RendererClass PangoFT2RendererClass;
+
+#define PANGO_FT2_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_RENDERER, PangoFT2RendererClass))
+#define PANGO_IS_FT2_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_RENDERER))
+#define PANGO_FT2_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_RENDERER, PangoFT2RendererClass))
+
+struct _PangoFT2Renderer
+{
+ PangoRenderer parent_instance;
+
+ FT_Bitmap *bitmap;
+};
+
+struct _PangoFT2RendererClass
+{
+ PangoRendererClass parent_class;
+};
+
+static void pango_ft2_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y);
+static void pango_ft2_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22);
+
+G_DEFINE_TYPE (PangoFT2Renderer, pango_ft2_renderer, PANGO_TYPE_RENDERER)
+
+static void
+pango_ft2_renderer_init (PangoFT2Renderer *renderer)
+{
+}
+
+static void
+pango_ft2_renderer_class_init (PangoFT2RendererClass *klass)
+{
+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
+
+ renderer_class->draw_glyph = pango_ft2_renderer_draw_glyph;
+ renderer_class->draw_trapezoid = pango_ft2_renderer_draw_trapezoid;
+}
+
+static void
+pango_ft2_renderer_set_bitmap (PangoFT2Renderer *renderer,
+ FT_Bitmap *bitmap)
+{
+ renderer->bitmap = bitmap;
+}
+
+typedef struct
+{
+ FT_Bitmap bitmap;
+ int bitmap_left;
+ int bitmap_top;
+} PangoFT2RenderedGlyph;
+
+static void
+pango_ft2_free_rendered_glyph (PangoFT2RenderedGlyph *rendered)
+{
+ g_free (rendered->bitmap.buffer);
+ g_slice_free (PangoFT2RenderedGlyph, rendered);
+}
+
+static PangoFT2RenderedGlyph *
+pango_ft2_font_render_box_glyph (int width,
+ int height,
+ int top)
+{
+ PangoFT2RenderedGlyph *box;
+ int i, j, offset1, offset2, line_width;
+
+ line_width = MAX ((height + 43) / 44, 1);
+ if (width < 1 || height < 1)
+ line_width = 0;
+
+ box = g_slice_new (PangoFT2RenderedGlyph);
+
+ box->bitmap_left = 0;
+ box->bitmap_top = top;
+
+ box->bitmap.pixel_mode = ft_pixel_mode_grays;
+
+ box->bitmap.width = width;
+ box->bitmap.rows = height;
+ box->bitmap.pitch = height;
+
+ box->bitmap.buffer = g_malloc0 (box->bitmap.rows * box->bitmap.pitch);
+
+ /* draw the box */
+ for (j = 0; j < line_width; j++)
+ {
+ offset1 = box->bitmap.pitch * (MIN (1 + j, height - 1));
+ offset2 = box->bitmap.pitch * (MAX (box->bitmap.rows - 2 - j, 0));
+ for (i = 1;
+ i < box->bitmap.width - 1;
+ i++)
+ {
+ box->bitmap.buffer[offset1 + i] = 0xff;
+ box->bitmap.buffer[offset2 + i] = 0xff;
+ }
+ }
+ for (j = 0; j < line_width; j++)
+ {
+ offset1 = MIN (1 + j, width - 1);
+ offset2 = MAX (box->bitmap.width - 2 - j, 0);
+ for (i = box->bitmap.pitch;
+ i < (box->bitmap.rows - 1) * box->bitmap.pitch;
+ i += box->bitmap.pitch)
+ {
+ box->bitmap.buffer[offset1 + i] = 0xff;
+ box->bitmap.buffer[offset2 + i] = 0xff;
+ }
+ }
+
+ return box;
+}
+
+static PangoFT2RenderedGlyph *
+pango_ft2_font_render_glyph (PangoFont *font,
+ int glyph_index)
+{
+ FT_Face face;
+
+ if (glyph_index & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ PangoFT2RenderedGlyph *box;
+ PangoFontMetrics *metrics;
+
+ if (!font)
+ goto generic_box;
+
+ metrics = pango_font_get_metrics (font, NULL);
+ if (!metrics)
+ goto generic_box;
+
+ box = pango_ft2_font_render_box_glyph (PANGO_PIXELS (metrics->approximate_char_width),
+ PANGO_PIXELS (metrics->ascent + metrics->descent),
+ PANGO_PIXELS (metrics->ascent));
+ pango_font_metrics_unref (metrics);
+
+ return box;
+ }
+
+ face = pango_ft2_font_get_face (font);
+
+ if (face)
+ {
+ PangoFT2RenderedGlyph *rendered;
+ PangoFT2Font *ft2font = (PangoFT2Font *) font;
+
+ rendered = g_slice_new (PangoFT2RenderedGlyph);
+
+ /* Draw glyph */
+ FT_Load_Glyph (face, glyph_index, ft2font->load_flags);
+ FT_Render_Glyph (face->glyph,
+ (ft2font->load_flags & FT_LOAD_TARGET_MONO ?
+ ft_render_mode_mono : ft_render_mode_normal));
+
+ rendered->bitmap = face->glyph->bitmap;
+ rendered->bitmap.buffer = g_memdup (face->glyph->bitmap.buffer,
+ face->glyph->bitmap.rows * face->glyph->bitmap.pitch);
+ rendered->bitmap_left = face->glyph->bitmap_left;
+ rendered->bitmap_top = face->glyph->bitmap_top;
+
+ return rendered;
+ }
+ else
+ {
+generic_box:
+ return pango_ft2_font_render_box_glyph (PANGO_UNKNOWN_GLYPH_WIDTH,
+ PANGO_UNKNOWN_GLYPH_HEIGHT,
+ PANGO_UNKNOWN_GLYPH_HEIGHT);
+ }
+}
+
+static void
+pango_ft2_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y)
+{
+ FT_Bitmap *bitmap = PANGO_FT2_RENDERER (renderer)->bitmap;
+ PangoFT2RenderedGlyph *rendered_glyph;
+ gboolean add_glyph_to_cache;
+ guchar *src, *dest;
+
+ int x_start, x_limit;
+ int y_start, y_limit;
+ int ixoff = floor (x + 0.5);
+ int iyoff = floor (y + 0.5);
+ int ix, iy;
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ glyph = pango_ft2_get_unknown_glyph (font);
+ if (glyph == PANGO_GLYPH_EMPTY)
+ {
+ /* No unknown glyph found for the font, draw a box */
+
+ /* Since we only draw an empty box for FT2 renderer,
+ * we unify the rendered bitmaps in the cache.
+ */
+ glyph = PANGO_GLYPH_UNKNOWN_FLAG;
+ }
+ }
+
+ rendered_glyph = _pango_ft2_font_get_cache_glyph_data (font, glyph);
+ add_glyph_to_cache = FALSE;
+ if (rendered_glyph == NULL)
+ {
+ rendered_glyph = pango_ft2_font_render_glyph (font, glyph);
+ add_glyph_to_cache = TRUE;
+ }
+
+ x_start = MAX (0, - (ixoff + rendered_glyph->bitmap_left));
+ x_limit = MIN (rendered_glyph->bitmap.width,
+ bitmap->width - (ixoff + rendered_glyph->bitmap_left));
+
+ y_start = MAX (0, - (iyoff - rendered_glyph->bitmap_top));
+ y_limit = MIN (rendered_glyph->bitmap.rows,
+ bitmap->rows - (iyoff - rendered_glyph->bitmap_top));
+
+ src = rendered_glyph->bitmap.buffer +
+ y_start * rendered_glyph->bitmap.pitch;
+
+ dest = bitmap->buffer +
+ (y_start + iyoff - rendered_glyph->bitmap_top) * bitmap->pitch +
+ x_start + ixoff + rendered_glyph->bitmap_left;
+
+ switch (rendered_glyph->bitmap.pixel_mode)
+ {
+ case ft_pixel_mode_grays:
+ src += x_start;
+ for (iy = y_start; iy < y_limit; iy++)
+ {
+ guchar *s = src;
+ guchar *d = dest;
+
+ for (ix = x_start; ix < x_limit; ix++)
+ {
+ switch (*s)
+ {
+ case 0:
+ break;
+ case 0xff:
+ *d = 0xff;
+ default:
+ *d = MIN ((gushort) *d + (gushort) *s, 0xff);
+ break;
+ }
+
+ s++;
+ d++;
+ }
+
+ dest += bitmap->pitch;
+ src += rendered_glyph->bitmap.pitch;
+ }
+ break;
+
+ case ft_pixel_mode_mono:
+ src += x_start / 8;
+ for (iy = y_start; iy < y_limit; iy++)
+ {
+ guchar *s = src;
+ guchar *d = dest;
+
+ for (ix = x_start; ix < x_limit; ix++)
+ {
+ if ((*s) & (1 << (7 - (ix % 8))))
+ *d |= 0xff;
+
+ if ((ix % 8) == 7)
+ s++;
+ d++;
+ }
+
+ dest += bitmap->pitch;
+ src += rendered_glyph->bitmap.pitch;
+ }
+ break;
+
+ default:
+ g_warning ("pango_ft2_render: "
+ "Unrecognized glyph bitmap pixel mode %d\n",
+ rendered_glyph->bitmap.pixel_mode);
+ break;
+ }
+
+ if (add_glyph_to_cache)
+ {
+ _pango_ft2_font_set_glyph_cache_destroy (font,
+ (GDestroyNotify) pango_ft2_free_rendered_glyph);
+ _pango_ft2_font_set_cache_glyph_data (font,
+ glyph, rendered_glyph);
+ }
+}
+
+typedef struct {
+ double y;
+ double x1;
+ double x2;
+} Position;
+
+static void
+draw_simple_trap (PangoRenderer *renderer,
+ Position *t,
+ Position *b)
+{
+ FT_Bitmap *bitmap = PANGO_FT2_RENDERER (renderer)->bitmap;
+ int iy = floor (t->y);
+ int x1, x2, x;
+ double dy = b->y - t->y;
+ guchar *dest;
+
+ if (iy < 0 || iy >= bitmap->rows)
+ return;
+ dest = bitmap->buffer + iy * bitmap->pitch;
+
+ if (t->x1 < b->x1)
+ x1 = floor (t->x1);
+ else
+ x1 = floor (b->x1);
+
+ if (t->x2 > b->x2)
+ x2 = ceil (t->x2);
+ else
+ x2 = ceil (b->x2);
+
+ x1 = CLAMP (x1, 0, bitmap->width);
+ x2 = CLAMP (x2, 0, bitmap->width);
+
+ for (x = x1; x < x2; x++)
+ {
+ double top_left = MAX (t->x1, x);
+ double top_right = MIN (t->x2, x + 1);
+ double bottom_left = MAX (b->x1, x);
+ double bottom_right = MIN (b->x2, x + 1);
+ double c = 0.5 * dy * ((top_right - top_left) + (bottom_right - bottom_left));
+
+ /* When converting to [0,255], we round up. This is intended
+ * to prevent the problem of pixels that get divided into
+ * multiple slices not being fully black.
+ */
+ int ic = c * 256;
+
+ dest[x] = MIN (dest[x] + ic, 255);
+ }
+}
+
+static void
+interpolate_position (Position *result,
+ Position *top,
+ Position *bottom,
+ double val,
+ double val1,
+ double val2)
+{
+ result->y = (top->y * (val2 - val) + bottom->y * (val - val1)) / (val2 - val1);
+ result->x1 = (top->x1 * (val2 - val) + bottom->x1 * (val - val1)) / (val2 - val1);
+ result->x2 = (top->x2 * (val2 - val) + bottom->x2 * (val - val1)) / (val2 - val1);
+}
+
+/* This draws a trapezoid with the parallel sides aligned with
+ * the X axis. We do this by subdividing the trapezoid vertically
+ * into thin slices (themselves trapezoids) where two edge sides are each
+ * contained within a single pixel and then rasterizing each
+ * slice. There are frequently multiple slices within a single
+ * line so we have to accumulate to get the final result.
+ */
+static void
+pango_ft2_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22)
+{
+ Position pos;
+ Position t;
+ Position b;
+ gboolean done = FALSE;
+
+ if (y1 == y2)
+ return;
+
+ pos.y = t.y = y1;
+ pos.x1 = t.x1 = x11;
+ pos.x2 = t.x2 = x21;
+ b.y = y2;
+ b.x1 = x12;
+ b.x2 = x22;
+
+ while (!done)
+ {
+ Position pos_next;
+ double y_next, x1_next, x2_next;
+ double ix1, ix2;
+
+ /* The algorithm here is written to emphasize simplicity and
+ * numerical stability as opposed to speed.
+ *
+ * While the end result is slicing up the polygon vertically,
+ * conceptually we aren't walking in the X direction, rather we
+ * are walking along the edges. When we compute crossing of
+ * horizontal pixel boundaries, we use the X coordinate as the
+ * interpolating variable, when we compute crossing for vertical
+ * pixel boundaries, we use the Y coordinate.
+ *
+ * This allows us to handle almost exactly horizontal edges without
+ * running into difficulties. (Almost exactly horizontal edges
+ * come up frequently due to inexactness in computing, say,
+ * a 90 degree rotation transformation)
+ */
+
+ pos_next = b;
+ done = TRUE;
+
+ /* Check for crossing vertical pixel boundaries */
+ y_next = floor (pos.y) + 1;
+ if (y_next < pos_next.y)
+ {
+ interpolate_position (&pos_next, &t, &b,
+ y_next, t.y, b.y);
+ pos_next.y = y_next;
+ done = FALSE;
+ }
+
+ /* Check left side for crossing horizontal pixel boundaries */
+ ix1 = floor (pos.x1);
+
+ if (b.x1 < t.x1)
+ {
+ if (ix1 == pos.x1)
+ x1_next = ix1 - 1;
+ else
+ x1_next = ix1;
+
+ if (x1_next > pos_next.x1)
+ {
+ interpolate_position (&pos_next, &t, &b,
+ x1_next, t.x1, b.x1);
+ pos_next.x1 = x1_next;
+ done = FALSE;
+ }
+ }
+ else if (b.x1 > t.x1)
+ {
+ x1_next = ix1 + 1;
+
+ if (x1_next < pos_next.x1)
+ {
+ interpolate_position (&pos_next, &t, &b,
+ x1_next, t.x1, b.x1);
+ pos_next.x1 = x1_next;
+ done = FALSE;
+ }
+ }
+
+ /* Check right side for crossing horizontal pixel boundaries */
+ ix2 = floor (pos.x2);
+
+ if (b.x2 < t.x2)
+ {
+ if (ix2 == pos.x2)
+ x2_next = ix2 - 1;
+ else
+ x2_next = ix2;
+
+ if (x2_next > pos_next.x2)
+ {
+ interpolate_position (&pos_next, &t, &b,
+ x2_next, t.x2, b.x2);
+ pos_next.x2 = x2_next;
+ done = FALSE;
+ }
+ }
+ else if (x22 > x21)
+ {
+ x2_next = ix2 + 1;
+
+ if (x2_next < pos_next.x2)
+ {
+ interpolate_position (&pos_next, &t, &b,
+ x2_next, t.x2, b.x2);
+ pos_next.x2 = x2_next;
+ done = FALSE;
+ }
+ }
+
+ draw_simple_trap (renderer, &pos, &pos_next);
+ pos = pos_next;
+ }
+}
+
+/**
+ * pango_ft2_render_layout_subpixel:
+ * @bitmap: a <type>FT_Bitmap</type> to render the layout onto
+ * @layout: a #PangoLayout
+ * @x: the X position of the left of the layout (in Pango units)
+ * @y: the Y position of the top of the layout (in Pango units)
+ *
+ * Render a #PangoLayout onto a FreeType2 bitmap, with he
+ * location specified in fixed-point Pango units rather than
+ * pixels. (Using this will avoid extra inaccuracies from
+ * rounding to integer pixels multiple times, even if the
+ * final glyph positions are integers.)
+ *
+ * Since: 1.6
+ */
+void
+pango_ft2_render_layout_subpixel (FT_Bitmap *bitmap,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (bitmap != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ context = pango_layout_get_context (layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = _pango_ft2_font_map_get_renderer (PANGO_FT2_FONT_MAP (fontmap));
+
+ pango_ft2_renderer_set_bitmap (PANGO_FT2_RENDERER (renderer), bitmap);
+
+ pango_renderer_draw_layout (renderer, layout, x, y);
+}
+
+/**
+ * pango_ft2_render_layout:
+ * @bitmap: a <type>FT_Bitmap</type> to render the layout onto
+ * @layout: a #PangoLayout
+ * @x: the X position of the left of the layout (in pixels)
+ * @y: the Y position of the top of the layout (in pixels)
+ *
+ * Render a #PangoLayout onto a FreeType2 bitmap
+ */
+void
+pango_ft2_render_layout (FT_Bitmap *bitmap,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ pango_ft2_render_layout_subpixel (bitmap, layout, x * PANGO_SCALE, y * PANGO_SCALE);
+}
+
+/**
+ * pango_ft2_render_layout_line_subpixel:
+ * @bitmap: a <type>FT_Bitmap</type> to render the line onto
+ * @line: a #PangoLayoutLine
+ * @x: the x position of start of string (in Pango units)
+ * @y: the y position of baseline (in Pango units)
+ *
+ * Render a #PangoLayoutLine onto a FreeType2 bitmap, with he
+ * location specified in fixed-point Pango units rather than
+ * pixels. (Using this will avoid extra inaccuracies from
+ * rounding to integer pixels multiple times, even if the
+ * final glyph positions are integers.)
+ *
+ * Since: 1.6
+ */
+void
+pango_ft2_render_layout_line_subpixel (FT_Bitmap *bitmap,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (bitmap != NULL);
+ g_return_if_fail (line != NULL);
+
+ context = pango_layout_get_context (line->layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = _pango_ft2_font_map_get_renderer (PANGO_FT2_FONT_MAP (fontmap));
+
+ pango_ft2_renderer_set_bitmap (PANGO_FT2_RENDERER (renderer), bitmap);
+
+ pango_renderer_draw_layout_line (renderer, line, x, y);
+}
+
+/**
+ * pango_ft2_render_layout_line:
+ * @bitmap: a <type>FT_Bitmap</type> to render the line onto
+ * @line: a #PangoLayoutLine
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Render a #PangoLayoutLine onto a FreeType2 bitmap
+ */
+void
+pango_ft2_render_layout_line (FT_Bitmap *bitmap,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ pango_ft2_render_layout_line_subpixel (bitmap, line, x * PANGO_SCALE, y * PANGO_SCALE);
+}
+
+/**
+ * pango_ft2_render_transformed:
+ * @bitmap: the FreeType2 bitmap onto which to draw the string
+ * @font: the font in which to draw the string
+ * @matrix: a #PangoMatrix, or %NULL to use an identity transformation
+ * @glyphs: the glyph string to draw
+ * @x: the x position of the start of the string (in Pango
+ * units in user space coordinates)
+ * @y: the y position of the baseline (in Pango units
+ * in user space coordinates)
+ *
+ * Renders a #PangoGlyphString onto a FreeType2 bitmap, possibly
+ * transforming the layed-out coordinates through a transformation
+ * matrix. Note that the transformation matrix for @font is not
+ * changed, so to produce correct rendering results, the @font
+ * must have been loaded using a #PangoContext with an identical
+ * transformation matrix to that passed in to this function.
+ *
+ * Since: 1.6
+ **/
+void
+pango_ft2_render_transformed (FT_Bitmap *bitmap,
+ const PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (bitmap != NULL);
+ g_return_if_fail (glyphs != NULL);
+ g_return_if_fail (PANGO_FT2_IS_FONT (font));
+
+ fontmap = PANGO_FC_FONT (font)->fontmap;
+ renderer = _pango_ft2_font_map_get_renderer (PANGO_FT2_FONT_MAP (fontmap));
+
+ pango_ft2_renderer_set_bitmap (PANGO_FT2_RENDERER (renderer), bitmap);
+ pango_renderer_set_matrix (renderer, matrix);
+
+ pango_renderer_draw_glyphs (renderer, font, glyphs, x, y);
+}
+
+/**
+ * pango_ft2_render:
+ * @bitmap: the FreeType2 bitmap onto which to draw the string
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of the start of the string (in pixels)
+ * @y: the y position of the baseline (in pixels)
+ *
+ * Renders a #PangoGlyphString onto a FreeType2 bitmap.
+ **/
+void
+pango_ft2_render (FT_Bitmap *bitmap,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ pango_ft2_render_transformed (bitmap, NULL, font, glyphs, x * PANGO_SCALE, y * PANGO_SCALE);
+}
+
diff --git a/trunk/pango/pangoft2.c b/trunk/pango/pangoft2.c
new file mode 100644
index 00000000..f23f1ed9
--- /dev/null
+++ b/trunk/pango/pangoft2.c
@@ -0,0 +1,601 @@
+/* Pango
+ * pangoft2.c: Routines for handling FreeType2 fonts
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include "pangoft2.h"
+#include "pangoft2-private.h"
+#include "pangofc-fontmap.h"
+#include "pangofc-private.h"
+
+PangoFT2WarningHistory _pango_ft2_warning_history = { FALSE };
+
+/* for compatibility with older freetype versions */
+#ifndef FT_LOAD_TARGET_MONO
+#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
+#endif
+
+#define PANGO_FT2_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_FONT, PangoFT2FontClass))
+#define PANGO_FT2_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_FONT))
+#define PANGO_FT2_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_FONT, PangoFT2FontClass))
+
+typedef struct _PangoFT2FontClass PangoFT2FontClass;
+
+struct _PangoFT2FontClass
+{
+ PangoFcFontClass parent_class;
+};
+
+static void pango_ft2_font_finalize (GObject *object);
+
+static void pango_ft2_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+static FT_Face pango_ft2_font_real_lock_face (PangoFcFont *font);
+static void pango_ft2_font_real_unlock_face (PangoFcFont *font);
+
+PangoFT2Font *
+_pango_ft2_font_new (PangoFT2FontMap *ft2fontmap,
+ FcPattern *pattern)
+{
+ PangoFontMap *fontmap = PANGO_FONT_MAP (ft2fontmap);
+ PangoFT2Font *ft2font;
+ double d;
+
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (pattern != NULL, NULL);
+
+ ft2font = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT,
+ "pattern", pattern,
+ NULL);
+
+ if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
+ ft2font->size = d*PANGO_SCALE;
+
+ return ft2font;
+}
+
+static void
+load_fallback_face (PangoFT2Font *ft2font,
+ const char *original_file)
+{
+ PangoFcFont *fcfont = PANGO_FC_FONT (ft2font);
+ FcPattern *sans;
+ FcPattern *matched;
+ FcResult result;
+ FT_Error error;
+ FcChar8 *filename2 = NULL;
+ gchar *name;
+ int id;
+
+ sans = FcPatternBuild (NULL,
+ FC_FAMILY, FcTypeString, "sans",
+ FC_PIXEL_SIZE, FcTypeDouble, (double)ft2font->size / PANGO_SCALE,
+ NULL);
+
+ _pango_ft2_font_map_default_substitute (fcfont->fontmap, sans);
+
+ matched = FcFontMatch (NULL, sans, &result);
+
+ if (FcPatternGetString (matched, FC_FILE, 0, &filename2) != FcResultMatch)
+ goto bail1;
+
+ if (FcPatternGetInteger (matched, FC_INDEX, 0, &id) != FcResultMatch)
+ goto bail1;
+
+ error = FT_New_Face (_pango_ft2_font_map_get_library (fcfont->fontmap),
+ (char *) filename2, id, &ft2font->face);
+
+
+ if (error)
+ {
+ bail1:
+ name = pango_font_description_to_string (fcfont->description);
+ g_warning ("Unable to open font file %s for font %s, exiting\n", filename2, name);
+ exit (1);
+ }
+ else
+ {
+ name = pango_font_description_to_string (fcfont->description);
+ g_warning ("Unable to open font file %s for font %s, falling back to %s\n", original_file, name, filename2);
+ g_free (name);
+ }
+
+ FcPatternDestroy (sans);
+ FcPatternDestroy (matched);
+}
+
+static void
+set_transform (PangoFT2Font *ft2font)
+{
+ PangoFcFont *fcfont = (PangoFcFont *)ft2font;
+ FcMatrix *fc_matrix;
+
+ if (FcPatternGetMatrix (fcfont->font_pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
+ {
+ FT_Matrix ft_matrix;
+
+ ft_matrix.xx = 0x10000L * fc_matrix->xx;
+ ft_matrix.yy = 0x10000L * fc_matrix->yy;
+ ft_matrix.xy = 0x10000L * fc_matrix->xy;
+ ft_matrix.yx = 0x10000L * fc_matrix->yx;
+
+ FT_Set_Transform (ft2font->face, &ft_matrix, NULL);
+ }
+}
+
+/**
+ * pango_ft2_font_get_face:
+ * @font: a #PangoFont
+ *
+ * Returns the native FreeType2 <type>FT_Face</type> structure used for this #PangoFont.
+ * This may be useful if you want to use FreeType2 functions directly.
+ *
+ * Use pango_fc_font_lock_face() instead; when you are done with a
+ * face from pango_fc_font_lock_face() you must call
+ * pango_fc_font_unlock_face().
+ *
+ * Return value: a pointer to a <type>FT_Face</type> structure, with the size set correctly
+ **/
+FT_Face
+pango_ft2_font_get_face (PangoFont *font)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)font;
+ PangoFcFont *fcfont = (PangoFcFont *)font;
+ FT_Error error;
+ FcPattern *pattern;
+ FcChar8 *filename;
+ FcBool antialias, hinting, autohint;
+ int hintstyle;
+ int id;
+
+ if (G_UNLIKELY (!PANGO_FT2_IS_FONT (font)))
+ {
+ if (!_pango_ft2_warning_history.get_face)
+ {
+ _pango_ft2_warning_history.get_face = TRUE;
+ g_warning ("pango_ft2_font_get_face called with bad font, expect ugly output");
+ }
+ return NULL;
+ }
+
+ pattern = fcfont->font_pattern;
+
+ if (!ft2font->face)
+ {
+ ft2font->load_flags = 0;
+
+ /* disable antialiasing if requested */
+ if (FcPatternGetBool (pattern,
+ FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
+ antialias = FcTrue;
+
+ if (antialias)
+ ft2font->load_flags |= FT_LOAD_NO_BITMAP;
+ else
+ ft2font->load_flags |= FT_LOAD_TARGET_MONO;
+
+ /* disable hinting if requested */
+ if (FcPatternGetBool (pattern,
+ FC_HINTING, 0, &hinting) != FcResultMatch)
+ hinting = FcTrue;
+
+#ifdef FC_HINT_STYLE
+ if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
+ hintstyle = FC_HINT_FULL;
+
+ if (!hinting || hintstyle == FC_HINT_NONE)
+ ft2font->load_flags |= FT_LOAD_NO_HINTING;
+
+ switch (hintstyle) {
+ case FC_HINT_SLIGHT:
+ case FC_HINT_MEDIUM:
+ ft2font->load_flags |= FT_LOAD_TARGET_LIGHT;
+ break;
+ default:
+ ft2font->load_flags |= FT_LOAD_TARGET_NORMAL;
+ break;
+ }
+#else
+ if (!hinting)
+ ft2font->load_flags |= FT_LOAD_NO_HINTING;
+#endif
+
+ /* force autohinting if requested */
+ if (FcPatternGetBool (pattern,
+ FC_AUTOHINT, 0, &autohint) != FcResultMatch)
+ autohint = FcFalse;
+
+ if (autohint)
+ ft2font->load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
+ if (FcPatternGetString (pattern, FC_FILE, 0, &filename) != FcResultMatch)
+ goto bail0;
+
+ if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
+ goto bail0;
+
+ error = FT_New_Face (_pango_ft2_font_map_get_library (fcfont->fontmap),
+ (char *) filename, id, &ft2font->face);
+ if (error != FT_Err_Ok)
+ {
+ bail0:
+ load_fallback_face (ft2font, filename);
+ }
+
+ g_assert (ft2font->face);
+
+ set_transform (ft2font);
+
+ error = FT_Set_Char_Size (ft2font->face,
+ PANGO_PIXELS_26_6 (ft2font->size),
+ PANGO_PIXELS_26_6 (ft2font->size),
+ 0, 0);
+ if (error)
+ g_warning ("Error in FT_Set_Char_Size: %d", error);
+ }
+
+ return ft2font->face;
+}
+
+G_DEFINE_TYPE (PangoFT2Font, pango_ft2_font, PANGO_TYPE_FC_FONT)
+
+static void
+pango_ft2_font_init (PangoFT2Font *ft2font)
+{
+ ft2font->face = NULL;
+
+ ft2font->size = 0;
+
+ ft2font->glyph_info = g_hash_table_new (NULL, NULL);
+}
+
+static void
+pango_ft2_font_class_init (PangoFT2FontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+ PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class);
+
+ object_class->finalize = pango_ft2_font_finalize;
+
+ font_class->get_glyph_extents = pango_ft2_font_get_glyph_extents;
+
+ fc_font_class->lock_face = pango_ft2_font_real_lock_face;
+ fc_font_class->unlock_face = pango_ft2_font_real_unlock_face;
+}
+
+static PangoFT2GlyphInfo *
+pango_ft2_font_get_glyph_info (PangoFont *font,
+ PangoGlyph glyph,
+ gboolean create)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)font;
+ PangoFcFont *fcfont = (PangoFcFont *)font;
+ PangoFT2GlyphInfo *info;
+
+ info = g_hash_table_lookup (ft2font->glyph_info, GUINT_TO_POINTER (glyph));
+
+ if ((info == NULL) && create)
+ {
+ info = g_slice_new0 (PangoFT2GlyphInfo);
+
+ pango_fc_font_get_raw_extents (fcfont, ft2font->load_flags,
+ glyph,
+ &info->ink_rect,
+ &info->logical_rect);
+
+ g_hash_table_insert (ft2font->glyph_info, GUINT_TO_POINTER(glyph), info);
+ }
+
+ return info;
+}
+
+static void
+pango_ft2_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoFT2GlyphInfo *info;
+
+ if (glyph == PANGO_GLYPH_EMPTY)
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
+ if (logical_rect)
+ logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
+ return;
+ }
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ glyph = pango_ft2_get_unknown_glyph (font);
+ if (glyph == PANGO_GLYPH_EMPTY)
+ {
+ /* No unknown glyph found for the font, draw a box */
+ PangoFontMetrics *metrics = pango_font_get_metrics (font, NULL);
+
+ if (metrics)
+ {
+ if (ink_rect)
+ {
+ ink_rect->x = PANGO_SCALE;
+ ink_rect->width = metrics->approximate_char_width - 2 * PANGO_SCALE;
+ ink_rect->y = - (metrics->ascent - PANGO_SCALE);
+ ink_rect->height = metrics->ascent + metrics->descent - 2 * PANGO_SCALE;
+ }
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->width = metrics->approximate_char_width;
+ logical_rect->y = -metrics->ascent;
+ logical_rect->height = metrics->ascent + metrics->descent;
+ }
+
+ pango_font_metrics_unref (metrics);
+ }
+ else
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
+ if (logical_rect)
+ logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
+ }
+ return;
+ }
+ }
+
+ info = pango_ft2_font_get_glyph_info (font, glyph, TRUE);
+
+ if (ink_rect)
+ *ink_rect = info->ink_rect;
+ if (logical_rect)
+ *logical_rect = info->logical_rect;
+}
+
+/**
+ * pango_ft2_font_get_kerning:
+ * @font: a #PangoFont
+ * @left: the left #PangoGlyph
+ * @right: the right #PangoGlyph
+ *
+ * Retrieves kerning information for a combination of two glyphs.
+ *
+ * Use pango_fc_font_kern_glyphs() instead.
+ *
+ * Return value: The amount of kerning (in Pango units) to apply for
+ * the given combination of glyphs.
+ **/
+int
+pango_ft2_font_get_kerning (PangoFont *font,
+ PangoGlyph left,
+ PangoGlyph right)
+{
+ PangoFcFont *fc_font = PANGO_FC_FONT (font);
+
+ FT_Face face;
+ FT_Error error;
+ FT_Vector kerning;
+
+ face = pango_fc_font_lock_face (fc_font);
+ if (!face)
+ return 0;
+
+ if (!FT_HAS_KERNING (face))
+ {
+ pango_fc_font_unlock_face (fc_font);
+ return 0;
+ }
+
+ error = FT_Get_Kerning (face, left, right, ft_kerning_default, &kerning);
+ if (error != FT_Err_Ok)
+ {
+ pango_fc_font_unlock_face (fc_font);
+ return 0;
+ }
+
+ pango_fc_font_unlock_face (fc_font);
+ return PANGO_UNITS_26_6 (kerning.x);
+}
+
+static FT_Face
+pango_ft2_font_real_lock_face (PangoFcFont *font)
+{
+ return pango_ft2_font_get_face ((PangoFont *)font);
+}
+
+static void
+pango_ft2_font_real_unlock_face (PangoFcFont *font)
+{
+}
+
+static gboolean
+pango_ft2_free_glyph_info_callback (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ PangoFT2Font *font = PANGO_FT2_FONT (data);
+ PangoFT2GlyphInfo *info = value;
+
+ if (font->glyph_cache_destroy && info->cached_glyph)
+ (*font->glyph_cache_destroy) (info->cached_glyph);
+
+ g_slice_free (PangoFT2GlyphInfo, info);
+ return TRUE;
+}
+
+static void
+pango_ft2_font_finalize (GObject *object)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)object;
+
+ if (ft2font->face)
+ {
+ FT_Done_Face (ft2font->face);
+ ft2font->face = NULL;
+ }
+
+ g_hash_table_foreach_remove (ft2font->glyph_info,
+ pango_ft2_free_glyph_info_callback, object);
+ g_hash_table_destroy (ft2font->glyph_info);
+
+ G_OBJECT_CLASS (pango_ft2_font_parent_class)->finalize (object);
+}
+
+/**
+ * pango_ft2_font_get_coverage:
+ * @font: a #PangoFT2Font.
+ * @language: a language tag.
+ * @returns: a #PangoCoverage.
+ *
+ * Gets the #PangoCoverage for a #PangoFT2Font. Use pango_font_get_coverage() instead.
+ **/
+PangoCoverage *
+pango_ft2_font_get_coverage (PangoFont *font,
+ PangoLanguage *language)
+{
+ return pango_font_get_coverage (font, language);
+}
+
+/* Utility functions */
+
+/**
+ * pango_ft2_get_unknown_glyph:
+ * @font: a #PangoFont
+ *
+ * Return the index of a glyph suitable for drawing unknown characters with
+ * @font, or %PANGO_GLYPH_EMPTY if no suitable glyph found.
+ *
+ * If you want to draw an unknown-box for a character that is not covered
+ * by the font,
+ * use PANGO_GET_UNKNOWN_GLYPH() instead.
+ *
+ * Return value: a glyph index into @font, or %PANGO_GLYPH_EMPTY
+ **/
+PangoGlyph
+pango_ft2_get_unknown_glyph (PangoFont *font)
+{
+ FT_Face face = pango_ft2_font_get_face (font);
+ if (face && FT_IS_SFNT (face))
+ /* TrueType fonts have an 'unknown glyph' box on glyph index 0 */
+ return 0;
+ else
+ return PANGO_GLYPH_EMPTY;
+}
+
+typedef struct
+{
+ FT_Error code;
+ const char msg[40];
+} ft_error_description;
+
+static int
+ft_error_compare (const void *pkey,
+ const void *pbase)
+{
+ return ((ft_error_description *) pkey)->code - ((ft_error_description *) pbase)->code;
+}
+
+G_CONST_RETURN char *
+_pango_ft2_ft_strerror (FT_Error error)
+{
+#undef __FTERRORS_H__
+#define FT_ERRORDEF( e, v, s ) { e, s },
+#define FT_ERROR_START_LIST {
+#define FT_ERROR_END_LIST };
+
+ static const ft_error_description ft_errors[] =
+#include FT_ERRORS_H
+
+#undef FT_ERRORDEF
+#undef FT_ERROR_START_LIST
+#undef FT_ERROR_END_LIST
+
+ ft_error_description *found =
+ bsearch (&error, ft_errors, G_N_ELEMENTS (ft_errors),
+ sizeof (ft_errors[0]), ft_error_compare);
+ if (found != NULL)
+ return found->msg;
+ else
+ {
+ static char *default_msg = NULL;
+
+ if (!default_msg)
+ default_msg = g_malloc (60);
+
+ g_sprintf (default_msg, "Unknown FreeType2 error %#x", error);
+ return default_msg;
+ }
+}
+
+void *
+_pango_ft2_font_get_cache_glyph_data (PangoFont *font,
+ int glyph_index)
+{
+ PangoFT2GlyphInfo *info;
+
+ if (!PANGO_FT2_IS_FONT (font))
+ return NULL;
+
+ info = pango_ft2_font_get_glyph_info (font, glyph_index, FALSE);
+
+ if (info == NULL)
+ return NULL;
+
+ return info->cached_glyph;
+}
+
+void
+_pango_ft2_font_set_cache_glyph_data (PangoFont *font,
+ int glyph_index,
+ void *cached_glyph)
+{
+ PangoFT2GlyphInfo *info;
+
+ if (!PANGO_FT2_IS_FONT (font))
+ return;
+
+ info = pango_ft2_font_get_glyph_info (font, glyph_index, TRUE);
+
+ info->cached_glyph = cached_glyph;
+
+ /* TODO: Implement limiting of the number of cached glyphs */
+}
+
+void
+_pango_ft2_font_set_glyph_cache_destroy (PangoFont *font,
+ GDestroyNotify destroy_notify)
+{
+ if (!PANGO_FT2_IS_FONT (font))
+ return;
+
+ PANGO_FT2_FONT (font)->glyph_cache_destroy = destroy_notify;
+}
diff --git a/trunk/pango/pangoft2.def b/trunk/pango/pangoft2.def
new file mode 100644
index 00000000..79165939
--- /dev/null
+++ b/trunk/pango/pangoft2.def
@@ -0,0 +1,78 @@
+EXPORTS
+ pango_fc_decoder_get_charset
+ pango_fc_decoder_get_glyph
+ pango_fc_decoder_get_type
+ pango_fc_font_create_metrics_for_context
+ pango_fc_font_description_from_pattern
+ pango_fc_font_get_glyph
+ pango_fc_font_get_raw_extents
+ pango_fc_font_get_type
+ pango_fc_font_get_unknown_glyph
+ pango_fc_font_has_char
+ pango_fc_font_kern_glyphs
+ pango_fc_font_lock_face
+ pango_fc_font_map_add_decoder_find_func
+ pango_fc_font_map_cache_clear
+ pango_fc_font_map_create_context
+ pango_fc_font_map_get_type
+ pango_fc_font_map_shutdown
+ pango_fc_font_unlock_face
+ pango_ft2_font_get_coverage
+ pango_ft2_font_get_face
+ pango_ft2_font_get_kerning
+ pango_ft2_font_get_type
+ pango_ft2_font_map_create_context
+ pango_ft2_font_map_for_display
+ pango_ft2_font_map_get_type
+ pango_ft2_font_map_new
+ pango_ft2_font_map_set_default_substitute
+ pango_ft2_font_map_set_resolution
+ pango_ft2_font_map_substitute_changed
+ pango_ft2_get_context
+ pango_ft2_get_unknown_glyph
+ pango_ft2_render
+ pango_ft2_render_layout
+ pango_ft2_render_layout_line
+ pango_ft2_render_layout_line_subpixel
+ pango_ft2_render_layout_subpixel
+ pango_ft2_render_transformed
+ pango_ft2_renderer_get_type
+ pango_ft2_shutdown_display
+ pango_ot_buffer_add_glyph
+ pango_ot_buffer_clear
+ pango_ot_buffer_destroy
+ pango_ot_buffer_get_glyphs
+ pango_ot_buffer_new
+ pango_ot_buffer_output
+ pango_ot_buffer_set_rtl
+ pango_ot_buffer_set_zero_width_marks
+ pango_ot_info_find_feature
+ pango_ot_info_find_language
+ pango_ot_info_find_script
+ pango_ot_info_get
+ pango_ot_info_get_gdef
+ pango_ot_info_get_gpos
+ pango_ot_info_get_gsub
+ pango_ot_info_get_type
+ pango_ot_info_list_features
+ pango_ot_info_list_languages
+ pango_ot_info_list_scripts
+ pango_ot_ruleset_add_feature
+ pango_ot_ruleset_description_copy
+ pango_ot_ruleset_description_equal
+ pango_ot_ruleset_description_free
+ pango_ot_ruleset_description_hash
+ pango_ot_ruleset_get_feature_count
+ pango_ot_ruleset_get_for_description
+ pango_ot_ruleset_get_type
+ pango_ot_ruleset_maybe_add_feature
+ pango_ot_ruleset_maybe_add_features
+ pango_ot_ruleset_new
+ pango_ot_ruleset_new_for
+ pango_ot_ruleset_new_from_description
+ pango_ot_ruleset_position
+ pango_ot_ruleset_substitute
+ pango_ot_tag_from_language
+ pango_ot_tag_from_script
+ pango_ot_tag_to_language
+ pango_ot_tag_to_script
diff --git a/trunk/pango/pangoft2.h b/trunk/pango/pangoft2.h
new file mode 100644
index 00000000..27acfa6e
--- /dev/null
+++ b/trunk/pango/pangoft2.h
@@ -0,0 +1,110 @@
+/* Pango
+ * pangoft2.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOFT2_H__
+#define __PANGOFT2_H__
+
+#include <fontconfig/fontconfig.h>
+
+#include <pango/pango-layout.h>
+#include <pango/pangofc-font.h>
+
+G_BEGIN_DECLS
+
+#ifndef PANGO_DISABLE_DEPRECATED
+#define PANGO_RENDER_TYPE_FT2 "PangoRenderFT2"
+#endif
+
+#define PANGO_TYPE_FT2_FONT_MAP (pango_ft2_font_map_get_type ())
+#define PANGO_FT2_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT_MAP, PangoFT2FontMap))
+#define PANGO_FT2_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_FONT_MAP))
+
+typedef struct _PangoFT2FontMap PangoFT2FontMap;
+
+typedef void (*PangoFT2SubstituteFunc) (FcPattern *pattern,
+ gpointer data);
+
+/* Calls for applications */
+
+void pango_ft2_render (FT_Bitmap *bitmap,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_ft2_render_transformed (FT_Bitmap *bitmap,
+ const PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+
+void pango_ft2_render_layout_line (FT_Bitmap *bitmap,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_ft2_render_layout_line_subpixel (FT_Bitmap *bitmap,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_ft2_render_layout (FT_Bitmap *bitmap,
+ PangoLayout *layout,
+ int x,
+ int y);
+void pango_ft2_render_layout_subpixel (FT_Bitmap *bitmap,
+ PangoLayout *layout,
+ int x,
+ int y);
+
+GType pango_ft2_font_map_get_type (void) G_GNUC_CONST;
+
+PangoFontMap *pango_ft2_font_map_new (void);
+void pango_ft2_font_map_set_resolution (PangoFT2FontMap *fontmap,
+ double dpi_x,
+ double dpi_y);
+void pango_ft2_font_map_set_default_substitute (PangoFT2FontMap *fontmap,
+ PangoFT2SubstituteFunc func,
+ gpointer data,
+ GDestroyNotify notify);
+void pango_ft2_font_map_substitute_changed (PangoFT2FontMap *fontmap);
+PangoContext *pango_ft2_font_map_create_context (PangoFT2FontMap *fontmap);
+
+
+/* API for rendering modules
+ */
+#ifndef PANGO_DISABLE_DEPRECATED
+PangoContext *pango_ft2_get_context (double dpi_x,
+ double dpi_y);
+PangoFontMap *pango_ft2_font_map_for_display (void);
+void pango_ft2_shutdown_display (void);
+
+PangoGlyph pango_ft2_get_unknown_glyph (PangoFont *font);
+int pango_ft2_font_get_kerning (PangoFont *font,
+ PangoGlyph left,
+ PangoGlyph right);
+FT_Face pango_ft2_font_get_face (PangoFont *font);
+PangoCoverage *pango_ft2_font_get_coverage (PangoFont *font,
+ PangoLanguage *language);
+#endif /* PANGO_DISABLE_DEPRECATED */
+
+G_END_DECLS
+
+#endif /* __PANGOFT2_H__ */
diff --git a/trunk/pango/pangoft2.rc.in b/trunk/pango/pangoft2.rc.in
new file mode 100644
index 00000000..c7ed1646
--- /dev/null
+++ b/trunk/pango/pangoft2.rc.in
@@ -0,0 +1,30 @@
+#include <winver.h>
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @PANGO_VERSION_MAJOR@,@PANGO_VERSION_MINOR@,@PANGO_VERSION_MICRO@,0
+ PRODUCTVERSION @PANGO_VERSION_MAJOR@,@PANGO_VERSION_MINOR@,@PANGO_VERSION_MICRO@,0
+ FILEFLAGSMASK 0
+ FILEFLAGS 0
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Red Hat Software"
+ VALUE "FileDescription", "PangoFT2"
+ VALUE "FileVersion", "@PANGO_VERSION_MAJOR@.@PANGO_VERSION_MINOR@.@PANGO_VERSION_MICRO@.0"
+ VALUE "InternalName", "pangoft2-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@"
+ VALUE "LegalCopyright", "Copyright © 1999 Red Hat Software. Copyright © 2000 Tor Lillqvist"
+ VALUE "OriginalFilename", "pangoft2-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@.dll"
+ VALUE "ProductName", "PangoFT2"
+ VALUE "ProductVersion", "@PANGO_VERSION_MAJOR@.@PANGO_VERSION_MINOR@.@PANGO_VERSION_MICRO@"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+ END
diff --git a/trunk/pango/pangowin32-fontcache.c b/trunk/pango/pangowin32-fontcache.c
new file mode 100644
index 00000000..4b66ca9f
--- /dev/null
+++ b/trunk/pango/pangowin32-fontcache.c
@@ -0,0 +1,434 @@
+/* Pango
+ * pangowin32-fontcache.c: Cache of HFONTs by LOGFONTW
+ *
+ * Copyright (C) 2000 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdio.h>
+
+#include "pangowin32-private.h"
+
+/* Font cache
+ */
+
+/* Number of fonts to retain after they are not otherwise referenced.
+ */
+#define CACHE_SIZE 16
+
+typedef struct _CacheEntry CacheEntry;
+
+struct _PangoWin32FontCache
+{
+ GHashTable *forward;
+ GHashTable *back;
+
+ GList *mru;
+ GList *mru_tail;
+ int mru_count;
+};
+
+struct _CacheEntry
+{
+ LOGFONTW logfontw;
+ HFONT hfont;
+
+ gint ref_count;
+ GList *mru;
+};
+
+static void
+free_cache_entry (LOGFONTW *logfont,
+ CacheEntry *entry,
+ PangoWin32FontCache *cache)
+{
+ if (!DeleteObject (entry->hfont))
+ PING (("DeleteObject for hfont %p failed", entry->hfont));
+
+ g_slice_free (CacheEntry, entry);
+}
+
+/**
+ * pango_win32_font_cache_free:
+ * @cache: a #PangoWin32FontCache
+ *
+ * Frees a #PangoWin32FontCache and all associated memory. All fonts loaded
+ * through this font cache will be freed along with the cache.
+ **/
+void
+pango_win32_font_cache_free (PangoWin32FontCache *cache)
+{
+ g_return_if_fail (cache != NULL);
+
+ g_hash_table_foreach (cache->forward, (GHFunc)free_cache_entry, cache);
+
+ g_hash_table_destroy (cache->forward);
+ g_hash_table_destroy (cache->back);
+
+ g_list_free (cache->mru);
+
+ g_slice_free (PangoWin32FontCache, cache);
+}
+
+static guint
+wcs_hash (gconstpointer v)
+{
+ /* 31 bit hash function */
+ const wchar_t *p = v;
+ guint32 h = *p;
+
+ if (h)
+ for (p += 1; *p != '\0'; p++)
+ h = (h << 5) - h + *p;
+
+ return h;
+}
+
+static guint
+logfontw_hash (gconstpointer v)
+{
+ const LOGFONTW *lfp = v;
+
+ return wcs_hash (lfp->lfFaceName) +
+ (lfp->lfItalic != 0) +
+ lfp->lfWeight/10 +
+ lfp->lfOrientation +
+ abs (lfp->lfHeight) * 10;
+}
+
+static gint
+logfontw_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const LOGFONTW *lfp1 = v1, *lfp2 = v2;
+
+ return (wcscmp (lfp1->lfFaceName, lfp2->lfFaceName) == 0
+ && lfp1->lfPitchAndFamily == lfp2->lfPitchAndFamily
+ && lfp1->lfStrikeOut == lfp2->lfStrikeOut
+ && lfp1->lfUnderline == lfp2->lfUnderline
+ && (lfp1->lfItalic != 0) == (lfp2->lfItalic != 0)
+ && lfp1->lfWeight == lfp2->lfWeight
+ && lfp1->lfOrientation == lfp2->lfOrientation
+ && lfp1->lfEscapement == lfp2->lfEscapement
+ && lfp1->lfWidth == lfp2->lfWidth
+ && lfp1->lfHeight == lfp2->lfHeight);
+}
+
+/**
+ * pango_win32_font_cache_new:
+ *
+ * Creates a font cache.
+ *
+ * Return value: The new font cache. This must be freed with
+ * pango_win32_font_cache_free().
+ **/
+PangoWin32FontCache *
+pango_win32_font_cache_new (void)
+{
+ PangoWin32FontCache *cache;
+
+ cache = g_slice_new (PangoWin32FontCache);
+
+ cache->forward = g_hash_table_new (logfontw_hash, logfontw_equal);
+ cache->back = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ cache->mru = NULL;
+ cache->mru_tail = NULL;
+ cache->mru_count = 0;
+
+ return cache;
+}
+
+static void
+cache_entry_unref (PangoWin32FontCache *cache,
+ CacheEntry *entry)
+{
+ entry->ref_count--;
+ if (entry->ref_count == 0)
+ {
+ PING (("removing cache entry %p", entry->hfont));
+
+ g_hash_table_remove (cache->forward, &entry->logfontw);
+ g_hash_table_remove (cache->back, entry->hfont);
+
+ free_cache_entry (NULL, entry, cache);
+ }
+}
+
+/**
+ * pango_win32_font_cache_load:
+ * @cache: a #PangoWin32FontCache
+ * @logfont: a pointer to a LOGFONTA structure describing the font to load.
+ *
+ * Creates a HFONT from a LOGFONTA. The
+ * result may be newly loaded, or it may have been previously
+ * stored
+ *
+ * Return value: The font structure, or %NULL if the font could
+ * not be loaded. In order to free this structure, you must call
+ * pango_win32_font_cache_unload().
+ **/
+HFONT
+pango_win32_font_cache_load (PangoWin32FontCache *cache,
+ const LOGFONTA *lfp)
+{
+ LOGFONTW lf;
+
+ /* We know that the lfFaceName is the last member in the structs */
+ *(LOGFONTA *)&lf = *lfp;
+
+ if (!MultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
+ lfp->lfFaceName, -1,
+ lf.lfFaceName, G_N_ELEMENTS (lf.lfFaceName)))
+ return NULL;
+
+ return pango_win32_font_cache_loadw (cache, &lf);
+}
+
+/**
+ * pango_win32_font_cache_loadw:
+ * @cache: a #PangoWin32FontCache
+ * @logfont: a pointer to a LOGFONTW structure describing the font to load.
+ *
+ * Creates a HFONT from a LOGFONTW. The
+ * result may be newly loaded, or it may have been previously
+ * stored
+ *
+ * Return value: The font structure, or %NULL if the font could
+ * not be loaded. In order to free this structure, you must call
+ * pango_win32_font_cache_unload().
+ *
+ * Since: 1.16
+ **/
+HFONT
+pango_win32_font_cache_loadw (PangoWin32FontCache *cache,
+ const LOGFONTW *lfp)
+{
+ CacheEntry *entry;
+ LOGFONTW lf;
+ HFONT hfont;
+ int tries;
+
+ g_return_val_if_fail (cache != NULL, NULL);
+ g_return_val_if_fail (lfp != NULL, NULL);
+
+ entry = g_hash_table_lookup (cache->forward, lfp);
+
+ if (entry)
+ {
+ entry->ref_count++;
+ PING (("increased refcount for cache entry %p: %d", entry->hfont, entry->ref_count));
+ }
+ else
+ {
+ BOOL font_smoothing;
+ lf = *lfp;
+ SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0);
+ /* If on XP or better, try to use ClearType if the global system
+ * settings ask for it.
+ */
+ if (font_smoothing &&
+ (_pango_win32_os_version_info.dwMajorVersion > 5 ||
+ (_pango_win32_os_version_info.dwMajorVersion == 5 &&
+ _pango_win32_os_version_info.dwMinorVersion >= 1)))
+ {
+ UINT smoothing_type;
+
+#ifndef SPI_GETFONTSMOOTHINGTYPE
+#define SPI_GETFONTSMOOTHINGTYPE 0x200a
+#endif
+#ifndef FE_FONTSMOOTHINGCLEARTYPE
+#define FE_FONTSMOOTHINGCLEARTYPE 2
+#endif
+#ifndef CLEARTYPE_QUALITY
+#define CLEARTYPE_QUALITY 5
+#endif
+ SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0);
+ lf.lfQuality =
+ (font_smoothing ?
+ (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE ?
+ CLEARTYPE_QUALITY : ANTIALIASED_QUALITY) :
+ DEFAULT_QUALITY);
+ }
+ else
+ lf.lfQuality = (font_smoothing ? ANTIALIASED_QUALITY : DEFAULT_QUALITY);
+ lf.lfCharSet = DEFAULT_CHARSET;
+ for (tries = 0; ; tries++)
+ {
+ PING (("... trying CreateFontIndirect "
+ "height=%ld,width=%ld,escapement=%ld,orientation=%ld,"
+ "weight=%ld,%s%s%s"
+ "charset=%d,outprecision=%d,clipprecision=%d,"
+ "quality=%d,pitchandfamily=%#.02x,facename=\"%S\")",
+ lf.lfHeight, lf.lfWidth, lf.lfEscapement, lf.lfOrientation,
+ lf.lfWeight, (lf.lfItalic ? "italic," : ""),
+ (lf.lfUnderline ? "underline," : ""),
+ (lf.lfStrikeOut ? "strikeout," : ""),
+ lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision,
+ lf.lfQuality, lf.lfPitchAndFamily, lf.lfFaceName));
+ hfont = CreateFontIndirectW (&lf);
+
+ if (hfont != NULL)
+ {
+ PING (("Success! hfont=%p", hfont));
+ break;
+ }
+
+ /* If we fail, try some similar fonts often found on Windows. */
+ if (tries == 0)
+ {
+ gchar *p = g_utf16_to_utf8 (lf.lfFaceName, -1, NULL, NULL, NULL);
+ if (!p)
+ ; /* Nothing */
+ else if (g_ascii_strcasecmp (p, "helvetica") == 0)
+ wcscpy (lf.lfFaceName, L"arial");
+ else if (g_ascii_strcasecmp (p, "new century schoolbook") == 0)
+ wcscpy (lf.lfFaceName, L"century schoolbook");
+ else if (g_ascii_strcasecmp (p, "courier") == 0)
+ wcscpy (lf.lfFaceName, L"courier new");
+ else if (g_ascii_strcasecmp (p, "lucida") == 0)
+ wcscpy (lf.lfFaceName, L"lucida sans unicode");
+ else if (g_ascii_strcasecmp (p, "lucidatypewriter") == 0)
+ wcscpy (lf.lfFaceName, L"lucida console");
+ else if (g_ascii_strcasecmp (p, "times") == 0)
+ wcscpy (lf.lfFaceName, L"times new roman");
+ g_free (p);
+ }
+ else if (tries == 1)
+ {
+ gchar *p = g_utf16_to_utf8 (lf.lfFaceName, -1, NULL, NULL, NULL);
+ if (!p)
+ ; /* Nothing */
+ else if (g_ascii_strcasecmp (p, "courier") == 0)
+ {
+ wcscpy (lf.lfFaceName, L"");
+ lf.lfPitchAndFamily |= FF_MODERN;
+ }
+ else if (g_ascii_strcasecmp (p, "times new roman") == 0)
+ {
+ wcscpy (lf.lfFaceName, L"");
+ lf.lfPitchAndFamily |= FF_ROMAN;
+ }
+ else if (g_ascii_strcasecmp (p, "helvetica") == 0
+ || g_ascii_strcasecmp (p, "lucida") == 0)
+ {
+ wcscpy (lf.lfFaceName, L"");
+ lf.lfPitchAndFamily |= FF_SWISS;
+ }
+ else
+ {
+ wcscpy (lf.lfFaceName, L"");
+ lf.lfPitchAndFamily = (lf.lfPitchAndFamily & 0x0F) | FF_DONTCARE;
+ }
+ g_free (p);
+ }
+ else
+ break;
+ tries++;
+ }
+
+ if (!hfont)
+ return NULL;
+
+ entry = g_slice_new (CacheEntry);
+
+ entry->logfontw = lf;
+ entry->hfont = hfont;
+
+ entry->ref_count = 1;
+ entry->mru = NULL;
+
+ g_hash_table_insert (cache->forward, &entry->logfontw, entry);
+ g_hash_table_insert (cache->back, entry->hfont, entry);
+ }
+
+ if (entry->mru)
+ {
+ if (cache->mru_count > 1 && entry->mru->prev)
+ {
+ /* Move to the head of the mru list */
+
+ if (entry->mru == cache->mru_tail)
+ {
+ cache->mru_tail = cache->mru_tail->prev;
+ cache->mru_tail->next = NULL;
+ }
+ else
+ {
+ entry->mru->prev->next = entry->mru->next;
+ entry->mru->next->prev = entry->mru->prev;
+ }
+
+ entry->mru->next = cache->mru;
+ entry->mru->prev = NULL;
+ cache->mru->prev = entry->mru;
+ cache->mru = entry->mru;
+ }
+ }
+ else
+ {
+ entry->ref_count++;
+
+ /* Insert into the mru list */
+
+ if (cache->mru_count == CACHE_SIZE)
+ {
+ CacheEntry *old_entry = cache->mru_tail->data;
+
+ cache->mru_tail = cache->mru_tail->prev;
+ cache->mru_tail->next = NULL;
+
+ g_list_free_1 (old_entry->mru);
+ old_entry->mru = NULL;
+ cache_entry_unref (cache, old_entry);
+ }
+ else
+ cache->mru_count++;
+
+ cache->mru = g_list_prepend (cache->mru, entry);
+ if (!cache->mru_tail)
+ cache->mru_tail = cache->mru;
+ entry->mru = cache->mru;
+ }
+
+ return entry->hfont;
+}
+
+/**
+ * pango_win32_font_cache_unload:
+ * @cache: a #PangoWin32FontCache
+ * @hfont: the HFONT to unload
+ *
+ * Frees a font structure previously loaded with pango_win32_font_cache_load().
+ **/
+void
+pango_win32_font_cache_unload (PangoWin32FontCache *cache,
+ HFONT hfont)
+{
+ CacheEntry *entry;
+
+ g_return_if_fail (cache != NULL);
+ g_return_if_fail (hfont != NULL);
+
+ entry = g_hash_table_lookup (cache->back, hfont);
+ g_return_if_fail (entry != NULL);
+
+ cache_entry_unref (cache, entry);
+}
diff --git a/trunk/pango/pangowin32-fontmap.c b/trunk/pango/pangowin32-fontmap.c
new file mode 100644
index 00000000..0f79dd7f
--- /dev/null
+++ b/trunk/pango/pangowin32-fontmap.c
@@ -0,0 +1,1334 @@
+/* Pango
+ * pangowin32-fontmap.c: Win32 font handling
+ *
+ * Copyright (C) 2000 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ * Copyright (C) 2001 Alexander Larsson
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pango-fontmap.h"
+#include "pango-impl-utils.h"
+#include "pangowin32-private.h"
+#include "modules.h"
+
+typedef struct _PangoWin32Family PangoWin32Family;
+typedef struct _PangoWin32SizeInfo PangoWin32SizeInfo;
+
+struct _PangoWin32Family
+{
+ PangoFontFamily parent_instance;
+
+ char *family_name;
+ GSList *font_entries;
+
+ gboolean is_monospace;
+};
+
+struct _PangoWin32SizeInfo
+{
+ GSList *logfontws;
+};
+
+#define PANGO_WIN32_TYPE_FAMILY (pango_win32_family_get_type ())
+#define PANGO_WIN32_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_WIN32_TYPE_FAMILY, PangoWin32Family))
+#define PANGO_WIN32_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_WIN32_TYPE_FAMILY))
+
+#define PANGO_WIN32_TYPE_FACE (pango_win32_face_get_type ())
+#define PANGO_WIN32_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_WIN32_TYPE_FACE, PangoWin32Face))
+#define PANGO_WIN32_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_WIN32_TYPE_FACE))
+
+static GType pango_win32_face_get_type (void);
+
+static GType pango_win32_family_get_type (void);
+
+static void pango_win32_face_list_sizes (PangoFontFace *face,
+ int **sizes,
+ int *n_sizes);
+
+static void pango_win32_font_map_finalize (GObject *object);
+static PangoFont *pango_win32_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description);
+static void pango_win32_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families);
+
+static PangoFont *pango_win32_font_map_real_find_font (PangoWin32FontMap *win32fontmap,
+ PangoContext *context,
+ PangoWin32Face *face,
+ const PangoFontDescription *description);
+
+static void pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap);
+
+static void pango_win32_insert_font (PangoWin32FontMap *fontmap,
+ LOGFONTW *lfp,
+ gboolean is_synthetic);
+
+static PangoWin32FontMap *default_fontmap = NULL;
+
+G_DEFINE_TYPE (PangoWin32FontMap, _pango_win32_font_map, PANGO_TYPE_FONT_MAP)
+
+#define TOLOWER(c) \
+ (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
+static guint
+case_insensitive_str_hash (const char *key)
+{
+ const char *p = key;
+ guint h = TOLOWER (*p);
+
+ if (h)
+ {
+ for (p += 1; *p != '\0'; p++)
+ h = (h << 5) - h + TOLOWER (*p);
+ }
+
+ return h;
+}
+
+static gboolean
+case_insensitive_str_equal (const char *key1,
+ const char *key2)
+{
+ while (*key1 && *key2 && TOLOWER (*key1) == TOLOWER (*key2))
+ key1++, key2++;
+ return (!*key1 && !*key2);
+}
+
+static guint
+case_insensitive_wcs_hash (const wchar_t *key)
+{
+ const wchar_t *p = key;
+ guint h = TOLOWER (*p);
+
+ if (h)
+ {
+ for (p += 1; *p != '\0'; p++)
+ h = (h << 5) - h + TOLOWER (*p);
+ }
+
+ return h;
+}
+
+static gboolean
+case_insensitive_wcs_equal (const wchar_t *key1,
+ const wchar_t *key2)
+{
+ while (*key1 && *key2 && TOLOWER (*key1) == TOLOWER (*key2))
+ key1++, key2++;
+ return (!*key1 && !*key2);
+}
+
+/* A hash function for LOGFONTWs that takes into consideration only
+ * those fields that indicate a specific .ttf file is in use:
+ * lfFaceName, lfItalic and lfWeight. Dunno how correct this is.
+ */
+static guint
+logfontw_nosize_hash (const LOGFONTW *lfp)
+{
+ return case_insensitive_wcs_hash (lfp->lfFaceName) + (lfp->lfItalic != 0) + lfp->lfWeight;
+}
+
+/* Ditto comparison function */
+static gboolean
+logfontw_nosize_equal (const LOGFONTW *lfp1,
+ const LOGFONTW *lfp2)
+{
+ return (case_insensitive_wcs_equal (lfp1->lfFaceName, lfp2->lfFaceName)
+ && (lfp1->lfItalic != 0) == (lfp2->lfItalic != 0)
+ && lfp1->lfWeight == lfp2->lfWeight);
+}
+
+static int CALLBACK
+pango_win32_inner_enum_proc (LOGFONTW *lfp,
+ TEXTMETRICW *metrics,
+ DWORD fontType,
+ LPARAM lParam)
+{
+ PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)lParam;
+
+ /* Windows generates synthetic vertical writing versions of East
+ * Asian fonts with @ prepended to their name, ignore them.
+ */
+ if (lfp->lfFaceName[0] != '@')
+ pango_win32_insert_font (win32fontmap, lfp, FALSE);
+
+ return 1;
+}
+
+static int CALLBACK
+pango_win32_enum_proc (LOGFONTW *lfp,
+ TEXTMETRICW *metrics,
+ DWORD fontType,
+ LPARAM lParam)
+{
+ LOGFONTW lf;
+
+ PING(("%S", lfp->lfFaceName));
+
+ if (fontType != TRUETYPE_FONTTYPE)
+ return 1;
+
+ lf = *lfp;
+
+ EnumFontFamiliesExW (_pango_win32_hdc, &lf,
+ (FONTENUMPROCW) pango_win32_inner_enum_proc,
+ lParam, 0);
+
+ return 1;
+}
+
+typedef struct _ItalicHelper
+{
+ PangoWin32FontMap *fontmap;
+ GSList *list;
+} ItalicHelper;
+
+static void
+ensure_italic (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ ItalicHelper *helper = (ItalicHelper *)user_data;
+ PangoWin32SizeInfo *sip = (PangoWin32SizeInfo *) value;
+ GSList *list = sip->logfontws;
+
+ while (list)
+ {
+ LOGFONTW *lfp = (LOGFONTW *) list->data;
+ PING(("%S it=%d wt=%ld", lfp->lfFaceName, lfp->lfItalic, lfp->lfWeight));
+ if (!lfp->lfItalic)
+ {
+ /* we have a non italic variant, look if there is an italic */
+ LOGFONTW logfontw = *lfp;
+ logfontw.lfItalic = 1;
+ sip = (PangoWin32SizeInfo *) g_hash_table_lookup (helper->fontmap->size_infos, &logfontw);
+ if (!sip)
+ {
+ /* remember the non italic variant to be added later as italic */
+ PING(("synthesizing italic"));
+ helper->list = g_slist_append (helper->list, lfp);
+ }
+ }
+ list = list->next;
+ }
+}
+
+static void
+_pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
+{
+ LOGFONTW logfont;
+ ItalicHelper helper = { win32fontmap, NULL };
+ GSList *list;
+
+ win32fontmap->families = g_hash_table_new ((GHashFunc) case_insensitive_str_hash,
+ (GEqualFunc) case_insensitive_str_equal);
+ win32fontmap->size_infos =
+ g_hash_table_new ((GHashFunc) logfontw_nosize_hash, (GEqualFunc) logfontw_nosize_equal);
+ win32fontmap->n_fonts = 0;
+
+ win32fontmap->font_cache = pango_win32_font_cache_new ();
+ win32fontmap->freed_fonts = g_queue_new ();
+
+ memset (&logfont, 0, sizeof (logfont));
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ EnumFontFamiliesExW (_pango_win32_hdc, &logfont,
+ (FONTENUMPROCW) pango_win32_enum_proc,
+ (LPARAM) win32fontmap, 0);
+
+ /* Create synthetic italic entries */
+ g_hash_table_foreach (win32fontmap->size_infos, ensure_italic, &helper);
+
+ /* Can't modify while iterating */
+ list = helper.list;
+ while (list)
+ {
+ LOGFONTW logfontw = *((LOGFONTW *)list->data);
+ logfontw.lfItalic = 1;
+ pango_win32_insert_font (win32fontmap, &logfontw, TRUE);
+ list = list->next;
+ }
+ g_slist_free (helper.list);
+
+ win32fontmap->resolution = (PANGO_SCALE / (double) GetDeviceCaps (_pango_win32_hdc, LOGPIXELSY)) * 72.0;
+}
+
+static void
+_pango_win32_font_map_class_init (PangoWin32FontMapClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class);
+ int i;
+
+ class->find_font = pango_win32_font_map_real_find_font;
+ object_class->finalize = pango_win32_font_map_finalize;
+ fontmap_class->load_font = pango_win32_font_map_load_font;
+ fontmap_class->list_families = pango_win32_font_map_list_families;
+ fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_WIN32;
+
+ pango_win32_get_dc ();
+
+ for (i = 0; _pango_included_win32_modules[i].list; i++)
+ pango_module_register (&_pango_included_win32_modules[i]);
+}
+
+/**
+ * pango_win32_font_map_for_display:
+ *
+ * Returns a #PangoWin32FontMap. Font maps are cached and should
+ * not be freed. If the font map is no longer needed, it can
+ * be released with pango_win32_shutdown_display().
+ *
+ * Return value: a #PangoFontMap.
+ **/
+PangoFontMap *
+pango_win32_font_map_for_display (void)
+{
+ /* Make sure that the type system is initialized */
+ g_type_init ();
+
+ if (default_fontmap != NULL)
+ return PANGO_FONT_MAP (default_fontmap);
+
+ default_fontmap = g_object_new (PANGO_TYPE_WIN32_FONT_MAP, NULL);
+
+ return PANGO_FONT_MAP (default_fontmap);
+}
+
+/**
+ * pango_win32_shutdown_display:
+ *
+ * Free cached resources.
+ **/
+void
+pango_win32_shutdown_display (void)
+{
+ if (default_fontmap)
+ {
+ pango_win32_fontmap_cache_clear (default_fontmap);
+ g_object_unref (default_fontmap);
+
+ default_fontmap = NULL;
+ }
+}
+
+static void
+pango_win32_font_map_finalize (GObject *object)
+{
+ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (object);
+
+ g_list_foreach (win32fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_queue_free (win32fontmap->freed_fonts);
+
+ pango_win32_font_cache_free (win32fontmap->font_cache);
+
+ G_OBJECT_CLASS (_pango_win32_font_map_parent_class)->finalize (object);
+}
+
+/*
+ * PangoWin32Family
+ */
+static void
+pango_win32_family_list_faces (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces)
+{
+ PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
+
+ *n_faces = g_slist_length (win32family->font_entries);
+ if (faces)
+ {
+ GSList *tmp_list;
+ int i = 0;
+
+ *faces = g_new (PangoFontFace *, *n_faces);
+
+ tmp_list = win32family->font_entries;
+ while (tmp_list)
+ {
+ (*faces)[i++] = tmp_list->data;
+ tmp_list = tmp_list->next;
+ }
+ }
+}
+
+static const char *
+pango_win32_family_get_name (PangoFontFamily *family)
+{
+ PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
+ return win32family->family_name;
+}
+
+static gboolean
+pango_win32_family_is_monospace (PangoFontFamily *family)
+{
+ PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
+
+ return win32family->is_monospace;
+}
+
+static void
+pango_win32_family_class_init (PangoFontFamilyClass *class)
+{
+ class->list_faces = pango_win32_family_list_faces;
+ class->get_name = pango_win32_family_get_name;
+ class->is_monospace = pango_win32_family_is_monospace;
+}
+
+static GType
+pango_win32_family_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFamilyClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_win32_family_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoWin32Family),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
+ I_("PangoWin32Family"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+list_families_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GSList **list = user_data;
+
+ *list = g_slist_prepend (*list, value);
+}
+
+static void
+pango_win32_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families)
+{
+ GSList *family_list = NULL;
+ GSList *tmp_list;
+ PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
+
+ if (!n_families)
+ return;
+
+ g_hash_table_foreach (win32fontmap->families, list_families_foreach, &family_list);
+
+ *n_families = g_slist_length (family_list);
+
+ if (families)
+ {
+ int i = 0;
+
+ *families = g_new (PangoFontFamily *, *n_families);
+
+ tmp_list = family_list;
+ while (tmp_list)
+ {
+ (*families)[i] = tmp_list->data;
+ i++;
+ tmp_list = tmp_list->next;
+ }
+ }
+
+ g_slist_free (family_list);
+}
+
+static PangoWin32Family *
+pango_win32_get_font_family (PangoWin32FontMap *win32fontmap,
+ const char *family_name)
+{
+ PangoWin32Family *win32family = g_hash_table_lookup (win32fontmap->families, family_name);
+ if (!win32family)
+ {
+ win32family = g_object_new (PANGO_WIN32_TYPE_FAMILY, NULL);
+ win32family->family_name = g_strdup (family_name);
+ win32family->font_entries = NULL;
+
+ g_hash_table_insert (win32fontmap->families, win32family->family_name, win32family);
+ }
+
+ return win32family;
+}
+
+static PangoFont *
+pango_win32_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description)
+{
+ PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
+ PangoWin32Family *win32family;
+ PangoFont *result = NULL;
+ GSList *tmp_list;
+
+ g_return_val_if_fail (description != NULL, NULL);
+
+ PING(("name=%s", pango_font_description_get_family (description)));
+
+ win32family = g_hash_table_lookup (win32fontmap->families,
+ pango_font_description_get_family (description));
+ if (win32family)
+ {
+ PangoWin32Face *best_match = NULL;
+
+ PING (("got win32family"));
+ tmp_list = win32family->font_entries;
+ while (tmp_list)
+ {
+ PangoWin32Face *face = tmp_list->data;
+
+ if (pango_font_description_better_match (description,
+ best_match ? best_match->description : NULL,
+ face->description))
+ best_match = face;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (best_match)
+ result = PANGO_WIN32_FONT_MAP_GET_CLASS (win32fontmap)->find_font (win32fontmap, context,
+ best_match,
+ description);
+ /* TODO: Handle the case that result == NULL. */
+ else
+ PING(("no best match!"));
+ }
+
+ return result;
+}
+
+static PangoWin32Font *
+pango_win32_font_neww (PangoFontMap *fontmap,
+ const LOGFONTW *lfp,
+ int size)
+{
+ PangoWin32Font *result;
+
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (lfp != NULL, NULL);
+
+ result = (PangoWin32Font *)g_object_new (PANGO_TYPE_WIN32_FONT, NULL);
+
+ result->fontmap = fontmap;
+ g_object_ref (fontmap);
+
+ result->size = size;
+ _pango_win32_make_matching_logfontw (fontmap, lfp, size, &result->logfontw);
+
+ return result;
+}
+
+static PangoFont *
+pango_win32_font_map_real_find_font (PangoWin32FontMap *win32fontmap,
+ PangoContext *context,
+ PangoWin32Face *face,
+ const PangoFontDescription *description)
+{
+ PangoFontMap *fontmap = PANGO_FONT_MAP (win32fontmap);
+ PangoWin32Font *win32font;
+ GSList *tmp_list = face->cached_fonts;
+ int size = pango_font_description_get_size (description);
+
+ if (pango_font_description_get_size_is_absolute (description))
+ size = (int) 0.5 + (size * win32fontmap->resolution) / PANGO_SCALE;
+
+ PING(("got best match:%S size=%d",face->logfontw.lfFaceName,size));
+
+ while (tmp_list)
+ {
+ win32font = tmp_list->data;
+ if (win32font->size == size)
+ {
+ PING (("size matches"));
+
+ g_object_ref (win32font);
+ if (win32font->in_cache)
+ _pango_win32_fontmap_cache_remove (fontmap, win32font);
+
+ return (PangoFont *)win32font;
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ win32font = pango_win32_font_neww (fontmap, &face->logfontw, size);
+
+ if (!win32font)
+ return NULL;
+
+ win32font->fontmap = fontmap;
+ win32font->win32face = face;
+ face->cached_fonts = g_slist_prepend (face->cached_fonts, win32font);
+
+ return (PangoFont *)win32font;
+}
+
+static gchar *
+get_family_nameA (const LOGFONTA *lfp)
+{
+ HFONT hfont;
+ HFONT oldhfont;
+
+ struct name_header header;
+ struct name_record record;
+
+ gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
+ gint name_ix;
+ gchar *codeset;
+
+ gchar *string = NULL;
+ gchar *name;
+
+ gint i, l;
+ gsize nbytes;
+
+ /* If lfFaceName is ASCII, assume it is the common (English) name
+ * for the font. Is this valid? Do some TrueType fonts have
+ * different names in French, German, etc, and does the system
+ * return these if the locale is set to use French, German, etc?
+ */
+ l = strlen (lfp->lfFaceName);
+ for (i = 0; i < l; i++)
+ if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
+ break;
+
+ if (i == l)
+ return g_strdup (lfp->lfFaceName);
+
+ if ((hfont = CreateFontIndirect (lfp)) == NULL)
+ goto fail0;
+
+ if ((oldhfont = SelectObject (_pango_win32_hdc, hfont)) == NULL)
+ goto fail1;
+
+ if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
+ goto fail2;
+
+ PING (("%d name records", header.num_records));
+
+ for (i = 0; i < header.num_records; i++)
+ {
+ if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
+ goto fail2;
+
+ if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
+ continue;
+
+ PING(("platform:%d encoding:%d language:%04x name_id:%d",
+ record.platform_id, record.encoding_id, record.language_id, record.name_id));
+
+ if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
+ record.platform_id == ISO_PLATFORM_ID)
+ unicode_ix = i;
+ else if (record.platform_id == MACINTOSH_PLATFORM_ID &&
+ record.encoding_id == 0 && /* Roman */
+ record.language_id == 0) /* English */
+ mac_ix = i;
+ else if (record.platform_id == MICROSOFT_PLATFORM_ID)
+ if ((microsoft_ix == -1 ||
+ PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
+ (record.encoding_id == SYMBOL_ENCODING_ID ||
+ record.encoding_id == UNICODE_ENCODING_ID ||
+ record.encoding_id == UCS4_ENCODING_ID))
+ microsoft_ix = i;
+ }
+
+ if (microsoft_ix >= 0)
+ name_ix = microsoft_ix;
+ else if (mac_ix >= 0)
+ name_ix = mac_ix;
+ else if (unicode_ix >= 0)
+ name_ix = unicode_ix;
+ else
+ goto fail2;
+
+ if (!_pango_win32_get_name_record (_pango_win32_hdc, name_ix, &record))
+ goto fail2;
+
+ string = g_malloc (record.string_length + 1);
+ if (GetFontData (_pango_win32_hdc, NAME,
+ header.string_storage_offset + record.string_offset,
+ string, record.string_length) != record.string_length)
+ goto fail2;
+
+ string[record.string_length] = '\0';
+
+ if (name_ix == microsoft_ix)
+ if (record.encoding_id == SYMBOL_ENCODING_ID ||
+ record.encoding_id == UNICODE_ENCODING_ID ||
+ record.encoding_id == UCS4_ENCODING_ID)
+ codeset = "UTF-16BE";
+ else
+ codeset = "UCS-4BE";
+ else if (name_ix == mac_ix)
+ codeset = "MacRoman";
+ else /* name_ix == unicode_ix */
+ codeset = "UCS-4BE";
+
+ name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL);
+ if (name == NULL)
+ goto fail2;
+ g_free (string);
+
+ PING(("%s", name));
+
+ SelectObject (_pango_win32_hdc, oldhfont);
+ DeleteObject (hfont);
+
+ return name;
+
+ fail2:
+ g_free (string);
+ SelectObject (_pango_win32_hdc, oldhfont);
+
+ fail1:
+ DeleteObject (hfont);
+
+ fail0:
+ return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
+}
+
+/**
+ * pango_win32_font_description_from_logfont:
+ * @lfp: a LOGFONTA
+ *
+ * Creates a #PangoFontDescription that matches the specified LOGFONTA.
+ *
+ * The face name, italicness and weight fields in the LOGFONTA are used
+ * to set up the resulting #PangoFontDescription. If the face name in
+ * the LOGFONTA contains non-ASCII characters the font is temporarily
+ * loaded (using CreateFontIndirect()) and an ASCII (usually English)
+ * name for it is looked up from the font name tables in the font
+ * data. If that doesn't work, the face name is converted from the
+ * system codepage to UTF-8 and that is used.
+ *
+ * Return value: the newly allocated #PangoFontDescription, which
+ * should be freed using pango_font_description_free()
+ *
+ * Since: 1.12
+ */
+PangoFontDescription *
+pango_win32_font_description_from_logfont (const LOGFONT *lfp)
+{
+ PangoFontDescription *description;
+ gchar *family;
+ PangoStyle style;
+ PangoVariant variant;
+ PangoWeight weight;
+ PangoStretch stretch;
+
+ family = get_family_nameA (lfp);
+
+ if (!lfp->lfItalic)
+ style = PANGO_STYLE_NORMAL;
+ else
+ style = PANGO_STYLE_ITALIC;
+
+ variant = PANGO_VARIANT_NORMAL;
+
+ /* The PangoWeight values PANGO_WEIGHT_* map exactly do Windows FW_*
+ * values. Is this on purpose? Quantize the weight to exact
+ * PANGO_WEIGHT_* values. Is this a good idea?
+ */
+ if (lfp->lfWeight == FW_DONTCARE)
+ weight = PANGO_WEIGHT_NORMAL;
+ else if (lfp->lfWeight <= (FW_ULTRALIGHT + FW_LIGHT) / 2)
+ weight = PANGO_WEIGHT_ULTRALIGHT;
+ else if (lfp->lfWeight <= (FW_LIGHT + FW_NORMAL) / 2)
+ weight = PANGO_WEIGHT_LIGHT;
+ else if (lfp->lfWeight <= (FW_NORMAL + FW_BOLD) / 2)
+ weight = PANGO_WEIGHT_NORMAL;
+ else if (lfp->lfWeight <= (FW_BOLD + FW_ULTRABOLD) / 2)
+ weight = PANGO_WEIGHT_BOLD;
+ else if (lfp->lfWeight <= (FW_ULTRABOLD + FW_HEAVY) / 2)
+ weight = PANGO_WEIGHT_ULTRABOLD;
+ else
+ weight = PANGO_WEIGHT_HEAVY;
+
+ /* XXX No idea how to figure out the stretch */
+ stretch = PANGO_STRETCH_NORMAL;
+
+ description = pango_font_description_new ();
+ pango_font_description_set_family (description, family);
+ pango_font_description_set_style (description, style);
+ pango_font_description_set_weight (description, weight);
+ pango_font_description_set_stretch (description, stretch);
+ pango_font_description_set_variant (description, variant);
+
+ return description;
+}
+
+static gchar *
+get_family_nameW (const LOGFONTW *lfp)
+{
+ HFONT hfont;
+ HFONT oldhfont;
+
+ struct name_header header;
+ struct name_record record;
+
+ gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
+ gint name_ix;
+ gchar *codeset;
+
+ gchar *string = NULL;
+ gchar *name;
+
+ gint i, l;
+ gsize nbytes;
+
+ /* If lfFaceName is ASCII, assume it is the common (English) name
+ * for the font. Is this valid? Do some TrueType fonts have
+ * different names in French, German, etc, and does the system
+ * return these if the locale is set to use French, German, etc?
+ */
+ l = wcslen (lfp->lfFaceName);
+ for (i = 0; i < l; i++)
+ if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
+ break;
+
+ if (i == l)
+ return g_utf16_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
+
+ if ((hfont = CreateFontIndirectW (lfp)) == NULL)
+ goto fail0;
+
+ if ((oldhfont = SelectObject (_pango_win32_hdc, hfont)) == NULL)
+ goto fail1;
+
+ if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
+ goto fail2;
+
+ PING (("%d name records", header.num_records));
+
+ for (i = 0; i < header.num_records; i++)
+ {
+ if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
+ goto fail2;
+
+ if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
+ continue;
+
+ PING(("platform:%d encoding:%d language:%04x name_id:%d",
+ record.platform_id, record.encoding_id, record.language_id, record.name_id));
+
+ if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
+ record.platform_id == ISO_PLATFORM_ID)
+ unicode_ix = i;
+ else if (record.platform_id == MACINTOSH_PLATFORM_ID &&
+ record.encoding_id == 0 && /* Roman */
+ record.language_id == 0) /* English */
+ mac_ix = i;
+ else if (record.platform_id == MICROSOFT_PLATFORM_ID)
+ if ((microsoft_ix == -1 ||
+ PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
+ (record.encoding_id == SYMBOL_ENCODING_ID ||
+ record.encoding_id == UNICODE_ENCODING_ID ||
+ record.encoding_id == UCS4_ENCODING_ID))
+ microsoft_ix = i;
+ }
+
+ if (microsoft_ix >= 0)
+ name_ix = microsoft_ix;
+ else if (mac_ix >= 0)
+ name_ix = mac_ix;
+ else if (unicode_ix >= 0)
+ name_ix = unicode_ix;
+ else
+ goto fail2;
+
+ if (!_pango_win32_get_name_record (_pango_win32_hdc, name_ix, &record))
+ goto fail2;
+
+ string = g_malloc (record.string_length + 1);
+ if (GetFontData (_pango_win32_hdc, NAME,
+ header.string_storage_offset + record.string_offset,
+ string, record.string_length) != record.string_length)
+ goto fail2;
+
+ string[record.string_length] = '\0';
+
+ if (name_ix == microsoft_ix)
+ if (record.encoding_id == SYMBOL_ENCODING_ID ||
+ record.encoding_id == UNICODE_ENCODING_ID ||
+ record.encoding_id == UCS4_ENCODING_ID)
+ codeset = "UTF-16BE";
+ else
+ codeset = "UCS-4BE";
+ else if (name_ix == mac_ix)
+ codeset = "MacRoman";
+ else /* name_ix == unicode_ix */
+ codeset = "UCS-4BE";
+
+ name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL);
+ if (name == NULL)
+ goto fail2;
+ g_free (string);
+
+ PING(("%s", name));
+
+ SelectObject (_pango_win32_hdc, oldhfont);
+ DeleteObject (hfont);
+
+ return name;
+
+ fail2:
+ g_free (string);
+ SelectObject (_pango_win32_hdc, oldhfont);
+
+ fail1:
+ DeleteObject (hfont);
+
+ fail0:
+ return g_utf16_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
+}
+
+/**
+ * pango_win32_font_description_from_logfontw:
+ * @lfp: a LOGFONTW
+ *
+ * Creates a #PangoFontDescription that matches the specified LOGFONTW.
+ *
+ * The face name, italicness and weight fields in the LOGFONTW are used
+ * to set up the resulting #PangoFontDescription. If the face name in
+ * the LOGFONTW contains non-ASCII characters the font is temporarily
+ * loaded (using CreateFontIndirect()) and an ASCII (usually English)
+ * name for it is looked up from the font name tables in the font
+ * data. If that doesn't work, the face name is converted from UTF-16
+ * to UTF-8 and that is used.
+ *
+ * Return value: the newly allocated #PangoFontDescription, which
+ * should be freed using pango_font_description_free()
+ *
+ * Since: 1.16
+ */
+PangoFontDescription *
+pango_win32_font_description_from_logfontw (const LOGFONTW *lfp)
+{
+ PangoFontDescription *description;
+ gchar *family;
+ PangoStyle style;
+ PangoVariant variant;
+ PangoWeight weight;
+ PangoStretch stretch;
+
+ family = get_family_nameW (lfp);
+
+ if (!lfp->lfItalic)
+ style = PANGO_STYLE_NORMAL;
+ else
+ style = PANGO_STYLE_ITALIC;
+
+ variant = PANGO_VARIANT_NORMAL;
+
+ /* The PangoWeight values PANGO_WEIGHT_* map exactly do Windows FW_*
+ * values. Is this on purpose? Quantize the weight to exact
+ * PANGO_WEIGHT_* values. Is this a good idea?
+ */
+ if (lfp->lfWeight == FW_DONTCARE)
+ weight = PANGO_WEIGHT_NORMAL;
+ else if (lfp->lfWeight <= (FW_ULTRALIGHT + FW_LIGHT) / 2)
+ weight = PANGO_WEIGHT_ULTRALIGHT;
+ else if (lfp->lfWeight <= (FW_LIGHT + FW_NORMAL) / 2)
+ weight = PANGO_WEIGHT_LIGHT;
+ else if (lfp->lfWeight <= (FW_NORMAL + FW_BOLD) / 2)
+ weight = PANGO_WEIGHT_NORMAL;
+ else if (lfp->lfWeight <= (FW_BOLD + FW_ULTRABOLD) / 2)
+ weight = PANGO_WEIGHT_BOLD;
+ else if (lfp->lfWeight <= (FW_ULTRABOLD + FW_HEAVY) / 2)
+ weight = PANGO_WEIGHT_ULTRABOLD;
+ else
+ weight = PANGO_WEIGHT_HEAVY;
+
+ /* XXX No idea how to figure out the stretch */
+ stretch = PANGO_STRETCH_NORMAL;
+
+ description = pango_font_description_new ();
+ pango_font_description_set_family (description, family);
+ pango_font_description_set_style (description, style);
+ pango_font_description_set_weight (description, weight);
+ pango_font_description_set_stretch (description, stretch);
+ pango_font_description_set_variant (description, variant);
+
+ return description;
+}
+
+
+/* This inserts the given font into the size_infos table. If a
+ * SizeInfo already exists with the same typeface name, italicness and
+ * weight, then the font is added to the SizeInfo's list, else a
+ * new SizeInfo is created and inserted in the table.
+ */
+static void
+pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
+ LOGFONTW *lfp,
+ gboolean is_synthetic)
+{
+ LOGFONTW *lfp2 = NULL;
+ PangoFontDescription *description;
+ PangoWin32Family *font_family;
+ PangoWin32Face *win32face;
+ PangoWin32SizeInfo *size_info;
+ GSList *tmp_list;
+ gint i;
+ gchar *p;
+
+ PING(("face=%S,charset=%d,it=%d,wt=%ld,ht=%ld",lfp->lfFaceName,lfp->lfCharSet,lfp->lfItalic,lfp->lfWeight,lfp->lfHeight));
+
+ /* Ignore Symbol fonts (which don't have any Unicode mapping
+ * table). We could also be fancy and use the PostScript glyph name
+ * table for such if present, and build a Unicode map by mapping
+ * each PostScript glyph name to Unicode character. Oh well.
+ */
+ if (lfp->lfCharSet == SYMBOL_CHARSET)
+ return;
+
+ /* First insert the LOGFONTW into the list of LOGFONTWs for the
+ * typeface name, italicness and weight.
+ */
+ size_info = g_hash_table_lookup (win32fontmap->size_infos, lfp);
+ if (!size_info)
+ {
+ PING(("SizeInfo not found"));
+ size_info = g_new (PangoWin32SizeInfo, 1);
+ size_info->logfontws = NULL;
+
+ lfp2 = g_new (LOGFONTW, 1);
+ *lfp2 = *lfp;
+ g_hash_table_insert (win32fontmap->size_infos, lfp2, size_info);
+ }
+ else
+ {
+ /* Don't store LOGFONTWs that differ only in charset
+ */
+ tmp_list = size_info->logfontws;
+ while (tmp_list)
+ {
+ LOGFONTW *rover = tmp_list->data;
+
+ /* We know that lfWeight, lfItalic and lfFaceName match. We
+ * don't check lfHeight and lfWidth, those are used
+ * when creating a font.
+ */
+ if (rover->lfEscapement == lfp->lfEscapement &&
+ rover->lfOrientation == lfp->lfOrientation &&
+ rover->lfUnderline == lfp->lfUnderline &&
+ rover->lfStrikeOut == lfp->lfStrikeOut)
+ {
+ PING(("already have it"));
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+ }
+
+ if (lfp2 == NULL)
+ {
+ lfp2 = g_new (LOGFONTW, 1);
+ *lfp2 = *lfp;
+ }
+
+ size_info->logfontws = g_slist_prepend (size_info->logfontws, lfp2);
+
+ PING(("g_slist_length(size_info->logfontws)=%d", g_slist_length(size_info->logfontws)));
+
+ description = pango_win32_font_description_from_logfontw (lfp2);
+
+ /* In some cases, extracting a name for a font can fail; such fonts
+ * aren't usable for us
+ */
+ if (!pango_font_description_get_family (description))
+ {
+ pango_font_description_free (description);
+ return;
+ }
+
+ win32face = g_object_new (PANGO_WIN32_TYPE_FACE, NULL);
+
+ win32face->logfontw = *lfp;
+ win32face->description = description;
+
+ for (i = 0; i < PANGO_WIN32_N_COVERAGES; i++)
+ win32face->coverages[i] = NULL;
+
+ win32face->is_synthetic = is_synthetic;
+
+ win32face->cmap_format = 0;
+ win32face->cmap = NULL;
+
+ win32face->cached_fonts = NULL;
+
+ font_family =
+ pango_win32_get_font_family (win32fontmap,
+ pango_font_description_get_family (win32face->description));
+ font_family->font_entries = g_slist_append (font_family->font_entries, win32face);
+ PING(("g_slist_length(font_family->font_entries)=%d", g_slist_length(font_family->font_entries)));
+
+ win32fontmap->n_fonts++;
+
+#if 1 /* Thought pango.aliases would make this code unnecessary, but no. */
+ /*
+ * There are magic family names coming from the X implementation.
+ * They can be simply mapped to lfPitchAndFamily flag of the logfont
+ * struct. These additional entries should probably only be references
+ * to the respective entry created above. Thy are simply using the
+ * same entry at the moment and it isn't crashing on g_free () ???
+ * Maybe a memory leak ...
+ */
+ switch (lfp->lfPitchAndFamily & 0xF0)
+ {
+ case FF_MODERN : /* monospace */
+ PING(("monospace"));
+ font_family->is_monospace = TRUE; /* modify before reuse */
+ font_family = pango_win32_get_font_family (win32fontmap, "monospace");
+ font_family->font_entries = g_slist_append (font_family->font_entries, win32face);
+ win32fontmap->n_fonts++;
+ break;
+ case FF_ROMAN : /* serif */
+ PING(("serif"));
+ font_family = pango_win32_get_font_family (win32fontmap, "serif");
+ font_family->font_entries = g_slist_append (font_family->font_entries, win32face);
+ win32fontmap->n_fonts++;
+ break;
+ case FF_SWISS : /* sans */
+ PING(("sans"));
+ font_family = pango_win32_get_font_family (win32fontmap, "sans");
+ font_family->font_entries = g_slist_append (font_family->font_entries, win32face);
+ win32fontmap->n_fonts++;
+ break;
+ }
+
+ /* Some other magic names */
+
+ /* Recognize just "courier" for "courier new" */
+ p = g_utf16_to_utf8 (win32face->logfontw.lfFaceName, -1, NULL, NULL, NULL);
+ if (p && g_ascii_strcasecmp (p, "courier new") == 0)
+ {
+ font_family = pango_win32_get_font_family (win32fontmap, "courier");
+ font_family->font_entries = g_slist_append (font_family->font_entries, win32face);
+ win32fontmap->n_fonts++;
+ }
+ g_free (p);
+#endif
+}
+
+/* Given a LOGFONTW and size, make a matching LOGFONTW corresponding to
+ * an installed font.
+ */
+void
+_pango_win32_make_matching_logfontw (PangoFontMap *fontmap,
+ const LOGFONTW *lfp,
+ int size,
+ LOGFONTW *out)
+{
+ PangoWin32FontMap *win32fontmap;
+ GSList *tmp_list;
+ PangoWin32SizeInfo *size_info;
+ LOGFONTW *closest_match = NULL;
+ gint match_distance = 0;
+
+ PING(("lfp.face=%S,wt=%ld,ht=%ld,size:%d",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight,size));
+ win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
+
+ size_info = g_hash_table_lookup (win32fontmap->size_infos, lfp);
+
+ if (!size_info)
+ {
+ PING(("SizeInfo not found"));
+ return;
+ }
+
+ tmp_list = size_info->logfontws;
+ while (tmp_list)
+ {
+ LOGFONTW *tmp_logfontw = tmp_list->data;
+ int font_size = abs (tmp_logfontw->lfHeight);
+
+ if (size != -1)
+ {
+ int new_distance = (font_size == 0) ? 0 : abs (font_size - size);
+
+ if (!closest_match ||
+ new_distance < match_distance ||
+ (new_distance < PANGO_SCALE && font_size != 0))
+ {
+ closest_match = tmp_logfontw;
+ match_distance = new_distance;
+ }
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (closest_match)
+ {
+ /* OK, we have a match; let's modify it to fit this size */
+
+ *out = *closest_match;
+ out->lfHeight = -(int)((double)size / win32fontmap->resolution + 0.5);
+ out->lfWidth = 0;
+ }
+ else
+ *out = *lfp; /* Whatever. We need to pass something... */
+}
+
+static PangoFontDescription *
+pango_win32_face_describe (PangoFontFace *face)
+{
+ PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
+
+ return pango_font_description_copy (win32face->description);
+}
+
+static const char *
+pango_win32_face_get_face_name (PangoFontFace *face)
+{
+ PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
+
+ if (!win32face->face_name)
+ {
+ PangoFontDescription *desc = pango_font_face_describe (face);
+
+ pango_font_description_unset_fields (desc,
+ PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE);
+
+ win32face->face_name = pango_font_description_to_string (desc);
+ pango_font_description_free (desc);
+ }
+
+ return win32face->face_name;
+}
+
+static gboolean
+pango_win32_face_is_synthesized (PangoFontFace *face)
+{
+ PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
+
+ return win32face->is_synthetic;
+}
+
+static void
+pango_win32_face_class_init (PangoFontFaceClass *class)
+{
+ class->describe = pango_win32_face_describe;
+ class->get_face_name = pango_win32_face_get_face_name;
+ class->list_sizes = pango_win32_face_list_sizes;
+ class->is_synthesized = pango_win32_face_is_synthesized;
+}
+
+static void
+pango_win32_face_list_sizes (PangoFontFace *face,
+ int **sizes,
+ int *n_sizes)
+{
+ /*
+ * for scalable fonts it's simple, and currently we only have such
+ * see : pango_win32_enum_proc(), TRUETYPE_FONTTYPE
+ */
+ *sizes = NULL;
+ *n_sizes = 0;
+}
+
+static GType
+pango_win32_face_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFaceClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_win32_face_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoWin32Face),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
+ I_("PangoWin32Face"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+/**
+ * pango_win32_font_map_get_font_cache:
+ * @font_map: a #PangoWin32FontMap.
+ *
+ * Obtains the font cache associated with the given font map.
+ *
+ * Return value: the #PangoWin32FontCache of @font_map.
+ **/
+PangoWin32FontCache *
+pango_win32_font_map_get_font_cache (PangoFontMap *font_map)
+{
+ g_return_val_if_fail (font_map != NULL, NULL);
+ g_return_val_if_fail (PANGO_WIN32_IS_FONT_MAP (font_map), NULL);
+
+ return PANGO_WIN32_FONT_MAP (font_map)->font_cache;
+}
+
+void
+_pango_win32_fontmap_cache_remove (PangoFontMap *fontmap,
+ PangoWin32Font *win32font)
+{
+ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
+ GList *link = g_queue_find (win32fontmap->freed_fonts, win32font);
+
+ if (link)
+ g_queue_delete_link (win32fontmap->freed_fonts, link);
+ win32font->in_cache = FALSE;
+
+ g_object_unref (win32font);
+}
+
+static void
+pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap)
+{
+ g_list_foreach (win32fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_queue_free (win32fontmap->freed_fonts);
+ win32fontmap->freed_fonts = g_queue_new ();
+}
diff --git a/trunk/pango/pangowin32-private.h b/trunk/pango/pangowin32-private.h
new file mode 100644
index 00000000..0450e5dc
--- /dev/null
+++ b/trunk/pango/pangowin32-private.h
@@ -0,0 +1,282 @@
+/* Pango
+ * pangowin32-private.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000-2002 Tor Lillqvist
+ * Copyright (C) 2001 Alexander Larsson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOWIN32_PRIVATE_H__
+#define __PANGOWIN32_PRIVATE_H__
+
+/* Define if you want the possibility to get copious debugging output.
+ * (You still need to set the PANGO_WIN32_DEBUG environment variable
+ * to get it.)
+ */
+#define PANGO_WIN32_DEBUGGING 1
+
+#ifdef PANGO_WIN32_DEBUGGING
+#ifdef __GNUC__
+#define PING(printlist) \
+(_pango_win32_debug ? \
+ (g_print ("%s:%d ", __PRETTY_FUNCTION__, __LINE__), \
+ g_print printlist, \
+ g_print ("\n"), \
+ 0) : \
+ 0)
+#else
+#define PING(printlist) \
+(_pango_win32_debug ? \
+ (g_print ("%s:%d ", __FILE__, __LINE__), \
+ g_print printlist, \
+ g_print ("\n"), \
+ 0) : \
+ 0)
+#endif
+#else /* !PANGO_WIN32_DEBUGGING */
+#define PING(printlist)
+#endif
+
+#include <pango/pango-modules.h>
+#include <pango/pangowin32.h>
+
+typedef enum
+ {
+ PANGO_WIN32_COVERAGE_UNSPEC,
+ PANGO_WIN32_COVERAGE_ZH_TW,
+ PANGO_WIN32_COVERAGE_ZH_CN,
+ PANGO_WIN32_COVERAGE_JA,
+ PANGO_WIN32_COVERAGE_KO,
+ PANGO_WIN32_COVERAGE_VI,
+ PANGO_WIN32_N_COVERAGES
+ } PangoWin32CoverageLanguageClass;
+
+#define PANGO_TYPE_WIN32_FONT_MAP (_pango_win32_font_map_get_type ())
+#define PANGO_WIN32_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_WIN32_FONT_MAP, PangoWin32FontMap))
+#define PANGO_WIN32_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_WIN32_FONT_MAP))
+#define PANGO_WIN32_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_WIN32_FONT_MAP, PangoWin32FontMapClass))
+#define PANGO_IS_WIN32_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_WIN32_FONT_MAP))
+#define PANGO_WIN32_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_WIN32_FONT_MAP, PangoWin32FontMapClass))
+
+#define PANGO_TYPE_WIN32_FONT (_pango_win32_font_get_type ())
+#define PANGO_WIN32_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_WIN32_FONT, PangoWin32Font))
+#define PANGO_WIN32_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_WIN32_FONT, PangoWin32FontClass))
+#define PANGO_WIN32_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_WIN32_FONT))
+#define PANGO_WIN32_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_WIN32_FONT))
+#define PANGO_WIN32_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_WIN32_FONT, PangoWin32FontClass))
+
+typedef struct _PangoWin32FontMap PangoWin32FontMap;
+typedef struct _PangoWin32FontMapClass PangoWin32FontMapClass;
+typedef struct _PangoWin32Font PangoWin32Font;
+typedef struct _PangoWin32FontClass PangoWin32FontClass;
+typedef struct _PangoWin32Face PangoWin32Face;
+typedef struct _PangoWin32GlyphInfo PangoWin32GlyphInfo;
+typedef struct _PangoWin32MetricsInfo PangoWin32MetricsInfo;
+
+struct _PangoWin32FontMap
+{
+ PangoFontMap parent_instance;
+
+ PangoWin32FontCache *font_cache;
+ GQueue *freed_fonts;
+
+ /* Map Pango family names to PangoWin32Family structs */
+ GHashTable *families;
+
+ /* Map LOGFONTWs (taking into account only the lfFaceName, lfItalic
+ * and lfWeight fields) to PangoWin32SizeInfo structs.
+ */
+ GHashTable *size_infos;
+
+ int n_fonts;
+
+ double resolution; /* (points / pixel) * PANGO_SCALE */
+};
+
+struct _PangoWin32FontMapClass
+{
+ PangoFontMapClass parent_class;
+
+ PangoFont *(*find_font) (PangoWin32FontMap *fontmap,
+ PangoContext *context,
+ PangoWin32Face *face,
+ const PangoFontDescription *desc);
+
+};
+
+struct _PangoWin32Font
+{
+ PangoFont font;
+
+ LOGFONTW logfontw;
+ int size;
+
+ GSList *metrics_by_lang;
+
+ PangoFontMap *fontmap;
+
+ /* Written by pango_win32_get_hfont: */
+ HFONT hfont;
+ gint tm_ascent;
+ gint tm_descent;
+ gint tm_overhang;
+
+ PangoWin32Face *win32face;
+
+ /* If TRUE, font is in cache of recently unused fonts and not otherwise
+ * in use.
+ */
+ gboolean in_cache;
+ GHashTable *glyph_info;
+};
+
+struct _PangoWin32FontClass
+{
+ PangoFontClass parent_class;
+
+ gboolean (*select_font) (PangoFont *font,
+ HDC hdc);
+ void (*done_font) (PangoFont *font);
+ double (*get_metrics_factor) (PangoFont *font);
+};
+
+struct _PangoWin32Face
+{
+ PangoFontFace parent_instance;
+
+ LOGFONTW logfontw;
+ PangoFontDescription *description;
+ PangoCoverage *coverages[PANGO_WIN32_N_COVERAGES];
+ char *face_name;
+ gboolean is_synthetic;
+
+ guint16 cmap_format;
+ gpointer cmap;
+
+ GSList *cached_fonts;
+};
+
+struct _PangoWin32GlyphInfo
+{
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+};
+
+struct _PangoWin32MetricsInfo
+{
+ const char *sample_str;
+ PangoFontMetrics *metrics;
+};
+
+/* TrueType defines: */
+
+#define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
+ (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))
+
+#define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
+#define CMAP_HEADER_SIZE 4
+
+#define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))
+#define NAME_HEADER_SIZE 6
+
+#define ENCODING_TABLE_SIZE 8
+
+#define APPLE_UNICODE_PLATFORM_ID 0
+#define MACINTOSH_PLATFORM_ID 1
+#define ISO_PLATFORM_ID 2
+#define MICROSOFT_PLATFORM_ID 3
+
+#define SYMBOL_ENCODING_ID 0
+#define UNICODE_ENCODING_ID 1
+#define UCS4_ENCODING_ID 10
+
+/* All the below structs must be packed! */
+
+struct cmap_encoding_subtable
+{
+ guint16 platform_id;
+ guint16 encoding_id;
+ guint32 offset;
+};
+
+struct format_4_cmap
+{
+ guint16 format;
+ guint16 length;
+ guint16 language;
+ guint16 seg_count_x_2;
+ guint16 search_range;
+ guint16 entry_selector;
+ guint16 range_shift;
+
+ guint16 reserved;
+
+ guint16 arrays[1];
+};
+
+struct format_12_cmap
+{
+ guint16 format;
+ guint16 reserved;
+ guint32 length;
+ guint32 language;
+ guint32 count;
+
+ guint32 groups[1];
+};
+
+struct name_header
+{
+ guint16 format_selector;
+ guint16 num_records;
+ guint16 string_storage_offset;
+};
+
+struct name_record
+{
+ guint16 platform_id;
+ guint16 encoding_id;
+ guint16 language_id;
+ guint16 name_id;
+ guint16 string_length;
+ guint16 string_offset;
+};
+
+GType _pango_win32_font_get_type (void) G_GNUC_CONST;
+
+void _pango_win32_make_matching_logfontw (PangoFontMap *fontmap,
+ const LOGFONTW *lfp,
+ int size,
+ LOGFONTW *out);
+
+GType _pango_win32_font_map_get_type (void) G_GNUC_CONST;
+
+void _pango_win32_fontmap_cache_remove (PangoFontMap *fontmap,
+ PangoWin32Font *xfont);
+
+gboolean _pango_win32_get_name_header (HDC hdc,
+ struct name_header *header);
+gboolean _pango_win32_get_name_record (HDC hdc,
+ gint i,
+ struct name_record *record);
+
+extern HDC _pango_win32_hdc;
+extern OSVERSIONINFO _pango_win32_os_version_info;
+extern gboolean _pango_win32_debug;
+
+#endif /* __PANGOWIN32_PRIVATE_H__ */
diff --git a/trunk/pango/pangowin32.c b/trunk/pango/pangowin32.c
new file mode 100644
index 00000000..10809c7b
--- /dev/null
+++ b/trunk/pango/pangowin32.c
@@ -0,0 +1,1787 @@
+/* Pango
+ * pangowin32.c: Routines for handling Windows fonts
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ * Copyright (C) 2001 Alexander Larsson
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+
+#include "pango-impl-utils.h"
+#include "pangowin32.h"
+#include "pangowin32-private.h"
+
+#define MAX_FREED_FONTS 16
+
+#define CH_IS_UNIHAN_BMP(ch) ((ch) >= 0x3400 && (ch) <= 0x9FFF)
+#define CH_IS_UNIHAN(ch) (CH_IS_UNIHAN_BMP (ch) || \
+ ((ch) >= 0x20000 && (ch) <= 0x2A6DF) || \
+ ((ch) >= 0x2F800 && (ch) <= 0x2FA1F))
+
+HDC _pango_win32_hdc;
+OSVERSIONINFO _pango_win32_os_version_info;
+gboolean _pango_win32_debug = FALSE;
+
+static void pango_win32_font_dispose (GObject *object);
+static void pango_win32_font_finalize (GObject *object);
+
+static gboolean pango_win32_font_real_select_font (PangoFont *font,
+ HDC hdc);
+static void pango_win32_font_real_done_font (PangoFont *font);
+static double pango_win32_font_real_get_metrics_factor (PangoFont *font);
+
+static PangoFontDescription *pango_win32_font_describe (PangoFont *font);
+static PangoFontDescription *pango_win32_font_describe_absolute (PangoFont *font);
+static PangoCoverage *pango_win32_font_get_coverage (PangoFont *font,
+ PangoLanguage *lang);
+static void pango_win32_font_calc_coverage (PangoFont *font,
+ PangoCoverage *coverage,
+ PangoLanguage *lang);
+static PangoEngineShape *pango_win32_font_find_shaper (PangoFont *font,
+ PangoLanguage *lang,
+ guint32 ch);
+static void pango_win32_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+static PangoFontMetrics * pango_win32_font_get_metrics (PangoFont *font,
+ PangoLanguage *lang);
+static PangoFontMap * pango_win32_font_get_font_map (PangoFont *font);
+
+static gboolean pango_win32_font_real_select_font (PangoFont *font,
+ HDC hdc);
+static void pango_win32_font_real_done_font (PangoFont *font);
+static double pango_win32_font_real_get_metrics_factor (PangoFont *font);
+
+static HFONT pango_win32_get_hfont (PangoFont *font);
+static void pango_win32_get_item_properties (PangoItem *item,
+ PangoUnderline *uline,
+ PangoAttrColor *fg_color,
+ gboolean *fg_set,
+ PangoAttrColor *bg_color,
+ gboolean *bg_set);
+
+static HFONT
+pango_win32_get_hfont (PangoFont *font)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ PangoWin32FontCache *cache;
+ TEXTMETRIC tm;
+
+ if (!win32font)
+ return NULL;
+
+ if (!win32font->hfont)
+ {
+ cache = pango_win32_font_map_get_font_cache (win32font->fontmap);
+
+ win32font->hfont = pango_win32_font_cache_loadw (cache, &win32font->logfontw);
+ if (!win32font->hfont)
+ {
+ gchar *face_utf8 = g_utf16_to_utf8 (win32font->logfontw.lfFaceName,
+ -1, NULL, NULL, NULL);
+ g_warning ("Cannot load font '%s\n", face_utf8);
+ g_free (face_utf8);
+ return NULL;
+ }
+
+ SelectObject (_pango_win32_hdc, win32font->hfont);
+ GetTextMetrics (_pango_win32_hdc, &tm);
+
+ win32font->tm_overhang = tm.tmOverhang;
+ win32font->tm_descent = tm.tmDescent;
+ win32font->tm_ascent = tm.tmAscent;
+ }
+
+ return win32font->hfont;
+}
+
+/**
+ * pango_win32_get_context:
+ *
+ * Retrieves a #PangoContext appropriate for rendering with Windows fonts.
+ *
+ * Return value: the new #PangoContext
+ **/
+PangoContext *
+pango_win32_get_context (void)
+{
+ PangoContext *result;
+
+ result = pango_context_new ();
+ pango_context_set_font_map (result, pango_win32_font_map_for_display ());
+
+ return result;
+}
+
+G_DEFINE_TYPE (PangoWin32Font, _pango_win32_font, PANGO_TYPE_FONT)
+
+static void
+_pango_win32_font_init (PangoWin32Font *win32font)
+{
+ win32font->size = -1;
+
+ win32font->metrics_by_lang = NULL;
+
+ win32font->glyph_info = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+}
+
+/**
+ * pango_win32_get_dc:
+ *
+ * Obtains a handle to the Windows device context that is used by Pango.
+ *
+ * Return value: A handle to the Windows device context that is used by Pango.
+ **/
+HDC
+pango_win32_get_dc (void)
+{
+ if (_pango_win32_hdc == NULL)
+ {
+ _pango_win32_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
+ memset (&_pango_win32_os_version_info, 0,
+ sizeof (_pango_win32_os_version_info));
+ _pango_win32_os_version_info.dwOSVersionInfoSize =
+ sizeof (OSVERSIONINFO);
+ GetVersionEx (&_pango_win32_os_version_info);
+
+ /* Also do some generic pangowin32 initialisations... this function
+ * is a suitable place for those as it is called from a couple
+ * of class_init functions.
+ */
+#ifdef PANGO_WIN32_DEBUGGING
+ if (getenv ("PANGO_WIN32_DEBUG") != NULL)
+ _pango_win32_debug = TRUE;
+#endif
+ }
+
+ return _pango_win32_hdc;
+}
+
+/**
+ * pango_win32_get_debug_flag:
+ *
+ * Returns whether debugging is turned on.
+ *
+ * Return value: %TRUE if debugging is turned on.
+ *
+ * Since: 1.2
+ */
+gboolean
+pango_win32_get_debug_flag (void)
+{
+ return _pango_win32_debug;
+}
+
+static void
+_pango_win32_font_class_init (PangoWin32FontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+
+ object_class->finalize = pango_win32_font_finalize;
+ object_class->dispose = pango_win32_font_dispose;
+
+ font_class->describe = pango_win32_font_describe;
+ font_class->describe_absolute = pango_win32_font_describe_absolute;
+ font_class->get_coverage = pango_win32_font_get_coverage;
+ font_class->find_shaper = pango_win32_font_find_shaper;
+ font_class->get_glyph_extents = pango_win32_font_get_glyph_extents;
+ font_class->get_metrics = pango_win32_font_get_metrics;
+ font_class->get_font_map = pango_win32_font_get_font_map;
+
+ class->select_font = pango_win32_font_real_select_font;
+ class->done_font = pango_win32_font_real_done_font;
+ class->get_metrics_factor = pango_win32_font_real_get_metrics_factor;
+
+ pango_win32_get_dc ();
+}
+
+/**
+ * pango_win32_render:
+ * @hdc: the device context
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Render a #PangoGlyphString onto a Windows DC
+ */
+void
+pango_win32_render (HDC hdc,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ HFONT hfont, old_hfont = NULL;
+ int i, j, num_valid_glyphs;
+ guint16 *glyph_indexes;
+ gint *dX;
+ gint this_x;
+ PangoGlyphUnit start_x_offset, x_offset, next_x_offset, cur_y_offset;
+
+ g_return_if_fail (glyphs != NULL);
+
+#ifdef PANGO_WIN32_DEBUGGING
+ if (_pango_win32_debug)
+ {
+ PING (("num_glyphs:%d", glyphs->num_glyphs));
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ g_print (" %d:%d", glyphs->glyphs[i].glyph, glyphs->glyphs[i].geometry.width);
+ if (glyphs->glyphs[i].geometry.x_offset != 0 ||
+ glyphs->glyphs[i].geometry.y_offset != 0)
+ g_print (":%d,%d", glyphs->glyphs[i].geometry.x_offset,
+ glyphs->glyphs[i].geometry.y_offset);
+ }
+ g_print ("\n");
+ }
+#endif
+
+ if (glyphs->num_glyphs == 0)
+ return;
+
+ hfont = pango_win32_get_hfont (font);
+ if (!hfont)
+ return;
+
+ old_hfont = SelectObject (hdc, hfont);
+
+ glyph_indexes = g_new (guint16, glyphs->num_glyphs);
+ dX = g_new (INT, glyphs->num_glyphs);
+
+ /* Render glyphs using one ExtTextOutW() call for each run of glyphs
+ * that have the same y offset. The big majoroty of glyphs will have
+ * y offset of zero, so in general, the whole glyph string will be
+ * rendered by one call to ExtTextOutW().
+ *
+ * In order to minimize buildup of rounding errors, we keep track of
+ * where the glyphs should be rendered in PangoGlyphUnits, and round
+ * to pixels separately for each glyph,
+ */
+
+ i = 0;
+
+ /* Outer loop through all glyphs in string */
+ while (i < glyphs->num_glyphs)
+ {
+ cur_y_offset = glyphs->glyphs[i].geometry.y_offset;
+ num_valid_glyphs = 0;
+ x_offset = 0;
+ start_x_offset = glyphs->glyphs[i].geometry.x_offset;
+ this_x = PANGO_PIXELS (start_x_offset);
+
+ /* Inner loop through glyphs with the same y offset, or code
+ * point zero (just spacing).
+ */
+ while (i < glyphs->num_glyphs &&
+ (glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY ||
+ cur_y_offset == glyphs->glyphs[i].geometry.y_offset))
+ {
+ if (glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY)
+ {
+ /* PANGO_GLYPH_EMPTY glyphs should not be rendered, but their
+ * indicated width (set up by PangoLayout) should be taken
+ * into account.
+ */
+
+ /* If the string starts with spacing, must shift the
+ * starting point for the glyphs actually rendered. For
+ * spacing in the middle of the glyph string, add to the dX
+ * of the previous glyph to be rendered.
+ */
+ if (num_valid_glyphs == 0)
+ start_x_offset += glyphs->glyphs[i].geometry.width;
+ else
+ {
+ x_offset += glyphs->glyphs[i].geometry.width;
+ dX[num_valid_glyphs-1] = PANGO_PIXELS (x_offset) - this_x;
+ }
+ }
+ else
+ {
+ if (glyphs->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ /* Glyph index is actually the char value that doesn't
+ * have any glyph (ORed with the flag). We should really
+ * do the same that pango_xft_real_render() does: render
+ * a box with the char value in hex inside it in a tiny
+ * font. Later. For now, use the TrueType invalid glyph
+ * at 0.
+ */
+ glyph_indexes[num_valid_glyphs] = 0;
+ }
+ else
+ glyph_indexes[num_valid_glyphs] = glyphs->glyphs[i].glyph;
+
+ x_offset += glyphs->glyphs[i].geometry.width;
+
+ /* If the next glyph has an X offset, take that into consideration now */
+ if (i < glyphs->num_glyphs - 1)
+ next_x_offset = glyphs->glyphs[i+1].geometry.x_offset;
+ else
+ next_x_offset = 0;
+
+ dX[num_valid_glyphs] = PANGO_PIXELS (x_offset + next_x_offset) - this_x;
+
+ /* Prepare for next glyph */
+ this_x += dX[num_valid_glyphs];
+ num_valid_glyphs++;
+ }
+ i++;
+ }
+#ifdef PANGO_WIN32_DEBUGGING
+ if (_pango_win32_debug)
+ {
+ g_print ("ExtTextOutW at %d,%d deltas:",
+ x + PANGO_PIXELS (start_x_offset),
+ y + PANGO_PIXELS (cur_y_offset));
+ for (j = 0; j < num_valid_glyphs; j++)
+ g_print (" %d", dX[j]);
+ g_print ("\n");
+ }
+#endif
+
+ ExtTextOutW (hdc,
+ x + PANGO_PIXELS (start_x_offset),
+ y + PANGO_PIXELS (cur_y_offset),
+ ETO_GLYPH_INDEX,
+ NULL,
+ glyph_indexes, num_valid_glyphs,
+ dX);
+ x += this_x;
+ }
+
+
+ SelectObject (hdc, old_hfont); /* restore */
+ g_free (glyph_indexes);
+ g_free (dX);
+}
+
+/**
+ * pango_win32_render_transformed:
+ * @hdc: a windows device context
+ * @matrix: a #PangoMatrix, or %NULL to use an identity transformation
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of the start of the string (in Pango
+ * units in user space coordinates)
+ * @y: the y position of the baseline (in Pango units
+ * in user space coordinates)
+ *
+ * Renders a #PangoGlyphString onto a windows DC, possibly
+ * transforming the layed-out coordinates through a transformation
+ * matrix. Note that the transformation matrix for @font is not
+ * changed, so to produce correct rendering results, the @font
+ * must have been loaded using a #PangoContext with an identical
+ * transformation matrix to that passed in to this function.
+ **/
+void
+pango_win32_render_transformed (HDC hdc,
+ const PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ XFORM xForm;
+ XFORM xFormPrev = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
+ int mode = GetGraphicsMode (hdc);
+
+ if (!SetGraphicsMode (hdc, GM_ADVANCED))
+ g_warning ("SetGraphicsMode() failed");
+ else if (!GetWorldTransform (hdc, &xFormPrev))
+ g_warning ("GetWorldTransform() failed");
+ else if (matrix)
+ {
+ xForm.eM11 = matrix->xx;
+ xForm.eM12 = matrix->yx;
+ xForm.eM21 = matrix->xy;
+ xForm.eM22 = matrix->yy;
+ xForm.eDx = matrix->x0;
+ xForm.eDy = matrix->y0;
+ if (!SetWorldTransform (hdc, &xForm))
+ g_warning ("GetWorldTransform() failed");
+ }
+
+ pango_win32_render (hdc, font, glyphs, x/PANGO_SCALE, y/PANGO_SCALE);
+
+ /* restore */
+ SetWorldTransform (hdc, &xFormPrev);
+ SetGraphicsMode (hdc, mode);
+}
+
+static void
+pango_win32_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ guint16 glyph_index = glyph;
+ GLYPHMETRICS gm;
+ guint32 res;
+ HFONT hfont;
+ MAT2 m = {{0,1}, {0,0}, {0,0}, {0,1}};
+ PangoWin32GlyphInfo *info;
+
+ if (glyph == PANGO_GLYPH_EMPTY)
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->width = ink_rect->y = ink_rect->height = 0;
+ if (logical_rect)
+ logical_rect->x = logical_rect->width = logical_rect->y = logical_rect->height = 0;
+ return;
+ }
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ glyph_index = glyph = 0;
+
+ info = g_hash_table_lookup (win32font->glyph_info, GUINT_TO_POINTER (glyph));
+
+ if (!info)
+ {
+ info = g_new0 (PangoWin32GlyphInfo, 1);
+
+ memset (&gm, 0, sizeof (gm));
+
+ hfont = pango_win32_get_hfont (font);
+ SelectObject (_pango_win32_hdc, hfont);
+ /* FIXME: (Alex) This constant reuse of _pango_win32_hdc is
+ not thread-safe */
+ res = GetGlyphOutlineA (_pango_win32_hdc,
+ glyph_index,
+ GGO_METRICS | GGO_GLYPH_INDEX,
+ &gm,
+ 0, NULL,
+ &m);
+
+ if (res == GDI_ERROR)
+ {
+ gchar *error = g_win32_error_message (GetLastError ());
+ g_warning ("GetGlyphOutline(%04X) failed: %s\n",
+ glyph_index, error);
+ g_free (error);
+
+ /* Don't just return now, use the still zeroed out gm */
+ }
+
+ info->ink_rect.x = PANGO_SCALE * gm.gmptGlyphOrigin.x;
+ info->ink_rect.width = PANGO_SCALE * gm.gmBlackBoxX;
+ info->ink_rect.y = - PANGO_SCALE * gm.gmptGlyphOrigin.y;
+ info->ink_rect.height = PANGO_SCALE * gm.gmBlackBoxY;
+
+ info->logical_rect.x = 0;
+ info->logical_rect.width = PANGO_SCALE * gm.gmCellIncX;
+ info->logical_rect.y = - PANGO_SCALE * win32font->tm_ascent;
+ info->logical_rect.height = PANGO_SCALE * (win32font->tm_ascent + win32font->tm_descent);
+
+ g_hash_table_insert (win32font->glyph_info, GUINT_TO_POINTER(glyph), info);
+ }
+
+ if (ink_rect)
+ *ink_rect = info->ink_rect;
+
+ if (logical_rect)
+ *logical_rect = info->logical_rect;
+}
+
+static int
+max_glyph_width (PangoLayout *layout)
+{
+ int max_width = 0;
+ GSList *l, *r;
+
+ for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
+ {
+ PangoLayoutLine *line = l->data;
+
+ for (r = line->runs; r; r = r->next)
+ {
+ PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ if (glyphs->glyphs[i].geometry.width > max_width)
+ max_width = glyphs->glyphs[i].geometry.width;
+ }
+ }
+
+ return max_width;
+}
+
+static PangoFontMetrics *
+pango_win32_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoWin32MetricsInfo *info = NULL; /* Quiet gcc */
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ GSList *tmp_list;
+
+ const char *sample_str = pango_language_get_sample_string (language);
+
+ tmp_list = win32font->metrics_by_lang;
+ while (tmp_list)
+ {
+ info = tmp_list->data;
+
+ if (info->sample_str == sample_str) /* We _don't_ need strcmp */
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list)
+ {
+ HFONT hfont;
+ PangoFontMetrics *metrics;
+
+ info = g_new (PangoWin32MetricsInfo, 1);
+ win32font->metrics_by_lang = g_slist_prepend (win32font->metrics_by_lang, info);
+
+ info->sample_str = sample_str;
+ info->metrics = metrics = pango_font_metrics_new ();
+
+ hfont = pango_win32_get_hfont (font);
+ if (hfont != NULL)
+ {
+ PangoCoverage *coverage;
+ TEXTMETRIC tm;
+
+ SelectObject (_pango_win32_hdc, hfont);
+ GetTextMetrics (_pango_win32_hdc, &tm);
+
+ metrics->ascent = tm.tmAscent * PANGO_SCALE;
+ metrics->descent = tm.tmDescent * PANGO_SCALE;
+ metrics->approximate_char_width = tm.tmAveCharWidth * PANGO_SCALE;
+
+ coverage = pango_win32_font_get_coverage (font, language);
+ if (pango_coverage_get (coverage, '0') != PANGO_COVERAGE_NONE &&
+ pango_coverage_get (coverage, '9') != PANGO_COVERAGE_NONE)
+ {
+ PangoContext *context;
+ PangoFontDescription *font_desc;
+ PangoLayout *layout;
+
+ /* Get the average width of the chars in "0123456789" */
+ context = pango_win32_get_context ();
+ pango_context_set_language (context, language);
+ font_desc = pango_font_describe_with_absolute_size (font);
+ pango_context_set_font_description (context, font_desc);
+ layout = pango_layout_new (context);
+ pango_layout_set_text (layout, "0123456789", -1);
+
+ metrics->approximate_digit_width = max_glyph_width (layout);
+
+ pango_font_description_free (font_desc);
+ g_object_unref (layout);
+ g_object_unref (context);
+ }
+ else
+ metrics->approximate_digit_width = metrics->approximate_char_width;
+
+ pango_coverage_unref (coverage);
+
+ /* FIXME: Should get the real values from the TrueType font file */
+ metrics->underline_position = -2 * PANGO_SCALE;
+ metrics->underline_thickness = 1 * PANGO_SCALE;
+ metrics->strikethrough_thickness = metrics->underline_thickness;
+ /* Really really wild guess */
+ metrics->strikethrough_position = metrics->ascent / 3;
+ }
+ }
+
+ return pango_font_metrics_ref (info->metrics);
+}
+
+static PangoFontMap *
+pango_win32_font_get_font_map (PangoFont *font)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+
+ return win32font->fontmap;
+}
+
+static gboolean
+pango_win32_font_real_select_font (PangoFont *font,
+ HDC hdc)
+{
+ HFONT hfont = pango_win32_get_hfont (font);
+
+ if (!hfont)
+ return FALSE;
+
+ if (!SelectObject (hdc, hfont))
+ {
+ g_warning ("pango_win32_font_real_select_font: Cannot select font\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+pango_win32_font_real_done_font (PangoFont *font)
+{
+}
+
+static double
+pango_win32_font_real_get_metrics_factor (PangoFont *font)
+{
+ return PANGO_SCALE;
+}
+
+/**
+ * pango_win32_font_logfont:
+ * @font: a #PangoFont which must be from the Win32 backend
+ *
+ * Determine the LOGFONTA struct for the specified font. Note that
+ * Pango internally uses LOGFONTW structs, so if converting the UTF-16
+ * face name in the LOGFONTW struct to system codepage fails, the
+ * returned LOGFONTA will have an emppty face name. To get the
+ * LOGFONTW of a PangoFont, use pango_win32_font_logfontw(). It
+ * is recommended to do that always even if you don't expect
+ * to come across fonts with odd names.
+ *
+ * Return value: A newly allocated LOGFONTA struct. It must be
+ * freed with g_free().
+ **/
+LOGFONTA *
+pango_win32_font_logfont (PangoFont *font)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ LOGFONTA *lfp;
+
+ g_return_val_if_fail (font != NULL, NULL);
+ g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), NULL);
+
+ lfp = g_new (LOGFONTA, 1);
+
+ *lfp = *(LOGFONTA*) &win32font->logfontw;
+ if (!WideCharToMultiByte (CP_ACP, 0,
+ win32font->logfontw.lfFaceName, -1,
+ lfp->lfFaceName, G_N_ELEMENTS (lfp->lfFaceName),
+ NULL, NULL))
+ lfp->lfFaceName[0] = '\0';
+
+ return lfp;
+}
+
+/**
+ * pango_win32_font_logfontw:
+ * @font: a #PangoFont which must be from the Win32 backend
+ *
+ * Determine the LOGFONTW struct for the specified font.
+ *
+ * Return value: A newly allocated LOGFONTW struct. It must be
+ * freed with g_free().
+ *
+ * Since: 1.16
+ **/
+LOGFONTW *
+pango_win32_font_logfontw (PangoFont *font)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ LOGFONTW *lfp;
+
+ g_return_val_if_fail (font != NULL, NULL);
+ g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), NULL);
+
+ lfp = g_new (LOGFONTW, 1);
+ *lfp = win32font->logfontw;
+
+ return lfp;
+}
+
+/**
+ * pango_win32_font_select_font:
+ * @font: a #PangoFont from the Win32 backend
+ * @hdc: a windows device context
+ *
+ * Selects the font into the specified DC and changes the mapping mode
+ * and world transformation of the DC appropriately for the font.
+ * You may want to surround the use of this function with calls
+ * to SaveDC() and RestoreDC(). Call pango_win32_font_done_font() when
+ * you are done using the DC to release allocated resources.
+ *
+ * See pango_win32_font_get_metrics_factor() for information about
+ * converting from the coordinate space used by this function
+ * into Pango units.
+ *
+ * Return value: %TRUE if the operation succeeded.
+ **/
+gboolean
+pango_win32_font_select_font (PangoFont *font,
+ HDC hdc)
+{
+ g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), FALSE);
+
+ return PANGO_WIN32_FONT_GET_CLASS (font)->select_font (font, hdc);
+}
+
+/**
+ * pango_win32_font_done_font:
+ * @font: a #PangoFont from the win32 backend
+ *
+ * Releases any resources allocated by pango_win32_font_done_font()
+ **/
+void
+pango_win32_font_done_font (PangoFont *font)
+{
+ g_return_if_fail (PANGO_WIN32_IS_FONT (font));
+
+ PANGO_WIN32_FONT_GET_CLASS (font)->done_font (font);
+}
+
+/**
+ * pango_win32_font_get_metrics_factor:
+ * @font: a #PangoFont from the win32 backend
+ *
+ * Returns the scale factor from logical units in the coordinate
+ * space used by pango_win32_font_select_font() to Pango units
+ * in user space.
+ *
+ * Return value: factor to multiply logical units by to get Pango
+ * units.
+ **/
+double
+pango_win32_font_get_metrics_factor (PangoFont *font)
+{
+ g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), 1.);
+
+ return PANGO_WIN32_FONT_GET_CLASS (font)->get_metrics_factor (font);
+}
+
+static void
+pango_win32_fontmap_cache_add (PangoFontMap *fontmap,
+ PangoWin32Font *win32font)
+{
+ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
+
+ if (win32fontmap->freed_fonts->length == MAX_FREED_FONTS)
+ {
+ PangoWin32Font *old_font = g_queue_pop_tail (win32fontmap->freed_fonts);
+ g_object_unref (old_font);
+ }
+
+ g_object_ref (win32font);
+ g_queue_push_head (win32fontmap->freed_fonts, win32font);
+ win32font->in_cache = TRUE;
+}
+
+static void
+pango_win32_font_dispose (GObject *object)
+{
+ PangoWin32Font *win32font = PANGO_WIN32_FONT (object);
+
+ /* If the font is not already in the freed-fonts cache, add it,
+ * if it is already there, do nothing and the font will be
+ * freed.
+ */
+ if (!win32font->in_cache && win32font->fontmap)
+ pango_win32_fontmap_cache_add (win32font->fontmap, win32font);
+
+ G_OBJECT_CLASS (_pango_win32_font_parent_class)->dispose (object);
+}
+
+static void
+free_metrics_info (PangoWin32MetricsInfo *info)
+{
+ pango_font_metrics_unref (info->metrics);
+ g_free (info);
+}
+
+static void
+pango_win32_font_entry_remove (PangoWin32Face *face,
+ PangoFont *font)
+{
+ face->cached_fonts = g_slist_remove (face->cached_fonts, font);
+}
+
+static void
+pango_win32_font_finalize (GObject *object)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)object;
+ PangoWin32FontCache *cache = pango_win32_font_map_get_font_cache (win32font->fontmap);
+
+ if (win32font->hfont != NULL)
+ pango_win32_font_cache_unload (cache, win32font->hfont);
+
+ g_slist_foreach (win32font->metrics_by_lang, (GFunc)free_metrics_info, NULL);
+ g_slist_free (win32font->metrics_by_lang);
+
+ if (win32font->win32face)
+ pango_win32_font_entry_remove (win32font->win32face, PANGO_FONT (win32font));
+
+ g_hash_table_destroy (win32font->glyph_info);
+
+ g_object_unref (win32font->fontmap);
+
+ G_OBJECT_CLASS (_pango_win32_font_parent_class)->finalize (object);
+}
+
+static PangoFontDescription *
+pango_win32_font_describe (PangoFont *font)
+{
+ PangoFontDescription *desc;
+ PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
+
+ desc = pango_font_description_copy (win32font->win32face->description);
+ pango_font_description_set_size (desc, win32font->size / (PANGO_SCALE / PANGO_WIN32_FONT_MAP (win32font->fontmap)->resolution));
+
+ return desc;
+}
+
+static PangoFontDescription *
+pango_win32_font_describe_absolute (PangoFont *font)
+{
+ PangoFontDescription *desc;
+ PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
+
+ desc = pango_font_description_copy (win32font->win32face->description);
+ pango_font_description_set_absolute_size (desc, win32font->size);
+
+ return desc;
+}
+
+static PangoMap *
+pango_win32_get_shaper_map (PangoLanguage *lang)
+{
+ static guint engine_type_id = 0;
+ static guint render_type_id = 0;
+
+ if (engine_type_id == 0)
+ {
+ engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_SHAPE);
+ render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_WIN32);
+ }
+
+ return pango_find_map (lang, engine_type_id, render_type_id);
+}
+
+static gint
+pango_win32_coverage_language_classify (PangoLanguage *lang)
+{
+ if (pango_language_matches (lang, "zh-tw"))
+ return PANGO_WIN32_COVERAGE_ZH_TW;
+ else if (pango_language_matches (lang, "zh-cn"))
+ return PANGO_WIN32_COVERAGE_ZH_CN;
+ else if (pango_language_matches (lang, "ja"))
+ return PANGO_WIN32_COVERAGE_JA;
+ else if (pango_language_matches (lang, "ko"))
+ return PANGO_WIN32_COVERAGE_KO;
+ else if (pango_language_matches (lang, "vi"))
+ return PANGO_WIN32_COVERAGE_VI;
+ else
+ return PANGO_WIN32_COVERAGE_UNSPEC;
+}
+
+static PangoCoverage *
+pango_win32_font_entry_get_coverage (PangoWin32Face *face,
+ PangoLanguage *lang)
+{
+ gint i = pango_win32_coverage_language_classify (lang);
+ if (face->coverages[i])
+ {
+ pango_coverage_ref (face->coverages[i]);
+ return face->coverages[i];
+ }
+
+ return NULL;
+}
+
+static void
+pango_win32_font_entry_set_coverage (PangoWin32Face *face,
+ PangoCoverage *coverage,
+ PangoLanguage *lang)
+{
+ face->coverages[pango_win32_coverage_language_classify (lang)] = pango_coverage_ref (coverage);
+}
+
+static PangoCoverage *
+pango_win32_font_get_coverage (PangoFont *font,
+ PangoLanguage *lang)
+{
+ PangoCoverage *coverage;
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+
+ coverage = pango_win32_font_entry_get_coverage (win32font->win32face, lang);
+ if (!coverage)
+ {
+ coverage = pango_coverage_new ();
+ pango_win32_font_calc_coverage (font, coverage, lang);
+
+ pango_win32_font_entry_set_coverage (win32font->win32face, coverage, lang);
+ }
+
+ return coverage;
+}
+
+static PangoEngineShape *
+pango_win32_font_find_shaper (PangoFont *font,
+ PangoLanguage *lang,
+ guint32 ch)
+{
+ PangoMap *shape_map = NULL;
+ PangoScript script;
+
+ shape_map = pango_win32_get_shaper_map (lang);
+ script = pango_script_for_unichar (ch);
+ return (PangoEngineShape *)pango_map_get_engine (shape_map, script);
+}
+
+/* Utility functions */
+
+/**
+ * pango_win32_get_unknown_glyph:
+ * @font: a #PangoFont
+ * @wc: the Unicode character for which a glyph is needed.
+ *
+ * Returns the index of a glyph suitable for drawing @wc as an
+ * unknown character.
+ *
+ * Use PANGO_GET_UNKNOWN_GLYPH() instead.
+ *
+ * Return value: a glyph index into @font
+ **/
+PangoGlyph
+pango_win32_get_unknown_glyph (PangoFont *font,
+ gunichar wc)
+{
+ return PANGO_GET_UNKNOWN_GLYPH (wc);
+}
+
+/**
+ * pango_win32_render_layout_line:
+ * @hdc: DC to use for uncolored drawing
+ * @line: a #PangoLayoutLine
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Render a #PangoLayoutLine onto a device context. For underlining to
+ * work property the text alignment of the DC should have TA_BASELINE
+ * and TA_LEFT.
+ */
+void
+pango_win32_render_layout_line (HDC hdc,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ GSList *tmp_list = line->runs;
+ PangoRectangle overall_rect;
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+
+ int x_off = 0;
+
+ pango_layout_line_get_extents (line,NULL, &overall_rect);
+
+ while (tmp_list)
+ {
+ HBRUSH oldfg = NULL;
+ HBRUSH brush = NULL;
+ POINT points[2];
+ PangoUnderline uline = PANGO_UNDERLINE_NONE;
+ PangoLayoutRun *run = tmp_list->data;
+ PangoAttrColor fg_color, bg_color;
+ gboolean fg_set, bg_set;
+
+ tmp_list = tmp_list->next;
+
+ pango_win32_get_item_properties (run->item, &uline, &fg_color, &fg_set, &bg_color, &bg_set);
+
+ if (uline == PANGO_UNDERLINE_NONE)
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ NULL, &logical_rect);
+ else
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ &ink_rect, &logical_rect);
+
+ if (bg_set)
+ {
+ HBRUSH oldbrush;
+
+ brush = CreateSolidBrush (RGB ((bg_color.color.red + 128) >> 8,
+ (bg_color.color.green + 128) >> 8,
+ (bg_color.color.blue + 128) >> 8));
+ oldbrush = SelectObject (hdc, brush);
+ Rectangle (hdc, x + PANGO_PIXELS (x_off + logical_rect.x),
+ y + PANGO_PIXELS (overall_rect.y),
+ PANGO_PIXELS (logical_rect.width),
+ PANGO_PIXELS (overall_rect.height));
+ SelectObject (hdc, oldbrush);
+ DeleteObject (brush);
+ }
+
+ if (fg_set)
+ {
+ brush = CreateSolidBrush (RGB ((fg_color.color.red + 128) >> 8,
+ (fg_color.color.green + 128) >> 8,
+ (fg_color.color.blue + 128) >> 8));
+ oldfg = SelectObject (hdc, brush);
+ }
+
+ pango_win32_render (hdc, run->item->analysis.font, run->glyphs,
+ x + PANGO_PIXELS (x_off), y);
+
+ switch (uline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
+ points[0].y = points[1].y = y + 4;
+ points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
+ Polyline (hdc, points, 2);
+ points[0].y = points[1].y = y + 2;
+ Polyline (hdc, points, 2);
+ break;
+ case PANGO_UNDERLINE_SINGLE:
+ points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
+ points[0].y = points[1].y = y + 2;
+ points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
+ Polyline (hdc, points, 2);
+ break;
+ case PANGO_UNDERLINE_ERROR:
+ {
+ int point_x;
+ int counter = 0;
+ int end_x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
+
+ for (point_x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
+ point_x <= end_x;
+ point_x += 2)
+ {
+ points[0].x = point_x;
+ points[1].x = MAX (point_x + 1, end_x);
+
+ if (counter)
+ points[0].y = points[1].y = y + 2;
+ else
+ points[0].y = points[1].y = y + 3;
+
+ Polyline (hdc, points, 2);
+ counter = (counter + 1) % 2;
+ }
+ }
+ break;
+ case PANGO_UNDERLINE_LOW:
+ points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
+ points[0].y = points[1].y = y + PANGO_PIXELS (ink_rect.y + ink_rect.height) + 2;
+ points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
+ Polyline (hdc, points, 2);
+ break;
+ }
+
+ if (fg_set)
+ {
+ SelectObject (hdc, oldfg);
+ DeleteObject (brush);
+ }
+
+ x_off += logical_rect.width;
+ }
+}
+
+/**
+ * pango_win32_render_layout:
+ * @hdc: HDC to use for uncolored drawing
+ * @layout: a #PangoLayout
+ * @x: the X position of the left of the layout (in pixels)
+ * @y: the Y position of the top of the layout (in pixels)
+ *
+ * Render a #PangoLayoutLine onto an X drawable
+ */
+void
+pango_win32_render_layout (HDC hdc,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ PangoLayoutIter *iter;
+
+ g_return_if_fail (hdc != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ iter = pango_layout_get_iter (layout);
+
+ do
+ {
+ PangoRectangle logical_rect;
+ PangoLayoutLine *line;
+ int baseline;
+
+ line = pango_layout_iter_get_line_readonly (iter);
+
+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+ baseline = pango_layout_iter_get_baseline (iter);
+
+ pango_win32_render_layout_line (hdc,
+ line,
+ x + PANGO_PIXELS (logical_rect.x),
+ y + PANGO_PIXELS (baseline));
+ }
+ while (pango_layout_iter_next_line (iter));
+
+ pango_layout_iter_free (iter);
+}
+
+/* This utility function is duplicated here and in pango-layout.c; should it be
+ * public? Trouble is - what is the appropriate set of properties?
+ */
+static void
+pango_win32_get_item_properties (PangoItem *item,
+ PangoUnderline *uline,
+ PangoAttrColor *fg_color,
+ gboolean *fg_set,
+ PangoAttrColor *bg_color,
+ gboolean *bg_set)
+{
+ GSList *tmp_list = item->analysis.extra_attrs;
+
+ if (fg_set)
+ *fg_set = FALSE;
+
+ if (bg_set)
+ *bg_set = FALSE;
+
+ while (tmp_list)
+ {
+ PangoAttribute *attr = tmp_list->data;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_UNDERLINE:
+ if (uline)
+ *uline = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_FOREGROUND:
+ if (fg_color)
+ *fg_color = *((PangoAttrColor *)attr);
+ if (fg_set)
+ *fg_set = TRUE;
+
+ break;
+
+ case PANGO_ATTR_BACKGROUND:
+ if (bg_color)
+ *bg_color = *((PangoAttrColor *)attr);
+ if (bg_set)
+ *bg_set = TRUE;
+
+ break;
+
+ default:
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+}
+
+static guint
+get_cmap_offset (HDC hdc,
+ guint16 encoding_id)
+{
+ guint16 n_tables;
+ struct cmap_encoding_subtable *table;
+ gint32 res;
+ int i;
+ guint32 offset;
+
+ /* Get The number of encoding tables, at offset 2 */
+ res = GetFontData (hdc, CMAP, 2, &n_tables, 2);
+ if (res != 2)
+ return 0;
+
+ n_tables = GUINT16_FROM_BE (n_tables);
+
+ table = g_malloc (ENCODING_TABLE_SIZE*n_tables);
+
+ res = GetFontData (hdc, CMAP, CMAP_HEADER_SIZE, table, ENCODING_TABLE_SIZE*n_tables);
+ if (res != ENCODING_TABLE_SIZE*n_tables)
+ return 0;
+
+ for (i = 0; i < n_tables; i++)
+ {
+ if (table[i].platform_id == GUINT16_TO_BE (MICROSOFT_PLATFORM_ID) &&
+ table[i].encoding_id == GUINT16_TO_BE (encoding_id))
+ {
+ offset = GUINT32_FROM_BE (table[i].offset);
+ g_free (table);
+ return offset;
+ }
+ }
+ g_free (table);
+ return 0;
+}
+
+static gpointer
+get_format_4_cmap (HDC hdc)
+{
+ guint32 offset;
+ guint32 res;
+ guint16 length;
+ guint16 *tbl, *tbl_end;
+ struct format_4_cmap *table;
+
+ /* FIXME: Could look here at the CRC for the font in the DC
+ and return a cached copy if the same */
+
+ offset = get_cmap_offset (hdc, UNICODE_ENCODING_ID);
+ if (offset == 0)
+ return NULL;
+
+ res = GetFontData (hdc, CMAP, offset + 2, &length, 2);
+ if (res != 2)
+ return NULL;
+ length = GUINT16_FROM_BE (length);
+
+ table = g_malloc (length);
+
+ res = GetFontData (hdc, CMAP, offset, table, length);
+ if (res != length ||
+ GUINT16_FROM_BE (table->format) != 4 ||
+ (GUINT16_FROM_BE (table->length) % 2) != 0)
+ {
+ g_free (table);
+ return NULL;
+ }
+
+ table->format = GUINT16_FROM_BE (table->format);
+ table->length = GUINT16_FROM_BE (table->length);
+ table->language = GUINT16_FROM_BE (table->language);
+ table->seg_count_x_2 = GUINT16_FROM_BE (table->seg_count_x_2);
+ table->search_range = GUINT16_FROM_BE (table->search_range);
+ table->entry_selector = GUINT16_FROM_BE (table->entry_selector);
+ table->range_shift = GUINT16_FROM_BE (table->range_shift);
+
+ tbl_end = (guint16 *)((char *)table + length);
+ tbl = &table->reserved;
+
+ while (tbl < tbl_end)
+ {
+ *tbl = GUINT16_FROM_BE (*tbl);
+ tbl++;
+ }
+
+ return table;
+}
+
+static guint16 *
+get_id_range_offset (struct format_4_cmap *table)
+{
+ gint32 seg_count = table->seg_count_x_2/2;
+ return &table->arrays[seg_count*3];
+}
+
+static guint16 *
+get_id_delta (struct format_4_cmap *table)
+{
+ gint32 seg_count = table->seg_count_x_2/2;
+ return &table->arrays[seg_count*2];
+}
+
+static guint16 *
+get_start_count (struct format_4_cmap *table)
+{
+ gint32 seg_count = table->seg_count_x_2/2;
+ return &table->arrays[seg_count*1];
+}
+
+static guint16 *
+get_end_count (struct format_4_cmap *table)
+{
+ gint32 seg_count = table->seg_count_x_2/2;
+ /* Apparently the reseved spot is not reserved for
+ the end_count array!? */
+ return (&table->arrays[seg_count*0])-1;
+}
+
+static gboolean
+find_segment (struct format_4_cmap *table,
+ guint16 wc,
+ guint16 *segment)
+{
+ guint16 start, end, i;
+ guint16 seg_count = table->seg_count_x_2/2;
+ guint16 *end_count = get_end_count (table);
+ guint16 *start_count = get_start_count (table);
+ static guint last = 0; /* Cache of one */
+
+ if (last < seg_count &&
+ wc >= start_count[last] &&
+ wc <= end_count[last])
+ {
+ *segment = last;
+ return TRUE;
+ }
+
+
+ /* Binary search for the segment */
+ start = 0; /* inclusive */
+ end = seg_count; /* not inclusive */
+ while (start < end)
+ {
+ /* Look at middle pos */
+ i = (start + end)/2;
+
+ if (i == start)
+ {
+ /* We made no progress. Look if this is the one. */
+
+ if (wc >= start_count[i] &&
+ wc <= end_count[i])
+ {
+ *segment = i;
+ last = i;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else if (wc < start_count[i])
+ {
+ end = i;
+ }
+ else if (wc > end_count[i])
+ {
+ start = i;
+ }
+ else
+ {
+ /* Found it! */
+ *segment = i;
+ last = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gpointer
+get_format_12_cmap (HDC hdc)
+{
+ guint32 offset;
+ guint32 res;
+ guint32 length;
+ guint32 *tbl, *tbl_end;
+ struct format_12_cmap *table;
+
+ offset = get_cmap_offset (hdc, UCS4_ENCODING_ID);
+ if (offset == 0)
+ return NULL;
+
+ res = GetFontData (hdc, CMAP, offset + 4, &length, 4);
+ if (res != 4)
+ return NULL;
+ length = GUINT32_FROM_BE (length);
+
+ table = g_malloc (length);
+
+ res = GetFontData (hdc, CMAP, offset, table, length);
+ if (res != length)
+ {
+ g_free (table);
+ return NULL;
+ }
+
+ table->format = GUINT16_FROM_BE (table->format);
+ table->length = GUINT32_FROM_BE (table->length);
+ table->language = GUINT32_FROM_BE (table->language);
+ table->count = GUINT32_FROM_BE (table->count);
+
+ if (table->format != 12 ||
+ (table->length % 4) != 0 ||
+ table->length > length ||
+ table->length < 16 + table->count * 12)
+ {
+ g_free (table);
+ return NULL;
+ }
+
+ tbl_end = (guint32 *) ((char *) table + length);
+ tbl = table->groups;
+
+ while (tbl < tbl_end)
+ {
+ *tbl = GUINT32_FROM_BE (*tbl);
+ tbl++;
+ }
+
+ return table;
+}
+
+static gpointer
+font_get_cmap (PangoFont *font)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ gpointer cmap;
+
+ if (win32font->win32face->cmap)
+ return win32font->win32face->cmap;
+
+ pango_win32_font_select_font (font, _pango_win32_hdc);
+
+ /* Prefer the format 12 cmap */
+ if ((cmap = get_format_12_cmap (_pango_win32_hdc)) != NULL)
+ {
+ win32font->win32face->cmap_format = 12;
+ win32font->win32face->cmap = cmap;
+ }
+ else if ((cmap = get_format_4_cmap (_pango_win32_hdc)) != NULL)
+ {
+ win32font->win32face->cmap_format = 4;
+ win32font->win32face->cmap = cmap;
+ }
+
+ pango_win32_font_done_font (font);
+
+ return cmap;
+}
+
+/**
+ * pango_win32_font_get_glyph_index:
+ * @font: a #PangoFont.
+ * @wc: a Unicode character.
+ *
+ * Obtains the index of the glyph for @wc in @font, or 0, if not
+ * covered.
+ *
+ * Return value: the glyph index for @wc.
+ **/
+gint
+pango_win32_font_get_glyph_index (PangoFont *font,
+ gunichar wc)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ gpointer cmap;
+ guint16 glyph;
+
+ /* Do GetFontData magic on font->hfont here. */
+ cmap = font_get_cmap (font);
+
+ if (cmap == NULL)
+ return 0;
+
+ if (win32font->win32face->cmap_format == 4)
+ {
+ struct format_4_cmap *cmap4 = cmap;
+ guint16 *id_range_offset;
+ guint16 *id_delta;
+ guint16 *start_count;
+ guint16 segment;
+ guint16 id;
+ guint16 ch = wc;
+
+ if (wc > 0xFFFF)
+ return 0;
+
+ if (!find_segment (cmap4, ch, &segment))
+ return 0;
+
+ id_range_offset = get_id_range_offset (cmap4);
+ id_delta = get_id_delta (cmap4);
+ start_count = get_start_count (cmap4);
+
+ if (id_range_offset[segment] == 0)
+ glyph = (id_delta[segment] + ch) % 65536;
+ else
+ {
+ id = *(id_range_offset[segment]/2 +
+ (ch - start_count[segment]) +
+ &id_range_offset[segment]);
+ if (id)
+ glyph = (id_delta[segment] + id) %65536;
+ else
+ glyph = 0;
+ }
+ }
+ else if (win32font->win32face->cmap_format == 12)
+ {
+ struct format_12_cmap *cmap12 = cmap;
+ guint32 i;
+
+ glyph = 0;
+ for (i = 0; i < cmap12->count; i++)
+ {
+ if (cmap12->groups[i*3+0] <= wc && wc <= cmap12->groups[i*3+1])
+ {
+ glyph = cmap12->groups[i*3+2] + (wc - cmap12->groups[i*3+0]);
+ break;
+ }
+ }
+ }
+ else
+ g_assert_not_reached ();
+
+ return glyph;
+}
+
+gboolean
+_pango_win32_get_name_header (HDC hdc,
+ struct name_header *header)
+{
+ if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header))
+ return FALSE;
+
+ header->num_records = GUINT16_FROM_BE (header->num_records);
+ header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset);
+
+ return TRUE;
+}
+
+gboolean
+_pango_win32_get_name_record (HDC hdc,
+ gint i,
+ struct name_record *record)
+{
+ if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
+ record, sizeof (*record)) != sizeof (*record))
+ return FALSE;
+
+ record->platform_id = GUINT16_FROM_BE (record->platform_id);
+ record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
+ record->language_id = GUINT16_FROM_BE (record->language_id);
+ record->name_id = GUINT16_FROM_BE (record->name_id);
+ record->string_length = GUINT16_FROM_BE (record->string_length);
+ record->string_offset = GUINT16_FROM_BE (record->string_offset);
+
+ return TRUE;
+}
+
+static gboolean
+font_has_name_in (PangoFont *font,
+ PangoWin32CoverageLanguageClass cjkv)
+{
+ HFONT hfont, oldhfont;
+ struct name_header header;
+ struct name_record record;
+ gint i;
+ gboolean retval = FALSE;
+
+ if (cjkv == PANGO_WIN32_COVERAGE_UNSPEC)
+ return TRUE;
+
+ hfont = pango_win32_get_hfont (font);
+ oldhfont = SelectObject (_pango_win32_hdc, hfont);
+
+ if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
+ {
+ SelectObject (_pango_win32_hdc, oldhfont);
+ return FALSE;
+ }
+
+ for (i = 0; i < header.num_records; i++)
+ {
+ if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
+ {
+ SelectObject (_pango_win32_hdc, oldhfont);
+ return FALSE;
+ }
+
+ if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
+ continue;
+
+ PING(("platform:%d encoding:%d language:%04x name_id:%d",
+ record.platform_id, record.encoding_id, record.language_id, record.name_id));
+
+ if (record.platform_id == MICROSOFT_PLATFORM_ID)
+ if ((cjkv == PANGO_WIN32_COVERAGE_ZH_TW &&
+ record.language_id == MAKELANGID (LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL))
+ ||
+ (cjkv == PANGO_WIN32_COVERAGE_ZH_CN &&
+ record.language_id == MAKELANGID (LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED))
+ ||
+ (cjkv == PANGO_WIN32_COVERAGE_JA &&
+ PRIMARYLANGID (record.language_id) == LANG_JAPANESE)
+ ||
+ (cjkv == PANGO_WIN32_COVERAGE_KO &&
+ PRIMARYLANGID (record.language_id) == LANG_KOREAN)
+ ||
+ (cjkv == PANGO_WIN32_COVERAGE_VI &&
+ PRIMARYLANGID (record.language_id) == LANG_VIETNAMESE))
+ {
+ PING (("yep:%d:%04x", cjkv, record.language_id));
+ retval = TRUE;
+ break;
+ }
+ }
+
+ SelectObject (_pango_win32_hdc, oldhfont);
+ return retval;
+}
+
+static void
+pango_win32_font_calc_coverage (PangoFont *font,
+ PangoCoverage *coverage,
+ PangoLanguage *lang)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ gpointer cmap;
+ guint32 ch;
+ guint32 i;
+ PangoWin32CoverageLanguageClass cjkv;
+ gboolean hide_unihan = FALSE;
+
+ PING(("font:%s lang:%s",
+ pango_font_description_to_string (pango_font_describe (font)),
+ pango_language_to_string (lang)));
+
+ cjkv = pango_win32_coverage_language_classify (lang);
+
+ if (cjkv != PANGO_WIN32_COVERAGE_UNSPEC && !font_has_name_in (font, cjkv))
+ {
+ PING(("hiding UniHan chars"));
+ hide_unihan = TRUE;
+ }
+
+ /* Do GetFontData magic on font->hfont here. */
+ cmap = font_get_cmap (font);
+ if (cmap == NULL)
+ {
+ PING(("no table"));
+ return;
+ }
+
+ PING (("coverage:"));
+ if (win32font->win32face->cmap_format == 4)
+ {
+ struct format_4_cmap *cmap4 = cmap;
+ guint16 *id_range_offset;
+ guint16 *start_count;
+ guint16 *end_count;
+ guint16 seg_count;
+ guint16 id;
+
+ seg_count = cmap4->seg_count_x_2/2;
+ end_count = get_end_count (cmap4);
+ start_count = get_start_count (cmap4);
+ id_range_offset = get_id_range_offset (cmap4);
+
+ for (i = 0; i < seg_count; i++)
+ {
+ if (id_range_offset[i] == 0)
+ {
+#ifdef PANGO_WIN32_DEBUGGING
+ if (_pango_win32_debug)
+ {
+ if (end_count[i] == start_count[i])
+ g_print ("%04x ", start_count[i]);
+ else
+ g_print ("%04x:%04x ", start_count[i], end_count[i]);
+ }
+#endif
+ for (ch = start_count[i]; ch <= end_count[i]; ch++)
+ if (hide_unihan && CH_IS_UNIHAN_BMP (ch))
+ pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
+ else
+ pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
+ }
+ else
+ {
+#ifdef PANGO_WIN32_DEBUGGING
+ guint32 ch0 = G_MAXUINT;
+#endif
+ for (ch = start_count[i]; ch <= end_count[i]; ch++)
+ {
+ if (ch == 0xFFFF)
+ break;
+
+ id = *(id_range_offset[i]/2 +
+ (ch - start_count[i]) +
+ &id_range_offset[i]);
+ if (id)
+ {
+#ifdef PANGO_WIN32_DEBUGGING
+ if (ch0 == G_MAXUINT)
+ ch0 = ch;
+#endif
+ if (hide_unihan && CH_IS_UNIHAN_BMP (ch))
+ pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
+ else
+ pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
+ }
+#ifdef PANGO_WIN32_DEBUGGING
+ else if (ch0 < G_MAXUINT)
+ {
+ if (_pango_win32_debug)
+ {
+ if (ch > ch0 + 2)
+ g_print ("%04x:%04x ", ch0, ch - 1);
+ else
+ g_print ("%04x ", ch0);
+ }
+ ch0 = G_MAXUINT;
+ }
+#endif
+ }
+#ifdef PANGO_WIN32_DEBUGGING
+ if (ch0 < G_MAXUINT)
+ {
+ if (_pango_win32_debug)
+ {
+ if (ch > ch0 + 2)
+ g_print ("%04x:%04x ", ch0, ch - 1);
+ else
+ g_print ("%04x ", ch0);
+ }
+ }
+#endif
+ }
+ }
+ }
+ else if (win32font->win32face->cmap_format == 12)
+ {
+ struct format_12_cmap *cmap12 = cmap;
+
+ for (i = 0; i < cmap12->count; i++)
+ {
+#ifdef PANGO_WIN32_DEBUGGING
+ if (_pango_win32_debug)
+ {
+ if (cmap12->groups[i*3+0] == cmap12->groups[i*3+1])
+ g_print ("%04x ", cmap12->groups[i*3+0]);
+ else
+ g_print ("%04x:%04x ", cmap12->groups[i*3+0], cmap12->groups[i*3+1]);
+ }
+#endif
+ for (ch = cmap12->groups[i*3+0]; ch <= cmap12->groups[i*3+1]; ch++)
+ {
+ if (hide_unihan && CH_IS_UNIHAN (ch))
+ pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
+ else
+ pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
+ }
+ }
+ }
+ else
+ g_assert_not_reached ();
+#ifdef PANGO_WIN32_DEBUGGING
+ if (_pango_win32_debug)
+ g_print ("\n");
+#endif
+}
diff --git a/trunk/pango/pangowin32.def b/trunk/pango/pangowin32.def
new file mode 100644
index 00000000..13b6e8b1
--- /dev/null
+++ b/trunk/pango/pangowin32.def
@@ -0,0 +1,29 @@
+EXPORTS
+ _pango_win32_fontmap_cache_remove
+ _pango_win32_make_matching_logfontw
+ _pango_win32_font_get_type
+ _pango_win32_font_map_get_type
+ pango_win32_font_cache_free
+ pango_win32_font_cache_load
+ pango_win32_font_cache_loadw
+ pango_win32_font_cache_new
+ pango_win32_font_cache_unload
+ pango_win32_font_description_from_logfont
+ pango_win32_font_description_from_logfontw
+ pango_win32_font_get_glyph_index
+ pango_win32_font_logfont
+ pango_win32_font_logfont
+ pango_win32_font_map_for_display
+ pango_win32_font_map_get_font_cache
+ pango_win32_get_context
+ pango_win32_get_dc
+ pango_win32_get_debug_flag
+ pango_win32_get_unknown_glyph
+ pango_win32_render
+ pango_win32_render_layout
+ pango_win32_render_layout_line
+ pango_win32_render_transformed
+ pango_win32_shutdown_display
+ pango_win32_font_done_font
+ pango_win32_font_get_metrics_factor
+ pango_win32_font_select_font
diff --git a/trunk/pango/pangowin32.h b/trunk/pango/pangowin32.h
new file mode 100644
index 00000000..8e07218e
--- /dev/null
+++ b/trunk/pango/pangowin32.h
@@ -0,0 +1,118 @@
+/* Pango
+ * pangowin32.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 Tor Lillqvist
+ * Copyright (C) 2001 Alexander Larsson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOWIN32_H__
+#define __PANGOWIN32_H__
+
+#include <glib.h>
+#include <pango/pango-font.h>
+#include <pango/pango-layout.h>
+
+G_BEGIN_DECLS
+
+#define STRICT
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501 /* To get ClearType-related macros */
+#endif
+#include <windows.h>
+#undef STRICT
+
+#define PANGO_RENDER_TYPE_WIN32 "PangoRenderWin32"
+
+/* Calls for applications
+ */
+PangoContext * pango_win32_get_context (void);
+
+void pango_win32_render (HDC hdc,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_win32_render_layout_line (HDC hdc,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_win32_render_layout (HDC hdc,
+ PangoLayout *layout,
+ int x,
+ int y);
+
+void pango_win32_render_transformed (HDC hdc,
+ const PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+
+#ifdef PANGO_ENABLE_ENGINE
+
+/* For shape engines
+ */
+
+#ifndef PANGO_DISABLE_DEPRECATED
+PangoGlyph pango_win32_get_unknown_glyph (PangoFont *font,
+ gunichar wc);
+#endif /* PANGO_DISABLE_DEPRECATED */
+gint pango_win32_font_get_glyph_index(PangoFont *font,
+ gunichar wc);
+
+HDC pango_win32_get_dc (void);
+
+gboolean pango_win32_get_debug_flag (void);
+
+gboolean pango_win32_font_select_font (PangoFont *font,
+ HDC hdc);
+void pango_win32_font_done_font (PangoFont *font);
+double pango_win32_font_get_metrics_factor (PangoFont *font);
+
+#endif
+
+/* API for libraries that want to use PangoWin32 mixed with classic
+ * Win32 fonts.
+ */
+typedef struct _PangoWin32FontCache PangoWin32FontCache;
+
+PangoWin32FontCache *pango_win32_font_cache_new (void);
+void pango_win32_font_cache_free (PangoWin32FontCache *cache);
+
+HFONT pango_win32_font_cache_load (PangoWin32FontCache *cache,
+ const LOGFONTA *logfont);
+HFONT pango_win32_font_cache_loadw (PangoWin32FontCache *cache,
+ const LOGFONTW *logfont);
+void pango_win32_font_cache_unload (PangoWin32FontCache *cache,
+ HFONT hfont);
+
+PangoFontMap *pango_win32_font_map_for_display (void);
+void pango_win32_shutdown_display (void);
+PangoWin32FontCache *pango_win32_font_map_get_font_cache (PangoFontMap *font_map);
+
+LOGFONTA *pango_win32_font_logfont (PangoFont *font);
+LOGFONTW *pango_win32_font_logfontw (PangoFont *font);
+
+PangoFontDescription *pango_win32_font_description_from_logfont (const LOGFONTA *lfp);
+
+PangoFontDescription *pango_win32_font_description_from_logfontw (const LOGFONTW *lfp);
+
+G_END_DECLS
+
+#endif /* __PANGOWIN32_H__ */
diff --git a/trunk/pango/pangowin32.rc.in b/trunk/pango/pangowin32.rc.in
new file mode 100644
index 00000000..f78465dc
--- /dev/null
+++ b/trunk/pango/pangowin32.rc.in
@@ -0,0 +1,30 @@
+#include <winver.h>
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @PANGO_VERSION_MAJOR@,@PANGO_VERSION_MINOR@,@PANGO_VERSION_MICRO@,0
+ PRODUCTVERSION @PANGO_VERSION_MAJOR@,@PANGO_VERSION_MINOR@,@PANGO_VERSION_MICRO@,0
+ FILEFLAGSMASK 0
+ FILEFLAGS 0
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Red Hat Software"
+ VALUE "FileDescription", "PangoWin32"
+ VALUE "FileVersion", "@PANGO_VERSION_MAJOR@.@PANGO_VERSION_MINOR@.@PANGO_VERSION_MICRO@.0"
+ VALUE "InternalName", "pangowin32-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@"
+ VALUE "LegalCopyright", "Copyright © 1999 Red Hat Software. Copyright © 2000 Tor Lillqvist"
+ VALUE "OriginalFilename", "pangowin32-@PANGO_API_VERSION@-@PANGO_CURRENT_MINUS_AGE@.dll"
+ VALUE "ProductName", "PangoWin32"
+ VALUE "ProductVersion", "@PANGO_VERSION_MAJOR@.@PANGO_VERSION_MINOR@.@PANGO_VERSION_MICRO@"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+ END
diff --git a/trunk/pango/pangox-fontcache.c b/trunk/pango/pangox-fontcache.c
new file mode 100644
index 00000000..ed556e74
--- /dev/null
+++ b/trunk/pango/pangox-fontcache.c
@@ -0,0 +1,248 @@
+/* Pango
+ * pango-fontcache.c: Cache of XFontStructs by XLFD
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "pangox.h"
+
+/* Font cache
+ */
+
+/* Number of fonts to retain after they are not otherwise referenced.
+ */
+#define CACHE_SIZE 16
+
+typedef struct _CacheEntry CacheEntry;
+
+struct _PangoXFontCache
+{
+ Display *display;
+
+ GHashTable *forward;
+ GHashTable *back;
+
+ GList *mru;
+ GList *mru_tail;
+ int mru_count;
+};
+
+struct _CacheEntry
+{
+ char *xlfd;
+ XFontStruct *fs;
+
+ gint ref_count;
+ GList *mru;
+};
+
+static void
+free_cache_entry (char *xlfd,
+ CacheEntry *entry,
+ PangoXFontCache *cache)
+{
+ g_free (entry->xlfd);
+ XFreeFont (cache->display, entry->fs);
+
+ g_free (entry);
+}
+
+/**
+ * pango_x_font_cache_free:
+ * @cache: a #PangoXFontCache
+ *
+ * Frees a #PangoXFontCache and all associated memory. All fonts loaded
+ * through this font cache will be freed along with the cache.
+ **/
+void
+pango_x_font_cache_free (PangoXFontCache *cache)
+{
+ g_return_if_fail (cache != NULL);
+
+ g_hash_table_foreach (cache->forward, (GHFunc)free_cache_entry, cache);
+
+ g_hash_table_destroy (cache->forward);
+ g_hash_table_destroy (cache->back);
+
+ g_list_free (cache->mru);
+}
+
+/**
+ * pango_x_font_cache_new:
+ * @display: an X display.
+ *
+ * Creates a font cache for the specified display.
+ *
+ * Return value: The newly allocated #PangoXFontCache, which should be
+ * freed with pango_x_font_cache_free().
+ **/
+PangoXFontCache *
+pango_x_font_cache_new (Display *display)
+{
+ PangoXFontCache *cache;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ cache = g_new (PangoXFontCache, 1);
+
+ cache->display = display;
+
+ cache->forward = g_hash_table_new (g_str_hash, g_str_equal);
+ cache->back = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ cache->mru = NULL;
+ cache->mru_tail = NULL;
+ cache->mru_count = 0;
+
+ return cache;
+}
+
+static void
+cache_entry_unref (PangoXFontCache *cache, CacheEntry *entry)
+{
+ entry->ref_count--;
+ if (entry->ref_count == 0)
+ {
+ g_hash_table_remove (cache->forward, entry->xlfd);
+ g_hash_table_remove (cache->back, entry->fs);
+
+ free_cache_entry (NULL, entry, cache);
+ }
+}
+
+/**
+ * pango_x_font_cache_load:
+ * @cache: a #PangoXFontCache
+ * @xlfd: the X Logical Font Description to load.
+ *
+ * Loads a #XFontStruct from a X Logical Font Description. The
+ * result may be newly loaded, or it may have been previously
+ * stored.
+ *
+ * Return value: The font structure, or %NULL if the font could
+ * not be loaded. In order to free this structure, you must call
+ * pango_x_font_cache_unload().
+ **/
+XFontStruct *
+pango_x_font_cache_load (PangoXFontCache *cache,
+ const char *xlfd)
+{
+ CacheEntry *entry;
+
+ g_return_val_if_fail (cache != NULL, NULL);
+ g_return_val_if_fail (xlfd != NULL, NULL);
+
+ entry = g_hash_table_lookup (cache->forward, xlfd);
+
+ if (entry)
+ {
+ entry->ref_count++;
+ }
+ else
+ {
+ XFontStruct *fs = XLoadQueryFont (cache->display, xlfd);
+
+ if (!fs)
+ return NULL;
+
+ entry = g_new (CacheEntry, 1);
+
+ entry->xlfd = g_strdup (xlfd);
+ entry->fs = fs;
+
+ entry->ref_count = 1;
+ entry->mru = NULL;
+
+ g_hash_table_insert (cache->forward, entry->xlfd, entry);
+ g_hash_table_insert (cache->back, entry->fs, entry);
+ }
+
+ if (entry->mru)
+ {
+ if (cache->mru_count > 1 && entry->mru->prev)
+ {
+ /* Move to the head of the mru list */
+
+ if (entry->mru == cache->mru_tail)
+ {
+ cache->mru_tail = cache->mru_tail->prev;
+ cache->mru_tail->next = NULL;
+ }
+ else
+ {
+ entry->mru->prev->next = entry->mru->next;
+ entry->mru->next->prev = entry->mru->prev;
+ }
+
+ entry->mru->next = cache->mru;
+ entry->mru->prev = NULL;
+ cache->mru->prev = entry->mru;
+ cache->mru = entry->mru;
+ }
+ }
+ else
+ {
+ entry->ref_count++;
+
+ /* Insert into the mru list */
+
+ if (cache->mru_count == CACHE_SIZE)
+ {
+ CacheEntry *old_entry = cache->mru_tail->data;
+
+ cache->mru_tail = cache->mru_tail->prev;
+ cache->mru_tail->next = NULL;
+
+ g_list_free_1 (old_entry->mru);
+ old_entry->mru = NULL;
+ cache_entry_unref (cache, old_entry);
+ }
+ else
+ cache->mru_count++;
+
+ cache->mru = g_list_prepend (cache->mru, entry);
+ if (!cache->mru_tail)
+ cache->mru_tail = cache->mru;
+ entry->mru = cache->mru;
+ }
+
+ return entry->fs;
+}
+
+/**
+ * pango_x_font_cache_unload:
+ * @cache: a #PangoXFontCache
+ * @fs: the font structure to unload
+ *
+ * Frees a font structure previously loaded with pango_x_font_cache_load().
+ **/
+void
+pango_x_font_cache_unload (PangoXFontCache *cache,
+ XFontStruct *fs)
+{
+ CacheEntry *entry;
+
+ g_return_if_fail (cache != NULL);
+ g_return_if_fail (fs != NULL);
+
+ entry = g_hash_table_lookup (cache->back, fs);
+ g_return_if_fail (entry != NULL);
+
+ cache_entry_unref (cache, entry);
+}
diff --git a/trunk/pango/pangox-fontmap.c b/trunk/pango/pangox-fontmap.c
new file mode 100644
index 00000000..3681b939
--- /dev/null
+++ b/trunk/pango/pangox-fontmap.c
@@ -0,0 +1,1675 @@
+/* Pango
+ * pangox-fontmap.c: X font handling
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+
+#include <X11/Xatom.h>
+
+/* For XExtSetCloseDisplay */
+#include <X11/Xlibint.h>
+
+#include "pango-engine-private.h"
+#include "pango-fontmap.h"
+#include "pango-impl-utils.h"
+
+#undef PANGO_DISABLE_DEPRECATED
+
+#include "pangox-private.h"
+
+typedef struct _PangoXFamily PangoXFamily;
+typedef struct _PangoXSizeInfo PangoXSizeInfo;
+
+/* Number of freed fonts */
+#define MAX_FREED_FONTS 16
+
+/* This is the largest field length we will accept. If a fontname has a field
+ larger than this we will skip it. */
+#define XLFD_MAX_FIELD_LEN 64
+#define MAX_FONTS 32767
+
+/* These are the field numbers in the X Logical Font Description fontnames,
+ e.g. -adobe-courier-bold-o-normal--25-180-100-100-m-150-iso8859-1 */
+typedef enum
+{
+ XLFD_FOUNDRY = 0,
+ XLFD_FAMILY = 1,
+ XLFD_WEIGHT = 2,
+ XLFD_SLANT = 3,
+ XLFD_SET_WIDTH = 4,
+ XLFD_ADD_STYLE = 5,
+ XLFD_PIXELS = 6,
+ XLFD_POINTS = 7,
+ XLFD_RESOLUTION_X = 8,
+ XLFD_RESOLUTION_Y = 9,
+ XLFD_SPACING = 10,
+ XLFD_AVERAGE_WIDTH = 11,
+ XLFD_CHARSET = 12,
+ XLFD_NUM_FIELDS
+} FontField;
+
+struct _PangoXFamily
+{
+ PangoFontFamily parent_instance;
+
+ char *family_name;
+ GSList *font_entries;
+};
+
+struct _PangoXFace
+{
+ PangoFontFace parent_instance;
+
+ char *xlfd;
+ PangoFontDescription *description;
+ PangoCoverage *coverage;
+
+ char *face_name;
+
+ GSList *cached_fonts;
+};
+
+struct _PangoXSizeInfo
+{
+ char *identifier;
+ GSList *xlfds;
+};
+
+static const struct {
+ const gchar text[12];
+ PangoWeight value;
+} weights_map[] = {
+ { "light", 300 },
+ { "regular", 400 },
+ { "book", 400 },
+ { "medium", 500 },
+ { "semibold", 600 },
+ { "demibold", 600 },
+ { "bold", 700 },
+ { "extrabold", 800 },
+ { "ultrabold", 800 },
+ { "heavy", 900 },
+ { "black", 900 }
+};
+
+static const struct {
+ const gchar text[4];
+ PangoStyle value;
+} styles_map[] = {
+ { "r", PANGO_STYLE_NORMAL },
+ { "i", PANGO_STYLE_ITALIC },
+ { "o", PANGO_STYLE_OBLIQUE }
+};
+
+static const struct {
+ const gchar text[16];
+ PangoStretch value;
+} stretches_map[] = {
+ { "normal", PANGO_STRETCH_NORMAL },
+ { "semicondensed", PANGO_STRETCH_SEMI_CONDENSED },
+ { "condensed", PANGO_STRETCH_CONDENSED },
+};
+
+static void pango_x_font_map_init (PangoXFontMap *fontmap);
+static void pango_x_font_map_class_init (PangoFontMapClass *class);
+
+static void pango_x_font_map_finalize (GObject *object);
+static PangoFont *pango_x_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description);
+static void pango_x_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families);
+
+static void pango_x_fontmap_cache_clear (PangoXFontMap *xfontmap);
+static void pango_x_font_map_read_aliases (PangoXFontMap *xfontmap);
+
+static gint pango_x_get_size (PangoXFontMap *fontmap,
+ const char *fontname);
+static void pango_x_insert_font (PangoXFontMap *fontmap,
+ const char *fontname);
+static gboolean pango_x_is_xlfd_font_name (const char *fontname);
+static char * pango_x_get_xlfd_field (const char *fontname,
+ FontField field_num,
+ char *buffer);
+static char * pango_x_get_identifier (const char *fontname);
+
+
+#define PANGO_X_TYPE_FAMILY (pango_x_family_get_type ())
+#define PANGO_X_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_X_TYPE_FAMILY, PangoXFamily))
+#define PANGO_X_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_X_TYPE_FAMILY))
+
+GType pango_x_family_get_type (void);
+
+
+#define PANGO_X_TYPE_FACE (pango_x_face_get_type ())
+#define PANGO_X_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_X_TYPE_FACE, PangoXFace))
+#define PANGO_X_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_X_TYPE_FACE))
+
+GType pango_x_face_get_type (void);
+
+
+static PangoFontClass *font_map_parent_class; /* Parent class structure for PangoXFontMap */
+
+GType
+pango_x_font_map_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoFontMapClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_x_font_map_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoXFontMap),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_x_font_map_init,
+ NULL /* value_table */
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_MAP,
+ I_("PangoXFontMap"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+pango_x_font_map_init (PangoXFontMap *xfontmap)
+{
+ xfontmap->families = g_hash_table_new (g_str_hash, g_str_equal);
+ xfontmap->size_infos = g_hash_table_new (g_str_hash, g_str_equal);
+ xfontmap->to_atom_cache = g_hash_table_new (g_str_hash, g_str_equal);
+ xfontmap->from_atom_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ xfontmap->n_fonts = 0;
+}
+
+static void
+pango_x_font_map_class_init (PangoFontMapClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ font_map_parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_x_font_map_finalize;
+ class->load_font = pango_x_font_map_load_font;
+ class->list_families = pango_x_font_map_list_families;
+ class->shape_engine_type = PANGO_RENDER_TYPE_X;
+}
+
+/*
+ * Hackery to set up notification when a Display is closed
+ */
+static GSList *registered_displays;
+
+static int
+close_display_cb (Display *display,
+ XExtCodes *extcodes)
+{
+ pango_x_shutdown_display (display);
+ registered_displays = g_slist_remove (registered_displays, display);
+
+ return 0;
+}
+
+static void
+register_display (Display *display)
+{
+ XExtCodes *extcodes;
+ GSList *tmp_list;
+
+ for (tmp_list = registered_displays; tmp_list; tmp_list = tmp_list->next)
+ {
+ if (tmp_list->data == display)
+ return;
+ }
+
+ registered_displays = g_slist_prepend (registered_displays, display);
+
+ extcodes = XAddExtension (display);
+ XESetCloseDisplay (display, extcodes->extension, close_display_cb);
+}
+
+static GList *fontmaps = NULL;
+
+/**
+ * pango_x_font_map_for_display:
+ * @display: an X #Display.
+ *
+ * Returns a #PangoXFontMap for @display. Font maps are cached and should
+ * not be freed. If the font map for a display is no longer needed, it can
+ * be released with pango_x_shutdown_display().
+ *
+ * Return value: a #PangoXFontMap for @display.
+ **/
+PangoFontMap *
+pango_x_font_map_for_display (Display *display)
+{
+ PangoXFontMap *xfontmap;
+ GList *tmp_list = fontmaps;
+ char **xfontnames;
+ int num_fonts, i;
+ int screen;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ /* Make sure that the type system is initialized */
+ g_type_init ();
+
+ while (tmp_list)
+ {
+ xfontmap = tmp_list->data;
+
+ if (xfontmap->display == display)
+ return PANGO_FONT_MAP (xfontmap);
+
+ tmp_list = tmp_list->next;
+ }
+
+ xfontmap = g_object_new (PANGO_TYPE_X_FONT_MAP, NULL);
+
+ xfontmap->display = display;
+ xfontmap->font_cache = pango_x_font_cache_new (display);
+ xfontmap->freed_fonts = g_queue_new ();
+
+ /* Get a maximum of MAX_FONTS fontnames from the X server.
+ Use "-*" as the pattern rather than "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" since
+ the latter may result in fonts being returned which don't actually exist.
+ xlsfonts also uses "*" so I think it's OK. "-*" gets rid of aliases. */
+ xfontnames = XListFonts (xfontmap->display, "-*", MAX_FONTS, &num_fonts);
+ if (num_fonts == MAX_FONTS)
+ g_warning("MAX_FONTS exceeded. Some fonts may be missing.");
+
+ /* Insert the font families into the main table */
+ for (i = 0; i < num_fonts; i++)
+ {
+ if (pango_x_is_xlfd_font_name (xfontnames[i]))
+ pango_x_insert_font (xfontmap, xfontnames[i]);
+ }
+
+ XFreeFontNames (xfontnames);
+
+ pango_x_font_map_read_aliases (xfontmap);
+
+ fontmaps = g_list_prepend (fontmaps, xfontmap);
+
+ /* This is a little screwed up, since different screens on the same display
+ * might have different resolutions
+ */
+ screen = DefaultScreen (xfontmap->display);
+ xfontmap->resolution = (PANGO_SCALE * 72.27 / 25.4) * ((double) DisplayWidthMM (xfontmap->display, screen) /
+ DisplayWidth (xfontmap->display, screen));
+
+ register_display (xfontmap->display);
+
+ return PANGO_FONT_MAP (xfontmap);
+}
+
+/**
+ * pango_x_shutdown_display:
+ * @display: an X #Display
+ *
+ * Free cached resources for the given X display structure.
+ **/
+void
+pango_x_shutdown_display (Display *display)
+{
+ GList *tmp_list;
+
+ g_return_if_fail (display != NULL);
+
+ tmp_list = fontmaps;
+ while (tmp_list)
+ {
+ PangoXFontMap *xfontmap = tmp_list->data;
+
+ if (xfontmap->display == display)
+ {
+ fontmaps = g_list_delete_link (fontmaps, tmp_list);
+ pango_x_fontmap_cache_clear (xfontmap);
+ g_object_unref (xfontmap);
+
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+static void
+pango_x_font_map_finalize (GObject *object)
+{
+ PangoXFontMap *xfontmap = PANGO_X_FONT_MAP (object);
+
+ g_list_foreach (xfontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_queue_free (xfontmap->freed_fonts);
+
+ pango_x_font_cache_free (xfontmap->font_cache);
+
+ /* FIXME: Lots more here */
+
+ fontmaps = g_list_remove (fontmaps, xfontmap);
+
+ G_OBJECT_CLASS (font_map_parent_class)->finalize (object);
+}
+
+static void
+list_families_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GSList **list = user_data;
+
+ *list = g_slist_prepend (*list, value);
+}
+
+static void
+pango_x_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families)
+{
+ GSList *family_list = NULL;
+ GSList *tmp_list;
+ PangoXFontMap *xfontmap = (PangoXFontMap *)fontmap;
+
+ if (!n_families)
+ return;
+
+ g_hash_table_foreach (xfontmap->families, list_families_foreach, &family_list);
+
+ *n_families = g_slist_length (family_list);
+
+ if (families)
+ {
+ int i = 0;
+
+ *families = g_new (PangoFontFamily *, *n_families);
+
+ tmp_list = family_list;
+ while (tmp_list)
+ {
+ (*families)[i] = tmp_list->data;
+ i++;
+ tmp_list = tmp_list->next;
+ }
+ }
+
+ g_slist_free (family_list);
+}
+
+static PangoXFamily *
+pango_x_get_font_family (PangoXFontMap *xfontmap,
+ const char *family_name)
+{
+ PangoXFamily *font_family = g_hash_table_lookup (xfontmap->families, family_name);
+ if (!font_family)
+ {
+ font_family = g_object_new (PANGO_X_TYPE_FAMILY, NULL);
+ font_family->family_name = g_strdup (family_name);
+ font_family->font_entries = NULL;
+
+ g_hash_table_insert (xfontmap->families, font_family->family_name, font_family);
+ }
+
+ return font_family;
+}
+
+static PangoFont *
+pango_x_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description)
+{
+ PangoXFontMap *xfontmap = (PangoXFontMap *)fontmap;
+ PangoXFamily *font_family;
+ PangoFont *result = NULL;
+ GSList *tmp_list;
+ gchar *name;
+ gint size;
+
+ g_return_val_if_fail (description != NULL, NULL);
+
+ name = g_ascii_strdown (pango_font_description_get_family (description), -1);
+ size = pango_font_description_get_size (description);
+
+ if (size < 0)
+ return NULL;
+
+ font_family = g_hash_table_lookup (xfontmap->families, name);
+ if (font_family)
+ {
+ PangoXFace *best_match = NULL;
+
+ tmp_list = font_family->font_entries;
+ while (tmp_list)
+ {
+ PangoXFace *font_entry = tmp_list->data;
+
+ if (pango_font_description_better_match (description,
+ best_match ? best_match->description : NULL,
+ font_entry->description))
+ best_match = font_entry;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (best_match)
+ {
+ GSList *tmp_list = best_match->cached_fonts;
+
+ while (tmp_list)
+ {
+ PangoXFont *xfont = tmp_list->data;
+ if (xfont->size == size)
+ {
+ result = (PangoFont *)xfont;
+
+ g_object_ref (result);
+ if (xfont->in_cache)
+ pango_x_fontmap_cache_remove (fontmap, xfont);
+
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ if (!result)
+ {
+ PangoXFont *xfont = pango_x_font_new (fontmap, best_match->xlfd, size);
+
+ xfont->fontmap = fontmap;
+ xfont->xface = best_match;
+ best_match->cached_fonts = g_slist_prepend (best_match->cached_fonts, xfont);
+
+ result = (PangoFont *)xfont;
+ }
+ }
+ }
+
+ g_free (name);
+ return result;
+}
+
+
+/************************
+ * Coverage Map Caching *
+ ************************/
+
+/* We need to be robust against errors accessing the coverage
+ * cache window, since it is not our window. So we temporarily
+ * set this error handler while accessing it. The error_occurred
+ * global allows us to tell whether an error occurred for
+ * XChangeProperty
+ */
+static gboolean error_occurred;
+
+static int
+ignore_error (Display *d,
+ XErrorEvent *e)
+{
+ return 0;
+}
+
+/* Retrieve the coverage window for the given display.
+ * We look for a property on the root window, and then
+ * check that the window that property points to also
+ * has the same property pointing to itself. The second
+ * check allows us to make sure that a stale property
+ * isn't just pointing to some other apps window
+ */
+static Window
+pango_x_real_get_coverage_win (Display *display)
+{
+ Atom type;
+ int format;
+ gulong n_items;
+ gulong bytes_after;
+ guchar *data;
+ Window retval = None;
+ int (*old_handler) (Display *, XErrorEvent *);
+
+ Atom coverage_win_atom = XInternAtom (display,
+ "PANGO_COVERAGE_WIN",
+ False);
+
+ XGetWindowProperty (display,
+ DefaultRootWindow (display),
+ coverage_win_atom,
+ 0, 4,
+ False, XA_WINDOW,
+ &type, &format, &n_items, &bytes_after,
+ &data);
+
+ if (type == XA_WINDOW)
+ {
+ if (format == 32 && n_items == 1 && bytes_after == 0)
+ retval = *(Atom *)data;
+
+ XFree (data);
+ }
+
+ old_handler= XSetErrorHandler (ignore_error);
+
+ if (XGetWindowProperty (display,
+ retval,
+ coverage_win_atom,
+ 0, 4,
+ False, XA_WINDOW,
+ &type, &format, &n_items, &bytes_after,
+ &data) == Success &&
+ type == XA_WINDOW)
+ {
+ if (format != 32 || n_items != 1 || bytes_after != 0 ||
+ *(Atom *)data != retval)
+ retval = None;
+
+ XFree (data);
+ }
+ else
+ retval = None;
+
+ XSync (display, False);
+ XSetErrorHandler (old_handler);
+
+ return retval;
+}
+
+/* Find or create the persistent window for caching font coverage
+ * information.
+ *
+ * To assure atomic creation, we first look for the window, then if we
+ * don't find it, grab the server, look for it again, and then if that
+ * still didn't find it, create it and ungrab.
+ */
+static Window
+pango_x_get_coverage_win (PangoXFontMap *xfontmap)
+{
+ if (!xfontmap->coverage_win)
+ xfontmap->coverage_win = pango_x_real_get_coverage_win (xfontmap->display);
+
+ if (!xfontmap->coverage_win)
+ {
+ Display *persistant_display;
+
+ persistant_display = XOpenDisplay (DisplayString (xfontmap->display));
+ if (!persistant_display)
+ {
+ g_warning ("Cannot create or retrieve display for font coverage cache");
+ return None;
+ }
+
+ XGrabServer (persistant_display);
+
+ xfontmap->coverage_win = pango_x_real_get_coverage_win (xfontmap->display);
+ if (!xfontmap->coverage_win)
+ {
+ XSetWindowAttributes attr;
+
+ attr.override_redirect = True;
+
+ XSetCloseDownMode (persistant_display, RetainPermanent);
+
+ xfontmap->coverage_win =
+ XCreateWindow (persistant_display,
+ DefaultRootWindow (persistant_display),
+ -100, -100, 10, 10, 0, 0,
+ InputOnly, CopyFromParent,
+ CWOverrideRedirect, &attr);
+
+ XChangeProperty (persistant_display,
+ DefaultRootWindow (persistant_display),
+ XInternAtom (persistant_display,
+ "PANGO_COVERAGE_WIN",
+ FALSE),
+ XA_WINDOW,
+ 32, PropModeReplace,
+ (guchar *)&xfontmap->coverage_win, 1);
+
+
+ XChangeProperty (persistant_display,
+ xfontmap->coverage_win,
+ XInternAtom (persistant_display,
+ "PANGO_COVERAGE_WIN",
+ FALSE),
+ XA_WINDOW,
+ 32, PropModeReplace,
+ (guchar *)&xfontmap->coverage_win, 1);
+ }
+
+ XUngrabServer (persistant_display);
+
+ XSync (persistant_display, False);
+ XCloseDisplay (persistant_display);
+ }
+
+ return xfontmap->coverage_win;
+}
+
+/* Find the cached value for the coverage map on the
+ * coverage cache window, if it exists. *atom is set
+ * to the interned value of str for later use in storing
+ * the property if the lookup fails
+ */
+static PangoCoverage *
+pango_x_get_cached_coverage (PangoXFontMap *xfontmap,
+ const char *str,
+ Atom *atom)
+{
+ int (*old_handler) (Display *, XErrorEvent *);
+ Window coverage_win;
+ PangoCoverage *result = NULL;
+
+ Atom type;
+ int format;
+ int tries = 5;
+ gulong n_items;
+ gulong bytes_after;
+ guchar *data;
+
+ *atom = XInternAtom (xfontmap->display, str, False);
+
+ while (tries--)
+ {
+ coverage_win = pango_x_get_coverage_win (xfontmap);
+
+ if (!coverage_win)
+ return NULL;
+
+ old_handler= XSetErrorHandler (ignore_error);
+
+ if (XGetWindowProperty (xfontmap->display,
+ coverage_win, *atom,
+ 0, G_MAXLONG,
+ False, XA_STRING,
+ &type, &format, &n_items, &bytes_after,
+ &data) == Success
+ && type == XA_STRING)
+ {
+ if (format == 8 && bytes_after == 0)
+ result = pango_coverage_from_bytes (data, n_items);
+
+ XSetErrorHandler (old_handler);
+ XFree (data);
+ break;
+ }
+ else
+ {
+ /* Window disappeared out from under us */
+ XSetErrorHandler (old_handler);
+ xfontmap->coverage_win = None;
+ }
+
+ }
+
+ return result;
+}
+
+/* Store the given coverage map on the coverage cache window.
+ * atom is the intern'ed value of the string that identifies
+ * the cache entry.
+ */
+static void
+pango_x_store_cached_coverage (PangoXFontMap *xfontmap,
+ Atom atom,
+ PangoCoverage *coverage)
+{
+ int (*old_handler) (Display *, XErrorEvent *);
+ guchar *bytes;
+ gint size;
+
+ int tries = 5;
+
+ pango_coverage_to_bytes (coverage, &bytes, &size);
+
+ while (tries--)
+ {
+ Window coverage_win = pango_x_get_coverage_win (xfontmap);
+
+ if (!coverage_win)
+ break;
+
+ old_handler = XSetErrorHandler (ignore_error);
+ error_occurred = False;
+
+ XChangeProperty (xfontmap->display,
+ coverage_win,
+ atom,
+ XA_STRING,
+ 8, PropModeReplace,
+ bytes, size);
+
+ XSync (xfontmap->display, False);
+ XSetErrorHandler (old_handler);
+
+ if (!error_occurred)
+ break;
+ else
+ {
+ /* Window disappeared out from under us */
+ XSetErrorHandler (old_handler);
+ xfontmap->coverage_win = None;
+ }
+ }
+
+ g_free (bytes);
+}
+
+
+static void
+pango_x_font_map_read_alias_file (PangoXFontMap *xfontmap,
+ const char *filename)
+{
+ FILE *infile;
+ char **xlfds;
+ int lineno = 0;
+ int i;
+ PangoXFace *xface = NULL;
+
+ infile = fopen (filename, "r");
+ if (infile)
+ {
+ GString *line_buf = g_string_new (NULL);
+ GString *tmp_buf = g_string_new (NULL);
+ gint lines_read;
+
+ while ((lines_read = pango_read_line (infile, line_buf)))
+ {
+ PangoXFamily *font_family;
+ PangoStyle style;
+ PangoVariant variant;
+ PangoWeight weight;
+ PangoStretch stretch;
+
+ const char *p = line_buf->str;
+
+ lineno += lines_read;
+
+ if (!pango_skip_space (&p))
+ continue;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ xface = g_object_new (PANGO_X_TYPE_FACE, NULL);
+ xface->xlfd = NULL;
+ xface->description = pango_font_description_new ();
+
+ g_string_ascii_down (tmp_buf);
+ pango_font_description_set_family (xface->description, tmp_buf->str);
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!pango_parse_style (tmp_buf->str, &style, TRUE))
+ goto error;
+ pango_font_description_set_style (xface->description, style);
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!pango_parse_variant (tmp_buf->str, &variant, TRUE))
+ goto error;
+ pango_font_description_set_variant (xface->description, variant);
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!pango_parse_weight (tmp_buf->str, &weight, TRUE))
+ goto error;
+ pango_font_description_set_weight (xface->description, weight);
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!pango_parse_stretch (tmp_buf->str, &stretch, TRUE))
+ goto error;
+ pango_font_description_set_stretch (xface->description, stretch);
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ /* Remove excess whitespace and check for complete fields */
+
+ xlfds = g_strsplit (tmp_buf->str, ",", -1);
+ for (i=0; xlfds[i]; i++)
+ {
+ char *trimmed = pango_trim_string (xlfds[i]);
+ g_free (xlfds[i]);
+ xlfds[i] = trimmed;
+
+ if (!pango_x_is_xlfd_font_name (xlfds[i]))
+ {
+ g_warning ("XLFD '%s' must be complete (14 fields)", xlfds[i]);
+ g_strfreev (xlfds);
+ goto error;
+ }
+ }
+
+ xface->xlfd = g_strjoinv (",", xlfds);
+ g_strfreev (xlfds);
+
+ /* Insert the font entry into our structures */
+
+ font_family = pango_x_get_font_family (xfontmap,
+ pango_font_description_get_family (xface->description));
+ font_family->font_entries = g_slist_prepend (font_family->font_entries, xface);
+ xfontmap->n_fonts++;
+
+ /* Save space by consolidating duplicated string */
+ pango_font_description_set_family_static (xface->description, font_family->family_name);
+ xface->cached_fonts = NULL;
+ xface->coverage = NULL;
+ }
+
+ if (ferror (infile))
+ g_warning ("Error reading '%s': %s", filename, g_strerror(errno));
+
+ goto out;
+
+ error:
+ if (xface)
+ {
+ g_free (xface->xlfd);
+ if (xface->description)
+ pango_font_description_free (xface->description);
+ g_free (xface);
+ }
+
+ g_warning ("Error parsing line %d of alias file '%s'", lineno, filename);
+
+ out:
+ g_string_free (tmp_buf, TRUE);
+ g_string_free (line_buf, TRUE);
+
+ fclose (infile);
+ }
+
+}
+
+static void
+pango_x_font_map_read_aliases (PangoXFontMap *xfontmap)
+{
+ char **files;
+ char *files_str = pango_config_key_get ("PangoX/AliasFiles");
+ int n;
+
+ if (!files_str)
+ files_str = g_strdup ("~/.pangox_aliases:" SYSCONFDIR "/pango/pangox.aliases");
+
+ files = pango_split_file_list (files_str);
+
+ n = 0;
+ while (files[n])
+ n++;
+
+ while (n-- > 0)
+ pango_x_font_map_read_alias_file (xfontmap, files[n]);
+
+ g_strfreev (files);
+ g_free (files_str);
+}
+
+/*
+ * Returns %TRUE if the fontname is a valid XLFD.
+ * (It just checks if the number of dashes is 14, and that each
+ * field < XLFD_MAX_FIELD_LEN characters long - that's not in the XLFD but it
+ * makes it easier for me).
+ */
+static gboolean
+pango_x_is_xlfd_font_name (const char *fontname)
+{
+ int i = 0;
+ int field_len = 0;
+
+ while (*fontname)
+ {
+ if (*fontname++ == '-')
+ {
+ if (field_len > XLFD_MAX_FIELD_LEN) return FALSE;
+ field_len = 0;
+ i++;
+ }
+ else
+ field_len++;
+ }
+
+ return (i == 14) ? TRUE : FALSE;
+}
+
+static int
+pango_x_get_size (PangoXFontMap *xfontmap, const char *fontname)
+{
+ char size_buffer[XLFD_MAX_FIELD_LEN];
+ int size;
+
+ if (!pango_x_get_xlfd_field (fontname, XLFD_PIXELS, size_buffer))
+ return -1;
+
+ size = atoi (size_buffer);
+ if (size != 0)
+ {
+ return (int)(0.5 + size * xfontmap->resolution);
+ }
+ else
+ {
+ /* We use the trick that scaled bitmaps have a non-zero RESOLUTION_X, while
+ * actual scaleable fonts have a zero RESOLUTION_X */
+ if (!pango_x_get_xlfd_field (fontname, XLFD_RESOLUTION_X, size_buffer))
+ return -1;
+
+ if (atoi (size_buffer) == 0)
+ return 0;
+ else
+ return -1;
+ }
+}
+
+static char *
+pango_x_get_identifier (const char *fontname)
+{
+ const char *p = fontname;
+ const char *start;
+ int n_dashes = 0;
+
+ while (n_dashes < 2)
+ {
+ if (*p == '-')
+ n_dashes++;
+ p++;
+ }
+
+ start = p;
+
+ while (n_dashes < 6)
+ {
+ if (*p == '-')
+ n_dashes++;
+ p++;
+ }
+
+ return g_strndup (start, (p - 1 - start));
+}
+
+/*
+ * This fills the buffer with the specified field from the X Logical Font
+ * Description name, and returns it. If fontname is %NULL or the field is
+ * longer than XFLD_MAX_FIELD_LEN it returns %NULL.
+ * Note: For the charset field, we also return the encoding, e.g. 'iso8859-1'.
+ */
+static char*
+pango_x_get_xlfd_field (const char *fontname,
+ FontField field_num,
+ char *buffer)
+{
+ const char *t1, *t2;
+ char *p;
+ int countdown, len, num_dashes;
+
+ if (!fontname)
+ return NULL;
+
+ /* we assume this is a valid fontname...that is, it has 14 fields */
+
+ countdown = field_num;
+ t1 = fontname;
+ while (*t1 && (countdown >= 0))
+ if (*t1++ == '-')
+ countdown--;
+
+ num_dashes = (field_num == XLFD_CHARSET) ? 2 : 1;
+ for (t2 = t1; *t2; t2++)
+ {
+ if (*t2 == '-' && --num_dashes == 0)
+ break;
+ }
+
+ if (t1 != t2)
+ {
+ /* Check we don't overflow the buffer */
+ len = (long) t2 - (long) t1;
+ if (len > XLFD_MAX_FIELD_LEN - 1)
+ return NULL;
+ strncpy (buffer, t1, len);
+ buffer[len] = 0;
+ /* Convert to lower case. */
+ for (p = buffer; *p; p++)
+ *p = g_ascii_tolower (*p);
+ }
+ else
+ strcpy(buffer, "(nil)");
+
+ return buffer;
+}
+
+/* This inserts the given fontname into the FontInfo table.
+ If a FontInfo already exists with the same family and foundry, then the
+ fontname is added to the FontInfos list of fontnames, else a new FontInfo
+ is created and inserted in alphabetical order in the table. */
+static void
+pango_x_insert_font (PangoXFontMap *xfontmap,
+ const char *fontname)
+{
+ PangoFontDescription *description;
+ char *family_name;
+ PangoStyle style;
+ PangoVariant variant;
+ PangoWeight weight;
+ PangoStretch stretch;
+ char family_buffer[XLFD_MAX_FIELD_LEN];
+ char weight_buffer[XLFD_MAX_FIELD_LEN];
+ char slant_buffer[XLFD_MAX_FIELD_LEN];
+ char set_width_buffer[XLFD_MAX_FIELD_LEN];
+ GSList *tmp_list;
+ PangoXFamily *font_family;
+ PangoXFace *xface;
+ PangoXSizeInfo *size_info;
+ char *identifier;
+ unsigned int i;
+
+ /* First insert the XLFD into the list of XLFDs for the "identifier" - which
+ * is the 2-4th fields of the XLFD
+ */
+ identifier = pango_x_get_identifier (fontname);
+ size_info = g_hash_table_lookup (xfontmap->size_infos, identifier);
+ if (!size_info)
+ {
+ size_info = g_new (PangoXSizeInfo, 1);
+ size_info->identifier = identifier;
+ size_info->xlfds = NULL;
+
+ g_hash_table_insert (xfontmap->size_infos, identifier, size_info);
+ }
+ else
+ g_free (identifier);
+
+ size_info->xlfds = g_slist_prepend (size_info->xlfds, g_strdup (fontname));
+
+ /* Convert the XLFD into a PangoFontDescription */
+
+ family_name = pango_x_get_xlfd_field (fontname, XLFD_FAMILY, family_buffer);
+ if (!family_name)
+ return;
+
+ style = PANGO_STYLE_NORMAL;
+ if (pango_x_get_xlfd_field (fontname, XLFD_SLANT, slant_buffer))
+ {
+ for (i=0; i<G_N_ELEMENTS(styles_map); i++)
+ {
+ if (!strcmp (styles_map[i].text, slant_buffer))
+ {
+ style = styles_map[i].value;
+ break;
+ }
+ }
+ }
+ else
+ strcpy (slant_buffer, "*");
+
+ variant = PANGO_VARIANT_NORMAL;
+
+ weight = PANGO_WEIGHT_NORMAL;
+ if (pango_x_get_xlfd_field (fontname, XLFD_WEIGHT, weight_buffer))
+ {
+ for (i=0; i<G_N_ELEMENTS(weights_map); i++)
+ {
+ if (!strcmp (weights_map[i].text, weight_buffer))
+ {
+ weight = weights_map[i].value;
+ break;
+ }
+ }
+ }
+ else
+ strcpy (weight_buffer, "*");
+
+ stretch = PANGO_STRETCH_NORMAL;
+ if (pango_x_get_xlfd_field (fontname, XLFD_SET_WIDTH, set_width_buffer))
+ {
+ for (i=0; i<G_N_ELEMENTS(stretches_map); i++)
+ {
+ if (!strcmp (stretches_map[i].text, set_width_buffer))
+ {
+ stretch = stretches_map[i].value;
+ break;
+ }
+ }
+ }
+ else
+ strcpy (set_width_buffer, "*");
+
+ font_family = pango_x_get_font_family (xfontmap, family_name);
+
+ tmp_list = font_family->font_entries;
+ while (tmp_list)
+ {
+ xface = tmp_list->data;
+
+ if (pango_font_description_get_style (xface->description) == style &&
+ pango_font_description_get_weight (xface->description) == weight &&
+ pango_font_description_get_stretch (xface->description) == stretch &&
+ pango_font_description_get_variant (xface->description) == variant)
+ return;
+
+ tmp_list = tmp_list->next;
+ }
+
+ description = pango_font_description_new ();
+ pango_font_description_set_family_static (description, font_family->family_name);
+ pango_font_description_set_style (description, style);
+ pango_font_description_set_weight (description, weight);
+ pango_font_description_set_stretch (description, stretch);
+ pango_font_description_set_variant (description, variant);
+
+ xface = g_object_new (PANGO_X_TYPE_FACE, NULL);
+ xface->description = description;
+ xface->cached_fonts = NULL;
+ xface->coverage = NULL;
+
+ xface->xlfd = g_strconcat ("-*-",
+ family_buffer,
+ "-",
+ weight_buffer,
+ "-",
+ slant_buffer,
+ "-",
+ set_width_buffer,
+ "--*-*-*-*-*-*-*-*",
+ NULL);
+
+ font_family->font_entries = g_slist_append (font_family->font_entries, xface);
+ xfontmap->n_fonts++;
+}
+
+/* Compare the tail of a to b */
+static gboolean
+match_end (const char *a, const char *b)
+{
+ size_t len_a = strlen (a);
+ size_t len_b = strlen (b);
+
+ if (len_b > len_a)
+ return FALSE;
+ else
+ return (strcmp (a + len_a - len_b, b) == 0);
+}
+
+/* Given a XLFD, charset and size, find the best matching installed X font.
+ * The XLFD must be a full XLFD (14 fields)
+ */
+char *
+pango_x_make_matching_xlfd (PangoFontMap *fontmap, char *xlfd, const char *charset, int size)
+{
+ PangoXFontMap *xfontmap;
+
+ GSList *tmp_list;
+ PangoXSizeInfo *size_info;
+ char *identifier;
+ char *closest_match = NULL;
+ gint match_distance = 0;
+ gboolean match_scaleable = FALSE;
+ char *result = NULL;
+
+ char *dash_charset;
+
+ xfontmap = PANGO_X_FONT_MAP (fontmap);
+
+ dash_charset = g_strconcat ("-", charset, NULL);
+
+ if (!match_end (xlfd, "-*-*") && !match_end (xlfd, dash_charset))
+ {
+ g_free (dash_charset);
+ return NULL;
+ }
+
+ identifier = pango_x_get_identifier (xlfd);
+ size_info = g_hash_table_lookup (xfontmap->size_infos, identifier);
+ g_free (identifier);
+
+ if (!size_info)
+ {
+ g_free (dash_charset);
+ return NULL;
+ }
+
+ tmp_list = size_info->xlfds;
+ while (tmp_list)
+ {
+ char *tmp_xlfd = tmp_list->data;
+
+ if (match_end (tmp_xlfd, dash_charset))
+ {
+ int font_size = pango_x_get_size (xfontmap, tmp_xlfd);
+
+ if (size != -1)
+ {
+ int new_distance = (font_size == 0) ? 0 : abs (font_size - size);
+
+ if (!closest_match ||
+ new_distance < match_distance ||
+ (new_distance < PANGO_SCALE && match_scaleable && font_size != 0))
+ {
+ closest_match = tmp_xlfd;
+ match_scaleable = (font_size == 0);
+ match_distance = new_distance;
+ }
+ }
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (closest_match)
+ {
+ if (match_scaleable)
+ {
+ char *prefix_end, *p;
+ int n_dashes = 0;
+ int target_size;
+ char *prefix;
+
+ /* OK, we have a match; let's modify it to fit this size and charset */
+
+ p = closest_match;
+ while (n_dashes < 6)
+ {
+ if (*p == '-')
+ n_dashes++;
+ p++;
+ }
+
+ prefix_end = p - 1;
+
+ while (n_dashes < 9)
+ {
+ if (*p == '-')
+ n_dashes++;
+ p++;
+ }
+
+ target_size = (int)((double)size / xfontmap->resolution + 0.5);
+ prefix = g_strndup (closest_match, prefix_end - closest_match);
+ result = g_strdup_printf ("%s--%d-*-*-*-*-*-%s", prefix, target_size, charset);
+ g_free (prefix);
+ }
+ else
+ {
+ result = g_strdup (closest_match);
+ }
+ }
+
+ g_free (dash_charset);
+
+ return result;
+}
+
+/**
+ * pango_x_font_map_get_font_cache:
+ * @font_map: a #PangoXFontMap.
+ *
+ * Obtains the font cache associated with the given font map.
+ *
+ * Return value: the #PangoXFontCache of @font_map.
+ **/
+PangoXFontCache *
+pango_x_font_map_get_font_cache (PangoFontMap *font_map)
+{
+ g_return_val_if_fail (font_map != NULL, NULL);
+ g_return_val_if_fail (PANGO_X_IS_FONT_MAP (font_map), NULL);
+
+ return PANGO_X_FONT_MAP (font_map)->font_cache;
+}
+
+Display *
+pango_x_fontmap_get_display (PangoFontMap *fontmap)
+{
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (PANGO_X_IS_FONT_MAP (fontmap), NULL);
+
+ return PANGO_X_FONT_MAP (fontmap)->display;
+}
+
+void
+pango_x_fontmap_cache_add (PangoFontMap *fontmap,
+ PangoXFont *xfont)
+{
+ PangoXFontMap *xfontmap = PANGO_X_FONT_MAP (fontmap);
+
+ if (xfontmap->freed_fonts->length == MAX_FREED_FONTS)
+ {
+ PangoXFont *old_font = g_queue_pop_tail (xfontmap->freed_fonts);
+ g_object_unref (old_font);
+ }
+
+ g_object_ref (xfont);
+ g_queue_push_head (xfontmap->freed_fonts, xfont);
+ xfont->in_cache = TRUE;
+}
+
+void
+pango_x_fontmap_cache_remove (PangoFontMap *fontmap,
+ PangoXFont *xfont)
+{
+ PangoXFontMap *xfontmap = PANGO_X_FONT_MAP (fontmap);
+
+ GList *link = g_list_find (xfontmap->freed_fonts->head, xfont);
+ if (link == xfontmap->freed_fonts->tail)
+ {
+ xfontmap->freed_fonts->tail = xfontmap->freed_fonts->tail->prev;
+ if (xfontmap->freed_fonts->tail)
+ xfontmap->freed_fonts->tail->next = NULL;
+ }
+
+ xfontmap->freed_fonts->head = g_list_delete_link (xfontmap->freed_fonts->head, link);
+ xfontmap->freed_fonts->length--;
+ xfont->in_cache = FALSE;
+
+ g_object_unref (xfont);
+}
+
+static void
+pango_x_fontmap_cache_clear (PangoXFontMap *xfontmap)
+{
+ g_list_foreach (xfontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_list_free (xfontmap->freed_fonts->head);
+ xfontmap->freed_fonts->head = NULL;
+ xfontmap->freed_fonts->tail = NULL;
+ xfontmap->freed_fonts->length = 0;
+}
+
+
+Atom
+pango_x_fontmap_atom_from_name (PangoFontMap *fontmap,
+ const char *atomname)
+{
+ PangoXFontMap *xfm = PANGO_X_FONT_MAP(fontmap);
+ gpointer found;
+ Atom atom;
+
+ found = g_hash_table_lookup (xfm->to_atom_cache, atomname);
+
+ if (found)
+ return (Atom)(GPOINTER_TO_UINT(found));
+
+ atom = XInternAtom (xfm->display, atomname, FALSE);
+ g_hash_table_insert (xfm->to_atom_cache, g_strdup (atomname),
+ (gpointer)atom);
+
+ return atom;
+}
+
+
+G_CONST_RETURN char *
+pango_x_fontmap_name_from_atom (PangoFontMap *fontmap,
+ Atom atom)
+{
+ PangoXFontMap *xfm = PANGO_X_FONT_MAP(fontmap);
+ gpointer found;
+ char *name, *name2;
+
+ found = g_hash_table_lookup (xfm->from_atom_cache, GUINT_TO_POINTER(atom));
+
+ if (found)
+ return (const char *)found;
+
+ name = XGetAtomName (xfm->display, atom);
+ name2 = g_strdup (name);
+ XFree (name);
+
+ g_hash_table_insert (xfm->from_atom_cache, (gpointer)atom, name2);
+
+ return name2;
+}
+
+/*
+ * PangoXFace
+ */
+
+static PangoFontDescription *
+pango_x_face_describe (PangoFontFace *face)
+{
+ PangoXFace *xface = PANGO_X_FACE (face);
+
+ return pango_font_description_copy (xface->description);
+}
+
+static const char *
+pango_x_face_get_face_name (PangoFontFace *face)
+{
+ PangoXFace *xface = PANGO_X_FACE (face);
+
+ if (!xface->face_name)
+ {
+ PangoFontDescription *desc = pango_font_face_describe (face);
+
+ pango_font_description_unset_fields (desc,
+ PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE);
+
+ xface->face_name = pango_font_description_to_string (desc);
+ pango_font_description_free (desc);
+ }
+
+ return xface->face_name;
+}
+
+static void
+pango_x_face_class_init (PangoFontFaceClass *class)
+{
+ class->describe = pango_x_face_describe;
+ class->get_face_name = pango_x_face_get_face_name;
+}
+
+GType
+pango_x_face_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFaceClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_x_face_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoXFace),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
+ I_("PangoXFace"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+/* Cut and paste here to avoid an inter-module dependency */
+static PangoCoverageLevel
+engine_shape_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *language,
+ gunichar wc)
+{
+ g_return_val_if_fail (PANGO_IS_ENGINE_SHAPE (engine), PANGO_COVERAGE_NONE);
+ g_return_val_if_fail (PANGO_IS_FONT (font), PANGO_COVERAGE_NONE);
+
+ return PANGO_ENGINE_SHAPE_GET_CLASS (engine)->covers (engine,
+ font,
+ language,
+ wc);
+}
+
+PangoCoverage *
+pango_x_face_get_coverage (PangoXFace *xface,
+ PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoXFont *xfont;
+ PangoXFontMap *xfontmap = NULL; /* Quiet gcc */
+ PangoCoverage *result = NULL;
+ Atom atom = None;
+
+ if (xface)
+ {
+ if (xface->coverage)
+ {
+ pango_coverage_ref (xface->coverage);
+ return xface->coverage;
+ }
+
+ xfont = (PangoXFont *)font;
+
+ xfontmap = (PangoXFontMap *)pango_x_font_map_for_display (xfont->display);
+ if (xface->xlfd)
+ {
+ const char *lang_str = language ? pango_language_to_string (language) : "*";
+
+ char *str = g_strconcat (lang_str, "|", xface->xlfd, NULL);
+ result = pango_x_get_cached_coverage (xfontmap, str, &atom);
+ g_free (str);
+ }
+ }
+
+ if (!result)
+ {
+ PangoMap *shape_map;
+ PangoEngineShape *engine;
+ gunichar wc;
+
+ result = pango_coverage_new ();
+
+ shape_map = pango_x_get_shaper_map (language);
+ engine = (PangoEngineShape *)pango_map_get_engine (shape_map, PANGO_SCRIPT_COMMON);
+
+ for (wc = 0; wc < 65536; wc++)
+ {
+ PangoCoverageLevel level;
+
+ level = engine_shape_covers (engine, font, language, wc);
+ if (level != PANGO_COVERAGE_NONE)
+ pango_coverage_set (result, wc, level);
+ }
+
+ if (atom)
+ pango_x_store_cached_coverage (xfontmap, atom, result);
+ }
+
+ if (xface)
+ {
+ xface->coverage = result;
+ pango_coverage_ref (result);
+ }
+
+ return result;
+}
+
+void
+pango_x_face_remove (PangoXFace *xface,
+ PangoFont *font)
+{
+ xface->cached_fonts = g_slist_remove (xface->cached_fonts, font);
+}
+
+/*
+ * PangoXFontFamily
+ */
+
+static void
+pango_x_family_list_faces (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces)
+{
+ PangoXFamily *xfamily = PANGO_X_FAMILY (family);
+
+ *n_faces = g_slist_length (xfamily->font_entries);
+ if (faces)
+ {
+ GSList *tmp_list;
+ int i = 0;
+
+ *faces = g_new (PangoFontFace *, *n_faces);
+
+ tmp_list = xfamily->font_entries;
+ while (tmp_list)
+ {
+ (*faces)[i++] = tmp_list->data;
+ tmp_list = tmp_list->next;
+ }
+ }
+}
+
+G_CONST_RETURN char *
+pango_x_family_get_name (PangoFontFamily *family)
+{
+ PangoXFamily *xfamily = PANGO_X_FAMILY (family);
+
+ return xfamily->family_name;
+}
+
+static void
+pango_x_family_class_init (PangoFontFamilyClass *class)
+{
+ class->list_faces = pango_x_family_list_faces;
+ class->get_name = pango_x_family_get_name;
+}
+
+GType
+pango_x_family_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFamilyClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_x_family_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoXFamily),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
+ I_("PangoXFamily"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
diff --git a/trunk/pango/pangox-private.h b/trunk/pango/pangox-private.h
new file mode 100644
index 00000000..b3a9c8f3
--- /dev/null
+++ b/trunk/pango/pangox-private.h
@@ -0,0 +1,122 @@
+/* Pango
+ * pangox-private.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOX_PRIVATE_H__
+#define __PANGOX_PRIVATE_H__
+
+#include <pango/pangox.h>
+#include <pango/pango-modules.h>
+
+typedef struct _PangoXFace PangoXFace;
+typedef struct _PangoXFont PangoXFont;
+typedef struct _PangoXSubfontInfo PangoXSubfontInfo;
+
+struct _PangoXFont
+{
+ PangoFont font;
+ Display *display;
+
+ char **fonts;
+ int n_fonts;
+ int size;
+
+ /* hash table mapping from charset-name to array of PangoXSubfont ids,
+ * of length n_fonts
+ */
+ GHashTable *subfonts_by_charset;
+
+ PangoXSubfontInfo **subfonts;
+
+ int n_subfonts;
+ int max_subfonts;
+
+ GSList *metrics_by_lang;
+
+ PangoFontMap *fontmap;
+ /* If TRUE, font is in cache of recently unused fonts and not otherwise
+ * in use.
+ */
+ gboolean in_cache;
+
+ PangoXFace *xface; /* Used to remove cached fonts */
+};
+
+
+#define PANGO_TYPE_X_FONT_MAP (pango_x_font_map_get_type ())
+#define PANGO_X_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_X_FONT_MAP, PangoXFontMap))
+#define PANGO_X_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_X_FONT_MAP, PangoXFontMapClass))
+#define PANGO_X_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_X_FONT_MAP))
+#define PANGO_X_IS_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_X_FONT_MAP))
+#define PANGO_X_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_X_FONT_MAP, PangoXFontMapClass))
+
+typedef struct _PangoXFontMap PangoXFontMap;
+typedef struct _PangoXFontMapClass PangoXFontMapClass;
+
+struct _PangoXFontMap
+{
+ PangoFontMap parent_instance;
+
+ Display *display;
+
+ PangoXFontCache *font_cache;
+ GQueue *freed_fonts;
+
+ GHashTable *families;
+ GHashTable *size_infos;
+
+ GHashTable *to_atom_cache;
+ GHashTable *from_atom_cache;
+
+ int n_fonts;
+
+ double resolution; /* (points / pixel) * PANGO_SCALE */
+
+ Window coverage_win;
+};
+
+GType pango_x_font_map_get_type (void) G_GNUC_CONST;
+
+PangoXFont * pango_x_font_new (PangoFontMap *fontmap,
+ const char *spec,
+ int size);
+PangoMap * pango_x_get_shaper_map (PangoLanguage *language);
+char * pango_x_make_matching_xlfd (PangoFontMap *fontmap,
+ char *xlfd,
+ const char *charset,
+ int size);
+PangoCoverage *pango_x_face_get_coverage (PangoXFace *xface,
+ PangoFont *font,
+ PangoLanguage *language);
+void pango_x_face_remove (PangoXFace *xface,
+ PangoFont *font);
+
+Display * pango_x_fontmap_get_display (PangoFontMap *fontmap);
+void pango_x_fontmap_cache_add (PangoFontMap *fontmap,
+ PangoXFont *xfont);
+void pango_x_fontmap_cache_remove (PangoFontMap *fontmap,
+ PangoXFont *xfont);
+
+Atom pango_x_fontmap_atom_from_name (PangoFontMap *fontmap,
+ const char *atomname);
+const char *pango_x_fontmap_name_from_atom (PangoFontMap *fontmap,
+ Atom atom);
+
+#endif /* __PANGOX_PRIVATE_H__ */
diff --git a/trunk/pango/pangox.aliases b/trunk/pango/pangox.aliases
new file mode 100644
index 00000000..9b41aa75
--- /dev/null
+++ b/trunk/pango/pangox.aliases
@@ -0,0 +1,220 @@
+# File defining aliases of PangoFontDescription to X font set
+#
+# family style variant weight stretch XLFD
+
+sans normal normal normal normal \
+ "-*-helvetica-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -*-gulim-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+sans italic normal normal normal \
+ "-*-helvetica-medium-o-normal--*-*-*-*-*-*-*-*,\
+ -*-gulim-medium-o-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+sans normal normal bold normal \
+ "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*,\
+ -*-gulim-bold-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+sans italic normal bold normal \
+ "-*-helvetica-bold-o-normal--*-*-*-*-*-*-*-*,\
+ -*-gulim-bold-o-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+
+serif normal normal normal normal \
+ "-*-times-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -*-batang-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+serif italic normal normal normal \
+ "-*-times-medium-i-normal--*-*-*-*-*-*-*-*,\
+ -*-batang-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+serif normal normal bold normal \
+ "-*-times-bold-r-normal--*-*-*-*-*-*-*-*,\
+ -*-batang-bold-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+serif italic normal bold normal \
+ "-*-times-bold-i-normal--*-*-*-*-*-*-*-*,\
+ -*-batang-bold-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+monospace normal normal normal normal \
+ "-*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -*-dotum-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+monospace italic normal normal normal \
+ "-*-fixed-medium-i-normal--*-*-*-*-*-*-*-*,\
+ -*-dotum-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+monospace normal normal bold normal \
+ "-*-fixed-bold-r-normal--*-*-*-*-*-*-*-*,\
+ -*-dotum-bold-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
+
+monospace italic normal bold normal \
+ "-*-fixed-bold-i-normal--*-*-*-*-*-*-*-*,\
+ -*-dotum-bold-r-normal--*-*-*-*-*-*-ksc5601.1987-0,\
+ -*-clearlyu-medium-r-normal--*-*-*-*-*-*-iso10646-1,\
+ -*-fixed-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -kaist-iyagi-bold-r-normal--*-*-*-*-*-*-johab-1,\
+ -*-song ti-medium-r-normal--*-*-*-*-*-*-*-*,\
+ -freetype-unitamil-medium-r-normal--*-*-*-*-*-*-iso10646-tam,\
+ -*-devanagari-medium-r-normal--*-*-*-*-*-*-iso10646-dev,\
+ -*-gujarati-medium-r-normal--*-*-*-*-*-*-iso10646-guj,\
+ -*-gurmukhi-medium-r-normal--*-*-*-*-*-*-iso10646-gur,\
+ -*-bengali-medium-r-normal--*-*-*-*-*-*-iso10646-bng,\
+ -*-kannada-medium-r-normal--*-*-*-*-*-*-iso10646-kan,\
+ -*-burmese-medium-r-normal--*-*-*-*-*-*-iso10646-brm,\
+ -*-buginese-medium-r-normal--*-*-*-*-*-*-iso10646-bgn,\
+ -*-oriya-medium-r-normal--*-*-*-*-*-*-iso10646-ori,\
+ -daewoo-mincho-medium-r-normal--*-*-*-*-*-*-ksc5601.1987-0"
diff --git a/trunk/pango/pangox.c b/trunk/pango/pangox.c
new file mode 100644
index 00000000..6ca0e578
--- /dev/null
+++ b/trunk/pango/pangox.c
@@ -0,0 +1,1807 @@
+/* pangox.c: Routines for handling X fonts
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 SuSE Linux Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <X11/Xlib.h>
+#include "pango-impl-utils.h"
+#include "modules.h"
+
+#undef PANGO_DISABLE_DEPRECATED
+
+#include "pangox.h"
+#include "pangox-private.h"
+
+#define PANGO_TYPE_X_FONT (pango_x_font_get_type ())
+#define PANGO_X_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_X_FONT, PangoXFont))
+#define PANGO_X_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_X_FONT, PangoXFontClass))
+#define PANGO_X_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_X_FONT))
+#define PANGO_X_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_X_FONT))
+#define PANGO_X_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_X_FONT, PangoXFontClass))
+
+typedef struct _PangoXFontClass PangoXFontClass;
+typedef struct _PangoXMetricsInfo PangoXMetricsInfo;
+typedef struct _PangoXContextInfo PangoXContextInfo;
+
+struct _PangoXSubfontInfo
+{
+ char *xlfd;
+ XFontStruct *font_struct;
+ gboolean is_1byte;
+ int range_byte1;
+ int range_byte2;
+};
+
+struct _PangoXMetricsInfo
+{
+ const char *sample_str;
+ PangoFontMetrics *metrics;
+};
+
+struct _PangoXContextInfo
+{
+ PangoGetGCFunc get_gc_func;
+ PangoFreeGCFunc free_gc_func;
+};
+
+struct _PangoXFontClass
+{
+ PangoFontClass parent_class;
+};
+
+static PangoFontClass *parent_class; /* Parent class structure for PangoXFont */
+
+static void pango_x_font_class_init (PangoXFontClass *class);
+static void pango_x_font_init (PangoXFont *xfont);
+static void pango_x_font_dispose (GObject *object);
+static void pango_x_font_finalize (GObject *object);
+
+static PangoFontDescription *pango_x_font_describe (PangoFont *font);
+static PangoCoverage * pango_x_font_get_coverage (PangoFont *font,
+ PangoLanguage *language);
+static PangoEngineShape * pango_x_font_find_shaper (PangoFont *font,
+ PangoLanguage *language,
+ guint32 ch);
+static void pango_x_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+static PangoFontMetrics * pango_x_font_get_metrics (PangoFont *font,
+ PangoLanguage *language);
+static PangoFontMap * pango_x_font_get_font_map (PangoFont *font);
+
+static PangoXSubfontInfo * pango_x_find_subfont (PangoFont *font,
+ PangoXSubfont subfont_index);
+static XCharStruct * pango_x_get_per_char (PangoFont *font,
+ PangoXSubfontInfo *subfont,
+ guint16 char_index);
+static gboolean pango_x_find_glyph (PangoFont *font,
+ PangoGlyph glyph,
+ PangoXSubfontInfo **subfont_return,
+ XCharStruct **charstruct_return);
+static XFontStruct * pango_x_get_font_struct (PangoFont *font,
+ PangoXSubfontInfo *info);
+
+static void pango_x_get_item_properties (PangoItem *item,
+ PangoUnderline *uline,
+ PangoAttrColor *fg_color,
+ gboolean *fg_set,
+ PangoAttrColor *bg_color,
+ gboolean *bg_set);
+
+static inline PangoXSubfontInfo *
+pango_x_find_subfont (PangoFont *font,
+ PangoXSubfont subfont_index)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+
+ if (subfont_index < 1 || subfont_index > xfont->n_subfonts)
+ {
+ g_warning ("Invalid subfont %d", subfont_index);
+ return NULL;
+ }
+
+ return xfont->subfonts[subfont_index-1];
+}
+
+static void
+pango_x_make_font_struct (PangoFont *font, PangoXSubfontInfo *info)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+ PangoXFontCache *cache;
+
+ cache = pango_x_font_map_get_font_cache (xfont->fontmap);
+
+ info->font_struct = pango_x_font_cache_load (cache, info->xlfd);
+ if (!info->font_struct)
+ {
+ g_warning ("Cannot load font for XLFD '%s\n", info->xlfd);
+
+ /* Prevent a segfault, but probably not much more */
+ info->font_struct = pango_x_font_cache_load (cache, "fixed");
+ }
+
+ info->is_1byte = (info->font_struct->min_byte1 == 0 && info->font_struct->max_byte1 == 0);
+ info->range_byte1 = info->font_struct->max_byte1 - info->font_struct->min_byte1 + 1;
+ info->range_byte2 = info->font_struct->max_char_or_byte2 - info->font_struct->min_char_or_byte2 + 1;
+}
+
+static inline XFontStruct *
+pango_x_get_font_struct (PangoFont *font, PangoXSubfontInfo *info)
+{
+ if (!info->font_struct)
+ pango_x_make_font_struct (font, info);
+
+ return info->font_struct;
+}
+
+/**
+ * pango_x_get_context:
+ * @display: an X display (As returned by XOpenDisplay().)
+ *
+ * Retrieves a #PangoContext appropriate for rendering with X fonts on the
+ * given display.
+ *
+ * Return value: the new #PangoContext.
+ **/
+PangoContext *
+pango_x_get_context (Display *display)
+{
+ PangoContext *result;
+ PangoXContextInfo *info;
+ int i;
+ static gboolean registered_modules = FALSE;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ if (!registered_modules)
+ {
+ registered_modules = TRUE;
+
+ for (i = 0; _pango_included_x_modules[i].list; i++)
+ pango_module_register (&_pango_included_x_modules[i]);
+ }
+
+ result = pango_context_new ();
+
+ info = g_new (PangoXContextInfo, 1);
+ info->get_gc_func = NULL;
+ info->free_gc_func = NULL;
+ g_object_set_qdata_full (G_OBJECT (result),
+ g_quark_from_static_string ("pango-x-info"),
+ info, (GDestroyNotify)g_free);
+
+ pango_context_set_font_map (result, pango_x_font_map_for_display (display));
+
+ return result;
+}
+
+/**
+ * pango_x_context_set_funcs:
+ * @context: a #PangoContext.
+ * @get_gc_func: function called to create a new GC for a given color.
+ * @free_gc_func: function called to free a GC created with @get_gc_func.
+ *
+ * Sets the functions that will be used to get GC's in various colors when
+ * rendering layouts with this context.
+ **/
+void
+pango_x_context_set_funcs (PangoContext *context,
+ PangoGetGCFunc get_gc_func,
+ PangoFreeGCFunc free_gc_func)
+{
+ PangoXContextInfo *info;
+
+ g_return_if_fail (context != NULL);
+
+ info = g_object_get_qdata (G_OBJECT (context),
+ g_quark_from_static_string ("pango-x-info"));
+
+ info->get_gc_func = get_gc_func;
+ info->free_gc_func = free_gc_func;
+}
+
+static GType
+pango_x_font_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (G_UNLIKELY (!object_type))
+ {
+ const GTypeInfo object_info =
+ {
+ sizeof (PangoXFontClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_x_font_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoXFont),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_x_font_init,
+ NULL /* value_table */
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT,
+ I_("PangoXFont"),
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+pango_x_font_init (PangoXFont *xfont)
+{
+ xfont->subfonts_by_charset = g_hash_table_new (g_str_hash, g_str_equal);
+ xfont->subfonts = g_new (PangoXSubfontInfo *, 1);
+
+ xfont->n_subfonts = 0;
+ xfont->max_subfonts = 1;
+
+ xfont->metrics_by_lang = NULL;
+
+ xfont->size = -1;
+ xfont->xface = NULL;
+}
+
+static void
+pango_x_font_class_init (PangoXFontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_x_font_finalize;
+ object_class->dispose = pango_x_font_dispose;
+
+ font_class->describe = pango_x_font_describe;
+ font_class->get_coverage = pango_x_font_get_coverage;
+ font_class->find_shaper = pango_x_font_find_shaper;
+ font_class->get_glyph_extents = pango_x_font_get_glyph_extents;
+ font_class->get_metrics = pango_x_font_get_metrics;
+ font_class->get_font_map = pango_x_font_get_font_map;
+}
+
+PangoXFont *
+pango_x_font_new (PangoFontMap *fontmap, const char *spec, int size)
+{
+ PangoXFont *result;
+
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (spec != NULL, NULL);
+
+ result = g_object_new (PANGO_TYPE_X_FONT, NULL);
+
+ result->fontmap = fontmap;
+ g_object_ref (fontmap);
+ result->display = pango_x_fontmap_get_display (fontmap);
+
+ result->fonts = g_strsplit(spec, ",", -1);
+ for (result->n_fonts = 0; result->fonts[result->n_fonts]; result->n_fonts++)
+ ; /* Nothing */
+
+ result->size = size;
+
+ return result;
+}
+
+/**
+ * pango_x_load_font:
+ * @display: the X display.
+ * @spec: a comma-separated list of XLFD's.
+ *
+ * Loads up a logical font based on a "fontset" style text
+ * specification. This is not remotely useful (Pango API's generally
+ * work in terms of #PangoFontDescription) and the result may not
+ * work correctly in all circumstances. Use of this function should
+ * be avoided.
+ *
+ * Returns a new #PangoFont.
+ */
+PangoFont *
+pango_x_load_font (Display *display,
+ const char *spec)
+{
+ PangoXFont *result;
+
+ g_return_val_if_fail (display != NULL, NULL);
+ g_return_val_if_fail (spec != NULL, NULL);
+
+ result = pango_x_font_new (pango_x_font_map_for_display (display), spec, -1);
+
+ return (PangoFont *)result;
+}
+
+
+#define FLUSH \
+ G_STMT_START { \
+ if (charcount) \
+ { \
+ XDrawString16 (display, d, gc, \
+ glyph_x0, glyph_y0, \
+ xcharbuffer, charcount); \
+ charcount = 0; \
+ } \
+ } G_STMT_END
+
+
+/**
+ * pango_x_render:
+ * @display: the X display.
+ * @d: the drawable on which to draw string.
+ * @gc: the graphics context.
+ * @font: the font in which to draw the string.
+ * @glyphs: the glyph string to draw.
+ * @x: the x position of start of string (in pixels).
+ * @y: the y position of baseline (in pixels).
+ *
+ * Renders a #PangoGlyphString onto an X drawable.
+ */
+void
+pango_x_render (Display *display,
+ Drawable d,
+ GC gc,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ Font old_fid = None;
+ XFontStruct *fs;
+ int i;
+ int x_off = 0;
+
+ /*
+ * We collect the characters in this buffer as long as the font does not
+ * change. At that time, or when the buffer runs full, or at the end,
+ * then we empty the buffer.
+ */
+ XChar2b xcharbuffer[1000];
+ int glyph_x0 = 0, expected_x = 0; /* x/y initializations are to quiet GCC */
+ int glyph_y0 = 0;
+ int charcount = 0;
+
+ g_return_if_fail (display != NULL);
+ g_return_if_fail (glyphs != NULL);
+
+ for (i=0; i<glyphs->num_glyphs; i++)
+ {
+ PangoGlyph glyph = glyphs->glyphs[i].glyph;
+ int glyph_x = x + PANGO_PIXELS (x_off + glyphs->glyphs[i].geometry.x_offset);
+ int glyph_y = y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset);
+
+ /* Clip glyphs into the X coordinate range; we really
+ * want to clip glyphs with an ink rect outside the
+ * [0,32767] x [0,32767] rectangle but looking up
+ * the ink rect here would be a noticeable speed hit.
+ * This is close enough.
+ */
+ if (!(glyph != PANGO_GLYPH_EMPTY &&
+ glyph_x >= -16384 && glyph_x <= 32767 &&
+ glyph_y >= -16384 && glyph_y <= 32767))
+ goto next_glyph;
+
+ if ((glyph & PANGO_GLYPH_UNKNOWN_FLAG) == 0)
+ {
+ guint16 index = PANGO_X_GLYPH_INDEX (glyph);
+ guint16 subfont_index = PANGO_X_GLYPH_SUBFONT (glyph);
+ PangoXSubfontInfo *subfont;
+
+ subfont = pango_x_find_subfont (font, subfont_index);
+ if (subfont)
+ {
+ fs = pango_x_get_font_struct (font, subfont);
+ if (!fs)
+ continue;
+
+ if (fs->fid != old_fid)
+ {
+ FLUSH;
+ XSetFont (display, gc, fs->fid);
+ old_fid = fs->fid;
+ }
+
+ if (charcount == G_N_ELEMENTS (xcharbuffer) ||
+ (charcount > 0 && (glyph_y != glyph_y0 ||
+ glyph_x != expected_x)))
+ FLUSH;
+
+ if (charcount == 0)
+ {
+ glyph_x0 = glyph_x;
+ glyph_y0 = glyph_y;
+ }
+ xcharbuffer[charcount].byte1 = index / 256;
+ xcharbuffer[charcount].byte2 = index % 256;
+
+ expected_x = glyph_x + XTextWidth16 (fs, &xcharbuffer[charcount], 1);
+
+ charcount++;
+ } else
+ goto unknown_glyph;
+ } else {
+ PangoFontMetrics *metrics;
+ int x1, y1, x2, y2; /* rectangle the character should go inside. */
+ int baseline;
+ int stroke_thick;
+ gunichar wc;
+
+ unknown_glyph:
+ FLUSH;
+
+ if (font)
+ metrics = pango_font_get_metrics (font, NULL);
+ else
+ metrics = NULL;
+
+ if (metrics)
+ {
+ y1 = glyph_y - PANGO_PIXELS (metrics->ascent);
+ y2 = y1 + PANGO_PIXELS (metrics->ascent + metrics->descent);
+ }
+ else
+ {
+ y2 = glyph_y;
+ y1 = y2 - PANGO_UNKNOWN_GLYPH_HEIGHT;
+ }
+
+ x1 = glyph_x;
+ x2 = x1 + PANGO_PIXELS (glyphs->glyphs[i].geometry.width);
+
+ baseline = glyph_y;
+ stroke_thick = MAX ((int) (0.5 + 0.075 * (y2 - y1)), 1);
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ wc = glyph & (~PANGO_GLYPH_UNKNOWN_FLAG);
+ else
+ wc = 0;
+
+ switch (wc)
+ {
+ case '\n':
+ case '\r':
+ case 0x2028: /* Line separator */
+ case 0x2029: /* Paragraph separator */
+ {
+ /* Draw a carriage-return thingy */
+ PangoRectangle up_stroke;
+ PangoRectangle across_stroke;
+
+ int hborder = (x2 - x1) * 0.1;
+ int arrow_height = 0.25 * (y2 - y1);
+ int top_border = (y2 - y1) * 0.25;
+
+ int arrow_x, arrow_width, tmp_height;
+
+ /* Draw the arrow-head */
+
+ tmp_height = (stroke_thick % 2 == 0) ? 2 : 1; /* Starting height */
+ arrow_height = 2 * ((1 + arrow_height - tmp_height) / 2) + tmp_height; /* Force symmetry */
+ arrow_width = 2 + arrow_height - tmp_height;
+
+ for (arrow_x = x1 + hborder; arrow_x < x1 + hborder + arrow_width; arrow_x++)
+ {
+ XDrawLine (display, d, gc,
+ arrow_x,
+ baseline - stroke_thick + (stroke_thick - tmp_height) / 2,
+ arrow_x,
+ baseline - stroke_thick + (stroke_thick - tmp_height) / 2 + tmp_height - 1);
+
+ if ((arrow_x - x1 - hborder) % 2 == 1)
+ tmp_height += 2;
+ }
+
+ across_stroke.x = arrow_x;
+ across_stroke.width = x2 - hborder - arrow_x - stroke_thick;
+ across_stroke.y = baseline - stroke_thick;
+ across_stroke.height = stroke_thick;
+
+ XFillRectangle (display, d, gc,
+ across_stroke.x, across_stroke.y,
+ across_stroke.width, across_stroke.height);
+
+ up_stroke.x = across_stroke.x + across_stroke.width;
+ up_stroke.width = stroke_thick;
+ up_stroke.y = y1 + top_border;
+ up_stroke.height = baseline - up_stroke.y;
+
+ XFillRectangle (display, d, gc,
+ up_stroke.x, up_stroke.y,
+ up_stroke.width, up_stroke.height);
+ }
+ break;
+
+ default:
+ {
+ /* Perhaps we should draw the box-with-numbers as in the
+ * Xft backend, though we have no guarantee of having
+ * an appropriate size of font. Right now, we just
+ * draw an empty box. (To draw the box-with-numbers.
+ * the backends would have to be changed to use
+ * pango_x_font_get_unknown_glyph() rather than
+ * pango_x_get_unknown_glyph().
+ */
+
+ int xspace = MAX ((int) (0.5 + 0.1 * (x2 - x1)), 1);
+ int yspace = MAX ((int) (0.5 + 0.1 * (y2 - y1)), 1);
+
+ x1 += xspace;
+ x2 -= xspace;
+ y1 += yspace;
+ y2 -= yspace;
+
+ XFillRectangle (display, d, gc,
+ x1, y1,
+ x2 - x1, stroke_thick);
+ XFillRectangle (display, d, gc,
+ x1, y1 + stroke_thick,
+ stroke_thick, y2 - y1 - 2 * stroke_thick);
+ XFillRectangle (display, d, gc,
+ x2 - stroke_thick, y1 + stroke_thick,
+ stroke_thick, y2 - y1 - 2 * stroke_thick);
+ XFillRectangle (display, d, gc,
+ x1, y2 - stroke_thick,
+ x2 - x1, stroke_thick);
+
+ break;
+ }
+ }
+
+ pango_font_metrics_unref (metrics);
+ }
+
+ next_glyph:
+ x_off += glyphs->glyphs[i].geometry.width;
+ }
+ FLUSH;
+}
+
+#undef FLUSH
+
+static void
+pango_x_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ XCharStruct *cs;
+ PangoXSubfontInfo *subfont;
+
+ if (glyph == PANGO_GLYPH_EMPTY)
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->width = ink_rect->y = ink_rect->height = 0;
+ if (logical_rect)
+ logical_rect->x = logical_rect->width = logical_rect->y = logical_rect->height = 0;
+ return;
+ }
+ if ((glyph & PANGO_GLYPH_UNKNOWN_FLAG) == 0 && pango_x_find_glyph (font, glyph, &subfont, &cs))
+ {
+ if (ink_rect)
+ {
+ ink_rect->x = PANGO_SCALE * cs->lbearing;
+ ink_rect->width = PANGO_SCALE * (cs->rbearing - cs->lbearing);
+ ink_rect->y = PANGO_SCALE * -cs->ascent;
+ ink_rect->height = PANGO_SCALE * (cs->ascent + cs->descent);
+ }
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->width = PANGO_SCALE * cs->width;
+ logical_rect->y = - PANGO_SCALE * subfont->font_struct->ascent;
+ logical_rect->height = PANGO_SCALE * (subfont->font_struct->ascent + subfont->font_struct->descent);
+ }
+ }
+ else
+ {
+ PangoFontMetrics *metrics;
+ gunichar wc;
+ gdouble width_factor;
+ int w;
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ wc = glyph & (~PANGO_GLYPH_UNKNOWN_FLAG);
+ else
+ wc = 0;
+
+ switch (wc)
+ {
+ case '\n':
+ case '\r':
+ case 0x2028: /* Line separator */
+ case 0x2029: /* Paragraph separator */
+ {
+#define MAGIC_FACTOR 1.2
+
+ /* carriage-return thingy */
+ width_factor = MAGIC_FACTOR;
+ break;
+ }
+ default:
+ {
+ /* Unknown glyph square */
+ width_factor = 1.0;
+ }
+ }
+
+ metrics = pango_font_get_metrics (font, NULL);
+
+ if (metrics)
+ {
+ w = metrics->approximate_char_width * width_factor;
+ w = PANGO_SCALE * PANGO_PIXELS (w);
+
+ if (ink_rect)
+ {
+ ink_rect->x = PANGO_SCALE;
+ ink_rect->width = w - 2 * PANGO_SCALE;
+ ink_rect->y = - (metrics->ascent - PANGO_SCALE);
+ ink_rect->height = metrics->ascent + metrics->descent - 2 * PANGO_SCALE;
+ }
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->width = w;
+ logical_rect->y = - metrics->ascent;
+ logical_rect->height = metrics->ascent + metrics->descent;
+ }
+
+ pango_font_metrics_unref (metrics);
+ }
+ else
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
+ if (logical_rect)
+ logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
+ }
+ }
+}
+
+static gboolean
+get_int_prop (Atom atom,
+ XFontStruct *fs,
+ int *val)
+{
+ int i;
+
+ *val = 0;
+
+ i = 0;
+ while (i < fs->n_properties)
+ {
+ if (fs->properties[i].name == atom)
+ {
+ *val = fs->properties[i].card32;
+ return TRUE;
+ }
+
+ ++i;
+ }
+
+ return FALSE;
+}
+
+/* Call @func with each glyph resulting from shaping @string with each
+ * glyph. This duplicates quite a bit of code from pango_itemize. This
+ * function should die and we should simply add the ability to specify
+ * particular fonts when itemizing.
+ */
+static void
+itemize_string_foreach (PangoFont *font,
+ PangoLanguage *language,
+ const char *str,
+ void (*func) (PangoFont *font,
+ PangoGlyphInfo *glyph_info,
+ gpointer data),
+ gpointer data)
+{
+ const char *start, *p;
+ PangoGlyphString *glyph_str = pango_glyph_string_new ();
+ PangoEngineShape *shaper, *last_shaper;
+ int last_level;
+ int i;
+ guint8 *embedding_levels;
+ PangoDirection base_dir = PANGO_DIRECTION_LTR;
+ gboolean finished = FALSE;
+
+ embedding_levels = pango_log2vis_get_embedding_levels (str, -1, &base_dir);
+
+ last_shaper = NULL;
+ last_level = 0;
+
+ i = 0;
+ p = start = str;
+ while (*p || !finished)
+ {
+ gunichar wc;
+
+ if (*p)
+ {
+ wc = g_utf8_get_char (p);
+ shaper = pango_font_find_shaper (font, language, wc);
+ }
+ else
+ {
+ finished = TRUE;
+ shaper = NULL;
+ }
+
+ if (p > start &&
+ (finished ||
+ (shaper != last_shaper || last_level != embedding_levels[i])))
+ {
+ PangoAnalysis analysis = {0};
+ int j;
+
+ analysis.shape_engine = last_shaper;
+ analysis.font = font;
+ analysis.language = language;
+ analysis.level = last_level;
+
+ pango_shape (start, p - start, &analysis, glyph_str);
+
+ for (j = 0; j < glyph_str->num_glyphs; j++)
+ (*func) (font, &glyph_str->glyphs[j], data);
+
+ start = p;
+ }
+
+ if (!finished)
+ {
+ p = g_utf8_next_char (p);
+
+ last_shaper = shaper;
+ last_level = embedding_levels[i];
+ i++;
+ }
+ }
+
+ pango_glyph_string_free (glyph_str);
+ g_free (embedding_levels);
+}
+
+/* Get composite font metrics for all subfonts in list
+ */
+static void
+get_font_metrics_from_subfonts (PangoFont *font,
+ GSList *subfonts,
+ PangoFontMetrics *metrics)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+ GSList *tmp_list = subfonts;
+ gboolean first = TRUE;
+ int total_avg_widths = 0;
+ int n_avg_widths = 0;
+ Atom avg_width_atom;
+
+ avg_width_atom = pango_x_fontmap_atom_from_name (xfont->fontmap,
+ "AVERAGE_WIDTH");
+
+ metrics->ascent = 0;
+ metrics->descent = 0;
+
+ while (tmp_list)
+ {
+ PangoXSubfontInfo *subfont = pango_x_find_subfont (font, GPOINTER_TO_UINT (tmp_list->data));
+
+ if (subfont)
+ {
+ XFontStruct *fs = pango_x_get_font_struct (font, subfont);
+ gint avg_width = 0;
+
+ if (fs)
+ {
+ if (first)
+ {
+ metrics->ascent = fs->ascent * PANGO_SCALE;
+ metrics->descent = fs->descent * PANGO_SCALE;
+ first = FALSE;
+ }
+ else
+ {
+ metrics->ascent = MAX (fs->ascent * PANGO_SCALE, metrics->ascent);
+ metrics->descent = MAX (fs->descent * PANGO_SCALE, metrics->descent);
+ }
+
+ if (get_int_prop (avg_width_atom, fs, &avg_width))
+ {
+ /* convert decipoints --> Pango units.
+ * Resolution is in (points * PANGO_SCALE) / pixel,
+ * avg_width in decipoints.
+ * We want pixels * PANGO_SCALE
+ */
+
+ /* Convert to points * PANGO_SCALE */
+ avg_width *= PANGO_SCALE / (double) 10.0;
+ /* Convert to pixels * PANGO_SCALE */
+ avg_width *= (PANGO_SCALE / PANGO_X_FONT_MAP (PANGO_X_FONT (font)->fontmap)->resolution);
+ }
+ else
+ {
+ avg_width = PANGO_SCALE * ((fs->min_bounds.width + fs->max_bounds.width) / 2);
+ }
+ }
+
+ if (avg_width)
+ {
+ total_avg_widths += avg_width;
+ n_avg_widths += 1;
+ }
+ }
+ else
+ g_warning ("Invalid subfont %d in get_font_metrics_from_subfonts", GPOINTER_TO_UINT (tmp_list->data));
+
+ tmp_list = tmp_list->next;
+ }
+
+ /* This is pretty darn bogus. */
+ if (n_avg_widths)
+ metrics->approximate_char_width = total_avg_widths / n_avg_widths;
+ else
+ metrics->approximate_char_width = PANGO_UNKNOWN_GLYPH_WIDTH * PANGO_SCALE;
+ if (metrics->ascent + metrics->descent == 0)
+ {
+ metrics->ascent = PANGO_UNKNOWN_GLYPH_HEIGHT * PANGO_SCALE;
+ metrics->descent = 0;
+ }
+}
+
+static void
+get_subfonts_foreach (PangoFont *font,
+ PangoGlyphInfo *glyph_info,
+ gpointer data)
+{
+ GSList **subfonts = data;
+ PangoGlyph glyph = glyph_info->glyph;
+ PangoXSubfont subfont;
+
+ if (glyph == PANGO_GLYPH_EMPTY)
+ return;
+
+ /* Use an arbitrary subfont for unknown glyphs...*/
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ if (((PangoXFont *)font)->n_subfonts > 0)
+ glyph = PANGO_X_MAKE_GLYPH (1, 0);
+ else
+ return;
+ }
+
+ subfont = PANGO_X_GLYPH_SUBFONT (glyph);
+ if (!g_slist_find (*subfonts, GUINT_TO_POINTER ((guint)subfont)))
+ *subfonts = g_slist_prepend (*subfonts, GUINT_TO_POINTER ((guint)subfont));
+}
+
+/* Get composite font metrics for all subfonts resulting from shaping
+ * string str with the given font
+ */
+static void
+get_font_metrics_from_string (PangoFont *font,
+ PangoLanguage *language,
+ const char *str,
+ PangoFontMetrics *metrics)
+{
+ GSList *subfonts = NULL;
+
+ itemize_string_foreach (font, language, str, get_subfonts_foreach, &subfonts);
+ get_font_metrics_from_subfonts (font, subfonts, metrics);
+ g_slist_free (subfonts);
+}
+
+static void
+average_width_foreach (PangoFont *font,
+ PangoGlyphInfo *glyph_info,
+ gpointer data)
+{
+ int *width = data;
+
+ *width += glyph_info->geometry.width;
+}
+
+/* Get composite font metrics for all subfonts resulting from shaping
+ * string str with the given font
+ */
+static gdouble
+get_total_width_for_string (PangoFont *font,
+ PangoLanguage *language,
+ const char *str)
+{
+ int width = 0;
+
+ itemize_string_foreach (font, language, str, average_width_foreach, &width);
+
+ return width;
+}
+
+static PangoFontMetrics *
+pango_x_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoXMetricsInfo *info = NULL; /* Quiet gcc */
+ PangoXFont *xfont = (PangoXFont *)font;
+ GSList *tmp_list;
+
+ const char *sample_str = pango_language_get_sample_string (language);
+
+ tmp_list = xfont->metrics_by_lang;
+ while (tmp_list)
+ {
+ info = tmp_list->data;
+
+ if (info->sample_str == sample_str) /* We _don't_ need strcmp */
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list)
+ {
+ PangoFontMetrics *metrics;
+
+ info = g_new0 (PangoXMetricsInfo, 1);
+
+ xfont->metrics_by_lang = g_slist_prepend (xfont->metrics_by_lang, info);
+
+ info->sample_str = sample_str;
+ metrics = pango_font_metrics_new ();
+
+ get_font_metrics_from_string (font, language, sample_str, metrics);
+
+ metrics->approximate_digit_width = get_total_width_for_string (font, language, "0123456789") / 10;
+
+ info->metrics = metrics;
+ }
+
+ return pango_font_metrics_ref (info->metrics);
+}
+
+static PangoFontMap *
+pango_x_font_get_font_map (PangoFont *font)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+
+ return xfont->fontmap;
+}
+
+/* Compare the tail of a to b */
+static gboolean
+match_end (const char *a, const char *b)
+{
+ size_t len_a = strlen (a);
+ size_t len_b = strlen (b);
+
+ if (len_b > len_a)
+ return FALSE;
+ else
+ return (strcmp (a + len_a - len_b, b) == 0);
+}
+
+/* Substitute in a charset into an XLFD. Return the
+ * (g_malloc'd) new name, or %NULL if the XLFD cannot
+ * match the charset
+ */
+static char *
+name_for_charset (char *xlfd, char *charset)
+{
+ char *p;
+ char *dash_charset = g_strconcat ("-", charset, NULL);
+ char *result = NULL;
+ int ndashes = 0;
+
+ for (p = xlfd; *p; p++)
+ if (*p == '-')
+ ndashes++;
+
+ if (ndashes == 14) /* Complete XLFD */
+ {
+ if (match_end (xlfd, "-*-*"))
+ {
+ result = g_malloc (strlen (xlfd) - 4 + strlen (dash_charset) + 1);
+ strncpy (result, xlfd, strlen (xlfd) - 4);
+ strcpy (result + strlen (xlfd) - 4, dash_charset);
+ }
+ if (match_end (xlfd, dash_charset))
+ result = g_strdup (xlfd);
+ }
+ else if (ndashes == 13)
+ {
+ if (match_end (xlfd, "-*"))
+ {
+ result = g_malloc (strlen (xlfd) - 2 + strlen (dash_charset) + 1);
+ strncpy (result, xlfd, strlen (xlfd) - 2);
+ strcpy (result + strlen (xlfd) - 2, dash_charset);
+ }
+ if (match_end (xlfd, dash_charset))
+ result = g_strdup (xlfd);
+ }
+ else
+ {
+ if (match_end (xlfd, "*"))
+ {
+ result = g_malloc (strlen (xlfd) + strlen (dash_charset) + 1);
+ strcpy (result, xlfd);
+ strcpy (result + strlen (xlfd), dash_charset);
+ }
+ if (match_end (xlfd, dash_charset))
+ result = g_strdup (xlfd);
+ }
+
+ g_free (dash_charset);
+ return result;
+}
+
+static PangoXSubfont
+pango_x_insert_subfont (PangoFont *font, const char *xlfd)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+ PangoXSubfontInfo *info;
+
+ info = g_new (PangoXSubfontInfo, 1);
+
+ info->xlfd = g_strdup (xlfd);
+ info->font_struct = NULL;
+
+ xfont->n_subfonts++;
+
+ if (xfont->n_subfonts > xfont->max_subfonts)
+ {
+ xfont->max_subfonts *= 2;
+ xfont->subfonts = g_renew (PangoXSubfontInfo *, xfont->subfonts, xfont->max_subfonts);
+ }
+
+ xfont->subfonts[xfont->n_subfonts - 1] = info;
+
+ return xfont->n_subfonts;
+}
+
+/**
+ * pango_x_list_subfonts:
+ * @font: a #PangoFont.
+ * @charsets: the charsets to list subfonts for.
+ * @n_charsets: the number of charsets in @charsets.
+ * @subfont_ids: location to store a pointer to an array of subfont IDs for each found subfont;
+ * the result must be freed using g_free().
+ * @subfont_charsets: location to store a pointer to an array of subfont IDs for each found subfont;
+ * the result must be freed using g_free().
+ *
+ * Lists the subfonts of a given font. The result is ordered first by charset,
+ * and then within each charset, by the order of fonts in the font specification.
+ *
+ * Return value: length of the arrays stored in @subfont_ids and
+ * @subfont_charsets.
+ **/
+int
+pango_x_list_subfonts (PangoFont *font,
+ char **charsets,
+ int n_charsets,
+ PangoXSubfont **subfont_ids,
+ int **subfont_charsets)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+ PangoXSubfont **subfont_lists;
+ PangoFontMap *fontmap;
+ int i, j;
+ int n_subfonts = 0;
+
+ g_return_val_if_fail (font != NULL, 0);
+ g_return_val_if_fail (n_charsets == 0 || charsets != NULL, 0);
+
+ fontmap = pango_x_font_map_for_display (xfont->display);
+
+ subfont_lists = g_new (PangoXSubfont *, n_charsets);
+
+ for (j=0; j<n_charsets; j++)
+ {
+ subfont_lists[j] = g_hash_table_lookup (xfont->subfonts_by_charset, charsets[j]);
+ if (!subfont_lists[j])
+ {
+ subfont_lists[j] = g_new (PangoXSubfont, xfont->n_fonts);
+
+ for (i = 0; i < xfont->n_fonts; i++)
+ {
+ PangoXSubfont subfont = 0;
+ char *xlfd;
+
+ if (xfont->size == -1)
+ {
+ xlfd = name_for_charset (xfont->fonts[i], charsets[j]);
+
+ if (xlfd)
+ {
+ int count;
+ char **names = XListFonts (xfont->display, xlfd, 1, &count);
+ if (count > 0)
+ subfont = pango_x_insert_subfont (font, names[0]);
+
+ XFreeFontNames (names);
+ g_free (xlfd);
+ }
+ }
+ else
+ {
+ xlfd = pango_x_make_matching_xlfd (fontmap, xfont->fonts[i], charsets[j], xfont->size);
+ if (xlfd)
+ {
+ subfont = pango_x_insert_subfont (font, xlfd);
+ g_free (xlfd);
+ }
+ }
+
+ subfont_lists[j][i] = subfont;
+ }
+
+ g_hash_table_insert (xfont->subfonts_by_charset, g_strdup (charsets[j]), subfont_lists[j]);
+ }
+
+ for (i = 0; i < xfont->n_fonts; i++)
+ if (subfont_lists[j][i])
+ n_subfonts++;
+ }
+
+ *subfont_ids = g_new (PangoXSubfont, n_subfonts);
+ *subfont_charsets = g_new (int, n_subfonts);
+
+ n_subfonts = 0;
+
+ for (j=0; j<n_charsets; j++)
+ for (i=0; i<xfont->n_fonts; i++)
+ if (subfont_lists[j][i])
+ {
+ (*subfont_ids)[n_subfonts] = subfont_lists[j][i];
+ (*subfont_charsets)[n_subfonts] = j;
+ n_subfonts++;
+ }
+
+ g_free (subfont_lists);
+
+ return n_subfonts;
+}
+
+/**
+ * pango_x_has_glyph:
+ * @font: a #PangoFont which must be from the X backend.
+ * @glyph: the index of a glyph in the font. (Formed
+ * using the #PANGO_X_MAKE_GLYPH macro)
+ *
+ * Checks if the given glyph is present in a X font.
+ *
+ * Return value: %TRUE if the glyph is present.
+ **/
+gboolean
+pango_x_has_glyph (PangoFont *font,
+ PangoGlyph glyph)
+{
+ PangoXSubfontInfo *subfont;
+ XCharStruct *cs;
+
+ guint16 char_index = PANGO_X_GLYPH_INDEX (glyph);
+ guint16 subfont_index = PANGO_X_GLYPH_SUBFONT (glyph);
+
+ subfont = pango_x_find_subfont (font, subfont_index);
+ if (!subfont)
+ return FALSE;
+
+ cs = pango_x_get_per_char (font, subfont, char_index);
+
+ if (cs && (cs->lbearing != cs->rbearing || cs->width != 0))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/**
+ * pango_x_font_subfont_xlfd:
+ * @font: a #PangoFont which must be from the X backend.
+ * @subfont_id: the id of a subfont within the font.
+ *
+ * Determines the X Logical Font Description for the specified
+ * subfont.
+ *
+ * Return value: A newly-allocated string containing the XLFD for the
+ * subfont. This string must be freed with g_free().
+ **/
+char *
+pango_x_font_subfont_xlfd (PangoFont *font,
+ PangoXSubfont subfont_id)
+{
+ PangoXSubfontInfo *subfont;
+
+ g_return_val_if_fail (font != NULL, NULL);
+ g_return_val_if_fail (PANGO_X_IS_FONT (font), NULL);
+
+ subfont = pango_x_find_subfont (font, subfont_id);
+ if (!subfont)
+ {
+ g_warning ("pango_x_font_subfont_xlfd: Invalid subfont_id specified");
+ return NULL;
+ }
+
+ return g_strdup (subfont->xlfd);
+}
+
+static void
+pango_x_font_dispose (GObject *object)
+{
+ PangoXFont *xfont = PANGO_X_FONT (object);
+
+ /* If the font is not already in the freed-fonts cache, add it,
+ * if it is already there, do nothing and the font will be
+ * freed.
+ */
+ if (!xfont->in_cache && xfont->fontmap)
+ pango_x_fontmap_cache_add (xfont->fontmap, xfont);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+
+static void
+subfonts_foreach (gpointer key, gpointer value, gpointer data)
+{
+ g_free (key);
+ g_free (value);
+}
+
+static void
+free_metrics_info (PangoXMetricsInfo *info)
+{
+ pango_font_metrics_unref (info->metrics);
+ g_free (info);
+}
+
+static void
+pango_x_font_finalize (GObject *object)
+{
+ PangoXFont *xfont = (PangoXFont *)object;
+ PangoXFontCache *cache = pango_x_font_map_get_font_cache (xfont->fontmap);
+
+ int i;
+
+ for (i=0; i<xfont->n_subfonts; i++)
+ {
+ PangoXSubfontInfo *info = xfont->subfonts[i];
+
+ g_free (info->xlfd);
+
+ if (info->font_struct)
+ pango_x_font_cache_unload (cache, info->font_struct);
+
+ g_free (info);
+ }
+
+ g_free (xfont->subfonts);
+
+ g_hash_table_foreach (xfont->subfonts_by_charset, subfonts_foreach, NULL);
+ g_hash_table_destroy (xfont->subfonts_by_charset);
+
+ g_slist_foreach (xfont->metrics_by_lang, (GFunc)free_metrics_info, NULL);
+ g_slist_free (xfont->metrics_by_lang);
+
+ if (xfont->xface)
+ pango_x_face_remove (xfont->xface, (PangoFont *)xfont);
+
+ g_object_unref (xfont->fontmap);
+
+ g_strfreev (xfont->fonts);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static PangoFontDescription *
+pango_x_font_describe (PangoFont *font)
+{
+ /* FIXME: this doesn't work for fonts from pango_x_font_load()
+ */
+ PangoXFont *xfont = (PangoXFont *)font;
+
+ if (xfont->xface)
+ {
+ PangoFontDescription *desc = pango_font_face_describe (PANGO_FONT_FACE (xfont->xface));
+ pango_font_description_set_size (desc, xfont->size);
+
+ return desc;
+ }
+ else
+ return NULL;
+}
+
+PangoMap *
+pango_x_get_shaper_map (PangoLanguage *language)
+{
+ static guint engine_type_id = 0;
+ static guint render_type_id = 0;
+
+ if (engine_type_id == 0)
+ {
+ engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_SHAPE);
+ render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_X);
+ }
+
+ return pango_find_map (language, engine_type_id, render_type_id);
+}
+
+static PangoCoverage *
+pango_x_font_get_coverage (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+
+ return pango_x_face_get_coverage (xfont->xface, font, language);
+}
+
+static PangoEngineShape *
+pango_x_font_find_shaper (PangoFont *font,
+ PangoLanguage *language,
+ guint32 ch)
+{
+ PangoMap *shape_map = NULL;
+ PangoScript script;
+
+ shape_map = pango_x_get_shaper_map (language);
+ script = pango_script_for_unichar (ch);
+ return (PangoEngineShape *)pango_map_get_engine (shape_map, script);
+}
+
+/* Utility functions */
+
+static XCharStruct *
+pango_x_get_per_char (PangoFont *font,
+ PangoXSubfontInfo *subfont,
+ guint16 char_index)
+{
+ XFontStruct *fs;
+
+ int index;
+ int byte1;
+ int byte2;
+
+ fs = pango_x_get_font_struct (font, subfont);
+ if (!fs)
+ return NULL;
+
+ if (subfont->is_1byte)
+ {
+ index = (int)char_index - fs->min_char_or_byte2;
+ if (index < 0 || index >= subfont->range_byte2)
+ return NULL;
+ }
+ else
+ {
+ byte1 = (int)(char_index / 256) - fs->min_byte1;
+ if (byte1 < 0 || byte1 >= subfont->range_byte1)
+ return NULL;
+
+ byte2 = (int)(char_index % 256) - fs->min_char_or_byte2;
+ if (byte2 < 0 || byte2 >= subfont->range_byte2)
+ return NULL;
+
+ index = byte1 * subfont->range_byte2 + byte2;
+ }
+
+ if (fs->per_char)
+ return &fs->per_char[index];
+ else
+ return &fs->min_bounds;
+}
+
+static gboolean
+pango_x_find_glyph (PangoFont *font,
+ PangoGlyph glyph,
+ PangoXSubfontInfo **subfont_return,
+ XCharStruct **charstruct_return)
+{
+ PangoXSubfontInfo *subfont;
+ XCharStruct *cs;
+
+ guint16 char_index = PANGO_X_GLYPH_INDEX (glyph);
+ guint16 subfont_index = PANGO_X_GLYPH_SUBFONT (glyph);
+
+ subfont = pango_x_find_subfont (font, subfont_index);
+ if (!subfont)
+ return FALSE;
+
+ cs = pango_x_get_per_char (font, subfont, char_index);
+
+ if (cs && (cs->lbearing != cs->rbearing || cs->width != 0))
+ {
+ if (subfont_return)
+ *subfont_return = subfont;
+
+ if (charstruct_return)
+ *charstruct_return = cs;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * pango_x_get_unknown_glyph:
+ * @font: a #PangoFont.
+ *
+ * Returns the index of a glyph suitable for drawing unknown characters;
+ * you should generally use PANGO_GET_UNKNOWN_GLYPH() instead,
+ * since that may return a glyph that provides a better representation
+ * of a particular char. (E.g., by showing hex digits, or a glyph
+ * representative of a certain Unicode range.)
+ *
+ * Return value: a glyph index into @font.
+ **/
+PangoGlyph
+pango_x_get_unknown_glyph (PangoFont *font)
+{
+ return PANGO_GET_UNKNOWN_GLYPH (0);
+}
+
+/**
+ * pango_x_render_layout_line:
+ * @display: the X display.
+ * @drawable: the drawable on which to draw.
+ * @gc: GC to use for uncolored drawing.
+ * @line: a #PangoLayoutLine.
+ * @x: the x position of start of string (in pixels).
+ * @y: the y position of baseline (in pixels).
+ *
+ * Renders a #PangoLayoutLine onto an X drawable.
+ */
+void
+pango_x_render_layout_line (Display *display,
+ Drawable drawable,
+ GC gc,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ GSList *tmp_list = line->runs;
+ PangoRectangle overall_rect;
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+ PangoContext *context = pango_layout_get_context (line->layout);
+ PangoXContextInfo *info =
+ g_object_get_qdata (G_OBJECT (context),
+ g_quark_from_static_string ("pango-x-info"));
+
+ int x_off = 0;
+
+ pango_layout_line_get_extents (line,NULL, &overall_rect);
+
+ while (tmp_list)
+ {
+ PangoUnderline uline = PANGO_UNDERLINE_NONE;
+ PangoLayoutRun *run = tmp_list->data;
+ PangoAttrColor fg_color, bg_color;
+ gboolean fg_set, bg_set;
+ GC fg_gc;
+
+ tmp_list = tmp_list->next;
+
+ pango_x_get_item_properties (run->item, &uline, &fg_color, &fg_set, &bg_color, &bg_set);
+
+ if (fg_set && info->get_gc_func)
+ fg_gc = info->get_gc_func (context, &fg_color.color, gc);
+ else
+ fg_gc = gc;
+
+ if (uline == PANGO_UNDERLINE_NONE)
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ NULL, &logical_rect);
+ else
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ &ink_rect, &logical_rect);
+
+ if (bg_set && info->get_gc_func)
+ {
+ GC bg_gc = info->get_gc_func (context, &bg_color.color, gc);
+
+ XFillRectangle (display, drawable, bg_gc,
+ x + (x_off + logical_rect.x) / PANGO_SCALE,
+ y + overall_rect.y / PANGO_SCALE,
+ logical_rect.width / PANGO_SCALE,
+ overall_rect.height / PANGO_SCALE);
+
+ if (info->free_gc_func)
+ info->free_gc_func (context, bg_gc);
+ }
+
+ pango_x_render (display, drawable, fg_gc, run->item->analysis.font, run->glyphs,
+ x + x_off / PANGO_SCALE, y);
+
+ switch (uline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ XDrawLine (display, drawable, fg_gc,
+ x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 4,
+ x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 4);
+ /* Fall through */
+ case PANGO_UNDERLINE_SINGLE:
+ XDrawLine (display, drawable, fg_gc,
+ x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 2,
+ x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 2);
+ break;
+ case PANGO_UNDERLINE_ERROR:
+ {
+ int point_x;
+ int counter = 0;
+ int end_x = x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE;
+
+ for (point_x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
+ point_x <= end_x;
+ point_x += 2)
+ {
+ if (counter)
+ XDrawLine (display, drawable, gc,
+ point_x, y + 2, MIN (point_x + 1, end_x), y + 2);
+ else
+ XDrawLine (display, drawable, gc,
+ point_x, y + 3, MIN (point_x + 1, end_x), y + 3);
+
+ counter = (counter + 1) % 2;
+ }
+ }
+ break;
+ case PANGO_UNDERLINE_LOW:
+ XDrawLine (display, drawable, fg_gc,
+ x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2,
+ x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2);
+ break;
+ }
+
+ if (fg_set && info->get_gc_func && info->free_gc_func)
+ info->free_gc_func (context, fg_gc);
+
+ x_off += logical_rect.width;
+ }
+}
+
+/**
+ * pango_x_render_layout:
+ * @display: the X display.
+ * @drawable: the drawable on which to draw.
+ * @gc: GC to use for uncolored drawing.
+ * @layout: a #PangoLayout.
+ * @x: the x position of the left of the layout (in pixels).
+ * @y: the y position of the top of the layout (in pixels).
+ *
+ * Renders a #PangoLayout onto an X drawable.
+ */
+void
+pango_x_render_layout (Display *display,
+ Drawable drawable,
+ GC gc,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ PangoLayoutIter *iter;
+
+ g_return_if_fail (display != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ iter = pango_layout_get_iter (layout);
+
+ do
+ {
+ PangoRectangle logical_rect;
+ PangoLayoutLine *line;
+ int baseline;
+
+ line = pango_layout_iter_get_line_readonly (iter);
+
+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+ baseline = pango_layout_iter_get_baseline (iter);
+
+ pango_x_render_layout_line (display, drawable, gc,
+ line,
+ x + PANGO_PIXELS (logical_rect.x),
+ y + PANGO_PIXELS (baseline));
+ }
+ while (pango_layout_iter_next_line (iter));
+
+ pango_layout_iter_free (iter);
+}
+
+/* This utility function is duplicated here and in pango-layout.c; should it be
+ * public? Trouble is - what is the appropriate set of properties?
+ */
+static void
+pango_x_get_item_properties (PangoItem *item,
+ PangoUnderline *uline,
+ PangoAttrColor *fg_color,
+ gboolean *fg_set,
+ PangoAttrColor *bg_color,
+ gboolean *bg_set)
+{
+ GSList *tmp_list = item->analysis.extra_attrs;
+
+ if (fg_set)
+ *fg_set = FALSE;
+
+ if (bg_set)
+ *bg_set = FALSE;
+
+ while (tmp_list)
+ {
+ PangoAttribute *attr = tmp_list->data;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_UNDERLINE:
+ if (uline)
+ *uline = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_FOREGROUND:
+ if (fg_color)
+ *fg_color = *((PangoAttrColor *)attr);
+ if (fg_set)
+ *fg_set = TRUE;
+
+ break;
+
+ case PANGO_ATTR_BACKGROUND:
+ if (bg_color)
+ *bg_color = *((PangoAttrColor *)attr);
+ if (bg_set)
+ *bg_set = TRUE;
+
+ break;
+
+ default:
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+}
+
+/**
+ * pango_x_apply_ligatures:
+ * @font: unused
+ * @subfont: unused
+ * @glyphs: unused
+ * @n_glyphs: unused
+ * @clusters: unused
+ *
+ * Previously did subfont-specific ligation. Now a no-op.
+ *
+ * Return value: %FALSE, always.
+ */
+gboolean
+pango_x_apply_ligatures (PangoFont *font,
+ PangoXSubfont subfont_id,
+ gunichar **glyphs,
+ int *n_glyphs,
+ int **clusters)
+{
+ return FALSE;
+}
+
+/**
+ * pango_x_find_first_subfont:
+ * @font: A #PangoFont.
+ * @rfont: A pointer to a #PangoXSubfont.
+ * @charsets: An array of charsets.
+ * @n_charsets: The number of charsets in @charsets.
+ *
+ * Looks for subfonts with the @charset charset,
+ * in @font, and puts the first one in *@rfont.
+ *
+ * Return value: %TRUE if *@rfont now contains a font.
+ */
+gboolean
+pango_x_find_first_subfont (PangoFont *font,
+ char **charsets,
+ int n_charsets,
+ PangoXSubfont *rfont)
+{
+ int n_subfonts;
+ gboolean result = FALSE;
+ PangoXSubfont *subfonts;
+ int *subfont_charsets;
+
+ g_return_val_if_fail (font, 0);
+ g_return_val_if_fail (charsets, 0);
+ g_return_val_if_fail (rfont, 0);
+
+ n_subfonts = pango_x_list_subfonts (font, charsets, n_charsets,
+ &subfonts, &subfont_charsets);
+
+ if (n_subfonts > 0)
+ {
+ *rfont = subfonts[0];
+ result = TRUE;
+ }
+
+ g_free (subfonts);
+ g_free (subfont_charsets);
+ return result;
+}
+
+/**
+ * pango_x_fallback_shape:
+ * @font: A #PangoFont.
+ * @glyphs: A pointer to a #PangoGlyphString.
+ * @text: UTF-8 string.
+ * @n_chars: Number of UTF-8 seqs in @text.
+ *
+ * This is a simple fallback shaper, that can be used
+ * if no subfont that supports a given script is found.
+ * For every character in @text, it puts the unknown glyph.
+ */
+void
+pango_x_fallback_shape (PangoFont *font,
+ PangoGlyphString *glyphs,
+ const char *text,
+ int n_chars)
+{
+ PangoGlyph unknown_glyph = pango_x_get_unknown_glyph (font);
+ PangoRectangle logical_rect;
+ const char *p;
+ int i;
+
+ g_return_if_fail (font);
+ g_return_if_fail (glyphs);
+ g_return_if_fail (text);
+ g_return_if_fail (n_chars >= 0);
+
+ pango_font_get_glyph_extents (font, unknown_glyph, NULL, &logical_rect);
+ pango_glyph_string_set_size (glyphs, n_chars);
+ p = text;
+ for (i = 0; i < n_chars; i++)
+ {
+ glyphs->glyphs[i].glyph = unknown_glyph;
+
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+
+ glyphs->log_clusters[i] = p - text;
+
+ p = g_utf8_next_char (p);
+ }
+}
+
+/**
+ * pango_x_font_get_unknown_glyph:
+ * @font: a #PangoFont.
+ * @wc: the Unicode character for which a glyph is needed.
+ *
+ * Returns the index of a glyph suitable for drawing @wc as an
+ * unknown character.
+ *
+ * Use PANGO_GET_UNKNOWN_GLYPH() instead.
+ *
+ * Return value: a glyph index into @font.
+ */
+PangoGlyph
+pango_x_font_get_unknown_glyph (PangoFont *font,
+ gunichar wc)
+{
+ return PANGO_GET_UNKNOWN_GLYPH (wc);
+}
diff --git a/trunk/pango/pangox.h b/trunk/pango/pangox.h
new file mode 100644
index 00000000..dc41b61e
--- /dev/null
+++ b/trunk/pango/pangox.h
@@ -0,0 +1,131 @@
+/* Pango
+ * pangox.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 SuSE Linux Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOX_H__
+#define __PANGOX_H__
+
+#include <glib.h>
+#include <pango/pango-layout.h>
+
+G_BEGIN_DECLS
+
+#include <X11/Xlib.h>
+
+#ifndef PANGO_DISABLE_DEPRECATED
+
+#define PANGO_RENDER_TYPE_X "PangoRenderX"
+
+typedef GC (*PangoGetGCFunc) (PangoContext *context, PangoColor *color, GC base_gc);
+typedef void (*PangoFreeGCFunc) (PangoContext *context, GC gc);
+
+/* Calls for applications
+ */
+PangoContext * pango_x_get_context (Display *display);
+void pango_x_context_set_funcs (PangoContext *context,
+ PangoGetGCFunc get_gc_func,
+ PangoFreeGCFunc free_gc_func);
+
+PangoFont * pango_x_load_font (Display *display,
+ const gchar *spec);
+void pango_x_render (Display *display,
+ Drawable d,
+ GC gc,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_x_render_layout_line (Display *display,
+ Drawable drawable,
+ GC gc,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_x_render_layout (Display *display,
+ Drawable drawable,
+ GC gc,
+ PangoLayout *layout,
+ int x,
+ int y);
+
+/* API for rendering modules
+ */
+typedef guint16 PangoXSubfont;
+
+#define PANGO_X_MAKE_GLYPH(subfont,index_) ((subfont)<<16 | (index_))
+#define PANGO_X_GLYPH_SUBFONT(glyph) ((glyph)>>16)
+#define PANGO_X_GLYPH_INDEX(glyph) ((glyph) & 0xffff)
+
+int pango_x_list_subfonts (PangoFont *font,
+ char **charsets,
+ int n_charsets,
+ PangoXSubfont **subfont_ids,
+ int **subfont_charsets);
+gboolean pango_x_has_glyph (PangoFont *font,
+ PangoGlyph glyph);
+PangoGlyph pango_x_get_unknown_glyph (PangoFont *font);
+
+#ifdef PANGO_ENABLE_ENGINE
+PangoGlyph pango_x_font_get_unknown_glyph (PangoFont *font,
+ gunichar wc);
+#endif /* PANGO_ENABLE_ENGINE */
+
+/* API for libraries that want to use PangoX mixed with classic X fonts.
+ */
+typedef struct _PangoXFontCache PangoXFontCache;
+
+PangoXFontCache *pango_x_font_cache_new (Display *display);
+void pango_x_font_cache_free (PangoXFontCache *cache);
+
+XFontStruct * pango_x_font_cache_load (PangoXFontCache *cache,
+ const char *xlfd);
+void pango_x_font_cache_unload (PangoXFontCache *cache,
+ XFontStruct *fs);
+
+PangoFontMap * pango_x_font_map_for_display (Display *display);
+void pango_x_shutdown_display (Display *display);
+PangoXFontCache *pango_x_font_map_get_font_cache (PangoFontMap *font_map);
+
+char *pango_x_font_subfont_xlfd (PangoFont *font,
+ PangoXSubfont subfont_id);
+
+
+gboolean pango_x_find_first_subfont (PangoFont *font,
+ char **charsets,
+ int n_charsets,
+ PangoXSubfont *rfont);
+
+void pango_x_fallback_shape (PangoFont *font,
+ PangoGlyphString *glyphs,
+ const char *text,
+ int n_chars);
+
+gboolean pango_x_apply_ligatures (PangoFont *font,
+ PangoXSubfont subfont,
+ gunichar **glyphs,
+ int *n_glyphs,
+ int **clusters);
+
+#endif /* PANGO_DISABLE_DEPRECATED */
+
+G_END_DECLS
+
+#endif /* __PANGOX_H__ */
diff --git a/trunk/pango/pangoxft-font.c b/trunk/pango/pangoxft-font.c
new file mode 100644
index 00000000..73e87104
--- /dev/null
+++ b/trunk/pango/pangoxft-font.c
@@ -0,0 +1,613 @@
+/* Pango
+ * pangoxft-font.c: Routines for handling X fonts
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include "pangofc-fontmap.h"
+#include "pangoxft-private.h"
+#include "pangofc-private.h"
+
+PangoXftWarningHistory _pango_xft_warning_history = { FALSE };
+
+#define PANGO_XFT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
+#define PANGO_XFT_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_FONT))
+#define PANGO_XFT_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
+
+typedef struct _PangoXftFontClass PangoXftFontClass;
+
+struct _PangoXftFontClass
+{
+ PangoFcFontClass parent_class;
+};
+
+static void pango_xft_font_finalize (GObject *object);
+
+static void pango_xft_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+static FT_Face pango_xft_font_real_lock_face (PangoFcFont *font);
+static void pango_xft_font_real_unlock_face (PangoFcFont *font);
+static gboolean pango_xft_font_real_has_char (PangoFcFont *font,
+ gunichar wc);
+static guint pango_xft_font_real_get_glyph (PangoFcFont *font,
+ gunichar wc);
+static void pango_xft_font_real_shutdown (PangoFcFont *font);
+
+static XftFont *xft_font_get_font (PangoFont *font);
+
+G_DEFINE_TYPE (PangoXftFont, pango_xft_font, PANGO_TYPE_FC_FONT)
+
+static void
+pango_xft_font_class_init (PangoXftFontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+ PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class);
+
+ object_class->finalize = pango_xft_font_finalize;
+
+ font_class->get_glyph_extents = pango_xft_font_get_glyph_extents;
+
+ fc_font_class->lock_face = pango_xft_font_real_lock_face;
+ fc_font_class->unlock_face = pango_xft_font_real_unlock_face;
+ fc_font_class->has_char = pango_xft_font_real_has_char;
+ fc_font_class->get_glyph = pango_xft_font_real_get_glyph;
+ fc_font_class->shutdown = pango_xft_font_real_shutdown;
+}
+
+static void
+pango_xft_font_init (PangoXftFont *xftfont)
+{
+}
+
+PangoXftFont *
+_pango_xft_font_new (PangoXftFontMap *xftfontmap,
+ FcPattern *pattern)
+{
+ PangoFontMap *fontmap = PANGO_FONT_MAP (xftfontmap);
+ PangoXftFont *xfont;
+
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (pattern != NULL, NULL);
+
+ xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT,
+ "pattern", pattern,
+ NULL);
+
+ /* Hack to force hinting of vertical metrics; hinting off for
+ * a Xft font just means to not hint outlines, but we still
+ * want integer line spacing, underline positions, etc
+ */
+ PANGO_FC_FONT (xfont)->is_hinted = TRUE;
+
+ xfont->xft_font = NULL;
+
+ return xfont;
+}
+
+/**
+ * _pango_xft_font_get_mini_font:
+ * @xfont: a #PangoXftFont
+ *
+ * Gets the font used for drawing the digits in the
+ * missing-character hex squares
+ *
+ * Return value: the #PangoFont used for the digits; this
+ * value is associated with the main font and will be freed
+ * along with the main font.
+ **/
+PangoFont *
+_pango_xft_font_get_mini_font (PangoXftFont *xfont)
+{
+ PangoFcFont *fcfont = (PangoFcFont *)xfont;
+
+ if (!fcfont || !fcfont->fontmap)
+ return NULL;
+
+ if (!xfont->mini_font)
+ {
+ Display *display;
+ int screen;
+ PangoFontDescription *desc = pango_font_description_new ();
+ PangoContext *context;
+ int i;
+ int width = 0, height = 0;
+ XGlyphInfo extents;
+ XftFont *mini_xft;
+ int new_size;
+
+ _pango_xft_font_map_get_info (fcfont->fontmap, &display, &screen);
+
+ context = pango_xft_get_context (display, screen);
+ pango_context_set_language (context, pango_language_from_string ("en"));
+
+ pango_font_description_set_family_static (desc, "monospace");
+
+ new_size = pango_font_description_get_size (fcfont->description) / 2;
+
+ if (pango_font_description_get_size_is_absolute (fcfont->description))
+ pango_font_description_set_absolute_size (desc, new_size);
+ else
+ pango_font_description_set_size (desc, new_size);
+
+ xfont->mini_font = pango_font_map_load_font (fcfont->fontmap, context, desc);
+ if (!xfont->mini_font)
+ return NULL;
+
+ pango_font_description_free (desc);
+ g_object_unref (context);
+
+ mini_xft = xft_font_get_font (xfont->mini_font);
+
+ for (i = 0 ; i < 16 ; i++)
+ {
+ char c = i < 10 ? '0' + i : 'A' + i - 10;
+ XftTextExtents8 (display, mini_xft, (FcChar8 *) &c, 1, &extents);
+ width = MAX (width, extents.width);
+ height = MAX (height, extents.height);
+ }
+
+
+ xfont->mini_width = PANGO_SCALE * width;
+ xfont->mini_height = PANGO_SCALE * height;
+ xfont->mini_pad = PANGO_SCALE * MIN (height / 2, MAX ((int)(2.2 * height + 27) / 28, 1));
+ }
+
+ return xfont->mini_font;
+}
+
+static void
+pango_xft_font_finalize (GObject *object)
+{
+ PangoXftFont *xfont = (PangoXftFont *)object;
+ PangoFcFont *fcfont = (PangoFcFont *)object;
+
+ if (xfont->mini_font)
+ g_object_unref (xfont->mini_font);
+
+ if (xfont->xft_font)
+ {
+ Display *display;
+
+ _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
+ XftFontClose (display, xfont->xft_font);
+ }
+
+ if (xfont->glyph_info)
+ g_hash_table_destroy (xfont->glyph_info);
+
+ G_OBJECT_CLASS (pango_xft_font_parent_class)->finalize (object);
+}
+
+static void
+get_glyph_extents_missing (PangoXftFont *xfont,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+
+{
+ PangoFont *font = PANGO_FONT (xfont);
+ XftFont *xft_font = xft_font_get_font (font);
+
+ gint cols = (glyph & ~PANGO_GLYPH_UNKNOWN_FLAG) > 0xffff ? 3 : 2;
+
+ _pango_xft_font_get_mini_font (xfont);
+
+ if (ink_rect)
+ {
+ ink_rect->x = 0;
+ ink_rect->y = - PANGO_SCALE * xft_font->ascent + PANGO_SCALE * (((xft_font->ascent + xft_font->descent) - (xfont->mini_height * 2 + xfont->mini_pad * 5 + PANGO_SCALE / 2) / PANGO_SCALE) / 2);
+ ink_rect->width = xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1);
+ ink_rect->height = xfont->mini_height * 2 + xfont->mini_pad * 5;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = - PANGO_SCALE * xft_font->ascent;
+ logical_rect->width = xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 2);
+ logical_rect->height = (xft_font->ascent + xft_font->descent) * PANGO_SCALE;
+ }
+}
+
+static void
+get_glyph_extents_xft (PangoFcFont *fcfont,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ XftFont *xft_font = xft_font_get_font ((PangoFont *)fcfont);
+ XGlyphInfo extents;
+ Display *display;
+ FT_UInt ft_glyph = glyph;
+
+ _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
+
+ XftGlyphExtents (display, xft_font, &ft_glyph, 1, &extents);
+
+ if (ink_rect)
+ {
+ ink_rect->x = - extents.x * PANGO_SCALE; /* Xft crack-rock sign choice */
+ ink_rect->y = - extents.y * PANGO_SCALE; /* " */
+ ink_rect->width = extents.width * PANGO_SCALE;
+ ink_rect->height = extents.height * PANGO_SCALE;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = - xft_font->ascent * PANGO_SCALE;
+ logical_rect->width = extents.xOff * PANGO_SCALE;
+ logical_rect->height = (xft_font->ascent + xft_font->descent) * PANGO_SCALE;
+ }
+}
+
+typedef struct
+{
+ PangoRectangle ink_rect;
+ PangoRectangle logical_rect;
+} Extents;
+
+static void
+extents_free (Extents *ext)
+{
+ g_slice_free (Extents, ext);
+}
+
+static void
+get_glyph_extents_raw (PangoXftFont *xfont,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ Extents *extents;
+
+ if (!xfont->glyph_info)
+ xfont->glyph_info = g_hash_table_new_full (NULL, NULL,
+ NULL, (GDestroyNotify)extents_free);
+
+ extents = g_hash_table_lookup (xfont->glyph_info,
+ GUINT_TO_POINTER (glyph));
+
+ if (!extents)
+ {
+ extents = g_slice_new (Extents);
+
+ pango_fc_font_get_raw_extents (PANGO_FC_FONT (xfont),
+ FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING,
+ glyph,
+ &extents->ink_rect,
+ &extents->logical_rect);
+
+ g_hash_table_insert (xfont->glyph_info,
+ GUINT_TO_POINTER (glyph),
+ extents);
+ }
+
+ if (ink_rect)
+ *ink_rect = extents->ink_rect;
+
+ if (logical_rect)
+ *logical_rect = extents->logical_rect;
+}
+
+static void
+pango_xft_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoXftFont *xfont = (PangoXftFont *)font;
+ PangoFcFont *fcfont = PANGO_FC_FONT (font);
+
+ if (!fcfont->fontmap) /* Display closed */
+ goto fallback;
+
+ if (glyph == PANGO_GLYPH_EMPTY)
+ {
+ fallback:
+ if (ink_rect)
+ ink_rect->x = ink_rect->width = ink_rect->y = ink_rect->height = 0;
+ if (logical_rect)
+ logical_rect->x = logical_rect->width = logical_rect->y = logical_rect->height = 0;
+ return;
+ }
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ get_glyph_extents_missing (xfont, glyph, ink_rect, logical_rect);
+ }
+ else
+ {
+ if (!fcfont->is_transformed)
+ get_glyph_extents_xft (fcfont, glyph, ink_rect, logical_rect);
+ else
+ get_glyph_extents_raw (xfont, glyph, ink_rect, logical_rect);
+ }
+}
+
+static void
+load_fallback_font (PangoXftFont *xfont)
+{
+ PangoFcFont *fcfont = PANGO_FC_FONT (xfont);
+ Display *display;
+ int screen;
+ XftFont *xft_font;
+ gboolean size_is_absolute;
+ double size;
+
+ _pango_xft_font_map_get_info (fcfont->fontmap, &display, &screen);
+
+ size_is_absolute = pango_font_description_get_size_is_absolute (fcfont->description);
+ size = pango_font_description_get_size (fcfont->description) / PANGO_SCALE;
+
+ xft_font = XftFontOpen (display, screen,
+ FC_FAMILY, FcTypeString, "sans",
+ size_is_absolute ? FC_PIXEL_SIZE : FC_SIZE, FcTypeDouble, size,
+ NULL);
+
+ if (!xft_font)
+ {
+ g_warning ("Cannot open fallback font, nothing to do");
+ exit (1);
+ }
+
+ xfont->xft_font = xft_font;
+}
+
+static XftFont *
+xft_font_get_font (PangoFont *font)
+{
+ PangoXftFont *xfont;
+ PangoFcFont *fcfont;
+ Display *display;
+ int screen;
+
+ xfont = (PangoXftFont *)font;
+ fcfont = (PangoFcFont *)font;
+
+ if (G_UNLIKELY (xfont->xft_font == NULL))
+ {
+ FcPattern *pattern = FcPatternDuplicate (fcfont->font_pattern);
+ FcPatternDel (pattern, FC_SPACING);
+
+ _pango_xft_font_map_get_info (fcfont->fontmap, &display, &screen);
+
+ xfont->xft_font = XftFontOpenPattern (display, pattern);
+ if (!xfont->xft_font)
+ {
+ gchar *name = pango_font_description_to_string (fcfont->description);
+ g_warning ("Cannot open font file for font %s", name);
+ g_free (name);
+
+ load_fallback_font (xfont);
+ }
+ }
+
+ return xfont->xft_font;
+}
+
+static FT_Face
+pango_xft_font_real_lock_face (PangoFcFont *font)
+{
+ XftFont *xft_font = xft_font_get_font ((PangoFont *)font);
+
+ return XftLockFace (xft_font);
+}
+
+static void
+pango_xft_font_real_unlock_face (PangoFcFont *font)
+{
+ XftFont *xft_font = xft_font_get_font ((PangoFont *)font);
+
+ XftUnlockFace (xft_font);
+}
+
+static gboolean
+pango_xft_font_real_has_char (PangoFcFont *font,
+ gunichar wc)
+{
+ XftFont *xft_font = xft_font_get_font ((PangoFont *)font);
+
+ return XftCharExists (NULL, xft_font, wc);
+}
+
+static guint
+pango_xft_font_real_get_glyph (PangoFcFont *font,
+ gunichar wc)
+{
+ XftFont *xft_font = xft_font_get_font ((PangoFont *)font);
+
+ return XftCharIndex (NULL, xft_font, wc);
+}
+
+static void
+pango_xft_font_real_shutdown (PangoFcFont *fcfont)
+{
+ PangoXftFont *xfont = PANGO_XFT_FONT (fcfont);
+
+ if (xfont->xft_font)
+ {
+ Display *display;
+
+ _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
+ XftFontClose (display, xfont->xft_font);
+ xfont->xft_font = NULL;
+ }
+}
+
+/**
+ * pango_xft_font_get_font:
+ * @font: a #PangoFont.
+ *
+ * Returns the XftFont of a font.
+ *
+ * Return value: the XftFont associated to @font.
+ **/
+XftFont *
+pango_xft_font_get_font (PangoFont *font)
+{
+ if (G_UNLIKELY (!PANGO_XFT_IS_FONT (font)))
+ {
+ if (!_pango_xft_warning_history.get_font)
+ {
+ _pango_xft_warning_history.get_font = TRUE;
+ g_warning ("pango_xft_font_get_font called with bad font, expect ugly output");
+ }
+ return NULL;
+ }
+
+ return xft_font_get_font (font);
+}
+
+/**
+ * pango_xft_font_get_display:
+ * @font: a #PangoFont.
+ *
+ * Returns the X display of the XftFont of a font.
+ *
+ * Return value: the X display of the XftFont associated to @font.
+ **/
+Display *
+pango_xft_font_get_display (PangoFont *font)
+{
+ PangoFcFont *fcfont;
+ Display *display;
+
+ g_return_val_if_fail (PANGO_XFT_IS_FONT (font), NULL);
+
+ fcfont = PANGO_FC_FONT (font);
+ _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
+
+ return display;
+}
+
+/**
+ * pango_xft_font_get_unknown_glyph:
+ * @font: a #PangoFont.
+ * @wc: the Unicode character for which a glyph is needed.
+ *
+ * Returns the index of a glyph suitable for drawing @wc as an
+ * unknown character.
+ *
+ * Use PANGO_GET_UNKNOWN_GLYPH() instead.
+ *
+ * Return value: a glyph index into @font.
+ **/
+PangoGlyph
+pango_xft_font_get_unknown_glyph (PangoFont *font,
+ gunichar wc)
+{
+ g_return_val_if_fail (PANGO_XFT_IS_FONT (font), PANGO_GLYPH_EMPTY);
+
+ return pango_fc_font_get_unknown_glyph (PANGO_FC_FONT (font), wc);
+}
+
+/**
+ * pango_xft_font_lock_face:
+ * @font: a #PangoFont.
+ *
+ * Gets the FreeType <type>FT_Face</type> associated with a font,
+ * This face will be kept around until you call
+ * pango_xft_font_unlock_face().
+ *
+ * Use pango_fc_font_lock_face() instead.
+ *
+ * Return value: the FreeType <type>FT_Face</type> associated with @font.
+ *
+ * Since: 1.2
+ **/
+FT_Face
+pango_xft_font_lock_face (PangoFont *font)
+{
+ g_return_val_if_fail (PANGO_XFT_IS_FONT (font), NULL);
+
+ return pango_fc_font_lock_face (PANGO_FC_FONT (font));
+}
+
+/**
+ * pango_xft_font_unlock_face:
+ * @font: a #PangoFont.
+ *
+ * Releases a font previously obtained with
+ * pango_xft_font_lock_face().
+ *
+ * Use pango_fc_font_unlock_face() instead.
+ *
+ * Since: 1.2
+ **/
+void
+pango_xft_font_unlock_face (PangoFont *font)
+{
+ g_return_if_fail (PANGO_XFT_IS_FONT (font));
+
+ pango_fc_font_unlock_face (PANGO_FC_FONT (font));
+}
+
+/**
+ * pango_xft_font_get_glyph:
+ * @font: a #PangoFont for the Xft backend
+ * @wc: Unicode codepoint to look up
+ *
+ * Gets the glyph index for a given Unicode character
+ * for @font. If you only want to determine
+ * whether the font has the glyph, use pango_xft_font_has_char().
+ *
+ * Use pango_fc_font_get_glyph() instead.
+ *
+ * Return value: the glyph index, or 0, if the Unicode
+ * character does not exist in the font.
+ *
+ * Since: 1.2
+ **/
+guint
+pango_xft_font_get_glyph (PangoFont *font,
+ gunichar wc)
+{
+ g_return_val_if_fail (PANGO_XFT_IS_FONT (font), 0);
+
+ return pango_fc_font_get_glyph (PANGO_FC_FONT (font), wc);
+}
+
+/**
+ * pango_xft_font_has_char:
+ * @font: a #PangoFont for the Xft backend
+ * @wc: Unicode codepoint to look up
+ *
+ * Determines whether @font has a glyph for the codepoint @wc.
+ *
+ * Use pango_fc_font_has_char() instead.
+ *
+ * Return value: %TRUE if @font has the requested codepoint.
+ *
+ * Since: 1.2
+ **/
+gboolean
+pango_xft_font_has_char (PangoFont *font,
+ gunichar wc)
+{
+ g_return_val_if_fail (PANGO_XFT_IS_FONT (font), 0);
+
+ return pango_fc_font_has_char (PANGO_FC_FONT (font), wc);
+}
diff --git a/trunk/pango/pangoxft-fontmap.c b/trunk/pango/pangoxft-fontmap.c
new file mode 100644
index 00000000..6c361282
--- /dev/null
+++ b/trunk/pango/pangoxft-fontmap.c
@@ -0,0 +1,377 @@
+/* Pango
+ * pangoxft-fontmap.c: Xft font handling
+ *
+ * Copyright (C) 2000-2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pangofc-fontmap.h"
+#include "pangoxft.h"
+#include "pangoxft-private.h"
+
+/* For XExtSetCloseDisplay */
+#include <X11/Xlibint.h>
+
+typedef struct _PangoXftFamily PangoXftFamily;
+typedef struct _PangoXftFontMapClass PangoXftFontMapClass;
+
+#define PANGO_TYPE_XFT_FONT_MAP (pango_xft_font_map_get_type ())
+#define PANGO_XFT_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMap))
+#define PANGO_XFT_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT_MAP))
+
+struct _PangoXftFontMap
+{
+ PangoFcFontMap parent_instance;
+
+ Display *display;
+ int screen;
+
+ /* Function to call on prepared patterns to do final
+ * config tweaking.
+ */
+ PangoXftSubstituteFunc substitute_func;
+ gpointer substitute_data;
+ GDestroyNotify substitute_destroy;
+
+ PangoRenderer *renderer;
+};
+
+struct _PangoXftFontMapClass
+{
+ PangoFcFontMapClass parent_class;
+};
+
+static void pango_xft_font_map_default_substitute (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern);
+static PangoFcFont * pango_xft_font_map_new_font (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern);
+static void pango_xft_font_map_finalize (GObject *object);
+
+static GSList *fontmaps = NULL;
+
+G_DEFINE_TYPE (PangoXftFontMap, pango_xft_font_map, PANGO_TYPE_FC_FONT_MAP)
+
+static void
+pango_xft_font_map_class_init (PangoXftFontMapClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class);
+
+ gobject_class->finalize = pango_xft_font_map_finalize;
+ fcfontmap_class->default_substitute = pango_xft_font_map_default_substitute;
+ fcfontmap_class->new_font = pango_xft_font_map_new_font;
+}
+
+static void
+pango_xft_font_map_init (PangoXftFontMap *xftfontmap)
+{
+}
+
+static void
+pango_xft_font_map_finalize (GObject *object)
+{
+ PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (object);
+
+ if (xftfontmap->renderer)
+ g_object_unref (xftfontmap->renderer);
+
+ fontmaps = g_slist_remove (fontmaps, object);
+
+ if (xftfontmap->substitute_destroy)
+ xftfontmap->substitute_destroy (xftfontmap->substitute_data);
+
+ G_OBJECT_CLASS (pango_xft_font_map_parent_class)->finalize (object);
+}
+
+
+static PangoFontMap *
+pango_xft_find_font_map (Display *display,
+ int screen)
+{
+ GSList *tmp_list;
+
+ tmp_list = fontmaps;
+ while (tmp_list)
+ {
+ PangoXftFontMap *xftfontmap = tmp_list->data;
+
+ if (xftfontmap->display == display &&
+ xftfontmap->screen == screen)
+ return PANGO_FONT_MAP (xftfontmap);
+
+ tmp_list = tmp_list->next;
+ }
+
+ return NULL;
+}
+
+/*
+ * Hackery to set up notification when a Display is closed
+ */
+static GSList *registered_displays;
+
+static int
+close_display_cb (Display *display,
+ XExtCodes *extcodes)
+{
+ GSList *tmp_list;
+
+ tmp_list = fontmaps;
+ while (tmp_list)
+ {
+ PangoXftFontMap *xftfontmap = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (xftfontmap->display == display)
+ pango_xft_shutdown_display (display, xftfontmap->screen);
+ }
+
+ registered_displays = g_slist_remove (registered_displays, display);
+
+ return 0;
+}
+
+static void
+register_display (Display *display)
+{
+ XExtCodes *extcodes;
+ GSList *tmp_list;
+
+ for (tmp_list = registered_displays; tmp_list; tmp_list = tmp_list->next)
+ {
+ if (tmp_list->data == display)
+ return;
+ }
+
+ registered_displays = g_slist_prepend (registered_displays, display);
+
+ extcodes = XAddExtension (display);
+ XESetCloseDisplay (display, extcodes->extension, close_display_cb);
+}
+
+/**
+ * pango_xft_get_font_map:
+ * @display: an X display
+ * @screen: the screen number of a screen within @display
+ *
+ * Returns the #PangoXftFontmap for the given display and screen.
+ * The fontmap is owned by Pango and will be valid until
+ * the display is closed.
+ *
+ * Return value: a #PangoFontMap object, owned by Pango.
+ *
+ * Since: 1.2
+ **/
+PangoFontMap *
+pango_xft_get_font_map (Display *display,
+ int screen)
+{
+ PangoFontMap *fontmap;
+ PangoXftFontMap *xftfontmap;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ fontmap = pango_xft_find_font_map (display, screen);
+ if (fontmap)
+ return fontmap;
+
+ /* Make sure that the type system is initialized */
+ g_type_init ();
+
+ xftfontmap = (PangoXftFontMap *)g_object_new (PANGO_TYPE_XFT_FONT_MAP, NULL);
+
+ xftfontmap->display = display;
+ xftfontmap->screen = screen;
+
+ register_display (display);
+
+ fontmaps = g_slist_prepend (fontmaps, xftfontmap);
+
+ return PANGO_FONT_MAP (xftfontmap);
+}
+
+/**
+ * pango_xft_shutdown_display:
+ * @display: an X display
+ * @screen: the screen number of a screen within @display
+ *
+ * Release any resources that have been cached for the
+ * combination of @display and @screen. Note that when the
+ * X display is closed, resources are released automatically,
+ * without needing to call this function.
+ *
+ * Since: 1.2
+ **/
+void
+pango_xft_shutdown_display (Display *display,
+ int screen)
+{
+ PangoFontMap *fontmap;
+
+ fontmap = pango_xft_find_font_map (display, screen);
+ if (fontmap)
+ {
+ PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fontmap);
+
+ fontmaps = g_slist_remove (fontmaps, fontmap);
+ pango_fc_font_map_shutdown (PANGO_FC_FONT_MAP (fontmap));
+
+ xftfontmap->display = NULL;
+ g_object_unref (fontmap);
+ }
+}
+
+/**
+ * pango_xft_set_default_substitute:
+ * @display: an X Display
+ * @screen: the screen number of a screen within @display
+ * @func: function to call to to do final config tweaking
+ * on #FcPattern objects.
+ * @data: data to pass to @func
+ * @notify: function to call when @data is no longer used.
+ *
+ * Sets a function that will be called to do final configuration
+ * substitution on a #FcPattern before it is used to load
+ * the font. This function can be used to do things like set
+ * hinting and antialiasing options.
+ *
+ * Since: 1.2
+ **/
+void
+pango_xft_set_default_substitute (Display *display,
+ int screen,
+ PangoXftSubstituteFunc func,
+ gpointer data,
+ GDestroyNotify notify)
+{
+ PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
+
+ if (xftfontmap->substitute_destroy)
+ xftfontmap->substitute_destroy (xftfontmap->substitute_data);
+
+ xftfontmap->substitute_func = func;
+ xftfontmap->substitute_data = data;
+ xftfontmap->substitute_destroy = notify;
+
+ pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (xftfontmap));
+}
+
+/**
+ * pango_xft_substitute_changed:
+ * @display: an X Display
+ * @screen: the screen number of a screen within @display
+ *
+ * Call this function any time the results of the
+ * default substitution function set with
+ * pango_xft_set_default_substitute() change.
+ * That is, if your substitution function will return different
+ * results for the same input pattern, you must call this function.
+ *
+ * Since: 1.2
+ **/
+void
+pango_xft_substitute_changed (Display *display,
+ int screen)
+{
+ PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
+
+ pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (xftfontmap));
+}
+
+void
+_pango_xft_font_map_get_info (PangoFontMap *fontmap,
+ Display **display,
+ int *screen)
+{
+ PangoXftFontMap *xftfontmap = (PangoXftFontMap *)fontmap;
+
+ if (display)
+ *display = xftfontmap->display;
+ if (screen)
+ *screen = xftfontmap->screen;
+}
+
+/**
+ * pango_xft_get_context:
+ * @display: an X display.
+ * @screen: an X screen.
+ *
+ * Retrieves a #PangoContext appropriate for rendering with
+ * Xft fonts on the given screen of the given display.
+ *
+ * Return value: the new #PangoContext.
+ **/
+PangoContext *
+pango_xft_get_context (Display *display,
+ int screen)
+{
+ PangoFontMap *fontmap;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ fontmap = pango_xft_get_font_map (display, screen);
+ return pango_fc_font_map_create_context (PANGO_FC_FONT_MAP (fontmap));
+}
+
+/**
+ * _pango_xft_font_map_get_renderer:
+ * @fontmap: a #PangoXftFontmap
+ *
+ * Gets the singleton #PangoXFTRenderer for this fontmap.
+ *
+ * Return value:
+ **/
+PangoRenderer *
+_pango_xft_font_map_get_renderer (PangoXftFontMap *xftfontmap)
+{
+ if (!xftfontmap->renderer)
+ xftfontmap->renderer = pango_xft_renderer_new (xftfontmap->display,
+ xftfontmap->screen);
+
+ return xftfontmap->renderer;
+}
+
+static void
+pango_xft_font_map_default_substitute (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern)
+{
+ PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fcfontmap);
+ double d;
+
+ FcConfigSubstitute (NULL, pattern, FcMatchPattern);
+ if (xftfontmap->substitute_func)
+ xftfontmap->substitute_func (pattern, xftfontmap->substitute_data);
+ XftDefaultSubstitute (xftfontmap->display, xftfontmap->screen, pattern);
+ if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch && d == 0.0)
+ {
+ FcValue v;
+ v.type = FcTypeDouble;
+ v.u.d = 1.0;
+ FcPatternAdd (pattern, FC_PIXEL_SIZE, v, FcFalse);
+ }
+}
+
+static PangoFcFont *
+pango_xft_font_map_new_font (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern)
+{
+ return (PangoFcFont *)_pango_xft_font_new (PANGO_XFT_FONT_MAP (fcfontmap), pattern);
+}
diff --git a/trunk/pango/pangoxft-private.h b/trunk/pango/pangoxft-private.h
new file mode 100644
index 00000000..1ee2da68
--- /dev/null
+++ b/trunk/pango/pangoxft-private.h
@@ -0,0 +1,68 @@
+/* Pango
+ * pangox-private.h:
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOXFT_PRIVATE_H__
+#define __PANGOXFT_PRIVATE_H__
+
+#include <pango/pangoxft.h>
+#include <pango/pango-renderer.h>
+
+G_BEGIN_DECLS
+
+struct _PangoXftFont
+{
+ PangoFcFont parent_instance;
+
+ XftFont *xft_font; /* created on demand */
+ PangoFont *mini_font; /* font used to display missing glyphs */
+
+ guint16 mini_width; /* metrics for missing glyph drawing */
+ guint16 mini_height;
+ guint16 mini_pad;
+
+ GHashTable *glyph_info; /* Used only when we can't get
+ * glyph extents out of Xft because
+ * we have a transformation in effect
+ */
+};
+
+PangoXftFont *_pango_xft_font_new (PangoXftFontMap *xftfontmap,
+ FcPattern *pattern);
+
+void _pango_xft_font_map_get_info (PangoFontMap *fontmap,
+ Display **display,
+ int *screen);
+
+PangoRenderer *_pango_xft_font_map_get_renderer (PangoXftFontMap *xftfontmap);
+
+PangoFont *_pango_xft_font_get_mini_font (PangoXftFont *xfont);
+
+typedef struct _PangoXftWarningHistory PangoXftWarningHistory;
+
+struct _PangoXftWarningHistory {
+ guint get_font : 1;
+};
+
+extern PangoXftWarningHistory _pango_xft_warning_history;
+
+G_END_DECLS
+
+#endif /* __PANGOXFT_PRIVATE_H__ */
diff --git a/trunk/pango/pangoxft-render.c b/trunk/pango/pangoxft-render.c
new file mode 100644
index 00000000..efaae64e
--- /dev/null
+++ b/trunk/pango/pangoxft-render.c
@@ -0,0 +1,897 @@
+/* Pango
+ * pangoxft-render.c: Rendering routines for the Xft library
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <math.h>
+
+#include "pangoxft-render.h"
+#include "pangoxft-private.h"
+
+enum {
+ PROP_0,
+ PROP_DISPLAY,
+ PROP_SCREEN
+};
+
+struct _PangoXftRendererPrivate
+{
+ PangoColor default_color;
+ guint16 alpha;
+
+ Picture src_picture;
+ Picture dest_picture;
+
+ XRenderPictFormat *mask_format;
+
+ GArray *trapezoids;
+ PangoRenderPart trapezoid_part;
+
+ GArray *glyphs;
+ PangoFont *glyph_font;
+};
+
+static void pango_xft_renderer_finalize (GObject *object);
+static void pango_xft_renderer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void pango_xft_renderer_real_composite_trapezoids (PangoXftRenderer *xftrenderer,
+ PangoRenderPart part,
+ XTrapezoid *trapezoids,
+ int n_trapezoids);
+static void pango_xft_renderer_real_composite_glyphs (PangoXftRenderer *xftrenderer,
+ XftFont *xft_font,
+ XftGlyphSpec *glyphs,
+ int n_glyphs);
+
+static void pango_xft_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+static void pango_xft_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22);
+static void pango_xft_renderer_part_changed (PangoRenderer *renderer,
+ PangoRenderPart part);
+static void pango_xft_renderer_end (PangoRenderer *renderer);
+
+static void flush_trapezoids (PangoXftRenderer *xftrenderer);
+static void flush_glyphs (PangoXftRenderer *xftrenderer);
+
+G_DEFINE_TYPE (PangoXftRenderer, pango_xft_renderer, PANGO_TYPE_RENDERER)
+
+static void
+pango_xft_renderer_init (PangoXftRenderer *xftrenderer)
+{
+ xftrenderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (xftrenderer,
+ PANGO_TYPE_XFT_RENDERER,
+ PangoXftRendererPrivate);
+ xftrenderer->priv->alpha = 0xffff;
+}
+
+static void
+pango_xft_renderer_class_init (PangoXftRendererClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
+
+ klass->composite_glyphs = pango_xft_renderer_real_composite_glyphs;
+ klass->composite_trapezoids = pango_xft_renderer_real_composite_trapezoids;
+
+ renderer_class->draw_glyphs = pango_xft_renderer_draw_glyphs;
+ renderer_class->draw_trapezoid = pango_xft_renderer_draw_trapezoid;
+ renderer_class->part_changed = pango_xft_renderer_part_changed;
+ renderer_class->end = pango_xft_renderer_end;
+
+ object_class->finalize = pango_xft_renderer_finalize;
+ object_class->set_property = pango_xft_renderer_set_property;
+
+ g_object_class_install_property (object_class, PROP_DISPLAY,
+ g_param_spec_pointer ("display",
+ "Display",
+ "The display being rendered to",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class, PROP_SCREEN,
+ g_param_spec_int ("screen",
+ "Screen",
+ "The screen being rendered to",
+ 0, G_MAXINT, 0,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (PangoXftRendererPrivate));
+}
+
+static void
+pango_xft_renderer_finalize (GObject *object)
+{
+ PangoXftRenderer *renderer = PANGO_XFT_RENDERER (object);
+
+ if (renderer->priv->glyphs)
+ g_array_free (renderer->priv->glyphs, TRUE);
+ if (renderer->priv->trapezoids)
+ g_array_free (renderer->priv->trapezoids, TRUE);
+
+ G_OBJECT_CLASS (pango_xft_renderer_parent_class)->finalize (object);
+}
+
+static void
+pango_xft_renderer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (object);
+
+ switch (prop_id)
+ {
+ case PROP_DISPLAY:
+ xftrenderer->display = g_value_get_pointer (value);
+ /* We possibly should use ARGB format when subpixel-AA is turned
+ * on for the fontmap; we could discover that using the technique
+ * for FC_DPI in pango_fc_face_list_sizes.
+ */
+ xftrenderer->priv->mask_format = XRenderFindStandardFormat (xftrenderer->display,
+ PictStandardA8);
+ break;
+ case PROP_SCREEN:
+ xftrenderer->screen = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+pango_xft_renderer_set_pictures (PangoXftRenderer *renderer,
+ Picture src_picture,
+ Picture dest_picture)
+{
+ renderer->priv->src_picture = src_picture;
+ renderer->priv->dest_picture = dest_picture;
+}
+
+static void
+flush_glyphs (PangoXftRenderer *xftrenderer)
+{
+ XftFont *xft_font;
+
+ if (!xftrenderer->priv->glyphs ||
+ xftrenderer->priv->glyphs->len == 0)
+ return;
+
+ xft_font = pango_xft_font_get_font (xftrenderer->priv->glyph_font);
+
+ PANGO_XFT_RENDERER_GET_CLASS (xftrenderer)->composite_glyphs (xftrenderer,
+ xft_font,
+ (XftGlyphSpec *)xftrenderer->priv->glyphs->data,
+ xftrenderer->priv->glyphs->len);
+
+ g_array_set_size (xftrenderer->priv->glyphs, 0);
+ g_object_unref (xftrenderer->priv->glyph_font);
+ xftrenderer->priv->glyph_font = NULL;
+}
+
+#define MAX_GLYPHS 1024
+
+static void
+draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ FT_UInt glyph,
+ int x,
+ int y)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+ XftGlyphSpec gs;
+ int pixel_x, pixel_y;
+
+ if (renderer->matrix)
+ {
+ pixel_x = floor (0.5 + (x * renderer->matrix->xx + y * renderer->matrix->xy) / PANGO_SCALE + renderer->matrix->x0);
+ pixel_y = floor (0.5 + (x * renderer->matrix->yx + y * renderer->matrix->yy) / PANGO_SCALE + renderer->matrix->y0);
+ }
+ else
+ {
+ pixel_x = PANGO_PIXELS (x);
+ pixel_y = PANGO_PIXELS (y);
+ }
+
+ /* Clip glyphs into the X coordinate range; we really
+ * want to clip glyphs with an ink rect outside the
+ * [0,32767] x [0,32767] rectangle but looking up
+ * the ink rect here would be a noticeable speed hit.
+ * This is close enough.
+ */
+ if (pixel_x < -32768 || pixel_x > 32767 ||
+ pixel_y < -32768 || pixel_y > 32767)
+ return;
+
+ flush_trapezoids (xftrenderer);
+
+ if (!xftrenderer->priv->glyphs)
+ xftrenderer->priv->glyphs = g_array_new (FALSE, FALSE,
+ sizeof (XftGlyphSpec));
+
+ if (xftrenderer->priv->glyph_font != font ||
+ xftrenderer->priv->glyphs->len == MAX_GLYPHS)
+ {
+ flush_glyphs (xftrenderer);
+
+ xftrenderer->priv->glyph_font = g_object_ref (font);
+ }
+
+ gs.x = pixel_x;
+ gs.y = pixel_y;
+ gs.glyph = glyph;
+
+ g_array_append_val (xftrenderer->priv->glyphs, gs);
+}
+
+static gboolean
+point_in_bounds (PangoRenderer *renderer,
+ gint x,
+ gint y)
+{
+ gdouble pixel_x = (x * renderer->matrix->xx + y * renderer->matrix->xy) / PANGO_SCALE + renderer->matrix->x0;
+ gdouble pixel_y = (x * renderer->matrix->yx + y * renderer->matrix->yy) / PANGO_SCALE + renderer->matrix->y0;
+
+ return (pixel_x >= -32768. && pixel_x < 32768. &&
+ pixel_y >= -32768. && pixel_y < 32768.);
+}
+
+static gboolean
+box_in_bounds (PangoRenderer *renderer,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ if (!renderer->matrix)
+ {
+#define COORD_MIN (PANGO_SCALE * -16384 - PANGO_SCALE / 2)
+#define COORD_MAX (PANGO_SCALE * 32767 + PANGO_SCALE / 2 - 1)
+ return (x >= COORD_MIN && x + width <= COORD_MAX &&
+ y >= COORD_MIN && y + width <= COORD_MAX);
+#undef COORD_MIN
+#undef COORD_MAX
+ }
+ else
+ {
+ return (point_in_bounds (renderer, x, y) &&
+ point_in_bounds (renderer, x + width, y) &&
+ point_in_bounds (renderer, x + width, y + height) &&
+ point_in_bounds (renderer, x, y + height));
+ }
+}
+
+static void
+draw_box (PangoRenderer *renderer,
+ gint line_width,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ x, y, width, line_width);
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ x, y + line_width, line_width, height - line_width * 2);
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ x + width - line_width, y + line_width, line_width, height - line_width * 2);
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ x, y + height - line_width, width, line_width);
+}
+
+static void
+_pango_xft_renderer_draw_box_glyph (PangoRenderer *renderer,
+ PangoGlyphInfo *gi,
+ int glyph_x,
+ int glyph_y)
+{
+ int x = glyph_x + PANGO_SCALE;
+ int y = glyph_y - PANGO_SCALE * (PANGO_UNKNOWN_GLYPH_HEIGHT - 1);
+ int width = gi->geometry.width - PANGO_SCALE * 2;
+ int height = PANGO_SCALE * (PANGO_UNKNOWN_GLYPH_HEIGHT - 2);
+
+ if (box_in_bounds (renderer, x, y, width, height))
+ draw_box (renderer, PANGO_SCALE, x, y, width, height);
+}
+
+static void
+_pango_xft_renderer_draw_unknown_glyph (PangoRenderer *renderer,
+ PangoXftFont *xfont,
+ XftFont *xft_font,
+ PangoGlyphInfo *gi,
+ int glyph_x,
+ int glyph_y)
+{
+ char buf[7];
+ int ys[3];
+ int xs[4];
+ int row, col;
+ int cols;
+ PangoGlyph glyph;
+
+ PangoFont *mini_font = _pango_xft_font_get_mini_font (xfont);
+ XftFont *mini_xft_font = pango_xft_font_get_font (mini_font);
+ if (!mini_xft_font)
+ {
+ _pango_xft_renderer_draw_box_glyph (renderer, gi, glyph_x, glyph_y);
+ return;
+ }
+
+ glyph = gi->glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
+
+ ys[0] = glyph_y - PANGO_SCALE * xft_font->ascent + PANGO_SCALE * (((xft_font->ascent + xft_font->descent) - (xfont->mini_height * 2 + xfont->mini_pad * 5 + PANGO_SCALE / 2) / PANGO_SCALE) / 2);
+ ys[1] = ys[0] + 2 * xfont->mini_pad + xfont->mini_height;
+ ys[2] = ys[1] + xfont->mini_height + xfont->mini_pad;
+
+ xs[0] = glyph_x;
+ xs[1] = xs[0] + 2 * xfont->mini_pad;
+ xs[2] = xs[1] + xfont->mini_width + xfont->mini_pad;
+ xs[3] = xs[2] + xfont->mini_width + xfont->mini_pad;
+
+ if (glyph > 0xffff)
+ {
+ cols = 3;
+ g_snprintf (buf, sizeof(buf), "%06X", glyph);
+ }
+ else
+ {
+ cols = 2;
+ g_snprintf (buf, sizeof(buf), "%04X", glyph);
+ }
+
+ if (box_in_bounds (renderer,
+ xs[0], ys[0],
+ xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1),
+ xfont->mini_height * 2 + xfont->mini_pad * 5))
+ {
+ if (xfont->mini_pad)
+ draw_box (renderer, xfont->mini_pad,
+ xs[0], ys[0],
+ xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1),
+ xfont->mini_height * 2 + xfont->mini_pad * 5);
+
+ for (row = 0; row < 2; row++)
+ for (col = 0; col < cols; col++)
+ {
+ draw_glyph (renderer, mini_font,
+ XftCharIndex (NULL, mini_xft_font,
+ buf[row * cols + col] & 0xff),
+ xs[col+1],
+ ys[row+1]);
+ }
+ }
+}
+
+static void
+pango_xft_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ PangoXftFont *xfont = PANGO_XFT_FONT (font);
+ PangoFcFont *fcfont = PANGO_FC_FONT (font);
+ XftFont *xft_font = pango_xft_font_get_font (font);
+ int i;
+ int x_off = 0;
+
+ if (!fcfont)
+ {
+ for (i=0; i<glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+
+ if (gi->glyph != PANGO_GLYPH_EMPTY)
+ {
+ int glyph_x = x + x_off + gi->geometry.x_offset;
+ int glyph_y = y + gi->geometry.y_offset;
+
+ _pango_xft_renderer_draw_box_glyph (renderer, gi, glyph_x, glyph_y);
+ }
+
+ x_off += gi->geometry.width;
+ }
+ return;
+ }
+
+ if (!fcfont->fontmap) /* Display closed */
+ return;
+
+ for (i=0; i<glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+
+ if (gi->glyph != PANGO_GLYPH_EMPTY)
+ {
+ int glyph_x = x + x_off + gi->geometry.x_offset;
+ int glyph_y = y + gi->geometry.y_offset;
+
+ if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ _pango_xft_renderer_draw_unknown_glyph (renderer,
+ xfont,
+ xft_font,
+ gi,
+ glyph_x,
+ glyph_y);
+ }
+ else
+ {
+ draw_glyph (renderer, font, gi->glyph, glyph_x, glyph_y);
+ }
+ }
+
+ x_off += gi->geometry.width;
+ }
+}
+
+static void
+flush_trapezoids (PangoXftRenderer *xftrenderer)
+{
+ if (!xftrenderer->priv->trapezoids ||
+ xftrenderer->priv->trapezoids->len == 0)
+ return;
+
+ PANGO_XFT_RENDERER_GET_CLASS (xftrenderer)->composite_trapezoids (xftrenderer,
+ xftrenderer->priv->trapezoid_part,
+ (XTrapezoid *)xftrenderer->priv->trapezoids->data,
+ xftrenderer->priv->trapezoids->len);
+
+ g_array_set_size (xftrenderer->priv->trapezoids, 0);
+}
+
+static void
+pango_xft_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+ XTrapezoid trap;
+
+ flush_glyphs (xftrenderer);
+
+ if (!xftrenderer->priv->trapezoids)
+ xftrenderer->priv->trapezoids = g_array_new (FALSE, FALSE,
+ sizeof (XTrapezoid));
+
+ if (xftrenderer->draw)
+ {
+ if (xftrenderer->priv->trapezoids->len > 0 &&
+ xftrenderer->priv->trapezoid_part != part)
+ flush_trapezoids (xftrenderer);
+
+ xftrenderer->priv->trapezoid_part = part;
+ }
+
+ trap.top = XDoubleToFixed (y1);
+ trap.bottom = XDoubleToFixed (y2);
+ trap.left.p1.x = XDoubleToFixed (x11);
+ trap.left.p1.y = XDoubleToFixed (y1);
+ trap.left.p2.x = XDoubleToFixed (x12);
+ trap.left.p2.y = XDoubleToFixed (y2);
+ trap.right.p1.x = XDoubleToFixed (x21);
+ trap.right.p1.y = XDoubleToFixed (y1);
+ trap.right.p2.x = XDoubleToFixed (x22);
+ trap.right.p2.y = XDoubleToFixed (y2);
+
+ g_array_append_val (xftrenderer->priv->trapezoids, trap);
+}
+
+static void
+pango_xft_renderer_part_changed (PangoRenderer *renderer,
+ PangoRenderPart part)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+
+ if (part == PANGO_RENDER_PART_FOREGROUND)
+ flush_glyphs (xftrenderer);
+
+ if (part == xftrenderer->priv->trapezoid_part)
+ flush_trapezoids (xftrenderer);
+}
+
+static void
+pango_xft_renderer_end (PangoRenderer *renderer)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+
+ flush_glyphs (xftrenderer);
+ flush_trapezoids (xftrenderer);
+}
+
+static void
+pango_xft_renderer_real_composite_trapezoids (PangoXftRenderer *xftrenderer,
+ PangoRenderPart part,
+ XTrapezoid *trapezoids,
+ int n_trapezoids)
+{
+ Picture src_picture;
+ Picture dest_picture;
+
+ if (!XftDefaultHasRender (xftrenderer->display))
+ return;
+
+ if (xftrenderer->priv->src_picture != None)
+ {
+ src_picture = xftrenderer->priv->src_picture;
+ dest_picture = xftrenderer->priv->dest_picture;
+ }
+ else
+ {
+ XftColor xft_color;
+ PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (xftrenderer),
+ part);
+ if (!color)
+ color = &xftrenderer->priv->default_color;
+
+ xft_color.color.red = color->red;
+ xft_color.color.green = color->green;
+ xft_color.color.blue = color->blue;
+ xft_color.color.alpha = xftrenderer->priv->alpha;
+
+ src_picture = XftDrawSrcPicture (xftrenderer->draw, &xft_color);
+ dest_picture = XftDrawPicture (xftrenderer->draw);
+ }
+
+ XRenderCompositeTrapezoids (xftrenderer->display,
+ PictOpOver,
+ src_picture, dest_picture,
+ xftrenderer->priv->mask_format,
+ 0, 0,
+ trapezoids, n_trapezoids);
+}
+
+static void
+pango_xft_renderer_real_composite_glyphs (PangoXftRenderer *xftrenderer,
+ XftFont *xft_font,
+ XftGlyphSpec *glyphs,
+ int n_glyphs)
+{
+ if (xftrenderer->priv->src_picture != None)
+ {
+ XftGlyphSpecRender (xftrenderer->display, PictOpOver,
+ xftrenderer->priv->src_picture,
+ xft_font,
+ xftrenderer->priv->dest_picture, 0, 0,
+ glyphs, n_glyphs);
+ }
+ else
+ {
+ XftColor xft_color;
+ PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (xftrenderer),
+ PANGO_RENDER_PART_FOREGROUND);
+ if (!color)
+ color = &xftrenderer->priv->default_color;
+
+ xft_color.color.red = color->red;
+ xft_color.color.green = color->green;
+ xft_color.color.blue = color->blue;
+ xft_color.color.alpha = xftrenderer->priv->alpha;
+
+ XftDrawGlyphSpec (xftrenderer->draw, &xft_color,
+ xft_font,
+ glyphs, n_glyphs);
+ }
+}
+
+static PangoRenderer *
+get_renderer (PangoFontMap *fontmap,
+ XftDraw *draw,
+ XftColor *color)
+{
+ PangoRenderer *renderer;
+ PangoXftRenderer *xftrenderer;
+ PangoColor pango_color;
+
+ renderer = _pango_xft_font_map_get_renderer (PANGO_XFT_FONT_MAP (fontmap));
+ xftrenderer = PANGO_XFT_RENDERER (renderer);
+
+ pango_xft_renderer_set_draw (xftrenderer, draw);
+
+ pango_color.red = color->color.red;
+ pango_color.green = color->color.green;
+ pango_color.blue = color->color.blue;
+ pango_xft_renderer_set_default_color (xftrenderer, &pango_color);
+ xftrenderer->priv->alpha = color->color.alpha;
+
+ return renderer;
+}
+
+static void
+release_renderer (PangoRenderer *renderer)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+
+ xftrenderer->priv->alpha = 0xffff;
+}
+
+/**
+ * pango_xft_render_layout:
+ * @draw: an #XftDraw
+ * @color: the foreground color in which to draw the layout
+ * (may be overridden by color attributes)
+ * @layout: a #PangoLayout
+ * @x: the X position of the left of the layout (in Pango units)
+ * @y: the Y position of the top of the layout (in Pango units)
+ *
+ * Render a #PangoLayout onto a #XftDraw
+ *
+ * Since: 1.8
+ */
+void
+pango_xft_render_layout (XftDraw *draw,
+ XftColor *color,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ context = pango_layout_get_context (layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = get_renderer (fontmap, draw, color);
+
+ pango_renderer_draw_layout (renderer, layout, x, y);
+
+ release_renderer (renderer);
+}
+
+/**
+ * pango_xft_render_layout_line:
+ * @draw: an #XftDraw
+ * @color: the foreground color in which to draw the layout line
+ * (may be overridden by color attributes)
+ * @line: a #PangoLayoutLine
+ * @x: the x position of start of string (in Pango units)
+ * @y: the y position of baseline (in Pango units)
+ *
+ * Render a #PangoLayoutLine onto a #XftDraw
+ *
+ * Since: 1.8
+ */
+void
+pango_xft_render_layout_line (XftDraw *draw,
+ XftColor *color,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (line != NULL);
+
+ context = pango_layout_get_context (line->layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = get_renderer (fontmap, draw, color);
+
+ pango_renderer_draw_layout_line (renderer, line, x, y);
+
+ release_renderer (renderer);
+}
+
+/**
+ * pango_xft_render_transformed:
+ * @draw: an #XftDraw
+ * @color: the color in which to draw the glyphs
+ * @font: the font in which to draw the string
+ * @matrix: a #PangoMatrix, or %NULL to use an identity transformation
+ * @glyphs: the glyph string to draw
+ * @x: the x position of the start of the string (in Pango
+ * units in user space coordinates)
+ * @y: the y position of the baseline (in Pango units
+ * in user space coordinates)
+ *
+ * Renders a #PangoGlyphString onto a #XftDraw, possibly
+ * transforming the layed-out coordinates through a transformation
+ * matrix. Note that the transformation matrix for @font is not
+ * changed, so to produce correct rendering results, the @font
+ * must have been loaded using a #PangoContext with an identical
+ * transformation matrix to that passed in to this function.
+ *
+ * Since: 1.8
+ **/
+void
+pango_xft_render_transformed (XftDraw *draw,
+ XftColor *color,
+ PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (PANGO_XFT_IS_FONT (font));
+ g_return_if_fail (glyphs != NULL);
+
+ fontmap = PANGO_FC_FONT (font)->fontmap;
+ renderer = get_renderer (fontmap, draw, color);
+
+ pango_renderer_set_matrix (renderer, matrix);
+
+ pango_renderer_draw_glyphs (renderer, font, glyphs, x, y);
+
+ release_renderer (renderer);
+}
+
+/**
+ * pango_xft_render:
+ * @draw: the <type>XftDraw</type> object.
+ * @color: the color in which to draw the string
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Renders a #PangoGlyphString onto an <type>XftDraw</type> object wrapping an X drawable.
+ */
+void
+pango_xft_render (XftDraw *draw,
+ XftColor *color,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y)
+{
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (PANGO_XFT_IS_FONT (font));
+ g_return_if_fail (glyphs != NULL);
+
+ pango_xft_render_transformed (draw, color, NULL, font, glyphs,
+ x * PANGO_SCALE, y * PANGO_SCALE);
+}
+
+/**
+ * pango_xft_picture_render:
+ * @display: an X display
+ * @src_picture: the source picture to draw the string with
+ * @dest_picture: the destination picture to draw the string onto
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Renders a #PangoGlyphString onto an Xrender <type>Picture</type> object.
+ */
+void
+pango_xft_picture_render (Display *display,
+ Picture src_picture,
+ Picture dest_picture,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y)
+{
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (display != NULL);
+ g_return_if_fail (src_picture != None);
+ g_return_if_fail (dest_picture != None);
+ g_return_if_fail (PANGO_XFT_IS_FONT (font));
+ g_return_if_fail (glyphs != NULL);
+
+ fontmap = PANGO_FC_FONT (font)->fontmap;
+ renderer = _pango_xft_font_map_get_renderer (PANGO_XFT_FONT_MAP (fontmap));
+
+ pango_xft_renderer_set_pictures (PANGO_XFT_RENDERER (renderer),
+ src_picture, dest_picture);
+ pango_renderer_set_matrix (renderer, NULL);
+
+ pango_renderer_draw_glyphs (renderer, font, glyphs, x * PANGO_SCALE, y * PANGO_SCALE);
+
+ pango_xft_renderer_set_pictures (PANGO_XFT_RENDERER (renderer),
+ None, None);
+}
+
+/**
+ * pango_xft_renderer_new:
+ * @display: an X display
+ * @screen: the index of the screen for @display to which rendering will be done
+ *
+ * Create a new #PangoXftRenderer to allow rendering Pango objects
+ * with the Xft library. You must call pango_xft_renderer_set_draw() before
+ * using the renderer.
+ *
+ * Return value: the newly created #PangoXftRenderer, which should
+ * be freed with g_object_unref().
+ *
+ * Since: 1.8
+ **/
+PangoRenderer *
+pango_xft_renderer_new (Display *display,
+ int screen)
+{
+ PangoXftRenderer *xftrenderer;
+
+ xftrenderer = g_object_new (PANGO_TYPE_XFT_RENDERER,
+ "display", display,
+ "screen", screen,
+ NULL);
+
+ return PANGO_RENDERER (xftrenderer);
+}
+
+/**
+ * pango_xft_renderer_set_draw:
+ * @xftrenderer: a #PangoXftRenderer
+ * @draw: a #XftDraw
+ *
+ * Sets the #XftDraw object that the renderer is drawing to.
+ * The renderer must not be currently active.
+ *
+ * Since: 1.8
+ **/
+void
+pango_xft_renderer_set_draw (PangoXftRenderer *xftrenderer,
+ XftDraw *draw)
+{
+ g_return_if_fail (PANGO_IS_XFT_RENDERER (xftrenderer));
+
+ xftrenderer->draw = draw;
+}
+
+/**
+ * pango_xft_renderer_set_default_color:
+ * @xftrenderer: a #XftRenderer
+ * @default_color: the default foreground color
+ *
+ * Sets the default foreground color for a #XftRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_xft_renderer_set_default_color (PangoXftRenderer *xftrenderer,
+ PangoColor *default_color)
+{
+ g_return_if_fail (PANGO_IS_XFT_RENDERER (xftrenderer));
+
+ xftrenderer->priv->default_color = *default_color;
+}
diff --git a/trunk/pango/pangoxft-render.h b/trunk/pango/pangoxft-render.h
new file mode 100644
index 00000000..87c26a75
--- /dev/null
+++ b/trunk/pango/pangoxft-render.h
@@ -0,0 +1,141 @@
+/* Pango
+ * pangoxft-render.h: Rendering routines for the Xft library
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOXFT_RENDER_H__
+#define __PANGOXFT_RENDER_H__
+
+#include <pango/pango-renderer.h>
+
+G_BEGIN_DECLS
+
+#define _XFT_NO_COMPAT_
+#include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
+#if defined(XftVersion) && XftVersion >= 20000
+#else
+#error "must have Xft version 2 or newer"
+#endif
+
+typedef struct _PangoXftRenderer PangoXftRenderer;
+typedef struct _PangoXftRendererClass PangoXftRendererClass;
+typedef struct _PangoXftRendererPrivate PangoXftRendererPrivate;
+
+#define PANGO_TYPE_XFT_RENDERER (pango_xft_renderer_get_type())
+#define PANGO_XFT_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_RENDERER, PangoXftRenderer))
+#define PANGO_IS_XFT_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_RENDERER))
+#define PANGO_XFT_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_RENDERER, PangoXftRendererClass))
+#define PANGO_IS_XFT_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_RENDERER))
+#define PANGO_XFT_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_RENDERER, PangoXftRendererClass))
+
+/**
+ * PangoXftRenderer
+ *
+ * #PangoXftRenderer is a subclass of #PangoRenderer used for rendering
+ * with Pango's Xft backend. It can be used directly, or it can be
+ * further subclassed to modify exactly how drawing of individual
+ * elements occurs.
+ *
+ * Since: 1.8
+ */
+struct _PangoXftRenderer
+{
+ /*< private >*/
+ PangoRenderer parent_instance;
+
+ Display *display;
+ int screen;
+ XftDraw *draw;
+
+ PangoXftRendererPrivate *priv;
+};
+
+/**
+ * PangoXftRendererClass
+ * @composite_trapezoids: draw the specified trapezoids using
+ * the current color and other attributes for @part
+ * @composite_glyphs: draw the specified glyphs using
+ * the current foreground color and other foreground
+ * attributes
+ *
+ * The class structure for #PangoXftRenderer
+ *
+ * Since: 1.8
+ */
+struct _PangoXftRendererClass
+{
+ /*< private >*/
+ PangoRendererClass parent_class;
+
+ /*< public >*/
+ void (*composite_trapezoids) (PangoXftRenderer *xftrenderer,
+ PangoRenderPart part,
+ XTrapezoid *trapezoids,
+ int n_trapezoids);
+ void (*composite_glyphs) (PangoXftRenderer *xftrenderer,
+ XftFont *xft_font,
+ XftGlyphSpec *glyphs,
+ int n_glyphs);
+};
+
+GType pango_xft_renderer_get_type (void) G_GNUC_CONST;
+
+PangoRenderer *pango_xft_renderer_new (Display *display,
+ int screen);
+void pango_xft_renderer_set_draw (PangoXftRenderer *xftrenderer,
+ XftDraw *draw);
+void pango_xft_renderer_set_default_color (PangoXftRenderer *xftrenderer,
+ PangoColor *default_color);
+
+void pango_xft_render (XftDraw *draw,
+ XftColor *color,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_xft_picture_render (Display *display,
+ Picture src_picture,
+ Picture dest_picture,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_xft_render_transformed (XftDraw *draw,
+ XftColor *color,
+ PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+void pango_xft_render_layout_line (XftDraw *draw,
+ XftColor *color,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_xft_render_layout (XftDraw *draw,
+ XftColor *color,
+ PangoLayout *layout,
+ int x,
+ int y);
+
+G_END_DECLS
+
+#endif /* __PANGOXFT_RENDER_H__ */
+
diff --git a/trunk/pango/pangoxft.h b/trunk/pango/pangoxft.h
new file mode 100644
index 00000000..a84571a8
--- /dev/null
+++ b/trunk/pango/pangoxft.h
@@ -0,0 +1,94 @@
+/* Pango
+ * pangoxft.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 SuSE Linux Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOXFT_H__
+#define __PANGOXFT_H__
+
+#include <pango/pango-context.h>
+#include <pango/pango-ot.h>
+#include <pango/pangofc-font.h>
+#include <pango/pango-layout.h>
+#include <pango/pangoxft-render.h>
+
+G_BEGIN_DECLS
+
+#ifndef PANGO_DISABLE_DEPRECATED
+#define PANGO_RENDER_TYPE_XFT "PangoRenderXft"
+#endif
+
+#define PANGO_TYPE_XFT_FONT_MAP (pango_xft_font_map_get_type ())
+#define PANGO_XFT_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMap))
+#define PANGO_XFT_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT_MAP))
+
+typedef struct _PangoXftFontMap PangoXftFontMap;
+
+typedef struct _PangoXftFont PangoXftFont;
+
+typedef void (*PangoXftSubstituteFunc) (FcPattern *pattern,
+ gpointer data);
+
+/* Calls for applications
+ */
+PangoFontMap *pango_xft_get_font_map (Display *display,
+ int screen);
+PangoContext *pango_xft_get_context (Display *display,
+ int screen);
+void pango_xft_shutdown_display (Display *display,
+ int screen);
+
+void pango_xft_set_default_substitute (Display *display,
+ int screen,
+ PangoXftSubstituteFunc func,
+ gpointer data,
+ GDestroyNotify notify);
+void pango_xft_substitute_changed (Display *display,
+ int screen);
+
+GType pango_xft_font_map_get_type (void) G_GNUC_CONST;
+
+#define PANGO_XFT_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT, PangoXftFont))
+#define PANGO_TYPE_XFT_FONT (pango_xft_font_get_type ())
+#define PANGO_XFT_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT))
+
+GType pango_xft_font_get_type (void) G_GNUC_CONST;
+
+/* For shape engines
+ */
+
+#ifdef PANGO_ENABLE_ENGINE
+XftFont * pango_xft_font_get_font (PangoFont *font);
+Display * pango_xft_font_get_display (PangoFont *font);
+#ifndef PANGO_DISABLE_DEPRECATED
+FT_Face pango_xft_font_lock_face (PangoFont *font);
+void pango_xft_font_unlock_face (PangoFont *font);
+guint pango_xft_font_get_glyph (PangoFont *font,
+ gunichar wc);
+gboolean pango_xft_font_has_char (PangoFont *font,
+ gunichar wc);
+PangoGlyph pango_xft_font_get_unknown_glyph (PangoFont *font,
+ gunichar wc);
+#endif /* PANGO_DISABLE_DEPRECATED */
+#endif /* PANGO_ENABLE_ENGINE */
+
+G_END_DECLS
+
+#endif /* __PANGOXFT_H__ */
diff --git a/trunk/pango/querymodules.c b/trunk/pango/querymodules.c
new file mode 100644
index 00000000..cf721423
--- /dev/null
+++ b/trunk/pango/querymodules.c
@@ -0,0 +1,284 @@
+/* Pango
+ * querymodules.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <config.h>
+
+#include <glib.h>
+#include <gmodule.h>
+#include "pango-break.h"
+#include "pango-context.h"
+#include "pango-impl-utils.h"
+#include "pango-engine.h"
+#include "pango-enum-types.h"
+
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <glib/gprintf.h>
+
+#ifdef USE_LA_MODULES
+#define SOEXT ".la"
+#else
+#define SOEXT ("." G_MODULE_SUFFIX)
+#endif
+#define SOEXT_LEN ((int) strlen (SOEXT))
+
+static gboolean
+string_needs_escape (const char *str)
+{
+ while (TRUE)
+ {
+ char c = *str++;
+
+ if (!c)
+ return FALSE;
+ else if (c == '\"' || c == '\\' || g_ascii_isspace (c))
+ return TRUE;
+ }
+}
+
+static char *
+escape_string (const char *str)
+{
+ GString *result = g_string_new (NULL);
+
+ while (TRUE)
+ {
+ char c = *str++;
+
+ switch (c)
+ {
+ case '\0':
+ goto done;
+ case '\n':
+ g_string_append (result, "\\n");
+ break;
+ case '\"':
+ g_string_append (result, "\\\"");
+ break;
+ case '\\':
+ g_string_append (result, "\\\\");
+ break;
+ default:
+ g_string_append_c (result, c);
+ }
+ }
+
+ done:
+ return g_string_free (result, FALSE);
+}
+
+#define GET_SYMBOL(module,name,location) \
+ g_module_symbol (module, name, (gpointer *)(void *)&location)
+
+static const char *
+string_from_script (PangoScript script)
+{
+ static GEnumClass *class = NULL;
+ GEnumValue *value;
+ if (!class)
+ class = g_type_class_ref (PANGO_TYPE_SCRIPT);
+
+ value = g_enum_get_value (class, script);
+ if (!value)
+ {
+ g_warning ("Engine reported invalid script value %d\n", script);
+ return string_from_script (PANGO_SCRIPT_INVALID_CODE);
+ }
+
+ return value->value_nick;
+}
+
+static void
+query_module (const char *dir, const char *name)
+{
+ void (*list) (PangoEngineInfo **engines, gint *n_engines);
+ void (*init) (GTypeModule *module);
+ void (*exit) (void);
+ PangoEngine *(*create) (const gchar *id);
+
+ GModule *module;
+ gchar *path;
+
+ if (g_path_is_absolute (name))
+ path = g_strdup (name);
+ else
+ path = g_build_filename (dir, name, NULL);
+
+ module = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+
+ if (!module)
+ g_printerr ("Cannot load module %s: %s\n", path, g_module_error ());
+
+ if (module &&
+ GET_SYMBOL (module, "script_engine_list", list) &&
+ GET_SYMBOL (module, "script_engine_init", init) &&
+ GET_SYMBOL (module, "script_engine_exit", exit) &&
+ GET_SYMBOL (module, "script_engine_create", create))
+ {
+ gint i,j;
+ PangoEngineInfo *engines;
+ gint n_engines;
+
+ (*list) (&engines, &n_engines);
+
+ for (i=0; i<n_engines; i++)
+ {
+ const gchar *quote;
+ gchar *quoted_path;
+
+ if (string_needs_escape (path))
+ {
+ quote = "\"";
+ quoted_path = escape_string (path);
+ }
+ else
+ {
+ quote = "";
+ quoted_path = g_strdup (path);
+ }
+
+ g_printf ("%s%s%s %s %s %s", quote, quoted_path, quote,
+ engines[i].id, engines[i].engine_type, engines[i].render_type);
+ g_free (quoted_path);
+
+ for (j=0; j < engines[i].n_scripts; j++)
+ {
+ g_printf (" %s:%s",
+ string_from_script (engines[i].scripts[j].script),
+ engines[i].scripts[j].langs);
+ }
+ g_printf ("\n");
+ }
+ }
+ else
+ {
+ g_printerr ("%s does not export Pango module API\n", path);
+ }
+
+ g_free (path);
+ if (module)
+ g_module_close (module);
+}
+
+static gboolean
+show_version(const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ g_printf("pango-querymodules (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ g_printf("module interface version: %s\n", MODULE_VERSION);
+ exit(0);
+}
+
+int
+main (int argc, char **argv)
+{
+ char *cwd;
+ int i;
+ char *path;
+ GOptionContext *context;
+ GError *parse_error = NULL;
+ GOptionEntry entries[] =
+ {
+ {"version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &show_version,
+ "Show version numbers", NULL},
+ {NULL}
+ };
+
+ context = g_option_context_new ("- [MODULE]...");
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ if (!g_option_context_parse (context, &argc, &argv, &parse_error))
+ {
+ if (parse_error != NULL)
+ {
+ g_printerr("Parse option error: %s\n", parse_error->message);
+ }
+ else
+ {
+ g_printerr("Parse option error\n");
+ }
+ exit(1);
+ }
+
+ g_option_context_free(context);
+
+ g_type_init ();
+
+ g_printf ("# Pango Modules file\n"
+ "# Automatically generated file, do not edit\n"
+ "#\n");
+
+ if (argc == 1) /* No arguments given */
+ {
+ char **dirs;
+ int i;
+
+ path = pango_config_key_get ("Pango/ModulesPath");
+ if (!path)
+ path = g_build_filename (pango_get_lib_subdirectory (),
+ MODULE_VERSION,
+ "modules",
+ NULL);
+
+ g_printf ("# ModulesPath = %s\n#\n", path);
+
+ dirs = pango_split_file_list (path);
+
+ g_free (path);
+
+ for (i=0; dirs[i]; i++)
+ {
+ GDir *dir = g_dir_open (dirs[i], 0, NULL);
+ if (dir)
+ {
+ const char *dent;
+
+ while ((dent = g_dir_read_name (dir)))
+ {
+ int len = strlen (dent);
+ if (len > SOEXT_LEN && strcmp (dent + len - SOEXT_LEN, SOEXT) == 0)
+ query_module (dirs[i], dent);
+ }
+
+ g_dir_close (dir);
+ }
+ }
+
+ g_strfreev (dirs);
+ }
+ else
+ {
+ cwd = g_get_current_dir ();
+
+ for (i=1; i<argc; i++)
+ query_module (cwd, argv[i]);
+
+ g_free (cwd);
+ }
+
+ return 0;
+}
diff --git a/trunk/pango/reorder-items.c b/trunk/pango/reorder-items.c
new file mode 100644
index 00000000..23ba5836
--- /dev/null
+++ b/trunk/pango/reorder-items.c
@@ -0,0 +1,114 @@
+/* Pango
+ * reorder-items.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "pango-glyph.h"
+
+/*
+ * NB: The contents of the file implement the exact same algorithm
+ * pango-layout.c:pango_layout_line_reorder().
+ */
+
+static GList *reorder_items_recurse (GList *items, int n_items);
+
+/**
+ * pango_reorder_items:
+ * @logical_items: a #GList of #PangoItem in logical order.
+ *
+ * From a list of items in logical order and the associated
+ * directional levels, produce a list in visual order.
+ * The original list is unmodified.
+ *
+ * Returns a #GList of #PangoItem structures in visual order.
+ *
+ * (Please open a bug if you use this function.
+ * It is not a particularly convenient interface, and the code
+ * is duplicated elsewhere in Pango for that reason.)
+ */
+GList *
+pango_reorder_items (GList *logical_items)
+{
+ return reorder_items_recurse (logical_items, g_list_length (logical_items));
+}
+
+static GList *
+reorder_items_recurse (GList *items, int n_items)
+{
+ GList *tmp_list, *level_start_node;
+ int i, level_start_i;
+ int min_level = G_MAXINT;
+ GList *result = NULL;
+
+ if (n_items == 0)
+ return NULL;
+
+ tmp_list = items;
+ for (i=0; i<n_items; i++)
+ {
+ PangoItem *item = tmp_list->data;
+
+ min_level = MIN (min_level, item->analysis.level);
+
+ tmp_list = tmp_list->next;
+ }
+
+ level_start_i = 0;
+ level_start_node = items;
+ tmp_list = items;
+ for (i=0; i<n_items; i++)
+ {
+ PangoItem *item = tmp_list->data;
+
+ if (item->analysis.level == min_level)
+ {
+ if (min_level % 2)
+ {
+ if (i > level_start_i)
+ result = g_list_concat (reorder_items_recurse (level_start_node, i - level_start_i), result);
+ result = g_list_prepend (result, item);
+ }
+ else
+ {
+ if (i > level_start_i)
+ result = g_list_concat (result, reorder_items_recurse (level_start_node, i - level_start_i));
+ result = g_list_append (result, item);
+ }
+
+ level_start_i = i + 1;
+ level_start_node = tmp_list->next;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (min_level % 2)
+ {
+ if (i > level_start_i)
+ result = g_list_concat (reorder_items_recurse (level_start_node, i - level_start_i), result);
+ }
+ else
+ {
+ if (i > level_start_i)
+ result = g_list_concat (result, reorder_items_recurse (level_start_node, i - level_start_i));
+ }
+
+ return result;
+}
diff --git a/trunk/pango/shape.c b/trunk/pango/shape.c
new file mode 100644
index 00000000..96bcb672
--- /dev/null
+++ b/trunk/pango/shape.c
@@ -0,0 +1,139 @@
+/* Pango
+ * shape.c: Convert characters into glyphs.
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "pango-impl-utils.h"
+#include "pango-glyph.h"
+#include "pango-engine-private.h"
+
+/**
+ * pango_shape:
+ * @text: the text to process
+ * @length: the length (in bytes) of @text
+ * @analysis: #PangoAnalysis structure from pango_itemize()
+ * @glyphs: glyph string in which to store results
+ *
+ * Given a segment of text and the corresponding
+ * #PangoAnalysis structure returned from pango_itemize(),
+ * convert the characters into glyphs. You may also pass
+ * in only a substring of the item from pango_itemize().
+ */
+void
+pango_shape (const gchar *text,
+ gint length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ int i;
+ int last_cluster;
+
+ glyphs->num_glyphs = 0;
+
+ if (G_LIKELY (PANGO_IS_ENGINE_SHAPE (analysis->shape_engine) && PANGO_IS_FONT (analysis->font)))
+ {
+ _pango_engine_shape_shape (analysis->shape_engine, analysis->font,
+ text, length, analysis, glyphs);
+
+ if (G_UNLIKELY (glyphs->num_glyphs == 0))
+ {
+ /* If a font has been correctly chosen, but no glyphs are output,
+ * there's probably something wrong with the shaper. Trying to be
+ * informative, we print out the font description, but to not
+ * flood the terminal with zillions of the message, we set a flag
+ * on the font to only err once per font.
+ */
+ static GQuark warned_quark = 0;
+
+ if (!warned_quark)
+ warned_quark = g_quark_from_static_string ("pango-shaper-warned");
+
+ if (!g_object_get_qdata (G_OBJECT (analysis->font), warned_quark))
+ {
+ PangoFontDescription *desc;
+ char *s;
+
+ desc = pango_font_describe (analysis->font);
+ s = pango_font_description_to_string (desc);
+ pango_font_description_free (desc);
+
+ /* TODO: Write out the beginning excerpt of text here? */
+ g_warning ("shape engine failure, expect ugly output. the offending font is '%s'", s);
+
+ g_free (s);
+
+ g_object_set_qdata_full (G_OBJECT (analysis->font), warned_quark,
+ GINT_TO_POINTER (1), NULL);
+ }
+ }
+ }
+ else
+ {
+ if (!PANGO_IS_ENGINE_SHAPE (analysis->shape_engine) &&
+ !_pango_warning_history.shape_shape_engine)
+ {
+ _pango_warning_history.shape_shape_engine = TRUE;
+ g_warning ("pango_shape called with bad shape_engine, expect ugly output");
+ }
+ if (!PANGO_IS_FONT (analysis->font) &&
+ !_pango_warning_history.shape_font)
+ {
+ _pango_warning_history.shape_font = TRUE;
+ g_warning ("pango_shape called with bad font, expect ugly output");
+ }
+
+ glyphs->num_glyphs = 0;
+ }
+
+ if (!glyphs->num_glyphs)
+ {
+ PangoEngineShape *fallback_engine = _pango_get_fallback_shaper ();
+
+ _pango_engine_shape_shape (fallback_engine, analysis->font,
+ text, length, analysis, glyphs);
+ }
+
+ /* make sure last_cluster is invalid */
+ last_cluster = glyphs->log_clusters[0] - 1;
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ /* Set glyphs[i].attr.is_cluster_start based on log_clusters[]
+ */
+ if (glyphs->log_clusters[i] != last_cluster)
+ {
+ glyphs->glyphs[i].attr.is_cluster_start = TRUE;
+ last_cluster = glyphs->log_clusters[i];
+ }
+ else
+ glyphs->glyphs[i].attr.is_cluster_start = FALSE;
+
+
+ /* Shift glyph if width is negative, and negate width.
+ * This is useful for rotated font matrices and shouldn't
+ * harm in normal cases.
+ */
+ if (glyphs->glyphs[i].geometry.width < 0)
+ {
+ glyphs->glyphs[i].geometry.width = -glyphs->glyphs[i].geometry.width;
+ glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[i].geometry.width;
+ }
+ }
+}
diff --git a/trunk/pangocairo-uninstalled.pc.in b/trunk/pangocairo-uninstalled.pc.in
new file mode 100644
index 00000000..69849e86
--- /dev/null
+++ b/trunk/pangocairo-uninstalled.pc.in
@@ -0,0 +1,7 @@
+Name: Pango Cairo Uninstalled
+Description: Cairo rendering support for Pango, Not Installed
+Version: @VERSION@
+Requires: pango cairo @PKGCONFIG_CAIRO_REQUIRES@
+Libs: ${pc_top_builddir}/${pcfiledir}/pango/libpangocairo-@PANGO_API_VERSION@.la @PKGCONFIG_CAIRO_LIBS@
+Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@
+
diff --git a/trunk/pangocairo.pc.in b/trunk/pangocairo.pc.in
new file mode 100644
index 00000000..8dbcfacc
--- /dev/null
+++ b/trunk/pangocairo.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Pango Cairo
+Description: Cairo rendering support for Pango
+Version: @VERSION@
+Requires: pango cairo @PKGCONFIG_CAIRO_REQUIRES@
+Libs: -L${libdir} -lpangocairo-@PANGO_API_VERSION@ @PKGCONFIG_CAIRO_LIBS@
+Cflags: -I${includedir}/pango-1.0
diff --git a/trunk/pangoft2-uninstalled.pc.in b/trunk/pangoft2-uninstalled.pc.in
new file mode 100644
index 00000000..01c38bf7
--- /dev/null
+++ b/trunk/pangoft2-uninstalled.pc.in
@@ -0,0 +1,7 @@
+Name: Pango FT2 Uninstalled
+Description: Freetype 2.0 font support for Pango, Not Installed
+Version: @VERSION@
+Requires: pango
+Libs: ${pc_top_builddir}/${pcfiledir}/pango/libpangoft2-@PANGO_API_VERSION@.la @FREETYPE_LIBS@
+Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@ @FREETYPE_CFLAGS@
+
diff --git a/trunk/pangoft2.pc.in b/trunk/pangoft2.pc.in
new file mode 100644
index 00000000..13ace234
--- /dev/null
+++ b/trunk/pangoft2.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Pango FT2
+Description: Freetype 2.0 font support for Pango
+Version: @VERSION@
+Requires: pango
+Libs: -L${libdir} -lpangoft2-@PANGO_API_VERSION@ @PKGCONFIG_FREETYPE_LIBS@
+Cflags: -I${includedir}/pango-1.0 @FONTCONFIG_CFLAGS@ @FREETYPE_CFLAGS@
+
diff --git a/trunk/pangowin32-uninstalled.pc.in b/trunk/pangowin32-uninstalled.pc.in
new file mode 100644
index 00000000..5541c4e4
--- /dev/null
+++ b/trunk/pangowin32-uninstalled.pc.in
@@ -0,0 +1,6 @@
+Name: Pango Win32 Uninstalled
+Description: Win32 GDI font support for Pango, Not Installed
+Version: @VERSION@
+Requires: pango
+Libs: ${pc_top_builddir}/${pcfiledir}/pango/libpangowin32.la @WIN32_LIBS@
+Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@
diff --git a/trunk/pangowin32.pc.in b/trunk/pangowin32.pc.in
new file mode 100644
index 00000000..ab74a201
--- /dev/null
+++ b/trunk/pangowin32.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Pango Win32
+Description: Win32 GDI font support for Pango
+Version: @VERSION@
+Requires: pango
+Libs: -L${libdir} -lpangowin32-@PANGO_API_VERSION@
+Cflags: -I${includedir}/pango-1.0
+
diff --git a/trunk/pangox-uninstalled.pc.in b/trunk/pangox-uninstalled.pc.in
new file mode 100644
index 00000000..34e2655c
--- /dev/null
+++ b/trunk/pangox-uninstalled.pc.in
@@ -0,0 +1,6 @@
+Name: Pango X Uninstalled
+Description: X Window System font support for Pango, Not Installed
+Version: @VERSION@
+Requires: pango
+Libs: ${pc_top_builddir}/${pcfiledir}/pango/libpangox-@PANGO_API_VERSION@.la @X_LIBS@
+Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@
diff --git a/trunk/pangox.pc.in b/trunk/pangox.pc.in
new file mode 100644
index 00000000..bb7ff511
--- /dev/null
+++ b/trunk/pangox.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Pango X
+Description: X Window System font support for Pango
+Version: @VERSION@
+Requires: pango
+Libs: -L${libdir} -lpangox-@PANGO_API_VERSION@ @PKGCONFIG_X_LIBS@
+Cflags: -I${includedir}/pango-1.0 @X_CFLAGS@
+
diff --git a/trunk/pangoxft-uninstalled.pc.in b/trunk/pangoxft-uninstalled.pc.in
new file mode 100644
index 00000000..97a6bb55
--- /dev/null
+++ b/trunk/pangoxft-uninstalled.pc.in
@@ -0,0 +1,7 @@
+Name: Pango Xft Uninstalled
+Description: Xft font support for Pango, Not Installed
+Version: @VERSION@
+Requires: pango
+Libs: ${pc_top_builddir}/${pcfiledir}/pango/libpangoxft-@PANGO_API_VERSION@.la @XFT_LIBS@
+Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@ @X_CFLAGS@ @FREETYPE_CFLAGS@
+
diff --git a/trunk/pangoxft.pc.in b/trunk/pangoxft.pc.in
new file mode 100644
index 00000000..46c2183d
--- /dev/null
+++ b/trunk/pangoxft.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Pango Xft
+Description: Xft font support for Pango
+Version: @VERSION@
+Requires: pango pangoft2
+Libs: -L${libdir} -lpangoxft-@PANGO_API_VERSION@ @PKGCONFIG_XFT_LIBS@
+Cflags: -I${includedir}/pango-1.0 @XFT_CFLAGS@
diff --git a/trunk/sanitize-la.sh b/trunk/sanitize-la.sh
new file mode 100755
index 00000000..9bc0ba2b
--- /dev/null
+++ b/trunk/sanitize-la.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+sed "s/dependency_libs=.*/dependency_libs=''/" < $1 > $1T && mv $1T $1
diff --git a/trunk/tests/Makefile.am b/trunk/tests/Makefile.am
new file mode 100644
index 00000000..f1b24a42
--- /dev/null
+++ b/trunk/tests/Makefile.am
@@ -0,0 +1,75 @@
+## Process this file with automake to create Makefile.in.
+
+EXTRA_DIST = \
+ all-unicode.txt \
+ boundaries.utf8 \
+ runtests.sh
+
+CLEANFILES = pangorc
+DISTCLEANFILES = all-unicode.txt runtests.log
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(PANGO_DEBUG_FLAGS) \
+ $(GLIB_CFLAGS) \
+ $(XFT_CFLAGS) \
+ $(CAIRO_CFLAGS) \
+ $(FREETYPE_CFLAGS) \
+ $(X_CFLAGS)
+
+if HAVE_XFT
+INCLUDES += -DHAVE_X
+endif
+if HAVE_XFT
+INCLUDES += -DHAVE_XFT
+endif
+if HAVE_FREETYPE
+INCLUDES += -DHAVE_FREETYPE
+endif
+if HAVE_WIN32
+INCLUDES += -DHAVE_WIN32
+endif
+
+
+if CROSS_COMPILING
+TESTS=
+else
+TESTS=runtests.sh
+endif
+
+TESTS_ENVIRONMENT = \
+ srcdir=$(srcdir) \
+ PANGO_RC_FILE=./pangorc
+
+noinst_PROGRAMS = gen-all-unicode dump-boundaries
+
+check_PROGRAMS = testboundaries testcolor testscript
+
+if HAVE_CAIRO
+check_PROGRAMS += testiter
+endif
+if HAVE_FREETYPE
+check_PROGRAMS += test-ot-tags
+endif
+
+gen_all_unicode_LDADD = $(GLIB_LIBS)
+testboundaries_LDADD = ../pango/libpango-$(PANGO_API_VERSION).la
+testcolor_LDADD = ../pango/libpango-$(PANGO_API_VERSION).la
+testiter_LDADD = ../pango/libpango-$(PANGO_API_VERSION).la ../pango/libpangocairo-$(PANGO_API_VERSION).la
+testscript_LDADD = ../pango/libpango-$(PANGO_API_VERSION).la
+test_ot_tags_LDADD = ../pango/libpango-$(PANGO_API_VERSION).la ../pango/libpangoft2-$(PANGO_API_VERSION).la
+
+dump_boundaries_LDADD = ../pango/libpango-$(PANGO_API_VERSION).la
+
+if HAVE_CXX
+check_PROGRAMS += cxx-test
+endif
+cxx_test_SOURCES = cxx-test.C
+
+all-unicode.txt: gen-all-unicode$(EXEEXT)
+ ./gen-all-unicode > all-unicode.txt
+
+pangorc: $(srcdir)/../modules/pangorc
+ cp $(srcdir)/../modules/pangorc $@
+
+$(noinst_PROGRAMS) $(check_PROGRAMS): pangorc
diff --git a/trunk/tests/boundaries.utf8 b/trunk/tests/boundaries.utf8
new file mode 100644
index 00000000..28782a82
--- /dev/null
+++ b/trunk/tests/boundaries.utf8
@@ -0,0 +1,765 @@
+Testing sentence boundaries - this is a sentence ending in several exclamation points!!! Several spaces there. Abbreviations such as Mr. or Mrs. should not result in sentence breaks, should they?! (Parentheses should be included in a sentence.) (((Even nested parentheses, with funny punctuation inside!!?!!...))) Anyhow, this should be enough testing.
+
+This text has carriage returns
+all over the freaking place
+ such as here here and here
+
+but not at the end of this line.
+
+This is some "quoted" text e.g. "this is some stuff in quotes" and
+'this is some other stuff in single quotes' and ""this is some stuff with
+two levels of double quotes"" and so on.
+
+Big string of Arabic:
+وقد بدأ ثلاث من أكثر المؤسسات تقدما ÙÙŠ شبكة اكسيون برامجها كمنظمات لا تسعى للربح، ثم تحولت ÙÙŠ السنوات الخمس الماضية إلى مؤسسات مالية منظمة، وباتت جزءا من النظام المالي ÙÙŠ بلدانها، ولكنها تتخصص ÙÙŠ خدمة قطاع المشروعات الصغيرة. وأحد أكثر هذه المؤسسات نجاحا هو »بانكوسول« ÙÙŠ بوليÙيا.
+
+
+Παν語
+
+This is a list of ways to say hello in various languages. Its purpose is to illustrate a number of scripts.
+
+(Converted into UTF-8)
+
+---------------------------------------------------------
+Arabic السلام عليكم
+Bengali (বাঙà§à¦²à¦¾) ষাগতোম
+Burmese (မ္ရန္မာ)
+Cherokee (á£áŽ³áŽ©) Ꭳáá²
+Czech (Äesky) Dobrý den
+Danish (Dansk) Hej, Goddag
+English Hello
+Esperanto Saluton
+Estonian Tere, Tervist
+FORTRAN PROGRAM
+Finnish (Suomi) Hei
+French (Français) Bonjour, Salut
+German (Deutsch Nord) Guten Tag
+German (Deutsch Süd) Grüß Gott
+Georgian (ქáƒáƒ áƒ—ველი) გáƒáƒ›áƒáƒ áƒ¯áƒáƒ‘áƒ
+Gujarati (ગà«àªœàª°àª¾àª¤àª¿)
+Greek (Ελληνικά) Γειά σας
+Hebrew שלו×
+Hindi नमसà¥à¤¤à¥‡, नमसà¥à¤•à¤¾à¤°à¥¤
+Italiano Ciao, Buon giorno
+ɪŋglɪʃ hɛləʊ
+Maltese Ċaw, Saħħa
+Nederlands, Vlaams Hallo, Dag
+Norwegian (Norsk) Hei, God dag
+Punjabi (à©à¨ªà©à¨‚ਜਾਬਿ)
+Polish Dzień dobry, Hej
+Russian (РуÑÑкий) ЗдравÑтвуйте!
+Slovak Dobrý deň
+Spanish (Español) ‎¡Hola!‎
+Swedish (Svenska) Hej, Goddag
+Thai (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ
+Turkish (Türkçe) Merhaba
+Vietnamese (Tiếng Việt) Xin Chào
+Yiddish (ײַדישע) ד×ָס הײַזעלע
+
+Japanese (日本語) ã“ã‚“ã«ã¡ã¯, コï¾ï¾†ï¾ï¾Š
+Chinese (中文,普通è¯,汉语) 你好
+Cantonese (粵語,廣æ±è©±) 早晨, 你好
+Korean (한글) 안녕하세요, 안녕하십니까
+
+Difference among chinese characters in GB, JIS, KSC, BIG5:‎
+ GB -- 元气 å¼€å‘
+ JIS -- 元気 開発
+ KSC -- 元氣 開發
+ BIG5 -- 元氣 開發
+
+
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á…¦
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ à¤
+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+ᆹ
+
+ 

+

+
à¤
+
+ 
 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᆩ က
+
+
 á…  â½” 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 
ᅦ
+ 
 ᆹ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᅡ က
+
+ᄅ


+ 
 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
 

+
+ᆨ
+
+ ᅡ ᆩ
+
+ᄅ 
 

+
+ 

+
+ â½” ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᆹ
+
+
+ 

+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
 á… 
+
+ 

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ á… 
+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á„€
+
 
 

+
+ 

+ 

+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
+
+ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+⽔

+
+⽔
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 
 
 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+
+
+á… 
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 

+
+ 
ᆨ
+ ᆨ
+

+
+ à¤
+ 
 ᅦॠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
à¤
+ 

+á…  
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á… 
+

ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ á…¦
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ à³à¤â€© á„€ 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€à³
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄅᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+á… 
+ ᄠ
 
 ᆨᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ むᆹ
+
+ᆹ
+

+
+

+
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む


+
+
 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
+
+
+
+
+
+
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+
+ á… ã‚€
+
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+
+
+
+
+
+
+ à¤
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 

+ᆩ
+á… 
+
 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むむ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+à³
+
+á…¡
+က á…  ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+à¤á…¦
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
ᄀà¤á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
 ᄀᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 

 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᆨᅦ
+
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 
 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+
+
ᅠ á„€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€à¥
+
 ठᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᆨ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
ॠᄠ

+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ à³
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+à¤
+
+ᄀᄅ
+á„€ á…¡
+à¤
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ á…¦ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ à³
+
+
+
+

+á… 
+
+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á„… 

+
+
+
+

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ 

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+á„€
+
+ᆩ ᆩ
+
+ ⽔ᆩ
+á…¡
+

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᅦ
+
+ᄀ
 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á„€
+ ᄀ

+
+
+ むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ 

+
+ ᆹᅠ
+ à¥
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 
ᅠ
+
+
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+à¥
+
+ 

+
 á…¡ 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ á„€
+ᄅ

+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+
+ᅡᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+

+
 

+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ က
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ à³á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ à¤á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”む

+
+
+á„€
+ ᆹᄅ
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+à¥
+
+ ã‚€
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
+ 

+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+á…¦
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
 

+
+ 

ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ à³
+
+ ᅦက ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
 à¤
+
+
+
 

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+
+á…¡
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ à¤á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+ೠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
 

+ॠà¥â€©
+
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+

+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+ 
 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+á… 
+
+
+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
 ⽔ᅦá„
+
က
+ 
 ᄅᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ à³â½”
+
+
+ 

+
+ むठ⽔
+
+
+

+
+
+ à³
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á…¡ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄅ
+
+á…¡ à¥â€©
+
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 


+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€à¤
+á„ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
 ã‚€ ᅦᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ᄠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á„€
+
+ॠ⽔ᄀ
+
+
+
+ ೠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᆹ ᆨ
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+

+ᅦᆹᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+

 ᄀ
+ ᄀᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むむᄀᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€à³
+ 

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
à¥â€©á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”むᅠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀ
 à¤
+ᄀᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むೠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 


+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᅠ
+ 

+
+
+
+
 ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á…¦ 
က

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むむ 

+à¥â€©
+ 
 ᅠ
+
+ 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ 

ᄅ
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ᅠ ᅠ 

+
+ 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ က
 
ᅠ
+ á„… ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᆹ
+
+⽔む
+á…¦
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むက
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€à³
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€à³â€©
+ ᆩ
+ᆨ
+

+

+
+ 

 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+á… 
+
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+á„…
+က ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ೠ

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄅᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+ ᆩ
+
+
+ 
ᆨà¥â€©
+
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ॠ



+ ᅦ 

+
+
+

+ ᆨ
+
+
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ã‚€
+ 

 ᆨ
+
ᆹ 
 ᄠ

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
+
 
 

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ठᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ã‚€
+

+â½”à¥
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
 
ᅠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
ᄠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
 â½”
+ 

+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+⽔ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
+
 
 ᄅ
 ᄀ 

+á„… ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄠ
 
á„
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ 

+
+
+
+á„
+
+
+ 

+ ကᄀ
+
+ á…¦
+
+ á…¡
+
+ 


+
+
+ ठᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 
à³â€©â€©
+á…  ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+

+
+

 á…¡á…¦ 
 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ã‚€
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

ᆩ
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᆨ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+á„…
+
+ᆨ
 

+
+
むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ â½” â½”
+
+á„€
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᆨ â½” ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
 ᄀᄀ
+á… 
+ᆨ
+ 

+
+
+ᆩ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む⽔
ᅡ
 

+ 
 

+ á„…
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᆩ
+ á„… ᆹ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€à¥
+
 

+
+ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ကᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀ á… 
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᆩ
+ 

+

+ᆨᄅ
+á„…
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+
+

+ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄅ
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+á…  
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+

+က
+ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 

 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᅦ 
 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
 à¤
+
+ᆨ á„€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 

+á…¡
+ 

+ᆨ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むむ က
+ ᆹ ᅡ 

+
+ठ

 à¤á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+
+
+
+á„€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ã‚€
+ à¤á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᆩᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ à¥
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᆩᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+

+á…¦
+ 

+

+
+
+

+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ ॠᄅ
 ᄠ


ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄅ
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ॠᄠᅡ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄅ
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᆨ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ む
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ á„… á… 
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+ á… 
+
+ 

+ ᅦᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ á„…
+
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
à³á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ à³á„€á… á†¨á„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
 á„€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+
+
+

 â½” á…¡ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

 
⽔
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+à³
+ 

 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᆨ
+
+
 

+
+
+
+

+
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 

+ à³
+
+


+
+ 
 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ ⽔ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᄅ á„… ᆩ 
 
 

ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ᄀ 

+
+
+
+

+
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ᆩ
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むむ
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᆨ
ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᆩ
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+â½”
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む

+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᆨ
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+ ᅡᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+á„
+ က ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+

+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ 
ᄀᆩ
+
+
+
+
+
+ᆨ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む


+ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᅡᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᅠ

+á„€à¤á„€à³â€©á…¡
+
+
+ 
 ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+
+
+
+
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+むᅡ
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᅡᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€à¥à¥ ᄀᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”む


+ â½”
+ က
+ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ 
ᆩ 
ᄠᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€ ᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”むᄀᅠᆨá„ᅡᆩ렚à¤à¥á€€à³â½”ã‚€
+ᆨ
diff --git a/trunk/tests/cxx-test.C b/trunk/tests/cxx-test.C
new file mode 100644
index 00000000..62099b3b
--- /dev/null
+++ b/trunk/tests/cxx-test.C
@@ -0,0 +1,33 @@
+/* This test makes sure that all Pango headers can be included
+ * and compiled in a C++ program.
+ */
+#define PANGO_ENABLE_ENGINE
+#define PANGO_ENABLE_BACKEND
+
+#include <pango/pango.h>
+
+#ifdef HAVE_WIN32
+#include <pango/pangowin32.h>
+#endif
+
+#ifdef HAVE_X
+#include <pango/pangox.h>
+#endif
+
+#ifdef HAVE_XFT
+#include <pango/pangoxft.h>
+#endif
+
+#ifdef HAVE_FREETYPE
+#include <pango/pangoft2.h>
+#endif
+
+#ifdef HAVE_CAIRO
+#include <pango/pangocairo.h>
+#endif
+
+int
+main ()
+{
+ return 0;
+}
diff --git a/trunk/tests/dump-boundaries.c b/trunk/tests/dump-boundaries.c
new file mode 100644
index 00000000..9c890d28
--- /dev/null
+++ b/trunk/tests/dump-boundaries.c
@@ -0,0 +1,132 @@
+/* Pango
+ * dump-boundaries.c: Dump text boundaries for a file
+ *
+ * Copyright (C) 1999-2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <pango/pango.h>
+
+#define CHFORMAT "%0#6x"
+
+static void fail (const char *format, ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN;
+static void fail (const char *format, ...)
+{
+ char *str;
+
+ va_list args;
+
+ va_start (args, format);
+ str = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ fprintf (stderr, "Error: %s\n", str);
+
+ g_free (str);
+
+ exit (1);
+}
+
+static void
+dump_text (const char *text)
+{
+ int len;
+ PangoLogAttr *attrs;
+ int i;
+ gunichar *ucs4;
+
+ if (!g_utf8_validate (text, -1, NULL))
+ fail ("Invalid UTF-8 in file");
+
+ len = g_utf8_strlen (text, -1);
+ attrs = g_new0 (PangoLogAttr, len + 1);
+
+ pango_get_log_attrs (text,
+ -1,
+ 0,
+ pango_language_from_string ("C"),
+ attrs,
+ len + 1);
+
+ ucs4 = g_utf8_to_ucs4 (text, -1, NULL, NULL, NULL);
+
+ i = 0;
+ while (i <= len)
+ {
+ char buf[7] = { '\0', };
+ char *loc;
+
+ g_unichar_to_utf8 (ucs4[i], buf);
+
+ if (*buf == '\n')
+ loc = g_strdup ("\\n");
+ else if (*buf == '\r')
+ loc = g_strdup ("\\r");
+ else
+ loc = g_locale_from_utf8 (buf, -1, NULL, NULL, NULL);
+
+ g_print (CHFORMAT " (%s):\t line_break = %d mandatory_break = %d char_break = %d\n"
+ " \t\t white = %d cursor_position = %d\n"
+ " \t\t word_start = %d word_end = %d\n"
+ " \t\t sentence_boundary = %d sentence_start = %d sentence_end = %d\n",
+ ucs4[i], loc ? loc : "?",
+ attrs[i].is_line_break,
+ attrs[i].is_mandatory_break,
+ attrs[i].is_char_break,
+ attrs[i].is_white,
+ attrs[i].is_cursor_position,
+ attrs[i].is_word_start,
+ attrs[i].is_word_end,
+ attrs[i].is_sentence_boundary,
+ attrs[i].is_sentence_start,
+ attrs[i].is_sentence_end);
+
+ g_free (loc);
+
+ ++i;
+ }
+
+ g_free (ucs4);
+ g_free (attrs);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ gchar *text;
+
+ g_setenv ("PANGO_RC_FILE", "./pangorc", TRUE);
+
+ if (argc < 2)
+ fail ("must give a filename on the command line");
+
+ if (!g_file_get_contents (argv[1], &text, NULL, NULL))
+ fail ("Couldn't open sample text file");
+
+ dump_text (text);
+
+ g_free (text);
+
+ return 0;
+}
+
diff --git a/trunk/tests/gen-all-unicode.c b/trunk/tests/gen-all-unicode.c
new file mode 100644
index 00000000..90ff4dbd
--- /dev/null
+++ b/trunk/tests/gen-all-unicode.c
@@ -0,0 +1,45 @@
+#include <glib.h>
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ gunichar i;
+ gint j;
+
+ /* Output all characters in the BMP twice, once directly
+ * concatenated, once with spaces between them
+ */
+ for (j = 0 ; j < 2 ; j++)
+ {
+ for (i = 0; i < 65536; i++)
+ {
+ if (g_unichar_validate (i))
+ {
+ gchar buffer[7];
+ int len = g_unichar_to_utf8 (i, buffer);
+ buffer[len] = '\0';
+
+ if (j == 1)
+ fputs (" ", stdout);
+
+ fputs (buffer, stdout);
+
+ if (j == 0)
+ {
+ if (i % 40 == 0 && i != 0)
+ fputs ("\n", stdout);
+ }
+ else
+ {
+ if (i % 20 == 0 && i != 0)
+ fputs ("\n", stdout);
+ }
+ }
+ }
+ }
+ fputs ("\n", stdout);
+
+ return 0;
+}
+
diff --git a/trunk/tests/runtests.sh.in b/trunk/tests/runtests.sh.in
new file mode 100755
index 00000000..0c3466e2
--- /dev/null
+++ b/trunk/tests/runtests.sh.in
@@ -0,0 +1,55 @@
+#! @SHELL@
+
+LOGFILE=runtests.log
+POTENTIAL_TESTS='testboundaries testcolor'
+
+ECHO_C='@ECHO_C@'
+ECHO_N='@ECHO_N@'
+
+for I in $POTENTIAL_TESTS
+do
+ GOOD=yes
+ test -f $I || {
+ echo "WARNING: test program $I not found, not running"
+ GOOD=no
+ }
+
+ if test x$GOOD = xyes; then
+ test -x $I || {
+ echo "WARNING: test program $I is not executable, not running"
+ GOOD=no
+ }
+ fi
+
+ if test x$GOOD = xyes; then
+ TESTS="$TESTS$I "
+ fi
+done
+
+echo "Logging to $LOGFILE"
+
+echo "Log file for Pango test programs." > $LOGFILE
+echo "" >> $LOGFILE
+echo "Tests are: "$TESTS >> $LOGFILE
+echo "" >> $LOGFILE
+
+for I in $TESTS
+do
+ echo $ECHO_N "Running test program \"$I\", please wait:$ECHO_C"
+ echo "" >> $LOGFILE
+ echo "Output of $I:" >> $LOGFILE
+ if ./$I >>$LOGFILE 2>&1; then
+ echo " passed"
+ else
+ echo
+ echo
+ echo '***'
+ echo " Test failed: $I"
+ echo " See $LOGFILE for errors"
+ echo
+ exit 1
+ fi
+done
+
+echo
+echo "All tests passed."
diff --git a/trunk/tests/test-ot-tags.c b/trunk/tests/test-ot-tags.c
new file mode 100644
index 00000000..5363c1bb
--- /dev/null
+++ b/trunk/tests/test-ot-tags.c
@@ -0,0 +1,131 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* Pango
+ * testscript.c: Test cases for PangoScriptIter
+ *
+ * Copyright (C) 2002 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#define PANGO_ENABLE_ENGINE
+#include <pango/pango-ot.h>
+
+#undef VERBOSE
+
+#define ASSERT(stmt) G_STMT_START { \
+ if (stmt) { } \
+ else \
+ { \
+ g_warning ("%s:%d (%s): assertion '%s' failed", \
+ __FILE__, __LINE__, G_GNUC_PRETTY_FUNCTION, #stmt); \
+ exit (1); \
+ } \
+} G_STMT_END
+
+static void
+test_script_tags (void)
+{
+ gunichar ch;
+ PangoScript i, max_script;
+
+ /* we need to know what the maximum script number is. but we don't
+ * provide an api for that. instead of looking into internal tables,
+ * we'll go over all chars and see what their script is, taking the max!
+ */
+
+ max_script = PANGO_SCRIPT_INVALID_CODE;
+ for (ch = 0; ch <= 0x10FFFF; ch++)
+ max_script = MAX (max_script, pango_script_for_unichar (ch));
+
+ for (i = PANGO_SCRIPT_COMMON; i <= max_script; i++)
+ {
+ PangoOTTag tag = pango_ot_tag_from_script (i);
+ PangoScript j = pango_ot_tag_to_script (tag);
+
+ if (i <= PANGO_SCRIPT_INHERITED || i == PANGO_SCRIPT_UNKNOWN)
+ {
+ ASSERT (tag == PANGO_OT_TAG_DEFAULT_SCRIPT);
+ ASSERT (j == PANGO_SCRIPT_COMMON);
+ }
+ else if (tag == FT_MAKE_TAG ('k', 'a', 'n', 'a'))
+ {
+ /* Hiragana and Katakana both map to tag 'kana' */
+ ASSERT (i == PANGO_SCRIPT_HIRAGANA || i == PANGO_SCRIPT_KATAKANA);
+ ASSERT (j == PANGO_SCRIPT_HIRAGANA || j == PANGO_SCRIPT_KATAKANA);
+ }
+ else
+ {
+ if (j != i)
+ g_error ("Got back %d for script %d (OT tag '%c%c%c%c')", j, i,
+ tag>>24, (tag>>16)&255, (tag>>8)&255, tag&255);
+ }
+ }
+
+ ASSERT (pango_ot_tag_to_script (FT_MAKE_TAG ('X', 'Y', 'Z', ' ')) == PANGO_SCRIPT_UNKNOWN);
+}
+
+static void
+test_language_tags (void)
+{
+ /* just test it for a few known languages to make sure it's working */
+ const char languages[][6] = {
+ "xy", /* hopefully nonexistent */
+ "aa",
+ "az_IR",
+ "en",
+ "en_US",
+ "fa",
+ "fa_IR",
+ "fr",
+ "zh_CN",
+ "zu"
+ };
+ unsigned int i;
+
+ for (i = 0; i < G_N_ELEMENTS (languages); i++)
+ {
+ PangoLanguage *l = pango_language_from_string (languages[i]);
+ PangoOTTag tag = pango_ot_tag_from_language (l);
+ PangoLanguage *m = pango_ot_tag_to_language (tag);
+
+ if (i == 0)
+ {
+ ASSERT (tag == PANGO_OT_TAG_DEFAULT_LANGUAGE);
+ ASSERT (strcmp (pango_language_to_string (m), "xx") == 0);
+ }
+ else
+ {
+ if (tag == PANGO_OT_TAG_DEFAULT_LANGUAGE)
+ g_error ("Got PANGO_OT_TAG_DEFAULT_LANGUAGE for language '%s'", pango_language_to_string (l));
+
+ if (!pango_language_matches (l, pango_language_to_string (m)))
+ g_error ("Got back %s for language %s (OT tag '%c%c%c%c')",
+ pango_language_to_string (m), pango_language_to_string (l),
+ tag>>24, (tag>>16)&255, (tag>>8)&255, tag&255);
+ }
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ g_setenv ("PANGO_RC_FILE", "./pangorc", TRUE);
+
+ test_script_tags ();
+ test_language_tags ();
+
+ return 0;
+}
diff --git a/trunk/tests/testboundaries.c b/trunk/tests/testboundaries.c
new file mode 100644
index 00000000..30a9f31a
--- /dev/null
+++ b/trunk/tests/testboundaries.c
@@ -0,0 +1,362 @@
+/* Pango
+ * testboundaries.c: Test text boundary algorithms
+ *
+ * Copyright (C) 1999-2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <pango/pango.h>
+
+#define CHFORMAT "%0#6x"
+
+/* FIXME for now this just tests that the breaking of some sample
+ * text conforms to certain rules and invariants. But eventually
+ * we should also have test-result pairs, i.e. a string and some
+ * encoding of the correct way to break the string, to check
+ * more precisely that things worked
+ */
+
+
+/* "virama script" is just an optimization; it includes a bunch of
+ * scripts without viramas in them
+ */
+#define VIRAMA_SCRIPT(wc) ((wc) >= 0x0901 && (wc) <= 0x17FF)
+#define VIRAMA(wc) ((wc) == 0x094D || \
+ (wc) == 0x09CD || \
+ (wc) == 0x0A4D || \
+ (wc) == 0x0ACD || \
+ (wc) == 0x0B4D || \
+ (wc) == 0x0BCD || \
+ (wc) == 0x0C4D || \
+ (wc) == 0x0CCD || \
+ (wc) == 0x0D4D || \
+ (wc) == 0x0DCA || \
+ (wc) == 0x0E3A || \
+ (wc) == 0x0F84 || \
+ (wc) == 0x1039 || \
+ (wc) == 0x17D2)
+/* Types of Japanese characters */
+#define JAPANESE(wc) ((wc) >= 0x2F00 && (wc) <= 0x30FF)
+#define KANJI(wc) ((wc) >= 0x2F00 && (wc) <= 0x2FDF)
+#define HIRAGANA(wc) ((wc) >= 0x3040 && (wc) <= 0x309F)
+#define KATAKANA(wc) ((wc) >= 0x30A0 && (wc) <= 0x30FF)
+
+static int offset = 0;
+static int line = 0;
+static gunichar current_wc = 0;
+static const char *line_start = NULL;
+static const char *line_end = NULL;
+
+static void fail (const char *format, ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN;
+static void fail (const char *format, ...)
+{
+ char *str;
+ char *line_text;
+
+ va_list args;
+
+ va_start (args, format);
+ str = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ line_text = g_strndup (line_start, line_end - line_start);
+
+ fprintf (stderr, "line %d offset %d char is " CHFORMAT ": %s\n (line is '%s')\n", line, offset, current_wc, str, line_text);
+ g_free (str);
+ g_free (line_text);
+
+ exit (1);
+}
+
+typedef void (* CharForeachFunc) (gunichar wc,
+ gunichar prev_wc,
+ gunichar next_wc,
+ GUnicodeType type,
+ GUnicodeType prev_type,
+ GUnicodeType next_type,
+ PangoLogAttr *attr,
+ PangoLogAttr *prev_attr,
+ PangoLogAttr *next_attr,
+ gpointer data);
+
+static void
+log_attr_foreach (const char *text,
+ PangoLogAttr *attrs,
+ CharForeachFunc func,
+ gpointer data)
+{
+ const gchar *next = text;
+ gint length = strlen (text);
+ const gchar *end = text + length;
+ gint i = 0;
+ gunichar prev_wc;
+ gunichar next_wc;
+ GUnicodeType prev_type;
+ GUnicodeType next_type;
+
+ if (next == end)
+ return;
+
+ offset = 0;
+ line = 0;
+
+ prev_type = (GUnicodeType) -1;
+ prev_wc = 0;
+
+ next_wc = g_utf8_get_char (next);
+ next_type = g_unichar_type (next_wc);
+
+ line_start = text;
+ line_end = text;
+
+ while (next_wc != 0)
+ {
+ GUnicodeType type;
+ gunichar wc;
+
+ wc = next_wc;
+ type = next_type;
+
+ current_wc = wc;
+
+ next = g_utf8_next_char (next);
+ line_end = next;
+
+ if (next >= end)
+ next_wc = 0;
+ else
+ next_wc = g_utf8_get_char (next);
+
+ if (next_wc)
+ next_type = g_unichar_type (next_wc);
+
+ (* func) (wc, prev_wc, next_wc,
+ type, prev_type, next_type,
+ &attrs[i],
+ i != 0 ? &attrs[i-1] : NULL,
+ next_wc != 0 ? &attrs[i+1] : NULL,
+ data);
+
+ prev_type = type;
+ prev_wc = wc;
+ ++i;
+ ++offset;
+ if (wc == '\n')
+ {
+ ++line;
+ offset = 0;
+ line_start = next;
+ line_end = next;
+ }
+ }
+}
+
+static void
+check_line_char (gunichar wc,
+ gunichar prev_wc,
+ gunichar next_wc,
+ GUnicodeType type,
+ GUnicodeType prev_type,
+ GUnicodeType next_type,
+ PangoLogAttr *attr,
+ PangoLogAttr *prev_attr,
+ PangoLogAttr *next_attr,
+ gpointer data)
+{
+ GUnicodeBreakType break_type;
+ GUnicodeBreakType prev_break_type;
+
+ break_type = g_unichar_break_type (wc);
+ if (prev_wc)
+ prev_break_type = g_unichar_break_type (prev_wc);
+ else
+ prev_break_type = G_UNICODE_BREAK_UNKNOWN;
+
+ if (wc == '\n')
+ {
+ if (prev_wc == '\r')
+ {
+ if (attr->is_line_break)
+ fail ("line break between \\r and \\n");
+ }
+
+ if (next_attr && !next_attr->is_line_break)
+ fail ("no line break after \\n");
+ }
+
+ if (attr->is_line_break && prev_wc == 0)
+ fail ("first char in string should not be marked as a line break");
+
+ if (break_type == G_UNICODE_BREAK_SPACE)
+ {
+ if (attr->is_line_break && prev_attr != NULL &&
+ !attr->is_mandatory_break &&
+ !(next_wc && g_unichar_break_type (next_wc) == G_UNICODE_BREAK_COMBINING_MARK))
+ fail ("can't break lines before a space unless a mandatory break char precedes it or a combining mark follows; prev char was " CHFORMAT, prev_wc);
+ }
+
+ if (attr->is_mandatory_break && !attr->is_line_break)
+ fail ("mandatory breaks must also be marked as regular breaks");
+
+
+
+ /* FIXME use the break tables from break.c to automatically
+ * check invariants for each cell in the table. Shouldn't
+ * be that hard to do.
+ */
+
+ if (break_type == G_UNICODE_BREAK_OPEN_PUNCTUATION &&
+ prev_break_type == G_UNICODE_BREAK_OPEN_PUNCTUATION &&
+ attr->is_line_break &&
+ !attr->is_mandatory_break)
+ fail ("can't break between two open punctuation chars");
+
+ if (break_type == G_UNICODE_BREAK_CLOSE_PUNCTUATION &&
+ prev_break_type == G_UNICODE_BREAK_CLOSE_PUNCTUATION &&
+ attr->is_line_break &&
+ !attr->is_mandatory_break)
+ fail ("can't break between two close punctuation chars");
+
+ if (break_type == G_UNICODE_BREAK_QUOTATION &&
+ prev_break_type == G_UNICODE_BREAK_ALPHABETIC &&
+ attr->is_line_break &&
+ !attr->is_mandatory_break)
+ fail ("can't break letter-quotemark sequence");
+}
+
+static void
+check_line_invariants (const char *text,
+ PangoLogAttr *attrs)
+{
+ log_attr_foreach (text, attrs, check_line_char, NULL);
+}
+
+static void
+check_word_invariants (const char *text,
+ PangoLogAttr *attrs)
+{
+
+
+}
+
+static void
+check_sentence_invariants (const char *text,
+ PangoLogAttr *attrs)
+{
+
+
+}
+
+static void
+check_grapheme_invariants (const char *text,
+ PangoLogAttr *attrs)
+{
+
+
+}
+
+static void print_sentences (const char *text,
+ PangoLogAttr *attrs);
+static void
+print_sentences (const char *text,
+ PangoLogAttr *attrs)
+{
+ const char *p;
+ const char *last;
+ int i = 0;
+
+ last = text;
+ p = text;
+
+ while (*p)
+ {
+ if (attrs[i].is_sentence_boundary)
+ {
+ char *s = g_strndup (last, p - last);
+ printf ("%s\n", s);
+ g_free (s);
+ last = p;
+ }
+
+ p = g_utf8_next_char (p);
+ ++i;
+ }
+}
+
+static void
+check_invariants (const char *text)
+{
+ int len;
+ PangoLogAttr *attrs;
+
+ if (!g_utf8_validate (text, -1, NULL))
+ fail ("Invalid UTF-8 in test text");
+
+ len = g_utf8_strlen (text, -1);
+ attrs = g_new0 (PangoLogAttr, len + 1);
+
+ pango_get_log_attrs (text,
+ -1,
+ 0,
+ pango_language_from_string ("C"),
+ attrs,
+ len + 1);
+
+ check_line_invariants (text, attrs);
+ check_sentence_invariants (text, attrs);
+ check_grapheme_invariants (text, attrs);
+ check_word_invariants (text, attrs);
+
+#if 0
+ print_sentences (text, attrs);
+#endif
+
+ g_free (attrs);
+}
+
+int
+main (int argc, char *argv[])
+{
+ gchar *text;
+ const gchar *srcdir;
+ const gchar *filename;
+
+ g_setenv ("PANGO_RC_FILE", "./pangorc", TRUE);
+
+ srcdir = getenv ("srcdir");
+ if (!srcdir)
+ srcdir = ".";
+
+ filename = g_strdup_printf ("%s/boundaries.utf8", srcdir);
+
+ if (!g_file_get_contents (filename, &text, NULL, NULL))
+ fail ("Couldn't open sample text file");
+
+ check_invariants (text);
+
+ g_free (text);
+
+ printf ("testboundaries passed\n");
+
+ return 0;
+}
+
diff --git a/trunk/tests/testcolor.c b/trunk/tests/testcolor.c
new file mode 100644
index 00000000..1995d3d6
--- /dev/null
+++ b/trunk/tests/testcolor.c
@@ -0,0 +1,94 @@
+/* Pango
+ * test-color.c: Test program for pango_color_parse()
+ *
+ * Copyright (C) 2002 Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include <pango/pango.h>
+
+typedef struct _ColorSpec {
+ const gchar *spec;
+ gboolean valid;
+ guint16 red;
+ guint16 green;
+ guint16 blue;
+} ColorSpec;
+
+static gboolean test_color (ColorSpec *spec)
+{
+ PangoColor color;
+ gboolean accepted;
+
+ accepted = pango_color_parse (&color, spec->spec);
+
+ if (accepted == spec->valid &&
+ (!accepted ||
+ (color.red == spec->red &&
+ color.green == spec->green &&
+ color.blue == spec->blue)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+ColorSpec specs [] = {
+ { "#abc", 1, 0xaaaa, 0xbbbb, 0xcccc },
+ { "#aabbcc", 1, 0xaaaa, 0xbbbb, 0xcccc },
+ { "#aaabbbccc", 1, 0xaaaa, 0xbbbb, 0xcccc },
+ { "#100100100", 1, 0x1001, 0x1001, 0x1001 },
+ { "#aaaabbbbcccc", 1, 0xaaaa, 0xbbbb, 0xcccc },
+ { "#fff", 1, 0xffff, 0xffff, 0xffff },
+ { "#ffffff", 1, 0xffff, 0xffff, 0xffff },
+ { "#fffffffff", 1, 0xffff, 0xffff, 0xffff },
+ { "#ffffffffffff", 1, 0xffff, 0xffff, 0xffff },
+ { "#000", 1, 0x0000, 0x0000, 0x0000 },
+ { "#000000", 1, 0x0000, 0x0000, 0x0000 },
+ { "#000000000", 1, 0x0000, 0x0000, 0x0000 },
+ { "#000000000000", 1, 0x0000, 0x0000, 0x0000 },
+ { "#AAAABBBBCCCC", 1, 0xaaaa, 0xbbbb, 0xcccc },
+ { "#aa bb cc ", 0, 0, 0, 0 },
+ { "#aa bb ccc", 0, 0, 0, 0 },
+ { "#ab", 0, 0, 0, 0 },
+ { "#aabb", 0, 0, 0, 0 },
+ { "#aaabb", 0, 0, 0, 0 },
+ { "aaabb", 0, 0, 0, 0 },
+ { "", 0, 0, 0, 0 },
+ { "#", 0, 0, 0, 0 },
+ { "##fff", 0, 0, 0, 0 },
+ { "#0000ff+", 0, 0, 0, 0 },
+ { "#0000f+", 0, 0, 0, 0 },
+ { "#0x00x10x2", 0, 0, 0, 0 },
+ { NULL, 0, 0, 0, 0 }
+};
+
+int
+main (int argc, char *argv[])
+{
+ gboolean success;
+ ColorSpec *spec;
+
+ g_setenv ("PANGO_RC_FILE", "./pangorc", TRUE);
+
+ success = TRUE;
+ for (spec = specs; spec->spec; spec++)
+ success &= test_color (spec);
+
+ return !success;
+}
diff --git a/trunk/tests/testiter.c b/trunk/tests/testiter.c
new file mode 100644
index 00000000..65986d52
--- /dev/null
+++ b/trunk/tests/testiter.c
@@ -0,0 +1,243 @@
+/* Pango
+ * testiter.c: Test pangolayoutiter.c
+ *
+ * Copyright (C) 2005 Amit Aronovitch
+ * Copyright (C) 2005 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#undef G_DISABLE_ASSERT
+#undef G_LOG_DOMAIN
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <pango/pangocairo.h>
+
+#undef VERBOSE
+
+static void verbose (const char *format, ...) G_GNUC_PRINTF (1, 2);
+static void
+verbose (const char *format, ...)
+{
+#ifdef VERBOSE
+ va_list vap;
+
+ va_start (vap, format);
+ vfprintf (stderr, format, vap);
+ va_end (vap);
+#endif
+}
+
+#define LAYOUT_WIDTH (80 * PANGO_SCALE)
+
+/* Note: The test expects that any newline sequence is of length 1
+ * use \n (not \r\n) in the test texts.
+ * I think the iterator itself should support \r\n without trouble,
+ * but there are comments in layout-iter.c suggesting otherwise.
+ */
+const char *test_texts[] =
+ {
+ /* English with embedded RTL runs (from ancient-hebrew.org) */
+ "The Hebrew word \xd7\x90\xd7\x93\xd7\x9d\xd7\x94 (adamah) is the feminine form of \xd7\x90\xd7\x93\xd7\x9d meaning \"ground\"\n",
+ /* Arabic, with vowel marks (from Sura Al Fatiha) */
+ "\xd8\xa8\xd9\x90\xd8\xb3\xd9\x92\xd9\x85\xd9\x90 \xd8\xa7\xd9\x84\xd9\x84\xd9\x91\xd9\x87\xd9\x90 \xd8\xa7\xd9\x84\xd8\xb1\xd9\x91\xd9\x8e\xd8\xad\xd9\x92\xd9\x85\xd9\x80\xd9\x8e\xd9\x86\xd9\x90 \xd8\xa7\xd9\x84\xd8\xb1\xd9\x91\xd9\x8e\xd8\xad\xd9\x90\xd9\x8a\xd9\x85\xd9\x90\n\xd8\xa7\xd9\x84\xd9\x92\xd8\xad\xd9\x8e\xd9\x85\xd9\x92\xd8\xaf\xd9\x8f \xd9\x84\xd9\x84\xd9\x91\xd9\x87\xd9\x90 \xd8\xb1\xd9\x8e\xd8\xa8\xd9\x91\xd9\x90 \xd8\xa7\xd9\x84\xd9\x92\xd8\xb9\xd9\x8e\xd8\xa7\xd9\x84\xd9\x8e\xd9\x85\xd9\x90\xd9\x8a\xd9\x86\xd9\x8e\n",
+ /* Arabic, with embedded LTR runs (from a Linux guide) */
+ "\xd8\xa7\xd9\x84\xd9\x85\xd8\xaa\xd8\xba\xd9\x8a\xd8\xb1 LC_ALL \xd9\x8a\xd8\xba\xd9\x8a\xd9\x8a\xd8\xb1 \xd9\x83\xd9\x84 \xd8\xa7\xd9\x84\xd9\x85\xd8\xaa\xd8\xba\xd9\x8a\xd8\xb1\xd8\xa7\xd8\xaa \xd8\xa7\xd9\x84\xd8\xaa\xd9\x8a \xd8\xaa\xd8\xa8\xd8\xaf\xd8\xa3 \xd8\xa8\xd8\xa7\xd9\x84\xd8\xb1\xd9\x85\xd8\xb2 LC.",
+ /* Hebrew, with vowel marks (from Genesis) */
+ "\xd7\x91\xd6\xbc\xd6\xb0\xd7\xa8\xd6\xb5\xd7\x90\xd7\xa9\xd7\x81\xd6\xb4\xd7\x99\xd7\xaa, \xd7\x91\xd6\xbc\xd6\xb8\xd7\xa8\xd6\xb8\xd7\x90 \xd7\x90\xd6\xb1\xd7\x9c\xd6\xb9\xd7\x94\xd6\xb4\xd7\x99\xd7\x9d, \xd7\x90\xd6\xb5\xd7\xaa \xd7\x94\xd6\xb7\xd7\xa9\xd6\xbc\xd7\x81\xd6\xb8\xd7\x9e\xd6\xb7\xd7\x99\xd6\xb4\xd7\x9d, \xd7\x95\xd6\xb0\xd7\x90\xd6\xb5\xd7\xaa \xd7\x94\xd6\xb8\xd7\x90\xd6\xb8\xd7\xa8\xd6\xb6\xd7\xa5",
+ /* Hebrew, with embedded LTR runs (from a Linux guide) */
+ "\xd7\x94\xd7\xa7\xd7\x9c\xd7\x93\xd7\x94 \xd7\xa2\xd7\x9c \xd7\xa9\xd7\xa0\xd7\x99 \xd7\x94 SHIFT\xd7\x99\xd7\x9d (\xd7\x99\xd7\x9e\xd7\x99\xd7\x9f \xd7\x95\xd7\xa9\xd7\x9e\xd7\x90\xd7\x9c \xd7\x91\xd7\x99\xd7\x97\xd7\x93) \xd7\x90\xd7\x9e\xd7\x95\xd7\xa8\xd7\x99\xd7\x9d \xd7\x9c\xd7\x94\xd7\x93\xd7\x9c\xd7\x99\xd7\xa7 \xd7\x90\xd7\xaa \xd7\xa0\xd7\x95\xd7\xa8\xd7\xaa \xd7\x94 Scroll Lock , \xd7\x95\xd7\x9c\xd7\x94\xd7\xa2\xd7\x91\xd7\x99\xd7\xa8 \xd7\x90\xd7\x95\xd7\xaa\xd7\xa0\xd7\x95 \xd7\x9c\xd7\x9e\xd7\xa6\xd7\x91 \xd7\x9b\xd7\xaa\xd7\x99\xd7\x91\xd7\x94 \xd7\x91\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa.",
+ /* Different line terminators */
+ "AAAA\nBBBB\nCCCC\n",
+ "DDDD\rEEEE\rFFFF\r",
+ "GGGG\r\nHHHH\r\nIIII\r\n",
+ NULL
+ };
+
+static void
+iter_char_test (PangoLayout *layout)
+{
+ PangoRectangle extents, run_extents;
+ PangoLayoutIter *iter;
+ PangoLayoutRun *run;
+ int num_chars;
+ int i, index, offset;
+ int leading_x, trailing_x, x0, x1;
+ gboolean iter_next_ok, rtl;
+ const char *text, *ptr;
+
+ text = pango_layout_get_text (layout);
+ num_chars = g_utf8_strlen (text, -1);
+
+ iter = pango_layout_get_iter (layout);
+ iter_next_ok = TRUE;
+
+ for (i = 0 ; i < num_chars; ++i)
+ {
+ gchar *char_str;
+ g_assert (iter_next_ok);
+
+ index = pango_layout_iter_get_index (iter);
+ ptr = text + index;
+ char_str = g_strndup (ptr, g_utf8_next_char (ptr) - ptr);
+ verbose ("i=%d (visual), index = %d '%s':\n",
+ i, index, char_str);
+ g_free (char_str);
+
+ pango_layout_iter_get_char_extents (iter, &extents);
+ verbose (" char extents: x=%d,y=%d w=%d,h=%d\n",
+ extents.x, extents.y,
+ extents.width, extents.height);
+
+ run = pango_layout_iter_get_run (iter);
+
+ if (run)
+ {
+ /* Get needed data for the GlyphString */
+ pango_layout_iter_get_run_extents(iter, NULL, &run_extents);
+ offset = run->item->offset;
+ rtl = run->item->analysis.level%2;
+ verbose (" (current run: offset=%d,x=%d,len=%d,rtl=%d)\n",
+ offset, run_extents.x, run->item->length, rtl);
+
+ /* Calculate expected x result using index_to_x */
+ pango_glyph_string_index_to_x (run->glyphs,
+ (char *)(text + offset), run->item->length,
+ &run->item->analysis,
+ index - offset, FALSE, &leading_x);
+ pango_glyph_string_index_to_x (run->glyphs,
+ (char *)(text + offset), run->item->length,
+ &run->item->analysis,
+ index - offset, TRUE, &trailing_x);
+
+ x0 = run_extents.x + MIN (leading_x, trailing_x);
+ x1 = run_extents.x + MAX (leading_x, trailing_x);
+
+ verbose (" (index_to_x ind=%d: expected x=%d, width=%d)\n",
+ index - offset, x0, x1 - x0);
+
+ g_assert (extents.x == x0);
+ g_assert (extents.width == x1 - x0);
+ }
+ else
+ {
+ /* We're on a line terminator */
+ }
+
+ iter_next_ok = pango_layout_iter_next_char (iter);
+ verbose ("more to go? %d\n", iter_next_ok);
+ }
+
+ /* There should be one character position iterator for each character in the
+ * input string */
+ g_assert (!iter_next_ok);
+
+ pango_layout_iter_free (iter);
+}
+
+/* char iteration test:
+ * - Total num of iterations match number of chars
+ * - GlyphString's index_to_x positions match those returned by the Iter
+ */
+static void
+iter_cluster_test (PangoLayout *layout)
+{
+ PangoRectangle extents;
+ PangoLayoutIter *iter;
+ int index;
+ gboolean iter_next_ok;
+ const char *text;
+ PangoLayoutLine *last_line = NULL;
+ int expected_next_x = 0;
+
+ text = pango_layout_get_text (layout);
+
+ iter = pango_layout_get_iter (layout);
+ iter_next_ok = TRUE;
+
+ while (iter_next_ok)
+ {
+ PangoLayoutLine *line = pango_layout_iter_get_line (iter);
+
+ /* Every cluster is part of a run */
+ g_assert (pango_layout_iter_get_run (iter));
+
+ index = pango_layout_iter_get_index (iter);
+
+ pango_layout_iter_get_cluster_extents (iter, NULL, &extents);
+
+ iter_next_ok = pango_layout_iter_next_cluster (iter);
+
+ verbose ("index = %d:\n", index);
+ verbose (" cluster extents: x=%d,y=%d w=%d,h=%d\n",
+ extents.x, extents.y,
+ extents.width, extents.height);
+ verbose ("more to go? %d\n", iter_next_ok);
+
+ /* All the clusters on a line should be next to each other and occupy
+ * the entire line. They advance linearly from left to right */
+ g_assert (extents.width >= 0);
+
+ if (last_line == line)
+ g_assert (extents.x == expected_next_x);
+
+ expected_next_x = extents.x + extents.width;
+
+ last_line = line;
+ }
+
+ g_assert (!iter_next_ok);
+
+ pango_layout_iter_free (iter);
+}
+
+int
+main (int argc, char *argv[])
+{
+ const char **ptext;
+ PangoFontMap *fontmap;
+ PangoContext *context;
+ PangoLayout *layout;
+
+ g_setenv ("PANGO_RC_FILE", "./pangorc", TRUE);
+
+ fontmap = pango_cairo_font_map_get_default ();
+ context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
+
+ layout = pango_layout_new (context);
+ pango_layout_set_width (layout, LAYOUT_WIDTH);
+
+ for (ptext = test_texts; *ptext != NULL; ++ptext)
+ {
+ verbose ("--------- checking next text ----------\n");
+ verbose (" <%s>\n", *ptext);
+ verbose ( "len=%ld, bytes=%ld\n",
+ (long)g_utf8_strlen (*ptext, -1), (long)strlen (*ptext));
+
+ pango_layout_set_text (layout, *ptext, -1);
+ iter_char_test (layout);
+ iter_cluster_test (layout);
+ }
+
+ g_object_unref (layout);
+ return 0;
+}
diff --git a/trunk/tests/testscript.c b/trunk/tests/testscript.c
new file mode 100644
index 00000000..8e788f71
--- /dev/null
+++ b/trunk/tests/testscript.c
@@ -0,0 +1,260 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* Pango
+ * testscript.c: Test cases for PangoScriptIter
+ *
+ * Copyright (C) 2002 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * The test strings here come from ICU:
+ *
+ * icu/sources/test/cintltst/cucdtst.c
+ *
+ ********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "pango/pango-script.h"
+#include "pango/pango-script-table.h"
+
+#undef VERBOSE
+
+#define ASSERT(stmt) G_STMT_START { \
+ if (stmt) { } \
+ else \
+ { \
+ g_warning ("%s:%d (%s): assertion '%s' failed", \
+ __FILE__, __LINE__, G_GNUC_PRETTY_FUNCTION, #stmt); \
+ exit (1); \
+ } \
+} G_STMT_END
+
+typedef struct
+{
+ const char *run_text_escaped;
+ char *run_text;
+ PangoScript run_code;
+} RunTestData;
+
+static gchar *
+unescape (const char *text)
+{
+ gboolean escaped = FALSE;
+ GString *result = g_string_new (NULL);
+ const gchar *p;
+
+ for (p = text; *p; p = g_utf8_next_char (p))
+ {
+ gunichar ch = g_utf8_get_char (p);
+
+ if (escaped)
+ {
+ if (ch == 'u' || ch == 'U')
+ {
+ int n_chars = ch == 'u' ? 4 : 8;
+ int i;
+
+ ch = 0;
+ for (i = 0; i < n_chars; i++)
+ {
+ p++;
+ ch <<= 4;
+ if (*p <= '9' && *p >= '0')
+ ch += *p - '0';
+ else if (*p <= 'F' && *p >= 'A')
+ ch += 10 + *p - 'A';
+ else if (*p <= 'f' && *p >= 'a')
+ ch += 10 + *p - 'a';
+ else
+ g_assert_not_reached ();
+ }
+ }
+ else if (ch == '\\')
+ {
+ ch = '\\';
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ escaped = FALSE;
+ }
+ else
+ {
+ if (ch == '\\')
+ {
+ escaped = TRUE;
+ continue;
+ }
+ }
+
+ g_string_append_unichar (result, ch);
+ }
+
+ return g_string_free (result, FALSE);
+}
+
+static void
+test_script_lookup (void)
+{
+ gunichar ch;
+ unsigned int i;
+ int j;
+
+ for (ch = 0; ch < G_N_ELEMENTS (pango_script_easy_table); ch++)
+ ASSERT (pango_script_for_unichar (ch) == pango_script_easy_table[ch]);
+
+ for (i = 0; i < G_N_ELEMENTS (pango_script_table); i++)
+ {
+ while (ch < pango_script_table[i].start)
+ {
+ ASSERT (pango_script_for_unichar (ch) == PANGO_SCRIPT_UNKNOWN);
+ ch++;
+ }
+
+ for (j = 0; j < pango_script_table[i].chars; j++)
+ {
+ ASSERT (pango_script_for_unichar (ch) == pango_script_table[i].script);
+ ch++;
+ }
+ }
+
+ ASSERT (pango_script_for_unichar (ch) == PANGO_SCRIPT_UNKNOWN);
+}
+
+static void
+test_script_iter (void)
+{
+ static RunTestData test_data[] = {
+ { "\\u0020\\u0946\\u0939\\u093F\\u0928\\u094D\\u0926\\u0940\\u0020", NULL, PANGO_SCRIPT_DEVANAGARI },
+ { "\\u0627\\u0644\\u0639\\u0631\\u0628\\u064A\\u0629\\u0020", NULL, PANGO_SCRIPT_ARABIC },
+ { "\\u0420\\u0443\\u0441\\u0441\\u043A\\u0438\\u0439\\u0020", NULL, PANGO_SCRIPT_CYRILLIC },
+ { "English (", NULL, PANGO_SCRIPT_LATIN },
+ { "\\u0E44\\u0E17\\u0E22", NULL, PANGO_SCRIPT_THAI },
+ { ") ", NULL, PANGO_SCRIPT_LATIN },
+ { "\\u6F22\\u5B75", NULL, PANGO_SCRIPT_HAN },
+ { "\\u3068\\u3072\\u3089\\u304C\\u306A\\u3068", NULL, PANGO_SCRIPT_HIRAGANA },
+ { "\\u30AB\\u30BF\\u30AB\\u30CA", NULL, PANGO_SCRIPT_KATAKANA },
+ { "\\U00010400\\U00010401\\U00010402\\U00010403", NULL, PANGO_SCRIPT_DESERET }
+ };
+
+ PangoScriptIter *iter;
+ GString *all = g_string_new (FALSE);
+ char *pos;
+ const char *start;
+ const char *end;
+ PangoScript script;
+ unsigned int i;
+
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++)
+ {
+ test_data[i].run_text = unescape (test_data[i].run_text_escaped);
+ g_string_append (all, test_data[i].run_text);
+ }
+
+ iter = pango_script_iter_new (all->str, -1);
+
+#ifdef VERBOSE
+ g_print ("Total length: %d\n", all->len);
+#endif
+
+ pos = all->str;
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++)
+ {
+ char *next_pos = pos + strlen (test_data[i].run_text);
+ gboolean result;
+
+ pango_script_iter_get_range (iter, &start, &end, &script);
+#ifdef VERBOSE
+ g_print ("Range: %d-%d: %d\n", start - all->str, end - all->str, script);
+#endif
+
+ ASSERT (start == pos);
+ ASSERT (end == next_pos);
+ ASSERT (script == test_data[i].run_code);
+
+ result = pango_script_iter_next (iter);
+ ASSERT (result == (i != G_N_ELEMENTS (test_data) - 1));
+
+ pos = next_pos;
+ }
+
+ pango_script_iter_free (iter);
+
+ /*
+ * Test an empty string.
+ */
+ iter = pango_script_iter_new (all->str, 0);
+
+ pango_script_iter_get_range (iter, &start, &end, &script);
+
+ ASSERT (start == all->str);
+ ASSERT (end == all->str);
+ ASSERT (script == PANGO_SCRIPT_COMMON);
+ ASSERT (!pango_script_iter_next (iter));
+
+ pango_script_iter_free (iter);
+
+ /* Cleanup */
+
+ for (i = 0; i < G_N_ELEMENTS (test_data); i++)
+ g_free (test_data[i].run_text);
+
+ g_string_free (all, TRUE);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_setenv ("PANGO_RC_FILE", "./pangorc", TRUE);
+
+ test_script_lookup ();
+ test_script_iter ();
+
+ return 0;
+}
diff --git a/trunk/tools/Makefile.am b/trunk/tools/Makefile.am
new file mode 100644
index 00000000..deecda93
--- /dev/null
+++ b/trunk/tools/Makefile.am
@@ -0,0 +1,20 @@
+## Process this file with automake to create Makefile.in.
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(GLIB_CFLAGS) \
+ -DPANGO_DISABLE_DEPRECATED \
+ $(PANGO_DEBUG_FLAGS)
+
+noinst_PROGRAMS = gen-script-for-lang
+
+EXTRA_DIST= \
+ add-copyright \
+ compress-table.pl \
+ gen-color-table.pl \
+ gen-script-table.pl \
+ maps/README \
+ maps/tis-620
+
+gen_script_for_lang_SOURCES = gen-script-for-lang.c
+gen_script_for_lang_LDADD = ../pango/libpango-$(PANGO_API_VERSION).la
diff --git a/trunk/tools/add-copyright b/trunk/tools/add-copyright
new file mode 100755
index 00000000..201d887d
--- /dev/null
+++ b/trunk/tools/add-copyright
@@ -0,0 +1,62 @@
+#!/usr/local/bin/perl -w
+
+# Spit the copyright
+
+# If there is a leading block comment that looks like this
+# license, don't add the license.
+
+$ARGV[0] =~ s!^\./!!;
+
+open IN, "<$ARGV[0]" or die "Cannot open $ARGV[0]: $!";
+open OUT, ">$ARGV[0].new" or die "Cannot open $ARGV[0].new: $!";
+
+$old = "";
+while (<IN>) {
+ $old .= $_;
+ m!^(/| )\*! or last;
+}
+
+if ($old !~ /Free Software Foundation/) {
+ while (<DATA>) {
+ s/\@NAME\@/$ARGV[0]/;
+ print OUT;
+ }
+}
+
+print OUT $old;
+while (<IN>) {
+ print OUT;
+}
+
+close IN;
+close OUT;
+
+if (system("diff $ARGV[0] $ARGV[0].new > /dev/null") != 0) {
+ system ("mv $ARGV[0] $ARGV[0].bak");
+ system ("mv $ARGV[0].new $ARGV[0]");
+} else {
+ system ("rm $ARGV[0].new");
+}
+
+__DATA__
+/* Pango
+ * @NAME@:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
diff --git a/trunk/tools/compress-table.pl b/trunk/tools/compress-table.pl
new file mode 100755
index 00000000..55129651
--- /dev/null
+++ b/trunk/tools/compress-table.pl
@@ -0,0 +1,123 @@
+#!/usr/bin/perl -w
+
+sub convert {
+ $s = shift;
+ $s = "ENC_".uc($s);
+ $s =~ s/-/_/g;
+ return $s;
+}
+
+$combo_index = 1;
+
+sub add {
+ my $combo = shift;
+ if (!exists($combos{$combo})) {
+ $combos{$combo} = $combo_index++;
+ printf " $combo,\n", $combos{$combo};
+ }
+}
+
+my $col = 0;
+
+sub output {
+ my ($start,$u,$index) = @_;
+
+ for (my $i = $start; $i < $u; $i++) {
+ print " 0,";
+ $col = ($col + 1) % 16;
+ if ($col == 0) {
+ print "\n";
+ }
+ }
+ printf " %2d,", $index;
+ $col = ($col + 1) % 16;
+ if ($col == 0) {
+ print "\n";
+ }
+}
+
+#
+# Read in the maps
+#
+my @codepoints = ();
+
+opendir (MAPS, "maps") || die "Cannot open maps/ subdirectory: $!\n";
+while (defined (my $map = readdir (MAPS))) {
+ next if ($map =~ /^\./);
+ next if ($map =~ /~$/);
+ next if ($map =~ /^CVS|README$/);
+
+ open (MAP, "maps/$map") || die "Cannot open map '$map:!\n";
+
+ $encoding = convert($map);
+ while (<MAP>) {
+ s/\s*#.*//;
+ s/\s*$//;
+ next if /^$/;
+ if (!/^\s*(0x[A-Fa-f0-9]+)\s+(0x[A-Fa-f0-9]+)$/) {
+ die "Cannot parse line '%s' in map '$map'\n";
+ }
+ push @codepoints, [hex($2), $encoding];
+ }
+ close (MAP);
+}
+
+#
+# And sort them
+#
+@codepoints = sort { $a->[0] <=> $b->[0] } @codepoints;
+
+print "const guint32 char_mask_map[] = {\n 0,\n";
+
+$encodings = "";
+
+for $cp (@codepoints) {
+ $u = $cp->[0]; $e = $cp->[1];
+
+ if (!defined $old_u) {
+ $old_u = $u;
+ $encodings = $e;
+ } elsif ($old_u ne $u) {
+ add($encodings);
+ $old_u = $u;
+ $encodings = $e;
+ } else {
+ $encodings .= "|".$e;
+ }
+}
+
+if (defined $old_u) {
+ add($encodings);
+}
+
+print <<EOF;
+};
+
+const guchar char_masks[] = {
+EOF
+
+$encodings = "";
+
+undef $old_u;
+$start = 0;
+for $cp (@codepoints) {
+ $u = $cp->[0]; $e = $cp->[1];
+
+ if (!defined $old_u) {
+ $old_u = $u;
+ $encodings = $e;
+ } elsif ($old_u ne $u) {
+ output($start, $old_u, $combos{$encodings});
+ $start = $old_u + 1;
+ $old_u = $u;
+ $encodings = $e;
+ } else {
+ $encodings .= "|".$e;
+ }
+}
+
+if (defined $old_u) {
+ output($start, $old_u, $combos{$encodings});
+}
+
+print "\n};\n";
diff --git a/trunk/tools/gen-color-table.pl b/trunk/tools/gen-color-table.pl
new file mode 100755
index 00000000..e62994e1
--- /dev/null
+++ b/trunk/tools/gen-color-table.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/perl -w
+
+if (@ARGV != 1) {
+ die "Usage: gen-colors.pl rgb.txt > pango-color-table.h\n";
+}
+
+open IN, $ARGV[0] || die "Cannot open $ARGV[0]: $!\n";
+
+@colors = ();
+while (defined($_ = <IN>)) {
+ next if /^!/;
+ if (!/^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+(.*\S)\s+$/) {
+ die "Cannot parse line $_";
+ }
+
+ push @colors, [$1, $2, $3, $4];
+}
+
+@colors = sort { lc($a->[3]) cmp lc($b->[3]) } @colors;
+
+$offset = 0;
+
+$date = gmtime;
+
+print <<EOT;
+/* pango-color-table.h: Generated by gen-color-table.pl from rgb.txt
+ *
+ * Date: $date
+ *
+ * Do not edit.
+ */
+static const char color_names[] =
+EOT
+
+for $color (@colors) {
+ $name = $color->[3];
+
+ if ($offset != 0) {
+ print qq(\n);
+ }
+ print qq( "$name\\0");
+
+ $color->[4] = $offset;
+ $offset += length($name) + 1;
+}
+
+print ";\n\n";
+
+print <<EOT;
+typedef struct {
+ guint16 name_offset;
+ guchar red;
+ guchar green;
+ guchar blue;
+} ColorEntry;
+
+static const ColorEntry color_entries[] = {
+EOT
+
+$i = 0;
+for $color (@colors) {
+ $red = $color->[0];
+ $green = $color->[1];
+ $blue = $color->[2];
+ $offset = $color->[4];
+
+ if ($i != 0) {
+ print ",\n";
+ }
+ print " { $offset, $red, $green, $blue }";
+ $i++;
+}
+
+print "\n};\n";
diff --git a/trunk/tools/gen-script-for-lang.c b/trunk/tools/gen-script-for-lang.c
new file mode 100644
index 00000000..6d866f64
--- /dev/null
+++ b/trunk/tools/gen-script-for-lang.c
@@ -0,0 +1,323 @@
+/* Pango
+ * gen-script-for-lang.c: Utility program to generate pango-script-lang-table.h
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pango/pango-enum-types.h>
+#include <pango/pango-script.h>
+#include <pango/pango-types.h>
+#include <pango/pango-utils.h>
+
+#define MAX_SCRIPTS 3
+
+typedef struct {
+ PangoLanguage *lang;
+ PangoScript scripts[MAX_SCRIPTS];
+} LangInfo;
+
+static void scripts_for_file (const char *base_dir,
+ const char *file_part,
+ LangInfo *info);
+
+static const char *get_script_name (PangoScript script)
+{
+ static GEnumClass *class = NULL;
+ GEnumValue *value;
+ if (!class)
+ class = g_type_class_ref (PANGO_TYPE_SCRIPT);
+
+ value = g_enum_get_value (class, script);
+ g_assert (value);
+
+ return value->value_name;
+}
+
+static void fail (const char *format, ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN;
+static void fail (const char *format, ...)
+{
+ va_list vap;
+
+ va_start (vap, format);
+ vfprintf (stderr, format, vap);
+ va_end (vap);
+
+ exit (1);
+}
+
+static gboolean scan_hex (const char **str, gunichar *result)
+{
+ const char *end;
+
+ *result = strtol (*str, (char **)&end, 16);
+ if (end == *str)
+ return FALSE;
+
+ *str = end;
+ return TRUE;
+}
+
+static void
+scripts_for_line (const char *base_dir,
+ const char *file_part,
+ const char *str,
+ LangInfo *info)
+{
+ gunichar start_char;
+ gunichar end_char;
+ gunichar ch;
+ const char *p = str;
+
+ if (g_str_has_prefix (str, "include"))
+ {
+ GString *file_part = g_string_new (NULL);
+
+ str += strlen ("include");
+ if (!pango_skip_space (&str))
+ goto err;
+
+ if (!pango_scan_string (&str, file_part) ||
+ pango_skip_space (&str))
+ goto err;
+
+ scripts_for_file (base_dir, file_part->str, info);
+ g_string_free (file_part, TRUE);
+
+ return;
+ }
+
+ /* Format is HEX_DIGITS or HEX_DIGITS-HEX_DIGITS */
+ if (!scan_hex (&p, &start_char))
+ goto err;
+
+ end_char = start_char;
+
+ pango_skip_space (&p);
+ if (*p == '-')
+ {
+ p++;
+ if (!scan_hex (&p, &end_char))
+ goto err;
+
+ pango_skip_space (&p);
+ }
+
+ /* The rest of the line is ignored */
+ /*
+ if (*p != '\0')
+ goto err;
+ */
+
+ for (ch = start_char; ch <= end_char; ch++)
+ {
+ PangoScript script = pango_script_for_unichar (ch);
+ if (script != PANGO_SCRIPT_COMMON &&
+ script != PANGO_SCRIPT_INHERITED)
+ {
+ int j;
+
+ if (script == PANGO_SCRIPT_UNKNOWN)
+ {
+ g_message ("Script unknown for U+%04X", ch);
+ continue;
+ }
+
+ for (j = 0; j < MAX_SCRIPTS; j++)
+ {
+ if (info->scripts[j] == script)
+ break;
+ if (info->scripts[j] == PANGO_SCRIPT_INVALID_CODE)
+ {
+ info->scripts[j] = script;
+ break;
+ }
+ }
+
+ if (j == MAX_SCRIPTS)
+ fail ("More than %d scripts found for %s\n", MAX_SCRIPTS, file_part);
+ }
+ }
+
+ return;
+
+ err:
+ fail ("While processing '%s', cannot parse line: '%s'\n", file_part, str);
+ return; /* Not reached */
+}
+
+static void
+scripts_for_file (const char *base_dir,
+ const char *file_part,
+ LangInfo *info)
+{
+ GError *error = NULL;
+ char *filename = g_build_filename (base_dir, file_part, NULL);
+ GIOChannel *channel = g_io_channel_new_file (filename, "r", &error);
+ GIOStatus status = G_IO_STATUS_NORMAL;
+
+ if (!channel)
+ fail ("Error opening '%s': %s\n", filename, error->message);
+
+ /* The files have ISO-8859-1 copyright signs in them */
+ if (!g_io_channel_set_encoding (channel, "ISO-8859-1", &error))
+ fail ("Cannot set encoding when reading '%s': %s\n", filename, error->message);
+
+ while (status == G_IO_STATUS_NORMAL)
+ {
+ char *str;
+ size_t term;
+ char *comment;
+
+ status = g_io_channel_read_line (channel, &str, NULL, &term, &error);
+ switch (status)
+ {
+ case G_IO_STATUS_NORMAL:
+ str[term] = '\0';
+ comment = strchr (str, '#');
+ if (comment)
+ *comment = '\0';
+ g_strstrip (str);
+ if (str[0] != '\0') /* Empty */
+ scripts_for_line (base_dir, file_part, str, info);
+ g_free (str);
+ break;
+ case G_IO_STATUS_EOF:
+ break;
+ case G_IO_STATUS_ERROR:
+ fail ("Error reading '%s': %s\n", filename, error->message);
+ break;
+ case G_IO_STATUS_AGAIN:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+
+ if (!g_io_channel_shutdown (channel, FALSE, &error))
+ fail ("Error closing '%s': %s\n", filename, error->message);
+
+ g_free (filename);
+}
+
+static void
+do_file (GArray *script_array,
+ const char *base_dir,
+ const char *file_part)
+{
+ char *langpart;
+ LangInfo info;
+ int j;
+
+ langpart = g_strndup (file_part, strlen (file_part) - strlen (".orth"));
+ info.lang = pango_language_from_string (langpart);
+ g_free (langpart);
+
+ for (j = 0; j < MAX_SCRIPTS; j++)
+ info.scripts[j] = PANGO_SCRIPT_INVALID_CODE;
+
+ scripts_for_file (base_dir, file_part, &info);
+
+ g_array_append_val (script_array, info);
+}
+
+static int
+compare_lang (gconstpointer a,
+ gconstpointer b)
+{
+ const LangInfo *info_a = a;
+ const LangInfo *info_b = b;
+
+ return strcmp (pango_language_to_string (info_a->lang),
+ pango_language_to_string (info_b->lang));
+}
+
+int main (int argc, char **argv)
+{
+ GDir *dir;
+ GError *error = NULL;
+ GArray *script_array;
+ unsigned int i;
+ int j;
+ int max_lang_len = 0;
+
+ g_type_init ();
+
+ if (argc != 2)
+ fail ("Usage: gen-script-for-lang DIR > script-for-lang.h\n");
+
+ dir = g_dir_open (argv[1], 0, &error);
+ if (!dir)
+ fail ("%s\n", error->message);
+
+ script_array = g_array_new (FALSE, FALSE, sizeof (LangInfo));
+
+ while (TRUE)
+ {
+ const char *name = g_dir_read_name (dir);
+ if (!name)
+ break;
+
+ if (g_str_has_suffix (name, ".orth"))
+ do_file (script_array, argv[1], name);
+ }
+
+ g_array_sort (script_array, compare_lang);
+
+ for (i = 0; i < script_array->len; i++)
+ {
+ LangInfo *info = &g_array_index (script_array, LangInfo, i);
+
+ max_lang_len = MAX (max_lang_len,
+ 1 + (int)strlen (pango_language_to_string (info->lang)));
+ }
+
+ g_print ("typedef struct {\n"
+ " const char lang[%d];\n"
+ " PangoScript scripts[%d];\n"
+ "} PangoScriptForLang;\n"
+ "\n"
+ "static const PangoScriptForLang pango_script_for_lang[] = {\n",
+ max_lang_len,
+ MAX_SCRIPTS);
+
+ for (i = 0; i < script_array->len; i++)
+ {
+ LangInfo *info = &g_array_index (script_array, LangInfo, i);
+
+ g_print (" { \"%s\", { ", pango_language_to_string (info->lang));
+ for (j = 0; j < MAX_SCRIPTS; j++)
+ {
+ if (j != 0)
+ g_print (", ");
+ g_print ("%s", get_script_name (info->scripts[j]));
+ }
+ g_print (" } },\n");
+ }
+
+ g_print ("};\n");
+
+
+ g_dir_close (dir);
+
+ return 0;
+}
diff --git a/trunk/tools/gen-script-table.pl b/trunk/tools/gen-script-table.pl
new file mode 100755
index 00000000..f3af7ce2
--- /dev/null
+++ b/trunk/tools/gen-script-table.pl
@@ -0,0 +1,117 @@
+#!/usr/bin/perl -w
+#
+# Script to convert http://www.unicode.org/Public/UNIDATA/Scripts.txt
+# into a machine-readable table.
+#
+######################################################################
+
+if (@ARGV != 1) {
+ die "Usage: gen-script-table.pl Scripts.txt > pango-script-table.h\n";
+}
+
+open IN, $ARGV[0] || die "Cannot open $ARGV[0]: $!\n";
+
+my @ranges;
+my $file;
+my $easy_range;
+my $i;
+my $start;
+my $end;
+my $script;
+
+
+while (<IN>) {
+ if (/^\#\s+(Scripts-.*.txt)/) {
+ $file = $1;
+ }
+
+ s/#.*//;
+ next if /^\s*$/;
+ if (!/^([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s*;\s*([A-Za-z_]+)\s*$/) {
+ die "Cannot parse line: '$_'\n";
+ }
+
+ if (defined $2) {
+ push @ranges, [ hex $1, hex $2, uc $3 ];
+ } else {
+ push @ranges, [ hex $1, hex $1, uc $3 ];
+ }
+}
+
+@ranges = sort { $a->[0] <=> $b->[0] } @ranges;
+$date = gmtime;
+
+print <<"EOT";
+/* pango-script-table.h: Generated by gen-script-table.pl
+ *
+ * Date: $date
+ * Source: $file
+ *
+ * Do not edit.
+ */
+
+EOT
+
+$easy_range = 0x2000;
+
+print <<"EOT";
+static const guchar pango_script_easy_table[$easy_range] = {
+EOT
+
+$i = 0;
+$end = -1;
+
+for (my $c = 0; $c < $easy_range; $c++) {
+
+ if ($c % 3 == 0) {
+ printf "\n ";
+ }
+
+ if ($c > $end) {
+ $start = $ranges[$i]->[0];
+ $end = $ranges[$i]->[1];
+ $script = $ranges[$i]->[2];
+ $i++;
+ }
+
+ if ($c < $start) {
+ printf " PANGO_SCRIPT_UNKNOWN,";
+ } else {
+ printf " PANGO_SCRIPT_%s,", $script;
+ }
+}
+
+if ($end >= $easy_range) {
+ $i--;
+ $ranges[$i]->[0] = $easy_range;
+}
+
+
+print <<"EOT";
+
+};
+
+static const struct {
+ gunichar start;
+ guint16 chars;
+ guint16 script;
+} pango_script_table[] = {
+EOT
+
+for (; $i <= $#ranges; $i++) {
+ $start = $ranges[$i]->[0];
+ $end = $ranges[$i]->[1];
+ $script = $ranges[$i]->[2];
+
+ while ($i <= $#ranges - 1 &&
+ $ranges[$i + 1]->[0] == $end + 1 &&
+ $ranges[$i + 1]->[2] eq $script) {
+ $i++;
+ $end = $ranges[$i]->[1];
+ }
+
+ printf " { %#06x, %5d, PANGO_SCRIPT_%s },\n", $start, $end - $start + 1, $script;
+}
+
+printf "};\n";
+
diff --git a/trunk/tools/maps/README b/trunk/tools/maps/README
new file mode 100644
index 00000000..036fc5b1
--- /dev/null
+++ b/trunk/tools/maps/README
@@ -0,0 +1,12 @@
+This directory is intentionally empty. It is located
+here so that mapping tables can be put here when
+running the make-table.sh script in the parent directory.
+
+However, the mapping tables that I've used are those
+provided by the Unicode consortium, which can't be
+distributed in their original form, though the data
+is freely useable.
+
+Owen Taylor
+otaylor@redhat.com
+10 Jul 1999 \ No newline at end of file
diff --git a/trunk/tools/maps/tis-620 b/trunk/tools/maps/tis-620
new file mode 100644
index 00000000..2a8bbd84
--- /dev/null
+++ b/trunk/tools/maps/tis-620
@@ -0,0 +1,185 @@
+# This table was created by Owen Taylor <otaylor@redhat.com>.
+# You may use, modify and redistribute it without restriction.
+
+0x20 0x0020
+0x21 0x0021
+0x22 0x0022
+0x23 0x0023
+0x24 0x0024
+0x25 0x0025
+0x26 0x0026
+0x27 0x0027
+0x28 0x0028
+0x29 0x0029
+0x2A 0x002A
+0x2B 0x002B
+0x2C 0x002C
+0x2D 0x002D
+0x2E 0x002E
+0x2F 0x002F
+0x30 0x0030
+0x31 0x0031
+0x32 0x0032
+0x33 0x0033
+0x34 0x0034
+0x35 0x0035
+0x36 0x0036
+0x37 0x0037
+0x38 0x0038
+0x39 0x0039
+0x3A 0x003A
+0x3B 0x003B
+0x3C 0x003C
+0x3D 0x003D
+0x3E 0x003E
+0x3F 0x003F
+0x40 0x0040
+0x41 0x0041
+0x42 0x0042
+0x43 0x0043
+0x44 0x0044
+0x45 0x0045
+0x46 0x0046
+0x47 0x0047
+0x48 0x0048
+0x49 0x0049
+0x4A 0x004A
+0x4B 0x004B
+0x4C 0x004C
+0x4D 0x004D
+0x4E 0x004E
+0x4F 0x004F
+0x50 0x0050
+0x51 0x0051
+0x52 0x0052
+0x53 0x0053
+0x54 0x0054
+0x55 0x0055
+0x56 0x0056
+0x57 0x0057
+0x58 0x0058
+0x59 0x0059
+0x5A 0x005A
+0x5B 0x005B
+0x5C 0x005C
+0x5D 0x005D
+0x5E 0x005E
+0x5F 0x005F
+0x60 0x0060
+0x61 0x0061
+0x62 0x0062
+0x63 0x0063
+0x64 0x0064
+0x65 0x0065
+0x66 0x0066
+0x67 0x0067
+0x68 0x0068
+0x69 0x0069
+0x6A 0x006A
+0x6B 0x006B
+0x6C 0x006C
+0x6D 0x006D
+0x6E 0x006E
+0x6F 0x006F
+0x70 0x0070
+0x71 0x0071
+0x72 0x0072
+0x73 0x0073
+0x74 0x0074
+0x75 0x0075
+0x76 0x0076
+0x77 0x0077
+0x78 0x0078
+0x79 0x0079
+0x7A 0x007A
+0x7B 0x007B
+0x7C 0x007C
+0x7D 0x007D
+0x7E 0x007E
+0xA1 0x0E01
+0xA2 0x0E02
+0xA3 0x0E03
+0xA4 0x0E04
+0xA5 0x0E05
+0xA6 0x0E06
+0xA7 0x0E07
+0xA8 0x0E08
+0xA9 0x0E09
+0xAA 0x0E0A
+0xAB 0x0E0B
+0xAC 0x0E0C
+0xAD 0x0E0D
+0xAE 0x0E0E
+0xAF 0x0E0F
+0xB0 0x0E10
+0xB1 0x0E11
+0xB2 0x0E12
+0xB3 0x0E13
+0xB4 0x0E14
+0xB5 0x0E15
+0xB6 0x0E16
+0xB7 0x0E17
+0xB8 0x0E18
+0xB9 0x0E19
+0xBA 0x0E1A
+0xBB 0x0E1B
+0xBC 0x0E1C
+0xBD 0x0E1D
+0xBE 0x0E1E
+0xBF 0x0E1F
+0xC0 0x0E20
+0xC1 0x0E21
+0xC2 0x0E22
+0xC3 0x0E23
+0xC4 0x0E24
+0xC5 0x0E25
+0xC6 0x0E26
+0xC7 0x0E27
+0xC8 0x0E28
+0xC9 0x0E29
+0xCA 0x0E2A
+0xCB 0x0E2B
+0xCC 0x0E2C
+0xCD 0x0E2D
+0xCE 0x0E2E
+0xCF 0x0E2F
+0xD0 0x0E30
+0xD1 0x0E31
+0xD2 0x0E32
+0xD3 0x0E33
+0xD4 0x0E34
+0xD5 0x0E35
+0xD6 0x0E36
+0xD7 0x0E37
+0xD8 0x0E38
+0xD9 0x0E39
+0xDA 0x0E3A
+0xDF 0x0E3F
+0xE0 0x0E40
+0xE1 0x0E41
+0xE2 0x0E42
+0xE3 0x0E43
+0xE4 0x0E44
+0xE5 0x0E45
+0xE6 0x0E46
+0xE7 0x0E47
+0xE8 0x0E48
+0xE9 0x0E49
+0xEA 0x0E4A
+0xEB 0x0E4B
+0xEC 0x0E4C
+0xED 0x0E4D
+0xEE 0x0E4E
+0xEF 0x0E4F
+0xF0 0x0E50
+0xF1 0x0E51
+0xF2 0x0E52
+0xF3 0x0E53
+0xF4 0x0E54
+0xF5 0x0E55
+0xF6 0x0E56
+0xF7 0x0E57
+0xF8 0x0E58
+0xF9 0x0E59
+0xFA 0x0E5A
+0xFB 0x0E5B