From f3a77d3c00c095a53f37aa7efb39d56168799596 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Wed, 6 Jan 2010 16:32:59 +0000 Subject: Port to core buildsystem. The python module (and associated make runes) need some love (as does non-GCC building with the core buildsystem in general) svn path=/trunk/rufl/; revision=9792 --- Glyphs | 1406 ---------------------------------- Makefile | 44 ++ build/tools/makeglyphs | 29 + include/rufl.h | 207 +++++ librufl.pc.in | 10 + makefile | 108 --- makeglyphs | 29 - python/Mk.old | 21 + python/ruflmodule.c | 203 +++++ rufl.h | 207 ----- rufl_character_set_test.c | 37 - rufl_chars.c | 315 -------- rufl_decompose.c | 161 ---- rufl_dump_state.c | 138 ---- rufl_find.c | 201 ----- rufl_init.c | 1678 ----------------------------------------- rufl_internal.h | 194 ----- rufl_invalidate_cache.c | 28 - rufl_metrics.c | 312 -------- rufl_paint.c | 621 --------------- rufl_quit.c | 49 -- rufl_test.c | 141 ---- ruflmodule.c | 203 ----- src/Glyphs | 1406 ++++++++++++++++++++++++++++++++++ src/Makefile | 12 + src/rufl_character_set_test.c | 37 + src/rufl_decompose.c | 161 ++++ src/rufl_dump_state.c | 138 ++++ src/rufl_find.c | 201 +++++ src/rufl_init.c | 1678 +++++++++++++++++++++++++++++++++++++++++ src/rufl_internal.h | 194 +++++ src/rufl_invalidate_cache.c | 28 + src/rufl_metrics.c | 312 ++++++++ src/rufl_paint.c | 621 +++++++++++++++ src/rufl_quit.c | 49 ++ src/strfuncs.c | 37 + src/strfuncs.h | 5 + strfuncs.c | 35 - strfuncs.h | 5 - test/Makefile | 4 + test/rufl_chars.c | 315 ++++++++ test/rufl_test.c | 149 ++++ 42 files changed, 5861 insertions(+), 5868 deletions(-) delete mode 100644 Glyphs create mode 100644 Makefile create mode 100755 build/tools/makeglyphs create mode 100644 include/rufl.h create mode 100644 librufl.pc.in delete mode 100644 makefile delete mode 100755 makeglyphs create mode 100644 python/Mk.old create mode 100644 python/ruflmodule.c delete mode 100644 rufl.h delete mode 100644 rufl_character_set_test.c delete mode 100644 rufl_chars.c delete mode 100644 rufl_decompose.c delete mode 100644 rufl_dump_state.c delete mode 100644 rufl_find.c delete mode 100644 rufl_init.c delete mode 100644 rufl_internal.h delete mode 100644 rufl_invalidate_cache.c delete mode 100644 rufl_metrics.c delete mode 100644 rufl_paint.c delete mode 100644 rufl_quit.c delete mode 100644 rufl_test.c delete mode 100644 ruflmodule.c create mode 100644 src/Glyphs create mode 100644 src/Makefile create mode 100644 src/rufl_character_set_test.c create mode 100644 src/rufl_decompose.c create mode 100644 src/rufl_dump_state.c create mode 100644 src/rufl_find.c create mode 100644 src/rufl_init.c create mode 100644 src/rufl_internal.h create mode 100644 src/rufl_invalidate_cache.c create mode 100644 src/rufl_metrics.c create mode 100644 src/rufl_paint.c create mode 100644 src/rufl_quit.c create mode 100644 src/strfuncs.c create mode 100644 src/strfuncs.h delete mode 100644 strfuncs.c delete mode 100644 strfuncs.h create mode 100644 test/Makefile create mode 100644 test/rufl_chars.c create mode 100644 test/rufl_test.c diff --git a/Glyphs b/Glyphs deleted file mode 100644 index d39fa0a..0000000 --- a/Glyphs +++ /dev/null @@ -1,1406 +0,0 @@ -# -# Name: Adobe Glyph List -# Table version: 1.2 -# Date: 22 Oct 1998 -# -# Description: -# -# The Adobe Glyph List (AGL) list relates Unicode values (UVs) to glyph -# names, and should be used only as described in the document "Unicode and -# Glyph Names," at -# http://www.adobe.com/supportservice/devrelations/typeforum/unicodegn.html . -# -# The glyph name to UV relation is one to many. 12 glyph names are mapped to -# two UVs each; each UV has a separate entry. All other glyph names are -# mapped to one UV each. -# -# The Unicode Standard version 2.1 is used for all UVs outside of the Private -# Use area, except for 4 entries (see Revision History for 1.2 below). -# -# There are 1051 entries in this list, 171 of which are in the Corporate Use -# subarea (CUS). Refer to the document "Unicode Corporate Use Subarea as used -# by Adobe Systems," at -# http://www.adobe.com/supportservice/devrelations/typeforum/corporateuse.txt -# for compatibility decompositions for these characters, and to the document -# "Unicode and Glyph Names" for more information the CUS. -# -# Format: Semicolon-delimited fields: -# -# (1) Standard UV or CUS UV. (4 uppercase hexadecimal digits) -# -# (2) Glyph name. (upper- and lowercase letters, digits) -# -# (3) Character names: Unicode character names for standard UVs, and -# descriptive names for CUS UVs. (uppercase letters, hyphen, space) -# -# (4) [optional] Comment. A comment of "Duplicate" indicates one of two -# UVs of a double-mapping. It is the UV that may be given a uni -# override, or the UV that is in the CUS, as described in the document -# "Unicode and Glyph Names." -# -# The entries are sorted by glyph name in increasing ASCII order; entries -# with the same glyph name are sorted in decreasing priority order. -# -# Lines starting with "#" are comments; blank lines should be ignored. -# -# Revision History: -# -# 1.2 [22 Oct 1998] -# -# Some Central European glyph names were remapped and the glyph "dotlessj" -# was added. Some entries in the table below have not changed but are -# included to provide a complete context for other glyphs that have been -# remapped or double-mapped. "-" means that the entry for that UV does not -# exist in the AGL. -# -# -------- ---------------------- ---------------- -------------- -# UV Character name AGL 1.1 AGL 1.2 -# (shortened) glyph name glyph name -# -------- ---------------------- ---------------- -------------- -# 015E/F S/s with cedilla S/scommaaccent S/scedilla -# 0162/3 T/t with cedilla T/tcommaaccent T/tcommaaccent -# 0218/9 S/s with comma below - S/scommaaccent -# 021A/B T/t with comma below - T/tcommaaccent -# 1E9E/F S/s with comma below S/scedilla - -# F6C1/2 S/s with cedilla S/scedilla S/scedilla -# F6BE dotless j - dotlessj -# -------- ---------------------- ---------------- -------------- -# -# The characters at U+1E9E/F in AGL 1.1, LATIN CAPITAL/SMALL LETTER S WITH -# COMMA BELOW, which are proposed new characters (see (b) in the notes for -# AGL 1.1 below), have since been reassigned by the Unicode Standard to new -# proposed values of U+0218/9. These characters, as well as U+021A/B, LATIN -# CAPITAL/SMALL LETTER T WITH COMMA BELOW, are not in the Unicode Standard -# 2.1. -# -# Entries with the same glyph name are now sorted in decreasing priority -# order instead of in increasing UV order. -# -# 1.1 [24 Nov 1997] -# -# a. The "Euro" glyph's UV assignment is changed from U+20A0 (EURO-CURRENCY -# SIGN) to U+20AC (EURO SIGN). While U+20AC is not defined in the -# Unicode Standard 2.0, it has been accepted by the Unicode Technical -# Committee for the next version of the Standard; it has not yet passed -# the ISO approval process as of 7 November '97. -# -# b. Glyphs "Scedilla" and "scedilla", which were assigned in the Corporate -# Use Subarea in AGL 1.0, are now additionally mapped to U+1E9E and -# U+1E9F respectively. These two UVs share the same Unicode approval -# status as the Euro glyph (see a. above). -# -# c. The "fraction" glyph is now additionally mapped to U+2215, to match -# Windows Glyph List 4. -# -# d. The descriptive name for glyph "onefitted", in the Corporate Use -# subarea, is changed from "TABULAR DIGIT ONE" to "PROPORTIONAL DIGIT -# ONE". -# -# 1.0 [17 Jul 1997] Original version -# -0041;A;LATIN CAPITAL LETTER A -00C6;AE;LATIN CAPITAL LETTER AE -01FC;AEacute;LATIN CAPITAL LETTER AE WITH ACUTE -F7E6;AEsmall;LATIN SMALL CAPITAL LETTER AE -00C1;Aacute;LATIN CAPITAL LETTER A WITH ACUTE -F7E1;Aacutesmall;LATIN SMALL CAPITAL LETTER A WITH ACUTE -0102;Abreve;LATIN CAPITAL LETTER A WITH BREVE -00C2;Acircumflex;LATIN CAPITAL LETTER A WITH CIRCUMFLEX -F7E2;Acircumflexsmall;LATIN SMALL CAPITAL LETTER A WITH CIRCUMFLEX -F6C9;Acute;CAPITAL ACUTE ACCENT -F7B4;Acutesmall;SMALL CAPITAL ACUTE ACCENT -00C4;Adieresis;LATIN CAPITAL LETTER A WITH DIAERESIS -F7E4;Adieresissmall;LATIN SMALL CAPITAL LETTER A WITH DIAERESIS -00C0;Agrave;LATIN CAPITAL LETTER A WITH GRAVE -F7E0;Agravesmall;LATIN SMALL CAPITAL LETTER A WITH GRAVE -0391;Alpha;GREEK CAPITAL LETTER ALPHA -0386;Alphatonos;GREEK CAPITAL LETTER ALPHA WITH TONOS -0100;Amacron;LATIN CAPITAL LETTER A WITH MACRON -0104;Aogonek;LATIN CAPITAL LETTER A WITH OGONEK -00C5;Aring;LATIN CAPITAL LETTER A WITH RING ABOVE -01FA;Aringacute;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE -F7E5;Aringsmall;LATIN SMALL CAPITAL LETTER A WITH RING ABOVE -F761;Asmall;LATIN SMALL CAPITAL LETTER A -00C3;Atilde;LATIN CAPITAL LETTER A WITH TILDE -F7E3;Atildesmall;LATIN SMALL CAPITAL LETTER A WITH TILDE -0042;B;LATIN CAPITAL LETTER B -0392;Beta;GREEK CAPITAL LETTER BETA -F6F4;Brevesmall;SMALL CAPITAL BREVE -F762;Bsmall;LATIN SMALL CAPITAL LETTER B -0043;C;LATIN CAPITAL LETTER C -0106;Cacute;LATIN CAPITAL LETTER C WITH ACUTE -F6CA;Caron;CAPITAL CARON -F6F5;Caronsmall;SMALL CAPITAL CARON -010C;Ccaron;LATIN CAPITAL LETTER C WITH CARON -00C7;Ccedilla;LATIN CAPITAL LETTER C WITH CEDILLA -F7E7;Ccedillasmall;LATIN SMALL CAPITAL LETTER C WITH CEDILLA -0108;Ccircumflex;LATIN CAPITAL LETTER C WITH CIRCUMFLEX -010A;Cdotaccent;LATIN CAPITAL LETTER C WITH DOT ABOVE -F7B8;Cedillasmall;SMALL CAPITAL CEDILLA -03A7;Chi;GREEK CAPITAL LETTER CHI -F6F6;Circumflexsmall;SMALL CAPITAL MODIFIER LETTER CIRCUMFLEX ACCENT -F763;Csmall;LATIN SMALL CAPITAL LETTER C -0044;D;LATIN CAPITAL LETTER D -010E;Dcaron;LATIN CAPITAL LETTER D WITH CARON -0110;Dcroat;LATIN CAPITAL LETTER D WITH STROKE -2206;Delta;INCREMENT -0394;Delta;GREEK CAPITAL LETTER DELTA;Duplicate -F6CB;Dieresis;CAPITAL DIAERESIS -F6CC;DieresisAcute;CAPITAL DIAERESIS ACUTE ACCENT -F6CD;DieresisGrave;CAPITAL DIAERESIS GRAVE ACCENT -F7A8;Dieresissmall;SMALL CAPITAL DIAERESIS -F6F7;Dotaccentsmall;SMALL CAPITAL DOT ABOVE -F764;Dsmall;LATIN SMALL CAPITAL LETTER D -0045;E;LATIN CAPITAL LETTER E -00C9;Eacute;LATIN CAPITAL LETTER E WITH ACUTE -F7E9;Eacutesmall;LATIN SMALL CAPITAL LETTER E WITH ACUTE -0114;Ebreve;LATIN CAPITAL LETTER E WITH BREVE -011A;Ecaron;LATIN CAPITAL LETTER E WITH CARON -00CA;Ecircumflex;LATIN CAPITAL LETTER E WITH CIRCUMFLEX -F7EA;Ecircumflexsmall;LATIN SMALL CAPITAL LETTER E WITH CIRCUMFLEX -00CB;Edieresis;LATIN CAPITAL LETTER E WITH DIAERESIS -F7EB;Edieresissmall;LATIN SMALL CAPITAL LETTER E WITH DIAERESIS -0116;Edotaccent;LATIN CAPITAL LETTER E WITH DOT ABOVE -00C8;Egrave;LATIN CAPITAL LETTER E WITH GRAVE -F7E8;Egravesmall;LATIN SMALL CAPITAL LETTER E WITH GRAVE -0112;Emacron;LATIN CAPITAL LETTER E WITH MACRON -014A;Eng;LATIN CAPITAL LETTER ENG -0118;Eogonek;LATIN CAPITAL LETTER E WITH OGONEK -0395;Epsilon;GREEK CAPITAL LETTER EPSILON -0388;Epsilontonos;GREEK CAPITAL LETTER EPSILON WITH TONOS -F765;Esmall;LATIN SMALL CAPITAL LETTER E -0397;Eta;GREEK CAPITAL LETTER ETA -0389;Etatonos;GREEK CAPITAL LETTER ETA WITH TONOS -00D0;Eth;LATIN CAPITAL LETTER ETH -F7F0;Ethsmall;LATIN SMALL CAPITAL LETTER ETH -20AC;Euro;EURO SIGN -0046;F;LATIN CAPITAL LETTER F -F766;Fsmall;LATIN SMALL CAPITAL LETTER F -0047;G;LATIN CAPITAL LETTER G -0393;Gamma;GREEK CAPITAL LETTER GAMMA -011E;Gbreve;LATIN CAPITAL LETTER G WITH BREVE -01E6;Gcaron;LATIN CAPITAL LETTER G WITH CARON -011C;Gcircumflex;LATIN CAPITAL LETTER G WITH CIRCUMFLEX -0122;Gcommaaccent;LATIN CAPITAL LETTER G WITH CEDILLA -0120;Gdotaccent;LATIN CAPITAL LETTER G WITH DOT ABOVE -F6CE;Grave;CAPITAL GRAVE ACCENT -F760;Gravesmall;SMALL CAPITAL GRAVE ACCENT -F767;Gsmall;LATIN SMALL CAPITAL LETTER G -0048;H;LATIN CAPITAL LETTER H -25CF;H18533;BLACK CIRCLE -25AA;H18543;BLACK SMALL SQUARE -25AB;H18551;WHITE SMALL SQUARE -25A1;H22073;WHITE SQUARE -0126;Hbar;LATIN CAPITAL LETTER H WITH STROKE -0124;Hcircumflex;LATIN CAPITAL LETTER H WITH CIRCUMFLEX -F768;Hsmall;LATIN SMALL CAPITAL LETTER H -F6CF;Hungarumlaut;CAPITAL DOUBLE ACUTE ACCENT -F6F8;Hungarumlautsmall;SMALL CAPITAL DOUBLE ACUTE ACCENT -0049;I;LATIN CAPITAL LETTER I -0132;IJ;LATIN CAPITAL LIGATURE IJ -00CD;Iacute;LATIN CAPITAL LETTER I WITH ACUTE -F7ED;Iacutesmall;LATIN SMALL CAPITAL LETTER I WITH ACUTE -012C;Ibreve;LATIN CAPITAL LETTER I WITH BREVE -00CE;Icircumflex;LATIN CAPITAL LETTER I WITH CIRCUMFLEX -F7EE;Icircumflexsmall;LATIN SMALL CAPITAL LETTER I WITH CIRCUMFLEX -00CF;Idieresis;LATIN CAPITAL LETTER I WITH DIAERESIS -F7EF;Idieresissmall;LATIN SMALL CAPITAL LETTER I WITH DIAERESIS -0130;Idotaccent;LATIN CAPITAL LETTER I WITH DOT ABOVE -2111;Ifraktur;BLACK-LETTER CAPITAL I -00CC;Igrave;LATIN CAPITAL LETTER I WITH GRAVE -F7EC;Igravesmall;LATIN SMALL CAPITAL LETTER I WITH GRAVE -012A;Imacron;LATIN CAPITAL LETTER I WITH MACRON -012E;Iogonek;LATIN CAPITAL LETTER I WITH OGONEK -0399;Iota;GREEK CAPITAL LETTER IOTA -03AA;Iotadieresis;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA -038A;Iotatonos;GREEK CAPITAL LETTER IOTA WITH TONOS -F769;Ismall;LATIN SMALL CAPITAL LETTER I -0128;Itilde;LATIN CAPITAL LETTER I WITH TILDE -004A;J;LATIN CAPITAL LETTER J -0134;Jcircumflex;LATIN CAPITAL LETTER J WITH CIRCUMFLEX -F76A;Jsmall;LATIN SMALL CAPITAL LETTER J -004B;K;LATIN CAPITAL LETTER K -039A;Kappa;GREEK CAPITAL LETTER KAPPA -0136;Kcommaaccent;LATIN CAPITAL LETTER K WITH CEDILLA -F76B;Ksmall;LATIN SMALL CAPITAL LETTER K -004C;L;LATIN CAPITAL LETTER L -F6BF;LL;LATIN CAPITAL LETTER LL -0139;Lacute;LATIN CAPITAL LETTER L WITH ACUTE -039B;Lambda;GREEK CAPITAL LETTER LAMDA -013D;Lcaron;LATIN CAPITAL LETTER L WITH CARON -013B;Lcommaaccent;LATIN CAPITAL LETTER L WITH CEDILLA -013F;Ldot;LATIN CAPITAL LETTER L WITH MIDDLE DOT -0141;Lslash;LATIN CAPITAL LETTER L WITH STROKE -F6F9;Lslashsmall;LATIN SMALL CAPITAL LETTER L WITH STROKE -F76C;Lsmall;LATIN SMALL CAPITAL LETTER L -004D;M;LATIN CAPITAL LETTER M -F6D0;Macron;CAPITAL MACRON -F7AF;Macronsmall;SMALL CAPITAL MACRON -F76D;Msmall;LATIN SMALL CAPITAL LETTER M -039C;Mu;GREEK CAPITAL LETTER MU -004E;N;LATIN CAPITAL LETTER N -0143;Nacute;LATIN CAPITAL LETTER N WITH ACUTE -0147;Ncaron;LATIN CAPITAL LETTER N WITH CARON -0145;Ncommaaccent;LATIN CAPITAL LETTER N WITH CEDILLA -F76E;Nsmall;LATIN SMALL CAPITAL LETTER N -00D1;Ntilde;LATIN CAPITAL LETTER N WITH TILDE -F7F1;Ntildesmall;LATIN SMALL CAPITAL LETTER N WITH TILDE -039D;Nu;GREEK CAPITAL LETTER NU -004F;O;LATIN CAPITAL LETTER O -0152;OE;LATIN CAPITAL LIGATURE OE -F6FA;OEsmall;LATIN SMALL CAPITAL LIGATURE OE -00D3;Oacute;LATIN CAPITAL LETTER O WITH ACUTE -F7F3;Oacutesmall;LATIN SMALL CAPITAL LETTER O WITH ACUTE -014E;Obreve;LATIN CAPITAL LETTER O WITH BREVE -00D4;Ocircumflex;LATIN CAPITAL LETTER O WITH CIRCUMFLEX -F7F4;Ocircumflexsmall;LATIN SMALL CAPITAL LETTER O WITH CIRCUMFLEX -00D6;Odieresis;LATIN CAPITAL LETTER O WITH DIAERESIS -F7F6;Odieresissmall;LATIN SMALL CAPITAL LETTER O WITH DIAERESIS -F6FB;Ogoneksmall;SMALL CAPITAL OGONEK -00D2;Ograve;LATIN CAPITAL LETTER O WITH GRAVE -F7F2;Ogravesmall;LATIN SMALL CAPITAL LETTER O WITH GRAVE -01A0;Ohorn;LATIN CAPITAL LETTER O WITH HORN -0150;Ohungarumlaut;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE -014C;Omacron;LATIN CAPITAL LETTER O WITH MACRON -2126;Omega;OHM SIGN -03A9;Omega;GREEK CAPITAL LETTER OMEGA;Duplicate -038F;Omegatonos;GREEK CAPITAL LETTER OMEGA WITH TONOS -039F;Omicron;GREEK CAPITAL LETTER OMICRON -038C;Omicrontonos;GREEK CAPITAL LETTER OMICRON WITH TONOS -00D8;Oslash;LATIN CAPITAL LETTER O WITH STROKE -01FE;Oslashacute;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE -F7F8;Oslashsmall;LATIN SMALL CAPITAL LETTER O WITH STROKE -F76F;Osmall;LATIN SMALL CAPITAL LETTER O -00D5;Otilde;LATIN CAPITAL LETTER O WITH TILDE -F7F5;Otildesmall;LATIN SMALL CAPITAL LETTER O WITH TILDE -0050;P;LATIN CAPITAL LETTER P -03A6;Phi;GREEK CAPITAL LETTER PHI -03A0;Pi;GREEK CAPITAL LETTER PI -03A8;Psi;GREEK CAPITAL LETTER PSI -F770;Psmall;LATIN SMALL CAPITAL LETTER P -0051;Q;LATIN CAPITAL LETTER Q -F771;Qsmall;LATIN SMALL CAPITAL LETTER Q -0052;R;LATIN CAPITAL LETTER R -0154;Racute;LATIN CAPITAL LETTER R WITH ACUTE -0158;Rcaron;LATIN CAPITAL LETTER R WITH CARON -0156;Rcommaaccent;LATIN CAPITAL LETTER R WITH CEDILLA -211C;Rfraktur;BLACK-LETTER CAPITAL R -03A1;Rho;GREEK CAPITAL LETTER RHO -F6FC;Ringsmall;SMALL CAPITAL RING ABOVE -F772;Rsmall;LATIN SMALL CAPITAL LETTER R -0053;S;LATIN CAPITAL LETTER S -250C;SF010000;BOX DRAWINGS LIGHT DOWN AND RIGHT -2514;SF020000;BOX DRAWINGS LIGHT UP AND RIGHT -2510;SF030000;BOX DRAWINGS LIGHT DOWN AND LEFT -2518;SF040000;BOX DRAWINGS LIGHT UP AND LEFT -253C;SF050000;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL -252C;SF060000;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL -2534;SF070000;BOX DRAWINGS LIGHT UP AND HORIZONTAL -251C;SF080000;BOX DRAWINGS LIGHT VERTICAL AND RIGHT -2524;SF090000;BOX DRAWINGS LIGHT VERTICAL AND LEFT -2500;SF100000;BOX DRAWINGS LIGHT HORIZONTAL -2502;SF110000;BOX DRAWINGS LIGHT VERTICAL -2561;SF190000;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE -2562;SF200000;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE -2556;SF210000;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE -2555;SF220000;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE -2563;SF230000;BOX DRAWINGS DOUBLE VERTICAL AND LEFT -2551;SF240000;BOX DRAWINGS DOUBLE VERTICAL -2557;SF250000;BOX DRAWINGS DOUBLE DOWN AND LEFT -255D;SF260000;BOX DRAWINGS DOUBLE UP AND LEFT -255C;SF270000;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE -255B;SF280000;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE -255E;SF360000;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE -255F;SF370000;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE -255A;SF380000;BOX DRAWINGS DOUBLE UP AND RIGHT -2554;SF390000;BOX DRAWINGS DOUBLE DOWN AND RIGHT -2569;SF400000;BOX DRAWINGS DOUBLE UP AND HORIZONTAL -2566;SF410000;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL -2560;SF420000;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT -2550;SF430000;BOX DRAWINGS DOUBLE HORIZONTAL -256C;SF440000;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL -2567;SF450000;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE -2568;SF460000;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE -2564;SF470000;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE -2565;SF480000;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE -2559;SF490000;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE -2558;SF500000;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE -2552;SF510000;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE -2553;SF520000;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE -256B;SF530000;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE -256A;SF540000;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE -015A;Sacute;LATIN CAPITAL LETTER S WITH ACUTE -0160;Scaron;LATIN CAPITAL LETTER S WITH CARON -F6FD;Scaronsmall;LATIN SMALL CAPITAL LETTER S WITH CARON -015E;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA -F6C1;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA;Duplicate -015C;Scircumflex;LATIN CAPITAL LETTER S WITH CIRCUMFLEX -0218;Scommaaccent;LATIN CAPITAL LETTER S WITH COMMA BELOW -03A3;Sigma;GREEK CAPITAL LETTER SIGMA -F773;Ssmall;LATIN SMALL CAPITAL LETTER S -0054;T;LATIN CAPITAL LETTER T -03A4;Tau;GREEK CAPITAL LETTER TAU -0166;Tbar;LATIN CAPITAL LETTER T WITH STROKE -0164;Tcaron;LATIN CAPITAL LETTER T WITH CARON -0162;Tcommaaccent;LATIN CAPITAL LETTER T WITH CEDILLA -021A;Tcommaaccent;LATIN CAPITAL LETTER T WITH COMMA BELOW;Duplicate -0398;Theta;GREEK CAPITAL LETTER THETA -00DE;Thorn;LATIN CAPITAL LETTER THORN -F7FE;Thornsmall;LATIN SMALL CAPITAL LETTER THORN -F6FE;Tildesmall;SMALL CAPITAL SMALL TILDE -F774;Tsmall;LATIN SMALL CAPITAL LETTER T -0055;U;LATIN CAPITAL LETTER U -00DA;Uacute;LATIN CAPITAL LETTER U WITH ACUTE -F7FA;Uacutesmall;LATIN SMALL CAPITAL LETTER U WITH ACUTE -016C;Ubreve;LATIN CAPITAL LETTER U WITH BREVE -00DB;Ucircumflex;LATIN CAPITAL LETTER U WITH CIRCUMFLEX -F7FB;Ucircumflexsmall;LATIN SMALL CAPITAL LETTER U WITH CIRCUMFLEX -00DC;Udieresis;LATIN CAPITAL LETTER U WITH DIAERESIS -F7FC;Udieresissmall;LATIN SMALL CAPITAL LETTER U WITH DIAERESIS -00D9;Ugrave;LATIN CAPITAL LETTER U WITH GRAVE -F7F9;Ugravesmall;LATIN SMALL CAPITAL LETTER U WITH GRAVE -01AF;Uhorn;LATIN CAPITAL LETTER U WITH HORN -0170;Uhungarumlaut;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE -016A;Umacron;LATIN CAPITAL LETTER U WITH MACRON -0172;Uogonek;LATIN CAPITAL LETTER U WITH OGONEK -03A5;Upsilon;GREEK CAPITAL LETTER UPSILON -03D2;Upsilon1;GREEK UPSILON WITH HOOK SYMBOL -03AB;Upsilondieresis;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA -038E;Upsilontonos;GREEK CAPITAL LETTER UPSILON WITH TONOS -016E;Uring;LATIN CAPITAL LETTER U WITH RING ABOVE -F775;Usmall;LATIN SMALL CAPITAL LETTER U -0168;Utilde;LATIN CAPITAL LETTER U WITH TILDE -0056;V;LATIN CAPITAL LETTER V -F776;Vsmall;LATIN SMALL CAPITAL LETTER V -0057;W;LATIN CAPITAL LETTER W -1E82;Wacute;LATIN CAPITAL LETTER W WITH ACUTE -0174;Wcircumflex;LATIN CAPITAL LETTER W WITH CIRCUMFLEX -1E84;Wdieresis;LATIN CAPITAL LETTER W WITH DIAERESIS -1E80;Wgrave;LATIN CAPITAL LETTER W WITH GRAVE -F777;Wsmall;LATIN SMALL CAPITAL LETTER W -0058;X;LATIN CAPITAL LETTER X -039E;Xi;GREEK CAPITAL LETTER XI -F778;Xsmall;LATIN SMALL CAPITAL LETTER X -0059;Y;LATIN CAPITAL LETTER Y -00DD;Yacute;LATIN CAPITAL LETTER Y WITH ACUTE -F7FD;Yacutesmall;LATIN SMALL CAPITAL LETTER Y WITH ACUTE -0176;Ycircumflex;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX -0178;Ydieresis;LATIN CAPITAL LETTER Y WITH DIAERESIS -F7FF;Ydieresissmall;LATIN SMALL CAPITAL LETTER Y WITH DIAERESIS -1EF2;Ygrave;LATIN CAPITAL LETTER Y WITH GRAVE -F779;Ysmall;LATIN SMALL CAPITAL LETTER Y -005A;Z;LATIN CAPITAL LETTER Z -0179;Zacute;LATIN CAPITAL LETTER Z WITH ACUTE -017D;Zcaron;LATIN CAPITAL LETTER Z WITH CARON -F6FF;Zcaronsmall;LATIN SMALL CAPITAL LETTER Z WITH CARON -017B;Zdotaccent;LATIN CAPITAL LETTER Z WITH DOT ABOVE -0396;Zeta;GREEK CAPITAL LETTER ZETA -F77A;Zsmall;LATIN SMALL CAPITAL LETTER Z -0061;a;LATIN SMALL LETTER A -00E1;aacute;LATIN SMALL LETTER A WITH ACUTE -0103;abreve;LATIN SMALL LETTER A WITH BREVE -00E2;acircumflex;LATIN SMALL LETTER A WITH CIRCUMFLEX -00B4;acute;ACUTE ACCENT -0301;acutecomb;COMBINING ACUTE ACCENT -00E4;adieresis;LATIN SMALL LETTER A WITH DIAERESIS -00E6;ae;LATIN SMALL LETTER AE -01FD;aeacute;LATIN SMALL LETTER AE WITH ACUTE -2015;afii00208;HORIZONTAL BAR -0410;afii10017;CYRILLIC CAPITAL LETTER A -0411;afii10018;CYRILLIC CAPITAL LETTER BE -0412;afii10019;CYRILLIC CAPITAL LETTER VE -0413;afii10020;CYRILLIC CAPITAL LETTER GHE -0414;afii10021;CYRILLIC CAPITAL LETTER DE -0415;afii10022;CYRILLIC CAPITAL LETTER IE -0401;afii10023;CYRILLIC CAPITAL LETTER IO -0416;afii10024;CYRILLIC CAPITAL LETTER ZHE -0417;afii10025;CYRILLIC CAPITAL LETTER ZE -0418;afii10026;CYRILLIC CAPITAL LETTER I -0419;afii10027;CYRILLIC CAPITAL LETTER SHORT I -041A;afii10028;CYRILLIC CAPITAL LETTER KA -041B;afii10029;CYRILLIC CAPITAL LETTER EL -041C;afii10030;CYRILLIC CAPITAL LETTER EM -041D;afii10031;CYRILLIC CAPITAL LETTER EN -041E;afii10032;CYRILLIC CAPITAL LETTER O -041F;afii10033;CYRILLIC CAPITAL LETTER PE -0420;afii10034;CYRILLIC CAPITAL LETTER ER -0421;afii10035;CYRILLIC CAPITAL LETTER ES -0422;afii10036;CYRILLIC CAPITAL LETTER TE -0423;afii10037;CYRILLIC CAPITAL LETTER U -0424;afii10038;CYRILLIC CAPITAL LETTER EF -0425;afii10039;CYRILLIC CAPITAL LETTER HA -0426;afii10040;CYRILLIC CAPITAL LETTER TSE -0427;afii10041;CYRILLIC CAPITAL LETTER CHE -0428;afii10042;CYRILLIC CAPITAL LETTER SHA -0429;afii10043;CYRILLIC CAPITAL LETTER SHCHA -042A;afii10044;CYRILLIC CAPITAL LETTER HARD SIGN -042B;afii10045;CYRILLIC CAPITAL LETTER YERU -042C;afii10046;CYRILLIC CAPITAL LETTER SOFT SIGN -042D;afii10047;CYRILLIC CAPITAL LETTER E -042E;afii10048;CYRILLIC CAPITAL LETTER YU -042F;afii10049;CYRILLIC CAPITAL LETTER YA -0490;afii10050;CYRILLIC CAPITAL LETTER GHE WITH UPTURN -0402;afii10051;CYRILLIC CAPITAL LETTER DJE -0403;afii10052;CYRILLIC CAPITAL LETTER GJE -0404;afii10053;CYRILLIC CAPITAL LETTER UKRAINIAN IE -0405;afii10054;CYRILLIC CAPITAL LETTER DZE -0406;afii10055;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I -0407;afii10056;CYRILLIC CAPITAL LETTER YI -0408;afii10057;CYRILLIC CAPITAL LETTER JE -0409;afii10058;CYRILLIC CAPITAL LETTER LJE -040A;afii10059;CYRILLIC CAPITAL LETTER NJE -040B;afii10060;CYRILLIC CAPITAL LETTER TSHE -040C;afii10061;CYRILLIC CAPITAL LETTER KJE -040E;afii10062;CYRILLIC CAPITAL LETTER SHORT U -F6C4;afii10063;CYRILLIC SMALL LETTER GHE VARIANT -F6C5;afii10064;CYRILLIC SMALL LETTER BE VARIANT -0430;afii10065;CYRILLIC SMALL LETTER A -0431;afii10066;CYRILLIC SMALL LETTER BE -0432;afii10067;CYRILLIC SMALL LETTER VE -0433;afii10068;CYRILLIC SMALL LETTER GHE -0434;afii10069;CYRILLIC SMALL LETTER DE -0435;afii10070;CYRILLIC SMALL LETTER IE -0451;afii10071;CYRILLIC SMALL LETTER IO -0436;afii10072;CYRILLIC SMALL LETTER ZHE -0437;afii10073;CYRILLIC SMALL LETTER ZE -0438;afii10074;CYRILLIC SMALL LETTER I -0439;afii10075;CYRILLIC SMALL LETTER SHORT I -043A;afii10076;CYRILLIC SMALL LETTER KA -043B;afii10077;CYRILLIC SMALL LETTER EL -043C;afii10078;CYRILLIC SMALL LETTER EM -043D;afii10079;CYRILLIC SMALL LETTER EN -043E;afii10080;CYRILLIC SMALL LETTER O -043F;afii10081;CYRILLIC SMALL LETTER PE -0440;afii10082;CYRILLIC SMALL LETTER ER -0441;afii10083;CYRILLIC SMALL LETTER ES -0442;afii10084;CYRILLIC SMALL LETTER TE -0443;afii10085;CYRILLIC SMALL LETTER U -0444;afii10086;CYRILLIC SMALL LETTER EF -0445;afii10087;CYRILLIC SMALL LETTER HA -0446;afii10088;CYRILLIC SMALL LETTER TSE -0447;afii10089;CYRILLIC SMALL LETTER CHE -0448;afii10090;CYRILLIC SMALL LETTER SHA -0449;afii10091;CYRILLIC SMALL LETTER SHCHA -044A;afii10092;CYRILLIC SMALL LETTER HARD SIGN -044B;afii10093;CYRILLIC SMALL LETTER YERU -044C;afii10094;CYRILLIC SMALL LETTER SOFT SIGN -044D;afii10095;CYRILLIC SMALL LETTER E -044E;afii10096;CYRILLIC SMALL LETTER YU -044F;afii10097;CYRILLIC SMALL LETTER YA -0491;afii10098;CYRILLIC SMALL LETTER GHE WITH UPTURN -0452;afii10099;CYRILLIC SMALL LETTER DJE -0453;afii10100;CYRILLIC SMALL LETTER GJE -0454;afii10101;CYRILLIC SMALL LETTER UKRAINIAN IE -0455;afii10102;CYRILLIC SMALL LETTER DZE -0456;afii10103;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I -0457;afii10104;CYRILLIC SMALL LETTER YI -0458;afii10105;CYRILLIC SMALL LETTER JE -0459;afii10106;CYRILLIC SMALL LETTER LJE -045A;afii10107;CYRILLIC SMALL LETTER NJE -045B;afii10108;CYRILLIC SMALL LETTER TSHE -045C;afii10109;CYRILLIC SMALL LETTER KJE -045E;afii10110;CYRILLIC SMALL LETTER SHORT U -040F;afii10145;CYRILLIC CAPITAL LETTER DZHE -0462;afii10146;CYRILLIC CAPITAL LETTER YAT -0472;afii10147;CYRILLIC CAPITAL LETTER FITA -0474;afii10148;CYRILLIC CAPITAL LETTER IZHITSA -F6C6;afii10192;CYRILLIC SMALL LETTER DE VARIANT -045F;afii10193;CYRILLIC SMALL LETTER DZHE -0463;afii10194;CYRILLIC SMALL LETTER YAT -0473;afii10195;CYRILLIC SMALL LETTER FITA -0475;afii10196;CYRILLIC SMALL LETTER IZHITSA -F6C7;afii10831;CYRILLIC SMALL LETTER PE VARIANT -F6C8;afii10832;CYRILLIC SMALL LETTER TE VARIANT -04D9;afii10846;CYRILLIC SMALL LETTER SCHWA -200E;afii299;LEFT-TO-RIGHT MARK -200F;afii300;RIGHT-TO-LEFT MARK -200D;afii301;ZERO WIDTH JOINER -066A;afii57381;ARABIC PERCENT SIGN -060C;afii57388;ARABIC COMMA -0660;afii57392;ARABIC-INDIC DIGIT ZERO -0661;afii57393;ARABIC-INDIC DIGIT ONE -0662;afii57394;ARABIC-INDIC DIGIT TWO -0663;afii57395;ARABIC-INDIC DIGIT THREE -0664;afii57396;ARABIC-INDIC DIGIT FOUR -0665;afii57397;ARABIC-INDIC DIGIT FIVE -0666;afii57398;ARABIC-INDIC DIGIT SIX -0667;afii57399;ARABIC-INDIC DIGIT SEVEN -0668;afii57400;ARABIC-INDIC DIGIT EIGHT -0669;afii57401;ARABIC-INDIC DIGIT NINE -061B;afii57403;ARABIC SEMICOLON -061F;afii57407;ARABIC QUESTION MARK -0621;afii57409;ARABIC LETTER HAMZA -0622;afii57410;ARABIC LETTER ALEF WITH MADDA ABOVE -0623;afii57411;ARABIC LETTER ALEF WITH HAMZA ABOVE -0624;afii57412;ARABIC LETTER WAW WITH HAMZA ABOVE -0625;afii57413;ARABIC LETTER ALEF WITH HAMZA BELOW -0626;afii57414;ARABIC LETTER YEH WITH HAMZA ABOVE -0627;afii57415;ARABIC LETTER ALEF -0628;afii57416;ARABIC LETTER BEH -0629;afii57417;ARABIC LETTER TEH MARBUTA -062A;afii57418;ARABIC LETTER TEH -062B;afii57419;ARABIC LETTER THEH -062C;afii57420;ARABIC LETTER JEEM -062D;afii57421;ARABIC LETTER HAH -062E;afii57422;ARABIC LETTER KHAH -062F;afii57423;ARABIC LETTER DAL -0630;afii57424;ARABIC LETTER THAL -0631;afii57425;ARABIC LETTER REH -0632;afii57426;ARABIC LETTER ZAIN -0633;afii57427;ARABIC LETTER SEEN -0634;afii57428;ARABIC LETTER SHEEN -0635;afii57429;ARABIC LETTER SAD -0636;afii57430;ARABIC LETTER DAD -0637;afii57431;ARABIC LETTER TAH -0638;afii57432;ARABIC LETTER ZAH -0639;afii57433;ARABIC LETTER AIN -063A;afii57434;ARABIC LETTER GHAIN -0640;afii57440;ARABIC TATWEEL -0641;afii57441;ARABIC LETTER FEH -0642;afii57442;ARABIC LETTER QAF -0643;afii57443;ARABIC LETTER KAF -0644;afii57444;ARABIC LETTER LAM -0645;afii57445;ARABIC LETTER MEEM -0646;afii57446;ARABIC LETTER NOON -0648;afii57448;ARABIC LETTER WAW -0649;afii57449;ARABIC LETTER ALEF MAKSURA -064A;afii57450;ARABIC LETTER YEH -064B;afii57451;ARABIC FATHATAN -064C;afii57452;ARABIC DAMMATAN -064D;afii57453;ARABIC KASRATAN -064E;afii57454;ARABIC FATHA -064F;afii57455;ARABIC DAMMA -0650;afii57456;ARABIC KASRA -0651;afii57457;ARABIC SHADDA -0652;afii57458;ARABIC SUKUN -0647;afii57470;ARABIC LETTER HEH -06A4;afii57505;ARABIC LETTER VEH -067E;afii57506;ARABIC LETTER PEH -0686;afii57507;ARABIC LETTER TCHEH -0698;afii57508;ARABIC LETTER JEH -06AF;afii57509;ARABIC LETTER GAF -0679;afii57511;ARABIC LETTER TTEH -0688;afii57512;ARABIC LETTER DDAL -0691;afii57513;ARABIC LETTER RREH -06BA;afii57514;ARABIC LETTER NOON GHUNNA -06D2;afii57519;ARABIC LETTER YEH BARREE -06D5;afii57534;ARABIC LETTER AE -20AA;afii57636;NEW SHEQEL SIGN -05BE;afii57645;HEBREW PUNCTUATION MAQAF -05C3;afii57658;HEBREW PUNCTUATION SOF PASUQ -05D0;afii57664;HEBREW LETTER ALEF -05D1;afii57665;HEBREW LETTER BET -05D2;afii57666;HEBREW LETTER GIMEL -05D3;afii57667;HEBREW LETTER DALET -05D4;afii57668;HEBREW LETTER HE -05D5;afii57669;HEBREW LETTER VAV -05D6;afii57670;HEBREW LETTER ZAYIN -05D7;afii57671;HEBREW LETTER HET -05D8;afii57672;HEBREW LETTER TET -05D9;afii57673;HEBREW LETTER YOD -05DA;afii57674;HEBREW LETTER FINAL KAF -05DB;afii57675;HEBREW LETTER KAF -05DC;afii57676;HEBREW LETTER LAMED -05DD;afii57677;HEBREW LETTER FINAL MEM -05DE;afii57678;HEBREW LETTER MEM -05DF;afii57679;HEBREW LETTER FINAL NUN -05E0;afii57680;HEBREW LETTER NUN -05E1;afii57681;HEBREW LETTER SAMEKH -05E2;afii57682;HEBREW LETTER AYIN -05E3;afii57683;HEBREW LETTER FINAL PE -05E4;afii57684;HEBREW LETTER PE -05E5;afii57685;HEBREW LETTER FINAL TSADI -05E6;afii57686;HEBREW LETTER TSADI -05E7;afii57687;HEBREW LETTER QOF -05E8;afii57688;HEBREW LETTER RESH -05E9;afii57689;HEBREW LETTER SHIN -05EA;afii57690;HEBREW LETTER TAV -FB2A;afii57694;HEBREW LETTER SHIN WITH SHIN DOT -FB2B;afii57695;HEBREW LETTER SHIN WITH SIN DOT -FB4B;afii57700;HEBREW LETTER VAV WITH HOLAM -FB1F;afii57705;HEBREW LIGATURE YIDDISH YOD YOD PATAH -05F0;afii57716;HEBREW LIGATURE YIDDISH DOUBLE VAV -05F1;afii57717;HEBREW LIGATURE YIDDISH VAV YOD -05F2;afii57718;HEBREW LIGATURE YIDDISH DOUBLE YOD -FB35;afii57723;HEBREW LETTER VAV WITH DAGESH -05B4;afii57793;HEBREW POINT HIRIQ -05B5;afii57794;HEBREW POINT TSERE -05B6;afii57795;HEBREW POINT SEGOL -05BB;afii57796;HEBREW POINT QUBUTS -05B8;afii57797;HEBREW POINT QAMATS -05B7;afii57798;HEBREW POINT PATAH -05B0;afii57799;HEBREW POINT SHEVA -05B2;afii57800;HEBREW POINT HATAF PATAH -05B1;afii57801;HEBREW POINT HATAF SEGOL -05B3;afii57802;HEBREW POINT HATAF QAMATS -05C2;afii57803;HEBREW POINT SIN DOT -05C1;afii57804;HEBREW POINT SHIN DOT -05B9;afii57806;HEBREW POINT HOLAM -05BC;afii57807;HEBREW POINT DAGESH OR MAPIQ -05BD;afii57839;HEBREW POINT METEG -05BF;afii57841;HEBREW POINT RAFE -05C0;afii57842;HEBREW PUNCTUATION PASEQ -02BC;afii57929;MODIFIER LETTER APOSTROPHE -2105;afii61248;CARE OF -2113;afii61289;SCRIPT SMALL L -2116;afii61352;NUMERO SIGN -202C;afii61573;POP DIRECTIONAL FORMATTING -202D;afii61574;LEFT-TO-RIGHT OVERRIDE -202E;afii61575;RIGHT-TO-LEFT OVERRIDE -200C;afii61664;ZERO WIDTH NON-JOINER -066D;afii63167;ARABIC FIVE POINTED STAR -02BD;afii64937;MODIFIER LETTER REVERSED COMMA -00E0;agrave;LATIN SMALL LETTER A WITH GRAVE -2135;aleph;ALEF SYMBOL -03B1;alpha;GREEK SMALL LETTER ALPHA -03AC;alphatonos;GREEK SMALL LETTER ALPHA WITH TONOS -0101;amacron;LATIN SMALL LETTER A WITH MACRON -0026;ampersand;AMPERSAND -F726;ampersandsmall;SMALL CAPITAL AMPERSAND -2220;angle;ANGLE -2329;angleleft;LEFT-POINTING ANGLE BRACKET -232A;angleright;RIGHT-POINTING ANGLE BRACKET -0387;anoteleia;GREEK ANO TELEIA -0105;aogonek;LATIN SMALL LETTER A WITH OGONEK -2248;approxequal;ALMOST EQUAL TO -00E5;aring;LATIN SMALL LETTER A WITH RING ABOVE -01FB;aringacute;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE -2194;arrowboth;LEFT RIGHT ARROW -21D4;arrowdblboth;LEFT RIGHT DOUBLE ARROW -21D3;arrowdbldown;DOWNWARDS DOUBLE ARROW -21D0;arrowdblleft;LEFTWARDS DOUBLE ARROW -21D2;arrowdblright;RIGHTWARDS DOUBLE ARROW -21D1;arrowdblup;UPWARDS DOUBLE ARROW -2193;arrowdown;DOWNWARDS ARROW -F8E7;arrowhorizex;HORIZONTAL ARROW EXTENDER -2190;arrowleft;LEFTWARDS ARROW -2192;arrowright;RIGHTWARDS ARROW -2191;arrowup;UPWARDS ARROW -2195;arrowupdn;UP DOWN ARROW -21A8;arrowupdnbse;UP DOWN ARROW WITH BASE -F8E6;arrowvertex;VERTICAL ARROW EXTENDER -005E;asciicircum;CIRCUMFLEX ACCENT -007E;asciitilde;TILDE -002A;asterisk;ASTERISK -2217;asteriskmath;ASTERISK OPERATOR -F6E9;asuperior;SUPERSCRIPT LATIN SMALL LETTER A -0040;at;COMMERCIAL AT -00E3;atilde;LATIN SMALL LETTER A WITH TILDE -0062;b;LATIN SMALL LETTER B -005C;backslash;REVERSE SOLIDUS -007C;bar;VERTICAL LINE -03B2;beta;GREEK SMALL LETTER BETA -2588;block;FULL BLOCK -F8F4;braceex;CURLY BRACKET EXTENDER -007B;braceleft;LEFT CURLY BRACKET -F8F3;braceleftbt;LEFT CURLY BRACKET BOTTOM -F8F2;braceleftmid;LEFT CURLY BRACKET MID -F8F1;bracelefttp;LEFT CURLY BRACKET TOP -007D;braceright;RIGHT CURLY BRACKET -F8FE;bracerightbt;RIGHT CURLY BRACKET BOTTOM -F8FD;bracerightmid;RIGHT CURLY BRACKET MID -F8FC;bracerighttp;RIGHT CURLY BRACKET TOP -005B;bracketleft;LEFT SQUARE BRACKET -F8F0;bracketleftbt;LEFT SQUARE BRACKET BOTTOM -F8EF;bracketleftex;LEFT SQUARE BRACKET EXTENDER -F8EE;bracketlefttp;LEFT SQUARE BRACKET TOP -005D;bracketright;RIGHT SQUARE BRACKET -F8FB;bracketrightbt;RIGHT SQUARE BRACKET BOTTOM -F8FA;bracketrightex;RIGHT SQUARE BRACKET EXTENDER -F8F9;bracketrighttp;RIGHT SQUARE BRACKET TOP -02D8;breve;BREVE -00A6;brokenbar;BROKEN BAR -F6EA;bsuperior;SUPERSCRIPT LATIN SMALL LETTER B -2022;bullet;BULLET -0063;c;LATIN SMALL LETTER C -0107;cacute;LATIN SMALL LETTER C WITH ACUTE -02C7;caron;CARON -21B5;carriagereturn;DOWNWARDS ARROW WITH CORNER LEFTWARDS -010D;ccaron;LATIN SMALL LETTER C WITH CARON -00E7;ccedilla;LATIN SMALL LETTER C WITH CEDILLA -0109;ccircumflex;LATIN SMALL LETTER C WITH CIRCUMFLEX -010B;cdotaccent;LATIN SMALL LETTER C WITH DOT ABOVE -00B8;cedilla;CEDILLA -00A2;cent;CENT SIGN -F6DF;centinferior;SUBSCRIPT CENT SIGN -F7A2;centoldstyle;OLDSTYLE CENT SIGN -F6E0;centsuperior;SUPERSCRIPT CENT SIGN -03C7;chi;GREEK SMALL LETTER CHI -25CB;circle;WHITE CIRCLE -2297;circlemultiply;CIRCLED TIMES -2295;circleplus;CIRCLED PLUS -02C6;circumflex;MODIFIER LETTER CIRCUMFLEX ACCENT -2663;club;BLACK CLUB SUIT -003A;colon;COLON -20A1;colonmonetary;COLON SIGN -002C;comma;COMMA -F6C3;commaaccent;COMMA BELOW -F6E1;commainferior;SUBSCRIPT COMMA -F6E2;commasuperior;SUPERSCRIPT COMMA -2245;congruent;APPROXIMATELY EQUAL TO -00A9;copyright;COPYRIGHT SIGN -F8E9;copyrightsans;COPYRIGHT SIGN SANS SERIF -F6D9;copyrightserif;COPYRIGHT SIGN SERIF -00A4;currency;CURRENCY SIGN -F6D1;cyrBreve;CAPITAL CYRILLIC BREVE -F6D2;cyrFlex;CAPITAL CYRILLIC CIRCUMFLEX -F6D4;cyrbreve;CYRILLIC BREVE -F6D5;cyrflex;CYRILLIC CIRCUMFLEX -0064;d;LATIN SMALL LETTER D -2020;dagger;DAGGER -2021;daggerdbl;DOUBLE DAGGER -F6D3;dblGrave;CAPITAL DOUBLE GRAVE ACCENT -F6D6;dblgrave;DOUBLE GRAVE ACCENT -010F;dcaron;LATIN SMALL LETTER D WITH CARON -0111;dcroat;LATIN SMALL LETTER D WITH STROKE -00B0;degree;DEGREE SIGN -03B4;delta;GREEK SMALL LETTER DELTA -2666;diamond;BLACK DIAMOND SUIT -00A8;dieresis;DIAERESIS -F6D7;dieresisacute;DIAERESIS ACUTE ACCENT -F6D8;dieresisgrave;DIAERESIS GRAVE ACCENT -0385;dieresistonos;GREEK DIALYTIKA TONOS -00F7;divide;DIVISION SIGN -2593;dkshade;DARK SHADE -2584;dnblock;LOWER HALF BLOCK -0024;dollar;DOLLAR SIGN -F6E3;dollarinferior;SUBSCRIPT DOLLAR SIGN -F724;dollaroldstyle;OLDSTYLE DOLLAR SIGN -F6E4;dollarsuperior;SUPERSCRIPT DOLLAR SIGN -20AB;dong;DONG SIGN -02D9;dotaccent;DOT ABOVE -0323;dotbelowcomb;COMBINING DOT BELOW -0131;dotlessi;LATIN SMALL LETTER DOTLESS I -F6BE;dotlessj;LATIN SMALL LETTER DOTLESS J -22C5;dotmath;DOT OPERATOR -F6EB;dsuperior;SUPERSCRIPT LATIN SMALL LETTER D -0065;e;LATIN SMALL LETTER E -00E9;eacute;LATIN SMALL LETTER E WITH ACUTE -0115;ebreve;LATIN SMALL LETTER E WITH BREVE -011B;ecaron;LATIN SMALL LETTER E WITH CARON -00EA;ecircumflex;LATIN SMALL LETTER E WITH CIRCUMFLEX -00EB;edieresis;LATIN SMALL LETTER E WITH DIAERESIS -0117;edotaccent;LATIN SMALL LETTER E WITH DOT ABOVE -00E8;egrave;LATIN SMALL LETTER E WITH GRAVE -0038;eight;DIGIT EIGHT -2088;eightinferior;SUBSCRIPT EIGHT -F738;eightoldstyle;OLDSTYLE DIGIT EIGHT -2078;eightsuperior;SUPERSCRIPT EIGHT -2208;element;ELEMENT OF -2026;ellipsis;HORIZONTAL ELLIPSIS -0113;emacron;LATIN SMALL LETTER E WITH MACRON -2014;emdash;EM DASH -2205;emptyset;EMPTY SET -2013;endash;EN DASH -014B;eng;LATIN SMALL LETTER ENG -0119;eogonek;LATIN SMALL LETTER E WITH OGONEK -03B5;epsilon;GREEK SMALL LETTER EPSILON -03AD;epsilontonos;GREEK SMALL LETTER EPSILON WITH TONOS -003D;equal;EQUALS SIGN -2261;equivalence;IDENTICAL TO -212E;estimated;ESTIMATED SYMBOL -F6EC;esuperior;SUPERSCRIPT LATIN SMALL LETTER E -03B7;eta;GREEK SMALL LETTER ETA -03AE;etatonos;GREEK SMALL LETTER ETA WITH TONOS -00F0;eth;LATIN SMALL LETTER ETH -0021;exclam;EXCLAMATION MARK -203C;exclamdbl;DOUBLE EXCLAMATION MARK -00A1;exclamdown;INVERTED EXCLAMATION MARK -F7A1;exclamdownsmall;SMALL CAPITAL INVERTED EXCLAMATION MARK -F721;exclamsmall;SMALL CAPITAL EXCLAMATION MARK -2203;existential;THERE EXISTS -0066;f;LATIN SMALL LETTER F -2640;female;FEMALE SIGN -FB00;ff;LATIN SMALL LIGATURE FF -FB03;ffi;LATIN SMALL LIGATURE FFI -FB04;ffl;LATIN SMALL LIGATURE FFL -FB01;fi;LATIN SMALL LIGATURE FI -2012;figuredash;FIGURE DASH -25A0;filledbox;BLACK SQUARE -25AC;filledrect;BLACK RECTANGLE -0035;five;DIGIT FIVE -215D;fiveeighths;VULGAR FRACTION FIVE EIGHTHS -2085;fiveinferior;SUBSCRIPT FIVE -F735;fiveoldstyle;OLDSTYLE DIGIT FIVE -2075;fivesuperior;SUPERSCRIPT FIVE -FB02;fl;LATIN SMALL LIGATURE FL -0192;florin;LATIN SMALL LETTER F WITH HOOK -0034;four;DIGIT FOUR -2084;fourinferior;SUBSCRIPT FOUR -F734;fouroldstyle;OLDSTYLE DIGIT FOUR -2074;foursuperior;SUPERSCRIPT FOUR -2044;fraction;FRACTION SLASH -2215;fraction;DIVISION SLASH;Duplicate -20A3;franc;FRENCH FRANC SIGN -0067;g;LATIN SMALL LETTER G -03B3;gamma;GREEK SMALL LETTER GAMMA -011F;gbreve;LATIN SMALL LETTER G WITH BREVE -01E7;gcaron;LATIN SMALL LETTER G WITH CARON -011D;gcircumflex;LATIN SMALL LETTER G WITH CIRCUMFLEX -0123;gcommaaccent;LATIN SMALL LETTER G WITH CEDILLA -0121;gdotaccent;LATIN SMALL LETTER G WITH DOT ABOVE -00DF;germandbls;LATIN SMALL LETTER SHARP S -2207;gradient;NABLA -0060;grave;GRAVE ACCENT -0300;gravecomb;COMBINING GRAVE ACCENT -003E;greater;GREATER-THAN SIGN -2265;greaterequal;GREATER-THAN OR EQUAL TO -00AB;guillemotleft;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK -00BB;guillemotright;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -2039;guilsinglleft;SINGLE LEFT-POINTING ANGLE QUOTATION MARK -203A;guilsinglright;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK -0068;h;LATIN SMALL LETTER H -0127;hbar;LATIN SMALL LETTER H WITH STROKE -0125;hcircumflex;LATIN SMALL LETTER H WITH CIRCUMFLEX -2665;heart;BLACK HEART SUIT -0309;hookabovecomb;COMBINING HOOK ABOVE -2302;house;HOUSE -02DD;hungarumlaut;DOUBLE ACUTE ACCENT -002D;hyphen;HYPHEN-MINUS -00AD;hyphen;SOFT HYPHEN;Duplicate -F6E5;hypheninferior;SUBSCRIPT HYPHEN-MINUS -F6E6;hyphensuperior;SUPERSCRIPT HYPHEN-MINUS -0069;i;LATIN SMALL LETTER I -00ED;iacute;LATIN SMALL LETTER I WITH ACUTE -012D;ibreve;LATIN SMALL LETTER I WITH BREVE -00EE;icircumflex;LATIN SMALL LETTER I WITH CIRCUMFLEX -00EF;idieresis;LATIN SMALL LETTER I WITH DIAERESIS -00EC;igrave;LATIN SMALL LETTER I WITH GRAVE -0133;ij;LATIN SMALL LIGATURE IJ -012B;imacron;LATIN SMALL LETTER I WITH MACRON -221E;infinity;INFINITY -222B;integral;INTEGRAL -2321;integralbt;BOTTOM HALF INTEGRAL -F8F5;integralex;INTEGRAL EXTENDER -2320;integraltp;TOP HALF INTEGRAL -2229;intersection;INTERSECTION -25D8;invbullet;INVERSE BULLET -25D9;invcircle;INVERSE WHITE CIRCLE -263B;invsmileface;BLACK SMILING FACE -012F;iogonek;LATIN SMALL LETTER I WITH OGONEK -03B9;iota;GREEK SMALL LETTER IOTA -03CA;iotadieresis;GREEK SMALL LETTER IOTA WITH DIALYTIKA -0390;iotadieresistonos;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS -03AF;iotatonos;GREEK SMALL LETTER IOTA WITH TONOS -F6ED;isuperior;SUPERSCRIPT LATIN SMALL LETTER I -0129;itilde;LATIN SMALL LETTER I WITH TILDE -006A;j;LATIN SMALL LETTER J -0135;jcircumflex;LATIN SMALL LETTER J WITH CIRCUMFLEX -006B;k;LATIN SMALL LETTER K -03BA;kappa;GREEK SMALL LETTER KAPPA -0137;kcommaaccent;LATIN SMALL LETTER K WITH CEDILLA -0138;kgreenlandic;LATIN SMALL LETTER KRA -006C;l;LATIN SMALL LETTER L -013A;lacute;LATIN SMALL LETTER L WITH ACUTE -03BB;lambda;GREEK SMALL LETTER LAMDA -013E;lcaron;LATIN SMALL LETTER L WITH CARON -013C;lcommaaccent;LATIN SMALL LETTER L WITH CEDILLA -0140;ldot;LATIN SMALL LETTER L WITH MIDDLE DOT -003C;less;LESS-THAN SIGN -2264;lessequal;LESS-THAN OR EQUAL TO -258C;lfblock;LEFT HALF BLOCK -20A4;lira;LIRA SIGN -F6C0;ll;LATIN SMALL LETTER LL -2227;logicaland;LOGICAL AND -00AC;logicalnot;NOT SIGN -2228;logicalor;LOGICAL OR -017F;longs;LATIN SMALL LETTER LONG S -25CA;lozenge;LOZENGE -0142;lslash;LATIN SMALL LETTER L WITH STROKE -F6EE;lsuperior;SUPERSCRIPT LATIN SMALL LETTER L -2591;ltshade;LIGHT SHADE -006D;m;LATIN SMALL LETTER M -00AF;macron;MACRON -02C9;macron;MODIFIER LETTER MACRON;Duplicate -2642;male;MALE SIGN -2212;minus;MINUS SIGN -2032;minute;PRIME -F6EF;msuperior;SUPERSCRIPT LATIN SMALL LETTER M -00B5;mu;MICRO SIGN -03BC;mu;GREEK SMALL LETTER MU;Duplicate -00D7;multiply;MULTIPLICATION SIGN -266A;musicalnote;EIGHTH NOTE -266B;musicalnotedbl;BEAMED EIGHTH NOTES -006E;n;LATIN SMALL LETTER N -0144;nacute;LATIN SMALL LETTER N WITH ACUTE -0149;napostrophe;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE -0148;ncaron;LATIN SMALL LETTER N WITH CARON -0146;ncommaaccent;LATIN SMALL LETTER N WITH CEDILLA -0039;nine;DIGIT NINE -2089;nineinferior;SUBSCRIPT NINE -F739;nineoldstyle;OLDSTYLE DIGIT NINE -2079;ninesuperior;SUPERSCRIPT NINE -2209;notelement;NOT AN ELEMENT OF -2260;notequal;NOT EQUAL TO -2284;notsubset;NOT A SUBSET OF -207F;nsuperior;SUPERSCRIPT LATIN SMALL LETTER N -00F1;ntilde;LATIN SMALL LETTER N WITH TILDE -03BD;nu;GREEK SMALL LETTER NU -0023;numbersign;NUMBER SIGN -006F;o;LATIN SMALL LETTER O -00F3;oacute;LATIN SMALL LETTER O WITH ACUTE -014F;obreve;LATIN SMALL LETTER O WITH BREVE -00F4;ocircumflex;LATIN SMALL LETTER O WITH CIRCUMFLEX -00F6;odieresis;LATIN SMALL LETTER O WITH DIAERESIS -0153;oe;LATIN SMALL LIGATURE OE -02DB;ogonek;OGONEK -00F2;ograve;LATIN SMALL LETTER O WITH GRAVE -01A1;ohorn;LATIN SMALL LETTER O WITH HORN -0151;ohungarumlaut;LATIN SMALL LETTER O WITH DOUBLE ACUTE -014D;omacron;LATIN SMALL LETTER O WITH MACRON -03C9;omega;GREEK SMALL LETTER OMEGA -03D6;omega1;GREEK PI SYMBOL -03CE;omegatonos;GREEK SMALL LETTER OMEGA WITH TONOS -03BF;omicron;GREEK SMALL LETTER OMICRON -03CC;omicrontonos;GREEK SMALL LETTER OMICRON WITH TONOS -0031;one;DIGIT ONE -2024;onedotenleader;ONE DOT LEADER -215B;oneeighth;VULGAR FRACTION ONE EIGHTH -F6DC;onefitted;PROPORTIONAL DIGIT ONE -00BD;onehalf;VULGAR FRACTION ONE HALF -2081;oneinferior;SUBSCRIPT ONE -F731;oneoldstyle;OLDSTYLE DIGIT ONE -00BC;onequarter;VULGAR FRACTION ONE QUARTER -00B9;onesuperior;SUPERSCRIPT ONE -2153;onethird;VULGAR FRACTION ONE THIRD -25E6;openbullet;WHITE BULLET -00AA;ordfeminine;FEMININE ORDINAL INDICATOR -00BA;ordmasculine;MASCULINE ORDINAL INDICATOR -221F;orthogonal;RIGHT ANGLE -00F8;oslash;LATIN SMALL LETTER O WITH STROKE -01FF;oslashacute;LATIN SMALL LETTER O WITH STROKE AND ACUTE -F6F0;osuperior;SUPERSCRIPT LATIN SMALL LETTER O -00F5;otilde;LATIN SMALL LETTER O WITH TILDE -0070;p;LATIN SMALL LETTER P -00B6;paragraph;PILCROW SIGN -0028;parenleft;LEFT PARENTHESIS -F8ED;parenleftbt;LEFT PAREN BOTTOM -F8EC;parenleftex;LEFT PAREN EXTENDER -208D;parenleftinferior;SUBSCRIPT LEFT PARENTHESIS -207D;parenleftsuperior;SUPERSCRIPT LEFT PARENTHESIS -F8EB;parenlefttp;LEFT PAREN TOP -0029;parenright;RIGHT PARENTHESIS -F8F8;parenrightbt;RIGHT PAREN BOTTOM -F8F7;parenrightex;RIGHT PAREN EXTENDER -208E;parenrightinferior;SUBSCRIPT RIGHT PARENTHESIS -207E;parenrightsuperior;SUPERSCRIPT RIGHT PARENTHESIS -F8F6;parenrighttp;RIGHT PAREN TOP -2202;partialdiff;PARTIAL DIFFERENTIAL -0025;percent;PERCENT SIGN -002E;period;FULL STOP -00B7;periodcentered;MIDDLE DOT -2219;periodcentered;BULLET OPERATOR;Duplicate -F6E7;periodinferior;SUBSCRIPT FULL STOP -F6E8;periodsuperior;SUPERSCRIPT FULL STOP -22A5;perpendicular;UP TACK -2030;perthousand;PER MILLE SIGN -20A7;peseta;PESETA SIGN -03C6;phi;GREEK SMALL LETTER PHI -03D5;phi1;GREEK PHI SYMBOL -03C0;pi;GREEK SMALL LETTER PI -002B;plus;PLUS SIGN -00B1;plusminus;PLUS-MINUS SIGN -211E;prescription;PRESCRIPTION TAKE -220F;product;N-ARY PRODUCT -2282;propersubset;SUBSET OF -2283;propersuperset;SUPERSET OF -221D;proportional;PROPORTIONAL TO -03C8;psi;GREEK SMALL LETTER PSI -0071;q;LATIN SMALL LETTER Q -003F;question;QUESTION MARK -00BF;questiondown;INVERTED QUESTION MARK -F7BF;questiondownsmall;SMALL CAPITAL INVERTED QUESTION MARK -F73F;questionsmall;SMALL CAPITAL QUESTION MARK -0022;quotedbl;QUOTATION MARK -201E;quotedblbase;DOUBLE LOW-9 QUOTATION MARK -201C;quotedblleft;LEFT DOUBLE QUOTATION MARK -201D;quotedblright;RIGHT DOUBLE QUOTATION MARK -2018;quoteleft;LEFT SINGLE QUOTATION MARK -201B;quotereversed;SINGLE HIGH-REVERSED-9 QUOTATION MARK -2019;quoteright;RIGHT SINGLE QUOTATION MARK -201A;quotesinglbase;SINGLE LOW-9 QUOTATION MARK -0027;quotesingle;APOSTROPHE -0072;r;LATIN SMALL LETTER R -0155;racute;LATIN SMALL LETTER R WITH ACUTE -221A;radical;SQUARE ROOT -F8E5;radicalex;RADICAL EXTENDER -0159;rcaron;LATIN SMALL LETTER R WITH CARON -0157;rcommaaccent;LATIN SMALL LETTER R WITH CEDILLA -2286;reflexsubset;SUBSET OF OR EQUAL TO -2287;reflexsuperset;SUPERSET OF OR EQUAL TO -00AE;registered;REGISTERED SIGN -F8E8;registersans;REGISTERED SIGN SANS SERIF -F6DA;registerserif;REGISTERED SIGN SERIF -2310;revlogicalnot;REVERSED NOT SIGN -03C1;rho;GREEK SMALL LETTER RHO -02DA;ring;RING ABOVE -F6F1;rsuperior;SUPERSCRIPT LATIN SMALL LETTER R -2590;rtblock;RIGHT HALF BLOCK -F6DD;rupiah;RUPIAH SIGN -0073;s;LATIN SMALL LETTER S -015B;sacute;LATIN SMALL LETTER S WITH ACUTE -0161;scaron;LATIN SMALL LETTER S WITH CARON -015F;scedilla;LATIN SMALL LETTER S WITH CEDILLA -F6C2;scedilla;LATIN SMALL LETTER S WITH CEDILLA;Duplicate -015D;scircumflex;LATIN SMALL LETTER S WITH CIRCUMFLEX -0219;scommaaccent;LATIN SMALL LETTER S WITH COMMA BELOW -2033;second;DOUBLE PRIME -00A7;section;SECTION SIGN -003B;semicolon;SEMICOLON -0037;seven;DIGIT SEVEN -215E;seveneighths;VULGAR FRACTION SEVEN EIGHTHS -2087;seveninferior;SUBSCRIPT SEVEN -F737;sevenoldstyle;OLDSTYLE DIGIT SEVEN -2077;sevensuperior;SUPERSCRIPT SEVEN -2592;shade;MEDIUM SHADE -03C3;sigma;GREEK SMALL LETTER SIGMA -03C2;sigma1;GREEK SMALL LETTER FINAL SIGMA -223C;similar;TILDE OPERATOR -0036;six;DIGIT SIX -2086;sixinferior;SUBSCRIPT SIX -F736;sixoldstyle;OLDSTYLE DIGIT SIX -2076;sixsuperior;SUPERSCRIPT SIX -002F;slash;SOLIDUS -263A;smileface;WHITE SMILING FACE -0020;space;SPACE -00A0;space;NO-BREAK SPACE;Duplicate -2660;spade;BLACK SPADE SUIT -F6F2;ssuperior;SUPERSCRIPT LATIN SMALL LETTER S -00A3;sterling;POUND SIGN -220B;suchthat;CONTAINS AS MEMBER -2211;summation;N-ARY SUMMATION -263C;sun;WHITE SUN WITH RAYS -0074;t;LATIN SMALL LETTER T -03C4;tau;GREEK SMALL LETTER TAU -0167;tbar;LATIN SMALL LETTER T WITH STROKE -0165;tcaron;LATIN SMALL LETTER T WITH CARON -0163;tcommaaccent;LATIN SMALL LETTER T WITH CEDILLA -021B;tcommaaccent;LATIN SMALL LETTER T WITH COMMA BELOW;Duplicate -2234;therefore;THEREFORE -03B8;theta;GREEK SMALL LETTER THETA -03D1;theta1;GREEK THETA SYMBOL -00FE;thorn;LATIN SMALL LETTER THORN -0033;three;DIGIT THREE -215C;threeeighths;VULGAR FRACTION THREE EIGHTHS -2083;threeinferior;SUBSCRIPT THREE -F733;threeoldstyle;OLDSTYLE DIGIT THREE -00BE;threequarters;VULGAR FRACTION THREE QUARTERS -F6DE;threequartersemdash;THREE QUARTERS EM DASH -00B3;threesuperior;SUPERSCRIPT THREE -02DC;tilde;SMALL TILDE -0303;tildecomb;COMBINING TILDE -0384;tonos;GREEK TONOS -2122;trademark;TRADE MARK SIGN -F8EA;trademarksans;TRADE MARK SIGN SANS SERIF -F6DB;trademarkserif;TRADE MARK SIGN SERIF -25BC;triagdn;BLACK DOWN-POINTING TRIANGLE -25C4;triaglf;BLACK LEFT-POINTING POINTER -25BA;triagrt;BLACK RIGHT-POINTING POINTER -25B2;triagup;BLACK UP-POINTING TRIANGLE -F6F3;tsuperior;SUPERSCRIPT LATIN SMALL LETTER T -0032;two;DIGIT TWO -2025;twodotenleader;TWO DOT LEADER -2082;twoinferior;SUBSCRIPT TWO -F732;twooldstyle;OLDSTYLE DIGIT TWO -00B2;twosuperior;SUPERSCRIPT TWO -2154;twothirds;VULGAR FRACTION TWO THIRDS -0075;u;LATIN SMALL LETTER U -00FA;uacute;LATIN SMALL LETTER U WITH ACUTE -016D;ubreve;LATIN SMALL LETTER U WITH BREVE -00FB;ucircumflex;LATIN SMALL LETTER U WITH CIRCUMFLEX -00FC;udieresis;LATIN SMALL LETTER U WITH DIAERESIS -00F9;ugrave;LATIN SMALL LETTER U WITH GRAVE -01B0;uhorn;LATIN SMALL LETTER U WITH HORN -0171;uhungarumlaut;LATIN SMALL LETTER U WITH DOUBLE ACUTE -016B;umacron;LATIN SMALL LETTER U WITH MACRON -005F;underscore;LOW LINE -2017;underscoredbl;DOUBLE LOW LINE -222A;union;UNION -2200;universal;FOR ALL -0173;uogonek;LATIN SMALL LETTER U WITH OGONEK -2580;upblock;UPPER HALF BLOCK -03C5;upsilon;GREEK SMALL LETTER UPSILON -03CB;upsilondieresis;GREEK SMALL LETTER UPSILON WITH DIALYTIKA -03B0;upsilondieresistonos;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS -03CD;upsilontonos;GREEK SMALL LETTER UPSILON WITH TONOS -016F;uring;LATIN SMALL LETTER U WITH RING ABOVE -0169;utilde;LATIN SMALL LETTER U WITH TILDE -0076;v;LATIN SMALL LETTER V -0077;w;LATIN SMALL LETTER W -1E83;wacute;LATIN SMALL LETTER W WITH ACUTE -0175;wcircumflex;LATIN SMALL LETTER W WITH CIRCUMFLEX -1E85;wdieresis;LATIN SMALL LETTER W WITH DIAERESIS -2118;weierstrass;SCRIPT CAPITAL P -1E81;wgrave;LATIN SMALL LETTER W WITH GRAVE -0078;x;LATIN SMALL LETTER X -03BE;xi;GREEK SMALL LETTER XI -0079;y;LATIN SMALL LETTER Y -00FD;yacute;LATIN SMALL LETTER Y WITH ACUTE -0177;ycircumflex;LATIN SMALL LETTER Y WITH CIRCUMFLEX -00FF;ydieresis;LATIN SMALL LETTER Y WITH DIAERESIS -00A5;yen;YEN SIGN -1EF3;ygrave;LATIN SMALL LETTER Y WITH GRAVE -007A;z;LATIN SMALL LETTER Z -017A;zacute;LATIN SMALL LETTER Z WITH ACUTE -017E;zcaron;LATIN SMALL LETTER Z WITH CARON -017C;zdotaccent;LATIN SMALL LETTER Z WITH DOT ABOVE -0030;zero;DIGIT ZERO -2080;zeroinferior;SUBSCRIPT ZERO -F730;zerooldstyle;OLDSTYLE DIGIT ZERO -2070;zerosuperior;SUPERSCRIPT ZERO -03B6;zeta;GREEK SMALL LETTER ZETA - -# -# Name: ITC Zapf Dingbats encoding, Unicode values, and -# glyph names -# Table version: 1.0 -# Date: 17 July 1997 -# -# Version of ITC Zapf Dingbats: -# -# ITC Zapf Dingbats (PostScript FontName: ZapfDingbats) contains 202 -# of the 379 glyphs in PCL Zapf Dingbats. -# -# Versions of ZapfDingbats previous to 002.000 do not encode 14 out of the -# 202 available glyphs in their PostScript encoding (though these 14 glyphs -# can be accessed on the Macintosh due to the FOND's reencoding of the -# glyphs). ZapfDingbats version 002.000 encodes all of the 202 glyphs in its -# PostScript encoding. -# -# Unicode encoding of ZapfDingbats: -# -# The 188 glyphs in the PostScript encoding of versions of ZapfDingbats -# previous to 002.000 have regular Unicode values (160 in the Dingbats block -# and 28 in other blocks). The remaining 14 glyphs have been assigned -# Unicode values in the Corporate Use subarea, and coincide exactly with -# Apple's MacOS Dingbats assignments in that area. -# -# Format: Four tab-separated columns: -# -# (1) The PostScript encoding. (2 uppercase hexadecimal digits) -# 202 code points are defined. -# Source: Adobe Systems. -# -# (2) The Unicode value. (4 uppercase hexadecimal digits) -# The 14 glyphs at code points 0x80-8D have Corporate Use subarea -# values. -# Source: ftp://unicode.org/pub/UNIX/MAPPINGS/VENDORS/APPLE/DINGBAT.TXT -# [as of 25 February 1997] -# -# (3) The glyph name. (upper- and lowercase letters, digits) -# Source: Adobe Systems. -# -# (4) The Unicode 2.0 character name. (uppercase letters, hyphen, space) -# Source: The Unicode Standard, Version 2.0 -# -# The 14 Corporate Use subarea glyphs obviously don't have a -# Unicode 2.0 character name. A descriptive name (in lowercase -# letters) taken from the source for (2) above is used instead. -# -# The entries are in PostScript encoding order. -# -# Lines starting with "#" are comments; blank lines are to be ignored. -# - -0020;space;SPACE -2701;a1;UPPER BLADE SCISSORS -2702;a2;BLACK SCISSORS -2703;a202;LOWER BLADE SCISSORS -2704;a3;WHITE SCISSORS -260E;a4;BLACK TELEPHONE -2706;a5;TELEPHONE LOCATION SIGN -2707;a119;TAPE DRIVE -2708;a118;AIRPLANE -2709;a117;ENVELOPE -261B;a11;BLACK RIGHT POINTING INDEX -261E;a12;WHITE RIGHT POINTING INDEX -270C;a13;VICTORY HAND -270D;a14;WRITING HAND -270E;a15;LOWER RIGHT PENCIL -270F;a16;PENCIL -2710;a105;UPPER RIGHT PENCIL -2711;a17;WHITE NIB -2712;a18;BLACK NIB -2713;a19;CHECK MARK -2714;a20;HEAVY CHECK MARK -2715;a21;MULTIPLICATION X -2716;a22;HEAVY MULTIPLICATION X -2717;a23;BALLOT X -2718;a24;HEAVY BALLOT X -2719;a25;OUTLINED GREEK CROSS -271A;a26;HEAVY GREEK CROSS -271B;a27;OPEN CENTRE CROSS -271C;a28;HEAVY OPEN CENTRE CROSS -271D;a6;LATIN CROSS -271E;a7;SHADOWED WHITE LATIN CROSS -271F;a8;OUTLINED LATIN CROSS -2720;a9;MALTESE CROSS -2721;a10;STAR OF DAVID -2722;a29;FOUR TEARDROP-SPOKED ASTERISK -2723;a30;FOUR BALLOON-SPOKED ASTERISK -2724;a31;HEAVY FOUR BALLOON-SPOKED ASTERISK -2725;a32;FOUR CLUB-SPOKED ASTERISK -2726;a33;BLACK FOUR POINTED STAR -2727;a34;WHITE FOUR POINTED STAR -2605;a35;BLACK STAR -2729;a36;STRESS OUTLINED WHITE STAR -272A;a37;CIRCLED WHITE STAR -272B;a38;OPEN CENTRE BLACK STAR -272C;a39;BLACK CENTRE WHITE STAR -272D;a40;OUTLINED BLACK STAR -272E;a41;HEAVY OUTLINED BLACK STAR -272F;a42;PINWHEEL STAR -2730;a43;SHADOWED WHITE STAR -2731;a44;HEAVY ASTERISK -2732;a45;OPEN CENTRE ASTERISK -2733;a46;EIGHT SPOKED ASTERISK -2734;a47;EIGHT POINTED BLACK STAR -2735;a48;EIGHT POINTED PINWHEEL STAR -2736;a49;SIX POINTED BLACK STAR -2737;a50;EIGHT POINTED RECTILINEAR BLACK STAR -2738;a51;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR -2739;a52;TWELVE POINTED BLACK STAR -273A;a53;SIXTEEN POINTED ASTERISK -273B;a54;TEARDROP-SPOKED ASTERISK -273C;a55;OPEN CENTRE TEARDROP-SPOKED ASTERISK -273D;a56;HEAVY TEARDROP-SPOKED ASTERISK -273E;a57;SIX PETALLED BLACK AND WHITE FLORETTE -273F;a58;BLACK FLORETTE -2740;a59;WHITE FLORETTE -2741;a60;EIGHT PETALLED OUTLINED BLACK FLORETTE -2742;a61;CIRCLED OPEN CENTRE EIGHT POINTED STAR -2743;a62;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK -2744;a63;SNOWFLAKE -2745;a64;TIGHT TRIFOLIATE SNOWFLAKE -2746;a65;HEAVY CHEVRON SNOWFLAKE -2747;a66;SPARKLE -2748;a67;HEAVY SPARKLE -2749;a68;BALLOON-SPOKED ASTERISK -274A;a69;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK -274B;a70;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK -25CF;a71;BLACK CIRCLE -274D;a72;SHADOWED WHITE CIRCLE -25A0;a73;BLACK SQUARE -274F;a74;LOWER RIGHT DROP-SHADOWED WHITE SQUARE -2750;a203;UPPER RIGHT DROP-SHADOWED WHITE SQUARE -2751;a75;LOWER RIGHT SHADOWED WHITE SQUARE -2752;a204;UPPER RIGHT SHADOWED WHITE SQUARE -25B2;a76;BLACK UP-POINTING TRIANGLE -25BC;a77;BLACK DOWN-POINTING TRIANGLE -25C6;a78;BLACK DIAMOND -2756;a79;BLACK DIAMOND MINUS WHITE X -25D7;a81;RIGHT HALF BLACK CIRCLE -2758;a82;LIGHT VERTICAL BAR -2759;a83;MEDIUM VERTICAL BAR -275A;a84;HEAVY VERTICAL BAR -275B;a97;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT -275C;a98;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT -275D;a99;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT -275E;a100;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT -F8D7;a89;MEDIUM LEFT PARENTHESIS ORNAMENT -F8D8;a90;MEDIUM RIGHT PARENTHESIS ORNAMENT -F8D9;a93;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT -F8DA;a94;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT -F8DB;a91;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT -F8DC;a92;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT -F8DD;a205;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT -F8DE;a85;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT -F8DF;a206;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT -F8E0;a86;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT -F8E1;a87;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT -F8E2;a88;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT -F8E3;a95;MEDIUM LEFT CURLY BRACKET ORNAMENT -F8E4;a96;MEDIUM RIGHT CURLY BRACKET ORNAMENT -2761;a101;CURVED STEM PARAGRAPH SIGN ORNAMENT -2762;a102;HEAVY EXCLAMATION MARK ORNAMENT -2763;a103;HEAVY HEART EXCLAMATION MARK ORNAMENT -2764;a104;HEAVY BLACK HEART -2765;a106;ROTATED HEAVY BLACK HEART BULLET -2766;a107;FLORAL HEART -2767;a108;ROTATED FLORAL HEART BULLET -2663;a112;BLACK CLUB SUIT -2666;a111;BLACK DIAMOND SUIT -2665;a110;BLACK HEART SUIT -2660;a109;BLACK SPADE SUIT -2460;a120;CIRCLED DIGIT ONE -2461;a121;CIRCLED DIGIT TWO -2462;a122;CIRCLED DIGIT THREE -2463;a123;CIRCLED DIGIT FOUR -2464;a124;CIRCLED DIGIT FIVE -2465;a125;CIRCLED DIGIT SIX -2466;a126;CIRCLED DIGIT SEVEN -2467;a127;CIRCLED DIGIT EIGHT -2468;a128;CIRCLED DIGIT NINE -2469;a129;CIRCLED NUMBER TEN -2776;a130;DINGBAT NEGATIVE CIRCLED DIGIT ONE -2777;a131;DINGBAT NEGATIVE CIRCLED DIGIT TWO -2778;a132;DINGBAT NEGATIVE CIRCLED DIGIT THREE -2779;a133;DINGBAT NEGATIVE CIRCLED DIGIT FOUR -277A;a134;DINGBAT NEGATIVE CIRCLED DIGIT FIVE -277B;a135;DINGBAT NEGATIVE CIRCLED DIGIT SIX -277C;a136;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN -277D;a137;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT -277E;a138;DINGBAT NEGATIVE CIRCLED DIGIT NINE -277F;a139;DINGBAT NEGATIVE CIRCLED NUMBER TEN -2780;a140;DINGBAT CIRCLED SANS-SERIF DIGIT ONE -2781;a141;DINGBAT CIRCLED SANS-SERIF DIGIT TWO -2782;a142;DINGBAT CIRCLED SANS-SERIF DIGIT THREE -2783;a143;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR -2784;a144;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE -2785;a145;DINGBAT CIRCLED SANS-SERIF DIGIT SIX -2786;a146;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN -2787;a147;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT -2788;a148;DINGBAT CIRCLED SANS-SERIF DIGIT NINE -2789;a149;DINGBAT CIRCLED SANS-SERIF NUMBER TEN -278A;a150;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE -278B;a151;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO -278C;a152;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE -278D;a153;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR -278E;a154;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE -278F;a155;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX -2790;a156;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN -2791;a157;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT -2792;a158;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE -2793;a159;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN -2794;a160;HEAVY WIDE-HEADED RIGHTWARDS ARROW -2192;a161;RIGHTWARDS ARROW -2194;a163;LEFT RIGHT ARROW -2195;a164;UP DOWN ARROW -2798;a196;HEAVY SOUTH EAST ARROW -2799;a165;HEAVY RIGHTWARDS ARROW -279A;a192;HEAVY NORTH EAST ARROW -279B;a166;DRAFTING POINT RIGHTWARDS ARROW -279C;a167;HEAVY ROUND-TIPPED RIGHTWARDS ARROW -279D;a168;TRIANGLE-HEADED RIGHTWARDS ARROW -279E;a169;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW -279F;a170;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW -27A0;a171;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW -27A1;a172;BLACK RIGHTWARDS ARROW -27A2;a173;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD -27A3;a162;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD -27A4;a174;BLACK RIGHTWARDS ARROWHEAD -27A5;a175;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW -27A6;a176;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW -27A7;a177;SQUAT BLACK RIGHTWARDS ARROW -27A8;a178;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW -27A9;a179;RIGHT-SHADED WHITE RIGHTWARDS ARROW -27AA;a193;LEFT-SHADED WHITE RIGHTWARDS ARROW -27AB;a180;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW -27AC;a199;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW -27AD;a181;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW -27AE;a200;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW -27AF;a182;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW -27B1;a201;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW -27B2;a183;CIRCLED HEAVY WHITE RIGHTWARDS ARROW -27B3;a184;WHITE-FEATHERED RIGHTWARDS ARROW -27B4;a197;BLACK-FEATHERED SOUTH EAST ARROW -27B5;a185;BLACK-FEATHERED RIGHTWARDS ARROW -27B6;a194;BLACK-FEATHERED NORTH EAST ARROW -27B7;a198;HEAVY BLACK-FEATHERED SOUTH EAST ARROW -27B8;a186;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW -27B9;a195;HEAVY BLACK-FEATHERED NORTH EAST ARROW -27BA;a187;TEARDROP-BARBED RIGHTWARDS ARROW -27BB;a188;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW -27BC;a189;WEDGE-TAILED RIGHTWARDS ARROW -27BD;a190;HEAVY WEDGE-TAILED RIGHTWARDS ARROW -27BE;a191;OPEN-OUTLINED RIGHTWARDS ARROW diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6928eb6 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +# Component settings +COMPONENT := rufl +COMPONENT_VERSION := 0.0.1 +# Default to a static library +COMPONENT_TYPE ?= lib-static + +# Setup the tooling +include build/makefiles/Makefile.tools + +TESTRUNNER := $(ECHO) + +# Toolchain flags +WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \ + -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ + -Wmissing-declarations -Wnested-externs -pedantic +# BeOS/Haiku/AmigaOS4 standard library headers create warnings +ifneq ($(TARGET),beos) + ifneq ($(TARGET),AmigaOS) + WARNFLAGS := $(WARNFLAGS) -Werror + endif +endif +CFLAGS := -I$(CURDIR)/include/ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS) +ifneq ($(GCCVER),2) + CFLAGS := $(CFLAGS) -std=c99 +else + # __inline__ is a GCCism + CFLAGS := $(CFLAGS) -Dinline="__inline__" +endif + +# OSLib +ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) + ifeq ($(TARGET),riscos) + CFLAGS := $(CFLAGS) -I$(PREFIX)/include + LDFLAGS := $(LDFLAGS) -lOSLib32 + endif +endif + +include build/makefiles/Makefile.top + +# Extra installation rules +I := /include +INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/rufl.h +INSTALL_ITEMS := $(INSTALL_ITEMS) /lib/pkgconfig:lib$(COMPONENT).pc.in +INSTALL_ITEMS := $(INSTALL_ITEMS) /lib:$(OUTPUT) diff --git a/build/tools/makeglyphs b/build/tools/makeglyphs new file mode 100755 index 0000000..6acb350 --- /dev/null +++ b/build/tools/makeglyphs @@ -0,0 +1,29 @@ +#!/usr/bin/perl -W + +%name = (); + +print "#include \n"; +print "#include \"rufl_internal.h\"\n"; +print "const struct rufl_glyph_map_entry rufl_glyph_map[] = {\n"; +print "\t{\" \", 0}, /* sentinel */\n"; + +while (<>) { + if (/^([0-9A-F]{4});([a-zA-Z0-9]+);/) { + $name{"$1:$2"} = 1; + } +} + +@glyph = (); +while (($un, ) = each %name) { + ($u, $n) = split ':', $un; + push @glyph, [$n, $u]; +} + +foreach $z (sort {$$a[0] cmp $$b[0] or $$a[1] cmp $$b[1]} @glyph) { + print "\t{\"$$z[0]\", 0x$$z[1]},\n"; +} + +print "\t{\"~\", 0} /* sentinel */\n"; +print "};\n"; +print "const size_t rufl_glyph_map_size = sizeof rufl_glyph_map /\n"; +print " sizeof rufl_glyph_map[0];\n"; diff --git a/include/rufl.h b/include/rufl.h new file mode 100644 index 0000000..767022e --- /dev/null +++ b/include/rufl.h @@ -0,0 +1,207 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +#ifndef RUFL_H +#define RUFL_H + +#include +#include +#include "oslib/os.h" + + +/** Return code for RUfl functions. */ +typedef enum { + /** Success. */ + rufl_OK, + /** Failure: memory was exhausted. */ + rufl_OUT_OF_MEMORY, + /** Failure: Font Manager error; details in rufl_fm_error. */ + rufl_FONT_MANAGER_ERROR, + /** Failure: no font with this name exists. */ + rufl_FONT_NOT_FOUND, + /** Failure: file input / output error: details in errno. */ + rufl_IO_ERROR, + /** Failure: file input unexpected eof. */ + rufl_IO_EOF, +} rufl_code; + +/** Font weight and slant. Normal weight is 400, 700 gives the "Bold" weight of + * fonts. */ +typedef enum { + rufl_WEIGHT_100 = 1, + rufl_WEIGHT_200 = 2, + rufl_WEIGHT_300 = 3, + rufl_WEIGHT_400 = 4, + rufl_WEIGHT_500 = 5, + rufl_WEIGHT_600 = 6, + rufl_WEIGHT_700 = 7, + rufl_WEIGHT_800 = 8, + rufl_WEIGHT_900 = 9, + rufl_SLANTED = 0x100, +} rufl_style; + +/** rufl_paint flags */ +#define rufl_BLEND_FONT 0x01 + +/** Last Font Manager error. */ +extern os_error *rufl_fm_error; + +/** List of available font families. */ +extern const char **rufl_family_list; +/** Number of entries in rufl_family_list. */ +extern unsigned int rufl_family_list_entries; + +/** Menu of font families. */ +extern void *rufl_family_menu; + +/* Callbacks used by rufl_decompose_glyph */ +typedef int (*rufl_move_to_func)(os_coord *to, void *user); +typedef int (*rufl_line_to_func)(os_coord *to, void *user); +typedef int (*rufl_cubic_to_func)(os_coord *control1, os_coord *control2, + os_coord *to, void *user); + +struct rufl_decomp_funcs { + rufl_move_to_func move_to; + rufl_line_to_func line_to; + rufl_cubic_to_func cubic_to; +}; + +/** + * Initialise RUfl. + * + * All available fonts are scanned. May take some time. + */ + +rufl_code rufl_init(void); + + +/** + * Render Unicode text. + */ + +rufl_code rufl_paint(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int x, int y, unsigned int flags); + + +/** + * Measure the width of Unicode text. + */ + +rufl_code rufl_width(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int *width); + + +/** + * Find where in a string a x coordinate falls. + */ + +rufl_code rufl_x_to_offset(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int click_x, + size_t *char_offset, int *actual_x); + + +/** + * Find the prefix of a string that will fit in a specified width. + */ + +rufl_code rufl_split(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int width, + size_t *char_offset, int *actual_x); + + +/** Type of callback function for rufl_paint_callback(). */ +typedef void (*rufl_callback_t)(void *context, + const char *font_name, unsigned int font_size, + const char *s8, unsigned short *s16, unsigned int n, + int x, int y); + + +/** + * Render text, but call a callback instead of each call to Font_Paint. + */ + +rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int x, int y, + rufl_callback_t callback, void *context); + + +/** + * Decompose a glyph to a path. + */ + +rufl_code rufl_decompose_glyph(const char *font_family, + rufl_style font_style, unsigned int font_size, + const char *string, size_t length, + struct rufl_decomp_funcs *funcs, void *user); + + +/** + * Read metrics for a font + */ + +rufl_code rufl_font_metrics(const char *font_family, rufl_style font_style, + os_box *bbox, int *xkern, int *ykern, int *italic, + int *ascent, int *descent, + int *xheight, int *cap_height, + signed char *uline_position, unsigned char *uline_thickness); + + +/** + * Read metrics for a glyph + */ + +rufl_code rufl_glyph_metrics(const char *font_family, + rufl_style font_style, unsigned int font_size, + const char *string, size_t length, + int *x_bearing, int *y_bearing, + int *width, int *height, + int *x_advance, int *y_advance); + + +/** + * Determine the maximum bounding box of a font. + */ + +rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, + unsigned int font_size, + int *bbox); + + +/** + * Dump the internal library state to stdout. + */ + +void rufl_dump_state(void); + + +/** + * Clear the internal font handle cache. + * + * Call this function on mode changes or output redirection changes. + */ + +void rufl_invalidate_cache(void); + + +/** + * Free all resources used by the library. + */ + +void rufl_quit(void); + + +#endif diff --git a/librufl.pc.in b/librufl.pc.in new file mode 100644 index 0000000..0996103 --- /dev/null +++ b/librufl.pc.in @@ -0,0 +1,10 @@ +prefix=PREFIX +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: librufl +Description: RISC OS Unicode font library +Version: VERSION +Libs: -L${libdir} -lrufl +Cflags: -I${includedir} diff --git a/makefile b/makefile deleted file mode 100644 index b5d7d24..0000000 --- a/makefile +++ /dev/null @@ -1,108 +0,0 @@ -# -# This file is part of RUfl -# Licensed under the MIT License, -# http://www.opensource.org/licenses/mit-license -# Copyright 2005 James Bursa -# - -# choose one of the two below -COMPILER = gcc -#COMPILER = norcroft - - -SOURCE = rufl_init.c rufl_quit.c rufl_dump_state.c \ - rufl_character_set_test.c \ - rufl_paint.c rufl_glyph_map.c rufl_invalidate_cache.c \ - rufl_find.c rufl_decompose.c rufl_metrics.c -HDRS = rufl.h rufl_internal.h - -.PHONY: all install clean - -ifeq ($(COMPILER), gcc) -# cross-compiling using GCCSDK or native build with GCC - -HOST := $(shell uname -s) -ifeq ($(HOST),) - HOST := riscos - $(warning Build platform determination failed but that's a known problem for RISC OS so we're assuming a native RISC OS build.) -else - ifeq ($(HOST),RISC OS) - # Fixup uname -s returning "RISC OS" - HOST := riscos - endif -endif - -ifeq ($(HOST),riscos) - GCCSDK_INSTALL_ENV ?= - CC := gcc - AR := ar -else - GCCSDK_INSTALL_CROSSBIN ?= /home/riscos/cross/bin - GCCSDK_INSTALL_ENV ?= /home/riscos/env - CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) - AR := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) -endif - -CFLAGS = -std=c99 -O3 -W -Wall -Wundef -Wpointer-arith -Wcast-qual \ - -Wcast-align -Wwrite-strings -Wstrict-prototypes \ - -Wmissing-prototypes -Wmissing-declarations \ - -Wnested-externs -Winline -Wno-unused-parameter \ - -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include -ARFLAGS = cr -LIBS = -L$(GCCSDK_INSTALL_ENV)/lib -lOSLib32 -INSTALL = $(GCCSDK_INSTALL_ENV)/ro-install -OBJS = $(SOURCE:.c=.o) -ifneq (,$(findstring arm-unknown-riscos-gcc,$(CC))) - EXEEXT=,e1f -else - EXEEXT=,ff8 -endif - -all: librufl.a rufl_test$(EXEEXT) rufl_chars$(EXEEXT) - -librufl.a: $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -install: librufl.a - $(INSTALL) librufl.a $(GCCSDK_INSTALL_ENV)/lib/librufl.a - $(INSTALL) rufl.h $(GCCSDK_INSTALL_ENV)/include/rufl.h -else -# compiling on RISC OS using Norcroft -CC = cc -CFLAGS = -fn -ecz -wap -IOSLib: -DNDEBUG -LD = link -LDFLAGS = -aof -LIBS = OSLib:o.oslib32 -MKDLK = makedlk -SOURCE += strfuncs.c -OBJS = $(SOURCE:.c=.o) -EXEEXT = - -all: librufl.a rufl/pyd rufl_test rufl_chars - -librufl.a: $(OBJS) - $(LD) $(LDFLAGS) -o $@ $(OBJS) -o.ruflmodule: ruflmodule.o librufl.a - $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) -ruflmodule.o: ruflmodule.c - $(CC) -fn -wp -IPyInc:Include,PyInc:RISCOS,TCPIPLibs:,OSLib: -c $@ $< -rufl/pyd: o.ruflmodule - $(MKDLK) -s .RISCOS.s.linktab -o $< -d $@ -e initrufl -endif - - -# common rules -rufl_glyph_map.c: Glyphs makeglyphs - ./makeglyphs < Glyphs > $@ - -rufl_test$(EXEEXT): rufl_test.c librufl.a - $(CC) $(CFLAGS) $(LIBS) -o $@ $^ - -rufl_chars$(EXEEXT): rufl_chars.c librufl.a - $(CC) $(CFLAGS) $(LIBS) -o $@ $^ - -.c.o: $(HDRS) - $(CC) $(CFLAGS) -c -o $@ $< - -clean: - -rm *.o librufl.a rufl_glyph_map.c rufl_test$(EXEEXT) rufl_chars$(EXEEXT) diff --git a/makeglyphs b/makeglyphs deleted file mode 100755 index 6acb350..0000000 --- a/makeglyphs +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/perl -W - -%name = (); - -print "#include \n"; -print "#include \"rufl_internal.h\"\n"; -print "const struct rufl_glyph_map_entry rufl_glyph_map[] = {\n"; -print "\t{\" \", 0}, /* sentinel */\n"; - -while (<>) { - if (/^([0-9A-F]{4});([a-zA-Z0-9]+);/) { - $name{"$1:$2"} = 1; - } -} - -@glyph = (); -while (($un, ) = each %name) { - ($u, $n) = split ':', $un; - push @glyph, [$n, $u]; -} - -foreach $z (sort {$$a[0] cmp $$b[0] or $$a[1] cmp $$b[1]} @glyph) { - print "\t{\"$$z[0]\", 0x$$z[1]},\n"; -} - -print "\t{\"~\", 0} /* sentinel */\n"; -print "};\n"; -print "const size_t rufl_glyph_map_size = sizeof rufl_glyph_map /\n"; -print " sizeof rufl_glyph_map[0];\n"; diff --git a/python/Mk.old b/python/Mk.old new file mode 100644 index 0000000..e996722 --- /dev/null +++ b/python/Mk.old @@ -0,0 +1,21 @@ +# compiling on RISC OS using Norcroft +CC = cc +CFLAGS = -fn -ecz -wap -IOSLib: -DNDEBUG +LD = link +LDFLAGS = -aof +LIBS = OSLib:o.oslib32 +MKDLK = makedlk +SOURCE += strfuncs.c +OBJS = $(SOURCE:.c=.o) +EXEEXT = + +all: librufl.a rufl/pyd rufl_test rufl_chars + +librufl.a: $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) +o.ruflmodule: ruflmodule.o librufl.a + $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) +ruflmodule.o: ruflmodule.c + $(CC) -fn -wp -IPyInc:Include,PyInc:RISCOS,TCPIPLibs:,OSLib: -c $@ $< +rufl/pyd: o.ruflmodule + $(MKDLK) -s .RISCOS.s.linktab -o $< -d $@ -e initrufl diff --git a/python/ruflmodule.c b/python/ruflmodule.c new file mode 100644 index 0000000..b62a883 --- /dev/null +++ b/python/ruflmodule.c @@ -0,0 +1,203 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +/* Python module for RUfl. */ + +#include "Python.h" +#include "rufl.h" + + +static char pyrufl_paint__doc__[] = +"paint(font_family, font_style, font_size, string, x, y, flags)\n\n" +"Render Unicode text." +; + +static PyObject * +pyrufl_paint(PyObject *self /* Not used */, PyObject *args) +{ + const char *font_family; + rufl_style font_style; + unsigned int font_size; + const char *string; + int length; + int x; + int y; + unsigned int flags; + + if (!PyArg_ParseTuple(args, "siIs#iiI", + &font_family, &font_style, &font_size, + &string, &length, &x, &y, &flags)) + return NULL; + + rufl_paint(font_family, font_style, font_size, string, length, + x, y, flags); + + Py_INCREF(Py_None); + return Py_None; +} + + +static char pyrufl_width__doc__[] = +"width(font_family, font_style, font_size, string)\n\n" +"Return the width of Unicode text." +; + +static PyObject * +pyrufl_width(PyObject *self /* Not used */, PyObject *args) +{ + const char *font_family; + rufl_style font_style; + unsigned int font_size; + const char *string; + int length; + int width = 0; + + if (!PyArg_ParseTuple(args, "siIs#", + &font_family, &font_style, &font_size, + &string, &length)) + return NULL; + + rufl_width(font_family, font_style, font_size, string, length, + &width); + + return PyInt_FromLong(width); +} + + +static char pyrufl_x_to_offset__doc__[] = +"x_to_offset(font_family, font_style, font_size, string, click_x)\n\n" +"Return a pair of the character offset in string that click_x falls,\n" +"and the actual x coordinate for that character offset." +; + +static PyObject * +pyrufl_x_to_offset(PyObject *self /* Not used */, PyObject *args) +{ + const char *font_family; + rufl_style font_style; + unsigned int font_size; + const char *string; + int length; + int click_x; + size_t char_offset = 0; + int actual_x = 0; + + if (!PyArg_ParseTuple(args, "siIs#i", + &font_family, &font_style, &font_size, + &string, &length, &click_x)) + return NULL; + + rufl_x_to_offset(font_family, font_style, font_size, string, length, + click_x, + &char_offset, &actual_x); + + return Py_BuildValue("ii", (int) char_offset, actual_x); +} + + +static char pyrufl_split__doc__[] = +"split(font_family, font_style, font_size, string, width)\n\n" +"Return a pair of the character offset in string that fits in width,\n" +"and the actual x coordinate for that character offset." +; + +static PyObject * +pyrufl_split(PyObject *self /* Not used */, PyObject *args) +{ + const char *font_family; + rufl_style font_style; + unsigned int font_size; + const char *string; + int length; + int width; + size_t char_offset = 0; + int actual_x = 0; + + if (!PyArg_ParseTuple(args, "siIs#i", + &font_family, &font_style, &font_size, + &string, &length, &width)) + return NULL; + + rufl_split(font_family, font_style, font_size, string, length, + width, + &char_offset, &actual_x); + + return Py_BuildValue("ii", (int) char_offset, actual_x); +} + + +static char pyrufl_invalidate_cache__doc__[] = +"invalidate_cache()\n\n" +"Clear the internal font handle cache.\n" +"Call this function on mode changes or output redirection changes." +; + +static PyObject * +pyrufl_invalidate_cache(PyObject *self /* Not used */, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + rufl_invalidate_cache(); + + Py_INCREF(Py_None); + return Py_None; +} + + +/* List of methods defined in the module */ + +static struct PyMethodDef pyrufl_methods[] = { + {"paint", (PyCFunction)pyrufl_paint, METH_VARARGS, pyrufl_paint__doc__}, + {"width", (PyCFunction)pyrufl_width, METH_VARARGS, pyrufl_width__doc__}, + {"x_to_offset", (PyCFunction)pyrufl_x_to_offset, METH_VARARGS, + pyrufl_x_to_offset__doc__}, + {"split", (PyCFunction)pyrufl_split, METH_VARARGS, pyrufl_split__doc__}, + {"invalidate_cache", (PyCFunction)pyrufl_invalidate_cache, METH_VARARGS, + pyrufl_invalidate_cache__doc__}, + + {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ +}; + + +/* Initialization function for the module (*must* be called initrufl) */ + +static char pyrufl_module_documentation[] = +"This module provides access to the RISC OS Unicode font library\n" +"All string parameters must be in UTF-8." +; + +void +initrufl(void) +{ + PyObject *module; + rufl_code code; + + code = rufl_init(); + if (code != rufl_OK) + Py_FatalError("rufl_init() failed"); + + Py_AtExit(rufl_quit); + + /* Create the module and add the functions */ + module = Py_InitModule4("rufl", pyrufl_methods, + pyrufl_module_documentation, + (PyObject *) NULL, PYTHON_API_VERSION); + + /* Add some symbolic constants to the module */ + PyModule_AddIntConstant(module, "regular", rufl_REGULAR); + PyModule_AddIntConstant(module, "slanted", rufl_SLANTED); + PyModule_AddIntConstant(module, "bold", rufl_BOLD); + PyModule_AddIntConstant(module, "bold_slanted", rufl_BOLD_SLANTED); + + PyModule_AddIntConstant(module, "blend", rufl_BLEND_FONT); + + /* Check for errors */ + if (PyErr_Occurred()) + Py_FatalError("can't initialize module rufl"); +} + diff --git a/rufl.h b/rufl.h deleted file mode 100644 index 767022e..0000000 --- a/rufl.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -#ifndef RUFL_H -#define RUFL_H - -#include -#include -#include "oslib/os.h" - - -/** Return code for RUfl functions. */ -typedef enum { - /** Success. */ - rufl_OK, - /** Failure: memory was exhausted. */ - rufl_OUT_OF_MEMORY, - /** Failure: Font Manager error; details in rufl_fm_error. */ - rufl_FONT_MANAGER_ERROR, - /** Failure: no font with this name exists. */ - rufl_FONT_NOT_FOUND, - /** Failure: file input / output error: details in errno. */ - rufl_IO_ERROR, - /** Failure: file input unexpected eof. */ - rufl_IO_EOF, -} rufl_code; - -/** Font weight and slant. Normal weight is 400, 700 gives the "Bold" weight of - * fonts. */ -typedef enum { - rufl_WEIGHT_100 = 1, - rufl_WEIGHT_200 = 2, - rufl_WEIGHT_300 = 3, - rufl_WEIGHT_400 = 4, - rufl_WEIGHT_500 = 5, - rufl_WEIGHT_600 = 6, - rufl_WEIGHT_700 = 7, - rufl_WEIGHT_800 = 8, - rufl_WEIGHT_900 = 9, - rufl_SLANTED = 0x100, -} rufl_style; - -/** rufl_paint flags */ -#define rufl_BLEND_FONT 0x01 - -/** Last Font Manager error. */ -extern os_error *rufl_fm_error; - -/** List of available font families. */ -extern const char **rufl_family_list; -/** Number of entries in rufl_family_list. */ -extern unsigned int rufl_family_list_entries; - -/** Menu of font families. */ -extern void *rufl_family_menu; - -/* Callbacks used by rufl_decompose_glyph */ -typedef int (*rufl_move_to_func)(os_coord *to, void *user); -typedef int (*rufl_line_to_func)(os_coord *to, void *user); -typedef int (*rufl_cubic_to_func)(os_coord *control1, os_coord *control2, - os_coord *to, void *user); - -struct rufl_decomp_funcs { - rufl_move_to_func move_to; - rufl_line_to_func line_to; - rufl_cubic_to_func cubic_to; -}; - -/** - * Initialise RUfl. - * - * All available fonts are scanned. May take some time. - */ - -rufl_code rufl_init(void); - - -/** - * Render Unicode text. - */ - -rufl_code rufl_paint(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int x, int y, unsigned int flags); - - -/** - * Measure the width of Unicode text. - */ - -rufl_code rufl_width(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int *width); - - -/** - * Find where in a string a x coordinate falls. - */ - -rufl_code rufl_x_to_offset(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int click_x, - size_t *char_offset, int *actual_x); - - -/** - * Find the prefix of a string that will fit in a specified width. - */ - -rufl_code rufl_split(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int width, - size_t *char_offset, int *actual_x); - - -/** Type of callback function for rufl_paint_callback(). */ -typedef void (*rufl_callback_t)(void *context, - const char *font_name, unsigned int font_size, - const char *s8, unsigned short *s16, unsigned int n, - int x, int y); - - -/** - * Render text, but call a callback instead of each call to Font_Paint. - */ - -rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int x, int y, - rufl_callback_t callback, void *context); - - -/** - * Decompose a glyph to a path. - */ - -rufl_code rufl_decompose_glyph(const char *font_family, - rufl_style font_style, unsigned int font_size, - const char *string, size_t length, - struct rufl_decomp_funcs *funcs, void *user); - - -/** - * Read metrics for a font - */ - -rufl_code rufl_font_metrics(const char *font_family, rufl_style font_style, - os_box *bbox, int *xkern, int *ykern, int *italic, - int *ascent, int *descent, - int *xheight, int *cap_height, - signed char *uline_position, unsigned char *uline_thickness); - - -/** - * Read metrics for a glyph - */ - -rufl_code rufl_glyph_metrics(const char *font_family, - rufl_style font_style, unsigned int font_size, - const char *string, size_t length, - int *x_bearing, int *y_bearing, - int *width, int *height, - int *x_advance, int *y_advance); - - -/** - * Determine the maximum bounding box of a font. - */ - -rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, - unsigned int font_size, - int *bbox); - - -/** - * Dump the internal library state to stdout. - */ - -void rufl_dump_state(void); - - -/** - * Clear the internal font handle cache. - * - * Call this function on mode changes or output redirection changes. - */ - -void rufl_invalidate_cache(void); - - -/** - * Free all resources used by the library. - */ - -void rufl_quit(void); - - -#endif diff --git a/rufl_character_set_test.c b/rufl_character_set_test.c deleted file mode 100644 index 45fbcaf..0000000 --- a/rufl_character_set_test.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2005 James Bursa - */ - -#include "rufl_internal.h" - - -/** - * Test if a character set contains a character. - * - * \param charset character set - * \param c character code - * \return true if present, false if absent - */ - -bool rufl_character_set_test(struct rufl_character_set *charset, - unsigned int c) -{ - unsigned int block = c >> 8; - unsigned int byte = (c >> 3) & 31; - unsigned int bit = c & 7; - - if (256 <= block) - return false; - - if (charset->index[block] == BLOCK_EMPTY) - return false; - else if (charset->index[block] == BLOCK_FULL) - return true; - else { - unsigned char z = charset->block[charset->index[block]][byte]; - return z & (1 << bit); - } -} diff --git a/rufl_chars.c b/rufl_chars.c deleted file mode 100644 index 440a1d0..0000000 --- a/rufl_chars.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -#include -#include -#include -#include -#include -#include "oslib/colourtrans.h" -#include "oslib/wimp.h" -#include "rufl.h" - - -unsigned int font = 0; -unsigned int weight = rufl_WEIGHT_400; -bool italic = false; - - -static rufl_code redraw(int x, int y, int y0, int y1); -static void try(rufl_code code, const char *context); -static void die(const char *error); - - -int main(void) -{ - unsigned int i; - bool quit = false; - const wimp_MESSAGE_LIST(2) messages = { { message_MODE_CHANGE, - message_QUIT } }; - wimp_t task; - wimp_menu *menu; - wimp_WINDOW(0) window = { - { 400, 400, 1700, 1200 }, - 0, 0, - wimp_TOP, - wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON | - wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | - wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | - wimp_WINDOW_SIZE_ICON | wimp_WINDOW_NEW_FORMAT, - wimp_COLOUR_BLACK, wimp_COLOUR_LIGHT_GREY, - wimp_COLOUR_BLACK, wimp_COLOUR_WHITE, - wimp_COLOUR_DARK_GREY, wimp_COLOUR_MID_LIGHT_GREY, - wimp_COLOUR_CREAM, - 0, - { 0, -81928, 1300, 0 }, - wimp_ICON_TEXT | wimp_ICON_HCENTRED, - 0, - 0, - 2, 1, - { "RUfl Chars" }, - 0 }; - wimp_w w; - wimp_window_state state; - wimp_block block; - wimp_event_no event; - wimp_pointer pointer; - osbool more; - os_error *error; - rufl_code code = rufl_OK; - - error = xwimp_initialise(wimp_VERSION_RO3, "RUfl Chars", - (const wimp_message_list *) (const void *) &messages, - 0, &task); - if (error) { - printf("error: xwimp_initialise: 0x%x: %s\n", - error->errnum, error->errmess); - exit(1); - } - - try(rufl_init(), "rufl_init"); - - menu = malloc(wimp_SIZEOF_MENU(10 + rufl_family_list_entries)); - if (!menu) - die("Out of memory"); - strcpy(menu->title_data.text, "Fonts"); - menu->title_fg = wimp_COLOUR_BLACK; - menu->title_bg = wimp_COLOUR_LIGHT_GREY; - menu->work_fg = wimp_COLOUR_RED; - menu->work_bg = wimp_COLOUR_WHITE; - menu->width = 200; - menu->height = wimp_MENU_ITEM_HEIGHT; - menu->gap = wimp_MENU_ITEM_GAP; - for (i = 0; i != 10; i++) { - menu->entries[i].menu_flags = 0; - menu->entries[i].sub_menu = wimp_NO_SUB_MENU; - menu->entries[i].icon_flags = wimp_ICON_TEXT | - (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | - (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); - strcpy(menu->entries[i].data.text, "100"); - menu->entries[i].data.text[0] = '1' + i; - } - menu->entries[9].menu_flags = wimp_MENU_SEPARATE; - menu->entries[9].sub_menu = wimp_NO_SUB_MENU; - menu->entries[9].icon_flags = wimp_ICON_TEXT | - (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | - (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); - strcpy(menu->entries[9].data.text, "Italic"); - for (i = 0; i != rufl_family_list_entries; i++) { - menu->entries[10 + i].menu_flags = 0; - menu->entries[10 + i].sub_menu = wimp_NO_SUB_MENU; - menu->entries[10 + i].icon_flags = wimp_ICON_TEXT | - wimp_ICON_INDIRECTED | - (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | - (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); - menu->entries[10 + i].data.indirected_text.text = - rufl_family_list[i]; - menu->entries[10 + i].data.indirected_text.validation = - (char *) -1; - menu->entries[10 + i].data.indirected_text.size = - strlen(rufl_family_list[i]); - } - menu->entries[3].menu_flags |= wimp_MENU_TICKED; - menu->entries[10].menu_flags |= wimp_MENU_TICKED; - menu->entries[i + 9].menu_flags |= wimp_MENU_LAST; - - error = xwimp_create_window((wimp_window *) &window, &w); - if (error) - die(error->errmess); - - state.w = w; - error = xwimp_get_window_state(&state); - if (error) - die(error->errmess); - - error = xwimp_open_window((wimp_open *) (void *) &state); - if (error) - die(error->errmess); - - while (!quit) { - error = xwimp_poll(wimp_MASK_NULL, &block, 0, &event); - if (error) - die(error->errmess); - - switch (event) { - case wimp_REDRAW_WINDOW_REQUEST: - error = xwimp_redraw_window(&block.redraw, &more); - if (error) - die(error->errmess); - xcolourtrans_set_font_colours(0, os_COLOUR_WHITE, - os_COLOUR_BLACK, 14, 0, 0, 0); - while (more) { - code = redraw(block.redraw.box.x0 - - block.redraw.xscroll, - block.redraw.box.y1 - - block.redraw.yscroll, - block.redraw.box.y1 - - block.redraw.yscroll - - block.redraw.clip.y1, - block.redraw.box.y1 - - block.redraw.yscroll - - block.redraw.clip.y0); - error = xwimp_get_rectangle(&block.redraw, - &more); - if (error) - die(error->errmess); - } - try(code, "redraw"); - break; - - case wimp_OPEN_WINDOW_REQUEST: - error = xwimp_open_window(&block.open); - if (error) - die(error->errmess); - break; - - case wimp_CLOSE_WINDOW_REQUEST: - quit = true; - break; - - case wimp_MOUSE_CLICK: - if (block.pointer.buttons == wimp_CLICK_MENU) { - error = xwimp_create_menu(menu, - block.pointer.pos.x - 64, - block.pointer.pos.y); - if (error) - die(error->errmess); - } - break; - - case wimp_MENU_SELECTION: - error = xwimp_get_pointer_info(&pointer); - if (error) - die(error->errmess); - if (block.selection.items[0] <= 8) { - menu->entries[weight - 1].menu_flags ^= - wimp_MENU_TICKED; - weight = block.selection.items[0] + 1; - menu->entries[weight - 1].menu_flags ^= - wimp_MENU_TICKED; - } else if (block.selection.items[0] == 9) { - italic = !italic; - menu->entries[9].menu_flags ^= wimp_MENU_TICKED; - } else { - menu->entries[10 + font].menu_flags ^= - wimp_MENU_TICKED; - font = block.selection.items[0] - 10; - menu->entries[10 + font].menu_flags ^= - wimp_MENU_TICKED; - } - error = xwimp_force_redraw(w, - window.extent.x0, window.extent.y0, - window.extent.x1, window.extent.y1); - if (error) - die(error->errmess); - if (pointer.buttons == wimp_CLICK_ADJUST) { - error = xwimp_create_menu(menu, - pointer.pos.x - 64, - pointer.pos.y); - if (error) - die(error->errmess); - } - break; - - case wimp_USER_MESSAGE: - case wimp_USER_MESSAGE_RECORDED: - switch (block.message.action) { - case message_QUIT: - quit = true; - break; - case message_MODE_CHANGE: - rufl_invalidate_cache(); - break; - } - break; - } - } - -/* try(rufl_paint("NewHall.Medium", 240, utf8_test, sizeof utf8_test - 1, */ -/* 1200, 1200), "rufl_paint"); */ - - xwimp_close_down(task); - - rufl_quit(); - - return 0; -} - - -rufl_code redraw(int x, int y, int y0, int y1) -{ - char s[10]; - unsigned int l; - unsigned int u; - rufl_code code; - rufl_style style = weight | (italic ? rufl_SLANTED : 0); - - for (u = y0 / 40 * 32; (int) u != (y1 / 40 + 1) * 32; u++) { - if (u <= 0x7f) - s[0] = u, l = 1; - else if (u <= 0x7ff) - s[0] = 0xc0 | (u >> 6), - s[1] = 0x80 | (u & 0x3f), l = 2; - else if (u <= 0xffff) - s[0] = 0xe0 | (u >> 12), - s[1] = 0x80 | ((u >> 6) & 0x3f), - s[2] = 0x80 | (u & 0x3f), l = 3; - else - break; - s[l] = 0; - - code = rufl_paint(rufl_family_list[font], style, 240, s, l, - x + 10 + 40 * (u % 32), - y - 40 - 40 * (u / 32), - 0); - if (code != rufl_OK) - return code; - } - - return rufl_OK; -} - - -void try(rufl_code code, const char *context) -{ - char s[200]; - if (code == rufl_OK) - return; - else if (code == rufl_OUT_OF_MEMORY) - snprintf(s, sizeof s, "error: %s: out of memory\n", context); - else if (code == rufl_FONT_MANAGER_ERROR) - snprintf(s, sizeof s, "error: %s: Font Manager error %x %s\n", - context, rufl_fm_error->errnum, - rufl_fm_error->errmess); - else if (code == rufl_FONT_NOT_FOUND) - snprintf(s, sizeof s, "error: %s: font not found\n", context); - else if (code == rufl_IO_ERROR) - snprintf(s, sizeof s, "error: %s: io error: %i %s\n", context, - errno, strerror(errno)); - else if (code == rufl_IO_EOF) - snprintf(s, sizeof s, "error: %s: eof\n", context); - else - snprintf(s, sizeof s, "error: %s: unknown error\n", context); - - die(s); -} - - -void die(const char *error) -{ - os_error warn_error; - - warn_error.errnum = 1; - strncpy(warn_error.errmess, error, - sizeof warn_error.errmess - 1); - warn_error.errmess[sizeof warn_error.errmess - 1] = '\0'; - xwimp_report_error(&warn_error, - wimp_ERROR_BOX_OK_ICON, - "RUfl Chars", 0); - rufl_quit(); - exit(EXIT_FAILURE); -} diff --git a/rufl_decompose.c b/rufl_decompose.c deleted file mode 100644 index edf9748..0000000 --- a/rufl_decompose.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2005 John-Mark Bell - */ - -#include -#include - -#include "oslib/font.h" - -#include "rufl_internal.h" - -/** - * Process a Draw path object - * - * \param path Pointer to path block - * \param funcs Struct of callback functions - * \param user User pointer to be passed to callbacks - * \return Pointer to word after this path, or NULL to terminate processing - */ -static int *process_path(int *path, struct rufl_decomp_funcs *funcs, - void *user) -{ - /* skip forward to style entry */ - path += 9; - - /* skip dash pattern */ - if (path[0] & (1<<7)) - path += path[2] + 2; - - /* and move to start of path components */ - path++; - - while (path[0] != 0) { - switch (path[0]) { - case 2: /* Move to */ - if (funcs->move_to((os_coord *)(path + 1), user)) - return NULL; - path += 3; - break; - case 5: /* Close path */ - path++; - break; - case 6: /* Cubic Bezier to */ - if (funcs->cubic_to((os_coord *)(path + 1), - (os_coord *)(path + 3), - (os_coord *)(path + 5), - user)) - return NULL; - path += 7; - break; - case 8: /* Line to */ - if (funcs->line_to((os_coord *)(path + 1), user)) - return NULL; - path += 3; - break; - default: /* Anything else is broken */ - assert(0); - } - } - - /* + 1 to account for tag 0 - end of path */ - return path + 1; -} - -rufl_code rufl_decompose_glyph(const char *font_family, - rufl_style font_style, unsigned int font_size, - const char *string, size_t len, - struct rufl_decomp_funcs *funcs, void *user) -{ - int *buf, *p, *ep; - int buf_size; - char *buf_end; - rufl_code err; - - /* Get required buffer size */ - rufl_fm_error = xfont_switch_output_to_buffer( - font_NO_OUTPUT | font_ADD_HINTS, (byte *)8, 0); - if (rufl_fm_error) { - LOG("xfont_switch_output_to_buffer: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - - err = rufl_paint(font_family, font_style, font_size, string, len, - 0, 0, rufl_BLEND_FONT); - if (err) { - /* reset font redirection - too bad if this fails */ - xfont_switch_output_to_buffer(0, 0, 0); - return err; - } - - rufl_fm_error = xfont_switch_output_to_buffer(0, NULL, &buf_end); - if (rufl_fm_error) { - LOG("xfont_switch_output_to_buffer: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - buf_size = buf_end - (char *)NULL; - - /* Allocate and initialise buffer */ - buf = malloc(buf_size); - if (!buf) { - LOG("Failed to allocate decompose buffer of size %i", buf_size); - return rufl_OUT_OF_MEMORY; - } - buf[0] = 0; - buf[1] = buf_size - 8; - - /* Populate buffer */ - rufl_fm_error = xfont_switch_output_to_buffer( - font_ADD_HINTS, (byte *)buf, 0); - if (rufl_fm_error) { - LOG("xfont_switch_output_to_buffer: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - free(buf); - return rufl_FONT_MANAGER_ERROR; - } - - err = rufl_paint(font_family, font_style, font_size, string, len, - 0, 0, rufl_BLEND_FONT); - if (err) { - /* reset font redirection - too bad if this fails */ - xfont_switch_output_to_buffer(0, 0, 0); - free(buf); - return err; - } - - rufl_fm_error = xfont_switch_output_to_buffer(0, 0, &buf_end); - if (rufl_fm_error) { - LOG("xfont_switch_output_to_buffer: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - free(buf); - return rufl_FONT_MANAGER_ERROR; - } - ep = (int *)(void *)buf_end; - - /* Parse buffer, calling callbacks as required */ - for (p = buf; p < ep;) { - if (p[0] != 2) { - LOG("Object type %d not known", p[0]); - break; - } - - p = process_path(p, funcs, user); - - /* Have the callbacks asked for us to stop? */ - if (p == NULL) - break; - } - - free(buf); - - return rufl_OK; -} diff --git a/rufl_dump_state.c b/rufl_dump_state.c deleted file mode 100644 index 06a1f22..0000000 --- a/rufl_dump_state.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -#include -#include "rufl_internal.h" - - -static void rufl_dump_character_set(struct rufl_character_set *charset); -static void rufl_dump_unicode_map(struct rufl_unicode_map *umap); -static void rufl_dump_substitution_table(void); - - -/** - * Dump the internal library state to stdout. - */ - -void rufl_dump_state(void) -{ - unsigned int i, j; - - printf("rufl_font_list:\n"); - for (i = 0; i != rufl_font_list_entries; i++) { - printf(" %u \"%s\"\n", i, rufl_font_list[i].identifier); - if (rufl_font_list[i].charset) { - printf(" "); - rufl_dump_character_set(rufl_font_list[i].charset); - printf("\n"); - } else { - printf(" (no charset table)\n"); - } - if (rufl_font_list[i].umap) { - for (j = 0; j < rufl_font_list[i].num_umaps; j++) { - struct rufl_unicode_map *map = - rufl_font_list[i].umap + j; - - printf(" "); - rufl_dump_unicode_map(map); - printf("\n"); - } - } - } - - printf("rufl_family_list:\n"); - for (i = 0; i != rufl_family_list_entries; i++) { - printf(" %u \"%s\"\n", i, rufl_family_list[i]); - for (j = 0; j != 9; j++) { - struct rufl_family_map_entry *e = &rufl_family_map[i]; - printf(" %u ", j); - if (e->font[j][0] == NO_FONT) - printf("- "); - else - printf("\"%s\" ", rufl_font_list[e->font[j][0]]. - identifier); - if (e->font[j][1] == NO_FONT) - printf("- "); - else - printf("\"%s\" ", rufl_font_list[e->font[j][1]]. - identifier); - printf("\n"); - } - } - - printf("rufl_substitution_table:\n"); - rufl_dump_substitution_table(); -} - - -/** - * Dump a representation of a character set to stdout. - * - * \param charset character set to print - */ - -void rufl_dump_character_set(struct rufl_character_set *charset) -{ - unsigned int u, t; - - u = 0; - while (u != 0x10000) { - while (u != 0x10000 && !rufl_character_set_test(charset, u)) - u++; - if (u != 0x10000) { - if (!rufl_character_set_test(charset, u + 1)) { - printf("%x ", u); - u++; - } else { - t = u; - while (rufl_character_set_test(charset, u)) - u++; - printf("%x-%x ", t, u - 1); - } - } - } -} - - -/** - * Dump a representation of a unicode map to stdout. - * - * \param umap unicode map to print - */ - -void rufl_dump_unicode_map(struct rufl_unicode_map *umap) -{ - unsigned int i; - - if (umap->encoding) - printf("%s: ", umap->encoding); - - for (i = 0; i != umap->entries; i++) - printf("%x:%x ", umap->map[i].u, umap->map[i].c); -} - - -/** - * Dump a representation of the substitution table to stdout. - */ - -void rufl_dump_substitution_table(void) -{ - unsigned int font; - unsigned int u, t; - - u = 0; - while (u != 0x10000) { - t = u; - font = rufl_substitution_table[t]; - while (u != 0x10000 && font == rufl_substitution_table[u]) - u++; - if (font != NOT_AVAILABLE) - printf(" %x-%x => %u \"%s\"\n", t, u - 1, - font, rufl_font_list[font].identifier); - } -} diff --git a/rufl_find.c b/rufl_find.c deleted file mode 100644 index a1c2785..0000000 --- a/rufl_find.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2005 James Bursa - * Copyright 2005 John-Mark Bell - */ - -#include -#include -#include -#include -#include - -#include "rufl_internal.h" - -static int rufl_family_list_cmp(const void *keyval, const void *datum); -static rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size, - const char *encoding, font_f f); - -/** - * Find a font family. - */ -rufl_code rufl_find_font_family(const char *font_family, - rufl_style font_style, unsigned int *font, - unsigned int *slanted, struct rufl_character_set **charset) -{ - const char **family; - unsigned int f; - unsigned int weight, slant, used_weight; - unsigned int search_direction; - - family = bsearch(font_family, rufl_family_list, - rufl_family_list_entries, - sizeof rufl_family_list[0], rufl_family_list_cmp); - if (!family) - return rufl_FONT_NOT_FOUND; - - weight = (font_style & 0xf) - 1; - assert(weight <= 8); - slant = font_style & rufl_SLANTED ? 1 : 0; - - struct rufl_family_map_entry *e = - &rufl_family_map[family - rufl_family_list]; - used_weight = weight; - if (weight <= 2) - search_direction = -1; - else - search_direction = +1; - while (1) { - if (e->font[used_weight][slant] != NO_FONT) { - /* the weight and slant is available */ - f = e->font[used_weight][slant]; - break; - } - if (e->font[used_weight][1 - slant] != NO_FONT) { - /* slanted, and non-slanted weight exists, or vv. */ - f = e->font[used_weight][1 - slant]; - break; - } - if (used_weight == 0) { - /* searched down without finding a weight: search up */ - used_weight = weight + 1; - search_direction = +1; - } else if (used_weight == 8) { - /* searched up without finding a weight: search down */ - used_weight = weight - 1; - search_direction = -1; - } else { - /* try the next weight in the current direction */ - used_weight += search_direction; - } - } - - if (font) - (*font) = f; - - if (slanted) - (*slanted) = slant; - - if (charset) - (*charset) = rufl_font_list[f].charset; - - return rufl_OK; -} - - -/** - * Find a sized font, placing in the cache if necessary. - */ -rufl_code rufl_find_font(unsigned int font, unsigned int font_size, - const char *encoding, font_f *fhandle) -{ - font_f f; - char font_name[80]; - unsigned int i; - rufl_code code; - - assert(fhandle != NULL); - - for (i = 0; i != rufl_CACHE_SIZE; i++) { - /* Comparing pointers for the encoding is fine, as the - * encoding string passed to us is either: - * - * a) NULL - * or b) statically allocated - * or c) resides in the font's umap, which is constant - * for the lifetime of the application. - */ - if (rufl_cache[i].font == font && - rufl_cache[i].size == font_size && - rufl_cache[i].encoding == encoding) - break; - } - if (i != rufl_CACHE_SIZE) { - /* found in cache */ - f = rufl_cache[i].f; - rufl_cache[i].last_used = rufl_cache_time++; - } else { - /* not found */ - if (font == rufl_CACHE_CORPUS) { - if (encoding) - snprintf(font_name, sizeof font_name, - "Corpus.Medium\\E%s", encoding); - else - snprintf(font_name, sizeof font_name, - "Corpus.Medium"); - } else { - if (encoding) - snprintf(font_name, sizeof font_name, - "%s\\E%s", - rufl_font_list[font].identifier, - encoding); - else - snprintf(font_name, sizeof font_name, "%s", - rufl_font_list[font].identifier); - } - - rufl_fm_error = xfont_find_font(font_name, - font_size, font_size, 0, 0, &f, 0, 0); - if (rufl_fm_error) { - LOG("xfont_find_font: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - /* place in cache */ - code = rufl_place_in_cache(font, font_size, encoding, f); - if (code != rufl_OK) - return code; - } - - (*fhandle) = f; - - return rufl_OK; -} - - -int rufl_family_list_cmp(const void *keyval, const void *datum) -{ - const char *key = keyval; - const char * const *entry = datum; - return strcasecmp(key, *entry); -} - - -/** - * Place a font into the recent-use cache, making space if necessary. - */ - -rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size, - const char *encoding, font_f f) -{ - unsigned int i; - unsigned int max_age = 0; - unsigned int evict = 0; - - for (i = 0; i != rufl_CACHE_SIZE; i++) { - if (rufl_cache[i].font == rufl_CACHE_NONE) { - evict = i; - break; - } else if (max_age < rufl_cache_time - - rufl_cache[i].last_used) { - max_age = rufl_cache_time - - rufl_cache[i].last_used; - evict = i; - } - } - if (rufl_cache[evict].font != rufl_CACHE_NONE) { - rufl_fm_error = xfont_lose_font(rufl_cache[evict].f); - if (rufl_fm_error) - return rufl_FONT_MANAGER_ERROR; - } - rufl_cache[evict].font = font; - rufl_cache[evict].size = font_size; - rufl_cache[evict].encoding = encoding; - rufl_cache[evict].f = f; - rufl_cache[evict].last_used = rufl_cache_time++; - - return rufl_OK; -} diff --git a/rufl_init.c b/rufl_init.c deleted file mode 100644 index 533955a..0000000 --- a/rufl_init.c +++ /dev/null @@ -1,1678 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -#define _GNU_SOURCE /* for strndup */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rufl_internal.h" - - -struct rufl_font_list_entry *rufl_font_list = 0; -size_t rufl_font_list_entries = 0; -const char **rufl_family_list = 0; -unsigned int rufl_family_list_entries = 0; -struct rufl_family_map_entry *rufl_family_map = 0; -os_error *rufl_fm_error = 0; -void *rufl_family_menu = 0; -unsigned short *rufl_substitution_table = 0; -struct rufl_cache_entry rufl_cache[rufl_CACHE_SIZE]; -int rufl_cache_time = 0; -bool rufl_old_font_manager = false; -wimp_w rufl_status_w = 0; -char rufl_status_buffer[80]; - -/** An entry in rufl_weight_table. */ -struct rufl_weight_table_entry { - const char *name; - unsigned int weight; -}; - -/** Map from font name part to font weight. Must be case-insensitive sorted by - * name. */ -const struct rufl_weight_table_entry rufl_weight_table[] = { - { "Black", 9 }, - { "Bold", 7 }, - { "Book", 3 }, - { "Demi", 6 }, - { "DemiBold", 6 }, - { "Extra", 8 }, - { "ExtraBlack", 9 }, - { "ExtraBold", 8 }, - { "ExtraLight", 1 }, - { "Heavy", 8 }, - { "Light", 2 }, - { "Medium", 5 }, - { "Regular", 4 }, - { "Semi", 6 }, - { "SemiBold", 6 }, - { "SemiLight", 3 }, - { "UltraBlack", 9 }, - { "UltraBold", 9 }, -}; - - -static rufl_code rufl_init_font_list(void); -static rufl_code rufl_init_add_font(const char *identifier, - const char *local_name); -static int rufl_weight_table_cmp(const void *keyval, const void *datum); -static rufl_code rufl_init_scan_font(unsigned int font); -static rufl_code rufl_init_scan_font_no_enumerate(unsigned int font); -static bool rufl_is_space(unsigned int u); -static rufl_code rufl_init_scan_font_old(unsigned int font_index); -static rufl_code rufl_init_scan_font_in_encoding(const char *font_name, - const char *encoding, struct rufl_character_set *charset, - struct rufl_unicode_map *umap, unsigned int *last); -static rufl_code rufl_init_read_encoding(font_f font, - struct rufl_unicode_map *umap); -static int rufl_glyph_map_cmp(const void *keyval, const void *datum); -static int rufl_unicode_map_cmp(const void *z1, const void *z2); -static rufl_code rufl_init_substitution_table(void); -static rufl_code rufl_save_cache(void); -static rufl_code rufl_load_cache(void); -static int rufl_font_list_cmp(const void *keyval, const void *datum); -static rufl_code rufl_init_family_menu(void); -static void rufl_init_status_open(void); -static void rufl_init_status(const char *status, float progress); -static void rufl_init_status_close(void); - - -/** - * Initialise RUfl. - * - * All available fonts are scanned. May take some time. - */ - -rufl_code rufl_init(void) -{ - bool rufl_broken_font_enumerate_characters = false; - unsigned int changes = 0; - unsigned int i; - int fm_version; - rufl_code code; - font_f font; - os_colour old_sand, old_glass; - - if (rufl_font_list_entries) - /* already initialized */ - return rufl_OK; - - xhourglass_on(); - - rufl_init_status_open(); - - /* determine if the font manager supports Unicode */ - rufl_fm_error = xfont_find_font("Homerton.Medium\\EUTF8", 160, 160, - 0, 0, &font, 0, 0); - if (rufl_fm_error) { - if (rufl_fm_error->errnum == error_FONT_ENCODING_NOT_FOUND) { - rufl_old_font_manager = true; - } else { - LOG("xfont_find_font: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - rufl_quit(); - xhourglass_off(); - return rufl_FONT_MANAGER_ERROR; - } - } else { - /* New font manager; see if character enumeration works */ - int next; - - rufl_fm_error = xfont_enumerate_characters(font, 0, - &next, NULL); - /* Broken if SWI fails or it doesn't return 0x20 as the first - * character to process. Font Managers earlier than 3.64 have - * a bug that means they do not return the first available - * range of characters in a font. We detect this by asking - * for the first character in Homerton.Medium, which we know - * is 0x20 (i.e. space). If the value returned is not this, - * then we assume the font manager is broken and fall back to - * the old code which is significantly slower. - */ - if (rufl_fm_error || next != 0x20) - rufl_broken_font_enumerate_characters = true; - - xfont_lose_font(font); - } - LOG("%s font manager", rufl_old_font_manager ? "old" : "new"); - - /* test if the font manager supports background blending */ - rufl_fm_error = xfont_cache_addr(&fm_version, 0, 0); - if (rufl_fm_error) - return rufl_FONT_MANAGER_ERROR; - if (fm_version >= 335) - rufl_can_background_blend = true; - - code = rufl_init_font_list(); - if (code != rufl_OK) { - rufl_quit(); - xhourglass_off(); - return code; - } - LOG("%zu faces, %u families", rufl_font_list_entries, - rufl_family_list_entries); - - code = rufl_load_cache(); - if (code != rufl_OK) { - LOG("rufl_load_cache: 0x%x", code); - rufl_quit(); - xhourglass_off(); - return code; - } - - xhourglass_leds(1, 0, 0); - for (i = 0; i != rufl_font_list_entries; i++) { - if (rufl_font_list[i].charset) { - /* character set loaded from cache */ - continue; - } - LOG("scanning %u \"%s\"", i, rufl_font_list[i].identifier); - xhourglass_percentage(100 * i / rufl_font_list_entries); - rufl_init_status(rufl_font_list[i].identifier, - (float) i / rufl_font_list_entries); - if (rufl_old_font_manager) - code = rufl_init_scan_font_old(i); - else if (rufl_broken_font_enumerate_characters) - code = rufl_init_scan_font_no_enumerate(i); - else - code = rufl_init_scan_font(i); - if (code != rufl_OK) { - LOG("rufl_init_scan_font: 0x%x", code); - rufl_quit(); - xhourglass_off(); - return code; - } - changes++; - } - - xhourglass_leds(2, 0, 0); - xhourglass_colours(0x0000ff, 0x00ffff, &old_sand, &old_glass); - code = rufl_init_substitution_table(); - if (code != rufl_OK) { - LOG("rufl_init_substitution_table: 0x%x", code); - rufl_quit(); - xhourglass_off(); - return code; - } - xhourglass_colours(old_sand, old_glass, 0, 0); - - if (changes) { - LOG("%u new charsets", changes); - xhourglass_leds(3, 0, 0); - code = rufl_save_cache(); - if (code != rufl_OK) { - LOG("rufl_save_cache: 0x%x", code); - rufl_quit(); - xhourglass_off(); - return code; - } - } - - for (i = 0; i != rufl_CACHE_SIZE; i++) - rufl_cache[i].font = rufl_CACHE_NONE; - - code = rufl_init_family_menu(); - if (code != rufl_OK) { - LOG("rufl_init_substitution_table: 0x%x", code); - rufl_quit(); - xhourglass_off(); - return code; - } - - rufl_init_status_close(); - - xhourglass_off(); - - return rufl_OK; -} - - -/** - * Build list of font in rufl_font_list and list of font families - * in rufl_family_list. - */ - -rufl_code rufl_init_font_list(void) -{ - rufl_code code; - font_list_context context = 0; - char identifier[80], local_name[80]; - - while (context != -1) { - /* read identifier */ - rufl_fm_error = xfont_list_fonts((byte *)identifier, - font_RETURN_FONT_NAME | - font_RETURN_LOCAL_FONT_NAME | - context, - sizeof identifier, - (byte *)local_name, sizeof local_name, 0, - &context, 0, 0); - if (rufl_fm_error) { - LOG("xfont_list_fonts: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - if (context == -1) - break; - - code = rufl_init_add_font(identifier, local_name); - if (code != rufl_OK) - return code; - } - - return rufl_OK; -} - - -rufl_code rufl_init_add_font(const char *identifier, const char *local_name) -{ - int size; - struct rufl_font_list_entry *font_list; - char *dot; - const char **family_list; - const char *family, *part; - unsigned int weight = 0; - unsigned int slant = 0; - bool special = false; - struct rufl_family_map_entry *family_map; - unsigned int i; - struct rufl_weight_table_entry *entry; - - /* Check that: - * a) it's not a RiScript generated font - * b) it's not a TeX font */ - - /* Read required buffer size */ - rufl_fm_error = xosfscontrol_canonicalise_path(identifier, 0, - "Font$Path", 0, 0, &size); - if (rufl_fm_error) { - LOG("xosfscontrol_canonicalise_path(\"%s\", ...): 0x%x: %s", - identifier, - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_OK; - } - /* size is -(space required - 1) so negate and add 1 */ - size = -size + 1; - - /* Create buffer and canonicalise path */ - char fullpath[size]; - rufl_fm_error = xosfscontrol_canonicalise_path(identifier, - fullpath, "Font$Path", 0, size, 0); - if (rufl_fm_error) { - LOG("xosfscontrol_canonicalise_path(\"%s\", ...): 0x%x: %s", - identifier, - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_OK; - } - - /* LOG("%s", fullpath); */ - - if (strstr(fullpath, "RiScript") || strstr(fullpath, "!TeXFonts")) - /* Ignore this font */ - return rufl_OK; - - /* add identifier to rufl_font_list */ - font_list = realloc(rufl_font_list, sizeof rufl_font_list[0] * - (rufl_font_list_entries + 1)); - if (!font_list) - return rufl_OUT_OF_MEMORY; - rufl_font_list = font_list; - rufl_font_list[rufl_font_list_entries].identifier = strdup(identifier); - if (!rufl_font_list[rufl_font_list_entries].identifier) - return rufl_OUT_OF_MEMORY; - rufl_font_list[rufl_font_list_entries].charset = 0; - rufl_font_list[rufl_font_list_entries].umap = 0; - rufl_font_list_entries++; - - /* determine family, weight, and slant */ - dot = strchr(local_name, '.'); - family = local_name; - if (dot) - *dot = 0; - while (dot) { - part = dot + 1; - dot = strchr(part, '.'); - if (dot) - *dot = 0; - if (strcasecmp(part, "Italic") == 0 || - strcasecmp(part, "Oblique") == 0) { - slant = 1; - continue; - } - entry = bsearch(part, rufl_weight_table, - sizeof rufl_weight_table / - sizeof rufl_weight_table[0], - sizeof rufl_weight_table[0], - rufl_weight_table_cmp); - if (entry) - weight = entry->weight; - else - special = true; /* unknown weight or style */ - } - if (!weight) - weight = 4; - weight--; - - if (rufl_family_list_entries == 0 || strcasecmp(family, - rufl_family_list[rufl_family_list_entries - 1]) != 0) { - /* new family */ - family_list = realloc(rufl_family_list, - sizeof rufl_family_list[0] * - (rufl_family_list_entries + 1)); - if (!family_list) - return rufl_OUT_OF_MEMORY; - rufl_family_list = family_list; - - family_map = realloc(rufl_family_map, - sizeof rufl_family_map[0] * - (rufl_family_list_entries + 1)); - if (!family_map) - return rufl_OUT_OF_MEMORY; - rufl_family_map = family_map; - - family = strdup(family); - if (!family) - return rufl_OUT_OF_MEMORY; - - rufl_family_list[rufl_family_list_entries] = family; - for (i = 0; i != 9; i++) - rufl_family_map[rufl_family_list_entries].font[i][0] = - rufl_family_map[rufl_family_list_entries].font[i][1] = - NO_FONT; - rufl_family_list_entries++; - } - - struct rufl_family_map_entry *e = - &rufl_family_map[rufl_family_list_entries - 1]; - /* prefer fonts with no unknown weight or style in their name, so that, - * for example, Alps.Light takes priority over Alps.Cond.Light */ - if (e->font[weight][slant] == NO_FONT || !special) - e->font[weight][slant] = rufl_font_list_entries - 1; - - rufl_font_list[rufl_font_list_entries - 1].family = - rufl_family_list_entries - 1; - rufl_font_list[rufl_font_list_entries - 1].weight = weight; - rufl_font_list[rufl_font_list_entries - 1].slant = slant; - - return rufl_OK; -} - - -int rufl_weight_table_cmp(const void *keyval, const void *datum) -{ - const char *key = keyval; - const struct rufl_weight_table_entry *entry = datum; - return strcasecmp(key, entry->name); -} - -/** - * Scan a font for available characters. - */ - -rufl_code rufl_init_scan_font(unsigned int font_index) -{ - char font_name[80]; - int x_out, y_out; - unsigned int byte, bit; - unsigned int last_used = 0; - unsigned int string[2] = { 0, 0 }; - unsigned int u, next; - struct rufl_character_set *charset; - struct rufl_character_set *charset2; - font_f font; - font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; - - /*LOG("font %u \"%s\"", font_index, - rufl_font_list[font_index].identifier);*/ - - charset = calloc(1, sizeof *charset); - if (!charset) - return rufl_OUT_OF_MEMORY; - for (u = 0; u != 256; u++) - charset->index[u] = BLOCK_EMPTY; - - snprintf(font_name, sizeof font_name, "%s\\EUTF8", - rufl_font_list[font_index].identifier); - - rufl_fm_error = xfont_find_font(font_name, 160, 160, 0, 0, &font, 0, 0); - if (rufl_fm_error) { - LOG("xfont_find_font(\"%s\"): 0x%x: %s", font_name, - rufl_fm_error->errnum, rufl_fm_error->errmess); - free(charset); - return rufl_OK; - } - - /* Scan through mapped characters */ - for (u = 0; u != (unsigned int) -1; u = next) { - unsigned int internal; - - rufl_fm_error = xfont_enumerate_characters(font, u, - (int *) &next, (int *) &internal); - if (rufl_fm_error) { - LOG("xfont_enumerate_characters: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - xfont_lose_font(font); - free(charset); - return rufl_OK; - } - - /* Skip DELETE and C0/C1 controls */ - if (u < 0x0020 || (0x007f <= u && u <= 0x009f)) - continue; - - /* Skip astral characters */ - if (u > 0xffff) - continue; - - /* Skip unmapped characters */ - if (internal == (unsigned int) -1) - continue; - - if (u % 0x200 == 0) - rufl_init_status(0, 0); - - /* Character is mapped, let's see if it's really there */ - string[0] = u; - rufl_fm_error = xfont_scan_string(font, (char *) string, - font_RETURN_BBOX | font_GIVEN32_BIT | - font_GIVEN_FONT | font_GIVEN_LENGTH | - font_GIVEN_BLOCK, - 0x7fffffff, 0x7fffffff, - &block, 0, 4, - 0, &x_out, &y_out, 0); - if (rufl_fm_error) - break; - - if (block.bbox.x0 == 0x20000000) { - /* absent (no definition) */ - } else if (x_out == 0 && y_out == 0 && - block.bbox.x0 == 0 && block.bbox.y0 == 0 && - block.bbox.x1 == 0 && block.bbox.y1 == 0) { - /* absent (empty) */ - } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && - block.bbox.x1 == 0 && block.bbox.y1 == 0 && - !rufl_is_space(u)) { - /* absent (space but not a space character - some - * fonts do this) */ - } else { - /* present */ - if (charset->index[u >> 8] == BLOCK_EMPTY) { - charset->index[u >> 8] = last_used; - last_used++; - if (last_used == 254) - /* too many characters */ - break; - } - - byte = (u >> 3) & 31; - bit = u & 7; - charset->block[charset->index[u >> 8]][byte] |= - 1 << bit; - } - } - - xfont_lose_font(font); - - if (rufl_fm_error) { - free(charset); - LOG("xfont_scan_string: 0x%x: %s", - rufl_fm_error->errnum, rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - - /* Determine which blocks are full, and mark them as such */ - for (u = 0; u != 256; u++) { - if (charset->index[u] == BLOCK_EMPTY) - continue; - - bit = 0xff; - - for (byte = 0; byte != 32; byte++) - bit &= charset->block[u][byte]; - - if (bit == 0xff) { - /* Block is full */ - charset->index[u] = BLOCK_FULL; - - for (byte = 0; byte != 32; byte++) - charset->block[u][byte] = 0; - } - } - - /* shrink-wrap */ - charset->size = offsetof(struct rufl_character_set, block) + - 32 * last_used; - charset2 = realloc(charset, charset->size); - if (!charset2) { - free(charset); - return rufl_OUT_OF_MEMORY; - } - - rufl_font_list[font_index].charset = charset; - - return rufl_OK; -} - -/** - * Scan a font for available characters (version without character enumeration) - */ - -rufl_code rufl_init_scan_font_no_enumerate(unsigned int font_index) -{ - char font_name[80]; - int x_out, y_out; - unsigned int byte, bit; - unsigned int block_count = 0; - unsigned int last_used = 0; - unsigned int string[2] = { 0, 0 }; - unsigned int u; - struct rufl_character_set *charset; - struct rufl_character_set *charset2; - font_f font; - font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; - - /*LOG("font %u \"%s\"", font_index, - rufl_font_list[font_index].identifier);*/ - - charset = calloc(1, sizeof *charset); - if (!charset) - return rufl_OUT_OF_MEMORY; - - snprintf(font_name, sizeof font_name, "%s\\EUTF8", - rufl_font_list[font_index].identifier); - - rufl_fm_error = xfont_find_font(font_name, 160, 160, 0, 0, &font, 0, 0); - if (rufl_fm_error) { - LOG("xfont_find_font(\"%s\"): 0x%x: %s", font_name, - rufl_fm_error->errnum, rufl_fm_error->errmess); - free(charset); - return rufl_OK; - } - - /* scan through all characters */ - for (u = 0x0020; u != 0x10000; u++) { - if (u == 0x007f) { - /* skip DELETE and C1 controls */ - u = 0x009f; - continue; - } - - if (u % 0x200 == 0) - rufl_init_status(0, 0); - - string[0] = u; - rufl_fm_error = xfont_scan_string(font, (char *) string, - font_RETURN_BBOX | font_GIVEN32_BIT | - font_GIVEN_FONT | font_GIVEN_LENGTH | - font_GIVEN_BLOCK, - 0x7fffffff, 0x7fffffff, - &block, 0, 4, - 0, &x_out, &y_out, 0); - if (rufl_fm_error) - break; - - if (block.bbox.x0 == 0x20000000) { - /* absent (no definition) */ - } else if (x_out == 0 && y_out == 0 && - block.bbox.x0 == 0 && block.bbox.y0 == 0 && - block.bbox.x1 == 0 && block.bbox.y1 == 0) { - /* absent (empty) */ - } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && - block.bbox.x1 == 0 && block.bbox.y1 == 0 && - !rufl_is_space(u)) { - /* absent (space but not a space character - some - * fonts do this) */ - } else { - /* present */ - byte = (u >> 3) & 31; - bit = u & 7; - charset->block[last_used][byte] |= 1 << bit; - - block_count++; - } - - if ((u + 1) % 256 == 0) { - /* end of block */ - if (block_count == 0) - charset->index[u >> 8] = BLOCK_EMPTY; - else if (block_count == 256) { - charset->index[u >> 8] = BLOCK_FULL; - for (byte = 0; byte != 32; byte++) - charset->block[last_used][byte] = 0; - } else { - charset->index[u >> 8] = last_used; - last_used++; - if (last_used == 254) - /* too many characters */ - break; - } - block_count = 0; - } - } - - xfont_lose_font(font); - - if (rufl_fm_error) { - free(charset); - LOG("xfont_scan_string: 0x%x: %s", - rufl_fm_error->errnum, rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - - /* shrink-wrap */ - charset->size = offsetof(struct rufl_character_set, block) + - 32 * last_used; - charset2 = realloc(charset, charset->size); - if (!charset2) { - free(charset); - return rufl_OUT_OF_MEMORY; - } - - rufl_font_list[font_index].charset = charset; - - return rufl_OK; -} - -/** - * A character is one of the Unicode space characters. - */ - -bool rufl_is_space(unsigned int u) -{ - return u == 0x0020 || u == 0x00a0 || - (0x2000 <= u && u <= 0x200b) || - u == 0x202f || u == 0x3000; -} - - -/** - * Scan a font for available characters (old font manager version). - */ - -rufl_code rufl_init_scan_font_old(unsigned int font_index) -{ - const char *font_name = rufl_font_list[font_index].identifier; - struct rufl_character_set *charset; - struct rufl_character_set *charset2; - struct rufl_unicode_map *umap = NULL; - unsigned int num_umaps = 0; - unsigned int i; - unsigned int last_used = 0; - rufl_code code; - font_list_context context = 0; - char encoding[80]; - - /*LOG("font %u \"%s\"", font_index, font_name);*/ - - charset = calloc(1, sizeof *charset); - if (!charset) - return rufl_OUT_OF_MEMORY; - for (i = 0; i != 256; i++) - charset->index[i] = BLOCK_EMPTY; - - /* Firstly, search through available encodings (Symbol fonts fail) */ - while (context != -1) { - struct rufl_unicode_map *temp; - - rufl_fm_error = xfont_list_fonts((byte *) encoding, - font_RETURN_FONT_NAME | - 0x400000 /* Return encoding name, instead */ | - context, - sizeof(encoding), NULL, 0, NULL, - &context, NULL, NULL); - if (rufl_fm_error) { - LOG("xfont_list_fonts: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - free(charset); - for (i = 0; i < num_umaps; i++) - free((umap + i)->encoding); - free(umap); - return rufl_FONT_MANAGER_ERROR; - } - if (context == -1) - break; - - temp = realloc(umap, (num_umaps + 1) * sizeof *umap); - if (!temp) { - free(charset); - for (i = 0; i < num_umaps; i++) - free((umap + i)->encoding); - free(umap); - return rufl_OUT_OF_MEMORY; - } - - memset(temp + num_umaps, 0, sizeof *umap); - - umap = temp; - num_umaps++; - - code = rufl_init_scan_font_in_encoding(font_name, encoding, - charset, umap + (num_umaps - 1), &last_used); - if (code != rufl_OK) { - /* Not finding the font isn't fatal */ - if (code != rufl_FONT_MANAGER_ERROR || - (rufl_fm_error->errnum != - error_FONT_NOT_FOUND && - rufl_fm_error->errnum != - error_FILE_NOT_FOUND)) { - free(charset); - for (i = 0; i < num_umaps; i++) - free((umap + i)->encoding); - free(umap); - return code; - } - - /* Ensure we reuse the currently allocated umap */ - num_umaps--; - } else { - /* If this mapping is identical to an existing one, - * then we can discard it */ - for (i = 0; i != num_umaps - 1; i++) { - const struct rufl_unicode_map *a = (umap + i); - const struct rufl_unicode_map *b = - (umap + num_umaps - 1); - - if (a->entries == b->entries && - memcmp(a->map, b->map, - sizeof a->map) == 0) { - /* Found identical map; discard */ - num_umaps--; - break; - } - } - } - } - - if (num_umaps == 0) { - /* This is a symbol font and can only be used - * without an encoding */ - struct rufl_unicode_map *temp; - - temp = realloc(umap, (num_umaps + 1) * sizeof *umap); - if (!temp) { - free(charset); - free(umap); - return rufl_OUT_OF_MEMORY; - } - - memset(temp + num_umaps, 0, sizeof *umap); - - umap = temp; - num_umaps++; - - code = rufl_init_scan_font_in_encoding(font_name, NULL, - charset, umap, &last_used); - if (code != rufl_OK) { - /* Not finding the font isn't fatal */ - if (code != rufl_FONT_MANAGER_ERROR || - (rufl_fm_error->errnum != - error_FONT_NOT_FOUND && - rufl_fm_error->errnum != - error_FILE_NOT_FOUND)) { - free(charset); - for (i = 0; i < num_umaps; i++) - free((umap + i)->encoding); - free(umap); - return code; - } - - num_umaps--; - } - } - - /* shrink-wrap */ - charset->size = offsetof(struct rufl_character_set, block) + - 32 * last_used; - charset2 = realloc(charset, charset->size); - if (!charset2) { - for (i = 0; i < num_umaps; i++) - free((umap + i)->encoding); - free(umap); - free(charset); - return rufl_OUT_OF_MEMORY; - } - - rufl_font_list[font_index].charset = charset; - rufl_font_list[font_index].umap = umap; - rufl_font_list[font_index].num_umaps = num_umaps; - - return rufl_OK; -} - -/** - * Helper function for rufl_init_scan_font_old. - * Scans the given font using the given font encoding (or none, if NULL) - */ - -rufl_code rufl_init_scan_font_in_encoding(const char *font_name, - const char *encoding, struct rufl_character_set *charset, - struct rufl_unicode_map *umap, unsigned int *last) -{ - char string[2] = { 0, 0 }; - int x_out, y_out; - unsigned int byte, bit; - unsigned int i; - unsigned int last_used = *last; - unsigned int u; - rufl_code code; - font_f font; - font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; - char buf[80]; - - if (encoding) - snprintf(buf, sizeof buf, "%s\\E%s", font_name, encoding); - else - snprintf(buf, sizeof buf, "%s", font_name); - - rufl_fm_error = xfont_find_font(buf, 160, 160, 0, 0, &font, 0, 0); - if (rufl_fm_error) { - LOG("xfont_find_font(\"%s\"): 0x%x: %s", buf, - rufl_fm_error->errnum, rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - - code = rufl_init_read_encoding(font, umap); - if (code != rufl_OK) { - xfont_lose_font(font); - return code; - } - - for (i = 0; i != umap->entries; i++) { - u = umap->map[i].u; - string[0] = umap->map[i].c; - rufl_fm_error = xfont_scan_string(font, (char *) string, - font_RETURN_BBOX | font_GIVEN_FONT | - font_GIVEN_LENGTH | font_GIVEN_BLOCK, - 0x7fffffff, 0x7fffffff, - &block, 0, 1, - 0, &x_out, &y_out, 0); - if (rufl_fm_error) - break; - - if (block.bbox.x0 == 0x20000000) { - /* absent (no definition) */ - } else if (x_out == 0 && y_out == 0 && - block.bbox.x0 == 0 && block.bbox.y0 == 0 && - block.bbox.x1 == 0 && block.bbox.y1 == 0) { - /* absent (empty) */ - } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && - block.bbox.x1 == 0 && block.bbox.y1 == 0 && - !rufl_is_space(u)) { - /* absent (space but not a space character - some - * fonts do this) */ - } else { - /* present */ - if (charset->index[u >> 8] == BLOCK_EMPTY) { - charset->index[u >> 8] = last_used; - last_used++; - if (last_used == 254) - /* too many characters */ - break; - } - - byte = (u >> 3) & 31; - bit = u & 7; - charset->block[charset->index[u >> 8]][byte] |= - 1 << bit; - } - } - - xfont_lose_font(font); - - if (rufl_fm_error) { - LOG("xfont_scan_string: 0x%x: %s", - rufl_fm_error->errnum, rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - - if (encoding) { - umap->encoding = strdup(encoding); - if (!umap->encoding) - return rufl_OUT_OF_MEMORY; - } - - *last = last_used; - - return rufl_OK; -} - - -/** - * Parse an encoding file and fill in a rufl_unicode_map. - */ - -rufl_code rufl_init_read_encoding(font_f font, - struct rufl_unicode_map *umap) -{ - unsigned int u = 0; - unsigned int i = 0; - int c; - int n; - char filename[200]; - char s[200]; - struct rufl_glyph_map_entry *entry; - FILE *fp; - - rufl_fm_error = xfont_read_encoding_filename(font, filename, - sizeof filename, 0); - if (rufl_fm_error) { - LOG("xfont_read_encoding_filename: 0x%x: %s", - rufl_fm_error->errnum, rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - - fp = fopen(filename, "r"); - if (!fp) - /* many "symbol" fonts have no encoding file: assume Latin 1 */ - fp = fopen("Resources:$.Fonts.Encodings.Latin1", "r"); - if (!fp) - return rufl_IO_ERROR; - - while (!feof(fp) && u != 256) { - c = fgetc(fp); - if (c == '%') { - /* comment line */ - fgets(s, sizeof s, fp); - } else if (c == '/') { - /* character definition */ - if (i++ < 32) - continue; - n = fscanf(fp, "%100s", s); - if (n != 1) - break; - entry = bsearch(s, rufl_glyph_map, - rufl_glyph_map_size, - sizeof rufl_glyph_map[0], - rufl_glyph_map_cmp); - if (entry) { - /* may be more than one unicode for the glyph - * sentinels stop overshooting array */ - while (strcmp(s, (entry - 1)->glyph_name) == 0) - entry--; - for (; strcmp(s, entry->glyph_name) == 0; - entry++) { - umap->map[u].u = entry->u; - umap->map[u].c = i - 1; - u++; - if (u == 256) - break; - } - } - } - } - - if (fclose(fp) == EOF) - return rufl_IO_ERROR; - - /* sort by unicode */ - qsort(umap->map, u, sizeof umap->map[0], rufl_unicode_map_cmp); - umap->entries = u; - - return rufl_OK; -} - - -int rufl_glyph_map_cmp(const void *keyval, const void *datum) -{ - const char *key = keyval; - const struct rufl_glyph_map_entry *entry = datum; - return strcmp(key, entry->glyph_name); -} - - -int rufl_unicode_map_cmp(const void *z1, const void *z2) -{ - const struct rufl_unicode_map_entry *entry1 = z1; - const struct rufl_unicode_map_entry *entry2 = z2; - if (entry1->u < entry2->u) - return -1; - else if (entry2->u < entry1->u) - return 1; - return 0; -} - - -/** - * Construct the font substitution table. - */ - -rufl_code rufl_init_substitution_table(void) -{ - unsigned char z; - unsigned int i; - unsigned int block, byte, bit; - unsigned int u; - unsigned int index; - const struct rufl_character_set *charset; - - rufl_substitution_table = malloc(65536 * - sizeof rufl_substitution_table[0]); - if (!rufl_substitution_table) { - LOG("malloc(%zu) failed", 65536 * - sizeof rufl_substitution_table[0]); - return rufl_OUT_OF_MEMORY; - } - - for (u = 0; u != 0x10000; u++) - rufl_substitution_table[u] = NOT_AVAILABLE; - - for (i = 0; i != rufl_font_list_entries; i++) { - charset = rufl_font_list[i].charset; - if (!charset) - continue; - for (block = 0; block != 256; block++) { - if (charset->index[block] == BLOCK_EMPTY) - continue; - if (charset->index[block] == BLOCK_FULL) { - for (u = block << 8; u != (block << 8) + 256; - u++) { - if (rufl_substitution_table[u] == - NOT_AVAILABLE) - rufl_substitution_table[u] = i; - } - continue; - } - index = charset->index[block]; - for (byte = 0; byte != 32; byte++) { - z = charset->block[index][byte]; - if (z == 0) - continue; - u = (block << 8) | (byte << 3); - for (bit = 0; bit != 8; bit++, u++) { - if (rufl_substitution_table[u] == - NOT_AVAILABLE && - z & (1 << bit)) - rufl_substitution_table[u] = i; - } - } - } - } - - return rufl_OK; -} - - -/** - * Save character sets to cache. - */ - -rufl_code rufl_save_cache(void) -{ - unsigned int i; - const unsigned int version = rufl_CACHE_VERSION; - size_t len; - FILE *fp; - - fp = fopen(rufl_CACHE, "wb"); - if (!fp) { - LOG("fopen: 0x%x: %s", errno, strerror(errno)); - return rufl_OK; - } - - /* cache format version */ - if (fwrite(&version, sizeof version, 1, fp) != 1) { - LOG("fwrite: 0x%x: %s", errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - - /* font manager type flag */ - if (fwrite(&rufl_old_font_manager, sizeof rufl_old_font_manager, 1, - fp) != 1) { - LOG("fwrite: 0x%x: %s", errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - - for (i = 0; i != rufl_font_list_entries; i++) { - if (!rufl_font_list[i].charset) - continue; - - /* length of font identifier */ - len = strlen(rufl_font_list[i].identifier); - if (fwrite(&len, sizeof len, 1, fp) != 1) { - LOG("fwrite: 0x%x: %s", errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - - /* font identifier */ - if (fwrite(rufl_font_list[i].identifier, len, 1, fp) != 1) { - LOG("fwrite: 0x%x: %s", errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - - /* character set */ - if (fwrite(rufl_font_list[i].charset, - rufl_font_list[i].charset->size, 1, fp) != 1) { - LOG("fwrite: 0x%x: %s", errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - - /* unicode map */ - if (rufl_old_font_manager) { - unsigned int j; - - if (fwrite(&rufl_font_list[i].num_umaps, - sizeof rufl_font_list[i].num_umaps, 1, - fp) != 1) { - LOG("fwrite: 0x%x: %s", errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - - for (j = 0; j < rufl_font_list[i].num_umaps; j++) { - const struct rufl_unicode_map *umap = - rufl_font_list[i].umap + j; - - len = umap->encoding ? - strlen(umap->encoding) : 0; - - if (fwrite(&len, sizeof len, 1, fp) != 1) { - LOG("fwrite: 0x%x: %s", - errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - - if (umap->encoding) { - if (fwrite(umap->encoding, len, 1, - fp) != 1) { - LOG("fwrite: 0x%x: %s", - errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - } - - if (fwrite(&umap->entries, sizeof umap->entries, - 1, fp) != 1) { - LOG("fwrite: 0x%x: %s", - errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - - if (fwrite(umap->map, umap->entries * - sizeof(struct rufl_unicode_map_entry), - 1, fp) != 1) { - LOG("fwrite: 0x%x: %s", - errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - } - } - } - - if (fclose(fp) == EOF) { - LOG("fclose: 0x%x: %s", errno, strerror(errno)); - return rufl_OK; - } - - LOG("%u charsets saved", i); - - return rufl_OK; -} - - -/** - * Load character sets from cache. - */ - -rufl_code rufl_load_cache(void) -{ - unsigned int version; - unsigned int i = 0; - bool old_font_manager; - char *identifier; - size_t len, size; - FILE *fp; - struct rufl_font_list_entry *entry; - struct rufl_character_set *charset; - struct rufl_unicode_map *umap = NULL; - unsigned int num_umaps = 0; - - fp = fopen(rufl_CACHE, "rb"); - if (!fp) { - LOG("fopen: 0x%x: %s", errno, strerror(errno)); - return rufl_OK; - } - - /* cache format version */ - if (fread(&version, sizeof version, 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - if (version != rufl_CACHE_VERSION) { - /* incompatible cache format */ - LOG("cache version %u (now %u)", version, rufl_CACHE_VERSION); - fclose(fp); - return rufl_OK; - } - - /* font manager type flag */ - if (fread(&old_font_manager, sizeof old_font_manager, 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, strerror(errno)); - fclose(fp); - return rufl_OK; - } - if (old_font_manager != rufl_old_font_manager) { - /* font manager type has changed */ - LOG("font manager %u (now %u)", old_font_manager, - rufl_old_font_manager); - fclose(fp); - return rufl_OK; - } - - while (!feof(fp)) { - /* length of font identifier */ - if (fread(&len, sizeof len, 1, fp) != 1) { - /* eof at this point simply means that the whole cache - * file has been loaded */ - if (!feof(fp)) - LOG("fread: 0x%x: %s", errno, strerror(errno)); - break; - } - - identifier = malloc(len + 1); - if (!identifier) { - LOG("malloc(%zu) failed", len + 1); - fclose(fp); - return rufl_OUT_OF_MEMORY; - } - - /* font identifier */ - if (fread(identifier, len, 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, strerror(errno)); - free(identifier); - break; - } - identifier[len] = 0; - - /* character set */ - if (fread(&size, sizeof size, 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, strerror(errno)); - free(identifier); - break; - } - - charset = malloc(size); - if (!charset) { - LOG("malloc(%zu) failed", size); - free(identifier); - fclose(fp); - return rufl_OUT_OF_MEMORY; - } - - charset->size = size; - if (fread(charset->index, size - sizeof size, 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, strerror(errno)); - free(charset); - free(identifier); - break; - } - - /* unicode map */ - if (rufl_old_font_manager) { - rufl_code code = rufl_OK; - unsigned int entry; - - /* Number of maps */ - if (fread(&num_umaps, sizeof num_umaps, 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, - strerror(errno)); - free(charset); - free(identifier); - break; - } - - umap = calloc(num_umaps, sizeof *umap); - if (!umap) { - LOG("malloc(%zu) failed", sizeof *umap); - free(charset); - free(identifier); - fclose(fp); - return rufl_OUT_OF_MEMORY; - } - - /* Load them */ - for (entry = 0; entry < num_umaps; entry++) { - struct rufl_unicode_map *map = umap + entry; - - if (fread(&len, sizeof(len), 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", - "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, - strerror(errno)); - break; - } - - if (len > 0) { - map->encoding = malloc(len + 1); - if (!map->encoding) { - LOG("malloc(%zu) failed", - len + 1); - code = rufl_OUT_OF_MEMORY; - break; - } - - if (fread(map->encoding, len, 1, - fp) != 1) { - if (feof(fp)) - LOG("fread: %s", - "unexpected eof"); - else - LOG("fread: 0x%x: %s", - errno, - strerror(errno)); - break; - } - map->encoding[len] = 0; - } - - if (fread(&map->entries, sizeof(map->entries), - 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", - "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, - strerror(errno)); - break; - } - - if (fread(map->map, map->entries * - sizeof(struct rufl_unicode_map_entry), - 1, fp) != 1) { - if (feof(fp)) - LOG("fread: %s", - "unexpected eof"); - else - LOG("fread: 0x%x: %s", errno, - strerror(errno)); - break; - } - } - - /* Clean up if loading failed */ - if (entry != num_umaps) { - for (num_umaps = 0; num_umaps <= entry; - num_umaps++) { - struct rufl_unicode_map *map = - umap + num_umaps; - - free(map->encoding); - } - free(umap); - free(charset); - free(identifier); - - if (code != rufl_OK) - return code; - - break; - } - } - - /* put in rufl_font_list */ - entry = lfind(identifier, rufl_font_list, - &rufl_font_list_entries, - sizeof rufl_font_list[0], rufl_font_list_cmp); - if (entry) { - entry->charset = charset; - entry->umap = umap; - entry->num_umaps = num_umaps; - i++; - } else { - LOG("\"%s\" not in font list", identifier); - while (num_umaps > 0) { - struct rufl_unicode_map *map = - umap + num_umaps - 1; - - free(map->encoding); - - num_umaps--; - } - free(umap); - free(charset); - } - - free(identifier); - } - fclose(fp); - - LOG("%u charsets loaded", i); - - return rufl_OK; -} - - -int rufl_font_list_cmp(const void *keyval, const void *datum) -{ - const char *key = keyval; - const struct rufl_font_list_entry *entry = datum; - return strcasecmp(key, entry->identifier); -} - - -/** - * Create a menu of font families. - */ - -rufl_code rufl_init_family_menu(void) -{ - wimp_menu *menu; - unsigned int i; - - menu = malloc(wimp_SIZEOF_MENU(rufl_family_list_entries)); - if (!menu) - return rufl_OUT_OF_MEMORY; - menu->title_data.indirected_text.text = (char *) "Fonts"; - menu->title_fg = wimp_COLOUR_BLACK; - menu->title_bg = wimp_COLOUR_LIGHT_GREY; - menu->work_fg = wimp_COLOUR_BLACK; - menu->work_bg = wimp_COLOUR_WHITE; - menu->width = 200; - menu->height = wimp_MENU_ITEM_HEIGHT; - menu->gap = wimp_MENU_ITEM_GAP; - for (i = 0; i != rufl_family_list_entries; i++) { - menu->entries[i].menu_flags = 0; - menu->entries[i].sub_menu = wimp_NO_SUB_MENU; - menu->entries[i].icon_flags = wimp_ICON_TEXT | - wimp_ICON_INDIRECTED | - (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | - (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); - menu->entries[i].data.indirected_text.text = - (char *) rufl_family_list[i]; - menu->entries[i].data.indirected_text.validation = (char *) -1; - menu->entries[i].data.indirected_text.size = - strlen(rufl_family_list[i]); - } - menu->entries[0].menu_flags = wimp_MENU_TITLE_INDIRECTED; - menu->entries[i - 1].menu_flags |= wimp_MENU_LAST; - - rufl_family_menu = menu; - - return rufl_OK; -} - - -/** - * Create and open the init status window. - */ - -void rufl_init_status_open(void) -{ - int xeig_factor, yeig_factor, xwind_limit, ywind_limit, width, height; - wimp_t task; - osbool window_task; - wimp_WINDOW(4) window = { { 0, 0, 0, 0 }, 0, 0, wimp_TOP, - wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_NEW_FORMAT, - wimp_COLOUR_BLACK, wimp_COLOUR_LIGHT_GREY, - wimp_COLOUR_BLACK, wimp_COLOUR_VERY_LIGHT_GREY, - wimp_COLOUR_DARK_GREY, wimp_COLOUR_LIGHT_GREY, - wimp_COLOUR_CREAM, 0, - { 0, -128, 800, 0 }, 0, 0, 0, 0, 0, { "" }, 4, - { { { 12, -56, 788, -12 }, wimp_ICON_TEXT | - wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | - wimp_ICON_INDIRECTED | - wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT | - wimp_COLOUR_VERY_LIGHT_GREY <errnum, error->errmess); - return; - } - if (!task) - return; /* not a Wimp task */ - - error = xtaskwindowtaskinfo_window_task(&window_task); - if (error) { - LOG("xtaskwindowtaskinfo_window_task: 0x%x: %s", - error->errnum, error->errmess); - return; - } - if (window_task) - return; /* in a TaskWindow */ - - xwimp_create_window((const wimp_window *) &window, &rufl_status_w); - state.w = rufl_status_w; - xwimp_get_window_state(&state); - xwimp_open_window((wimp_open *) (void *) &state); -} - - -/** - * Update the status window and multitask. - */ - -void rufl_init_status(const char *status, float progress) -{ - wimp_block block; - static os_t last_t = 0; - os_t t; - - if (!rufl_status_w) - return; - - if (status) { - strncpy(rufl_status_buffer, status, sizeof rufl_status_buffer); - rufl_status_buffer[sizeof rufl_status_buffer - 1] = 0; - xwimp_set_icon_state(rufl_status_w, 3, 0, 0); - } - if (progress) - xwimp_resize_icon(rufl_status_w, 2, 16, -112, - 16 + 768 * progress, -68); - xos_read_monotonic_time(&t); - if (last_t == t) - return; - xwimp_poll(wimp_QUEUE_REDRAW | wimp_MASK_LEAVING | wimp_MASK_ENTERING | - wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_MASK_MESSAGE | - wimp_MASK_RECORDED | wimp_MASK_ACKNOWLEDGE, - &block, 0, 0); - last_t = t; -} - - -/** - * Close and delete the status window. - */ - -void rufl_init_status_close(void) -{ - if (!rufl_status_w) - return; - - xwimp_delete_window(rufl_status_w); - rufl_status_w = 0; -} diff --git a/rufl_internal.h b/rufl_internal.h deleted file mode 100644 index 1c01e36..0000000 --- a/rufl_internal.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -#include -#include "oslib/font.h" -#include "rufl.h" -#ifdef __CC_NORCROFT -#include "strfuncs.h" -#endif - - -/** The available characters in a font. The range which can be represented is - * 0x0000 to 0xffff. The size of the structure is 4 + 256 + 32 * blocks. A - * typical * 200 glyph font might have characters in 10 blocks, giving 580 - * bytes. The maximum possible size of the structure is 8388 bytes. Note that - * since two index values are reserved, fonts with 65280-65024 glyphs may be - * unrepresentable, if there are no full blocks. This is unlikely. The primary - * aim of this structure is to make lookup fast. */ -struct rufl_character_set { - /** Size of structure / bytes. */ - size_t size; - - /** Index table. Each entry represents a block of 256 characters, so - * i[k] refers to characters [256*k, 256*(k+1)). The value is either - * BLOCK_EMPTY, BLOCK_FULL, or an offset into the block table. */ - unsigned char index[256]; - /** The block has no characters present. */ -# define BLOCK_EMPTY 254 - /** All characters in the block are present. */ -# define BLOCK_FULL 255 - - /** Block table. Each entry is a 256-bit bitmap indicating which - * characters in the block are present and absent. */ - unsigned char block[254][32]; -}; - - -/** Part of struct rufl_unicode_map. */ -struct rufl_unicode_map_entry { - /** Unicode value. */ - unsigned short u; - /** Corresponding character. */ - unsigned char c; -}; - - -/** Old font manager: mapping from Unicode to character code. This is simply - * an array sorted by Unicode value, suitable for bsearch(). If a font has - * support for multiple encodings, then it will have multiple unicode maps. - * The encoding field contains the name of the encoding to pass to the - * font manager. This will be NULL if the font is a Symbol font. */ -struct rufl_unicode_map { - /** Corresponding encoding name */ - char *encoding; - /** Number of valid entries in map. */ - unsigned int entries; - /** Map from Unicode to character code. */ - struct rufl_unicode_map_entry map[256]; -}; - - -/** An entry in rufl_font_list. */ -struct rufl_font_list_entry { - /** Font identifier (name). */ - char *identifier; - /** Character set of font. */ - struct rufl_character_set *charset; - /** Number of Unicode mapping tables */ - unsigned int num_umaps; - /** Mappings from Unicode to character code. */ - struct rufl_unicode_map *umap; - /** Family that this font belongs to (index in rufl_family_list and - * rufl_family_map). */ - unsigned int family; - /** Font weight (0 to 8). */ - unsigned int weight; - /** Font slant (0 or 1). */ - unsigned int slant; -}; -/** List of all available fonts. */ -extern struct rufl_font_list_entry *rufl_font_list; -/** Number of entries in rufl_font_list. */ -extern size_t rufl_font_list_entries; - - -/** An entry in rufl_family_map. */ -struct rufl_family_map_entry { - /** This style does not exist in this family. */ -# define NO_FONT UINT_MAX - /** Map from weight and slant to index in rufl_font_list, or NO_FONT. */ - unsigned int font[9][2]; -}; -/** Map from font family to fonts, rufl_family_list_entries entries. */ -extern struct rufl_family_map_entry *rufl_family_map; - - -/** No font contains this character. */ -#define NOT_AVAILABLE 65535 -/** Font substitution table. */ -extern unsigned short *rufl_substitution_table; - - -/** Number of slots in recent-use cache. This is the maximum number of RISC OS - * font handles that will be used at any time by the library. */ -#define rufl_CACHE_SIZE 10 - -/** An entry in rufl_cache. */ -struct rufl_cache_entry { - /** Font number (index in rufl_font_list), or rufl_CACHE_*. */ - unsigned int font; - /** No font cached in this slot. */ -#define rufl_CACHE_NONE UINT_MAX - /** Font for rendering hex substitutions in this slot. */ -#define rufl_CACHE_CORPUS (UINT_MAX - 1) - /** Font size. */ - unsigned int size; - /** Font encoding */ - const char *encoding; - /** Value of rufl_cache_time when last used. */ - unsigned int last_used; - /** RISC OS font handle. */ - font_f f; -}; -/** Cache of rufl_CACHE_SIZE most recently used font handles. */ -extern struct rufl_cache_entry rufl_cache[rufl_CACHE_SIZE]; -/** Counter for measuring age of cache entries. */ -extern int rufl_cache_time; - -/** Font manager does not support Unicode. */ -extern bool rufl_old_font_manager; - -/** Font manager supports background blending */ -extern bool rufl_can_background_blend; - -rufl_code rufl_find_font_family(const char *family, rufl_style font_style, - unsigned int *font, unsigned int *slanted, - struct rufl_character_set **charset); -rufl_code rufl_find_font(unsigned int font, unsigned int font_size, - const char *encoding, font_f *fhandle); -bool rufl_character_set_test(struct rufl_character_set *charset, - unsigned int c); - - -#define rufl_utf8_read(s, l, u) \ - if (4 <= l && ((s[0] & 0xf8) == 0xf0) && ((s[1] & 0xc0) == 0x80) && \ - ((s[2] & 0xc0) == 0x80) && ((s[3] & 0xc0) == 0x80)) { \ - u = ((s[0] & 0x7) << 18) | ((s[1] & 0x3f) << 12) | \ - ((s[2] & 0x3f) << 6) | (s[3] & 0x3f); \ - s += 4; l -= 4; \ - } else if (3 <= l && ((s[0] & 0xf0) == 0xe0) && \ - ((s[1] & 0xc0) == 0x80) && \ - ((s[2] & 0xc0) == 0x80)) { \ - u = ((s[0] & 0xf) << 12) | ((s[1] & 0x3f) << 6) | \ - (s[2] & 0x3f); \ - s += 3; l -= 3; \ - } else if (2 <= l && ((s[0] & 0xe0) == 0xc0) && \ - ((s[1] & 0xc0) == 0x80)) { \ - u = ((s[0] & 0x3f) << 6) | (s[1] & 0x3f); \ - s += 2; l -= 2; \ - } else if ((s[0] & 0x80) == 0) { \ - u = s[0]; \ - s++; l--; \ - } else { \ - u = 0xfffd; \ - s++; l--; \ - } - -#define rufl_CACHE ".RUfl_cache" -#define rufl_CACHE_VERSION 3 - - -struct rufl_glyph_map_entry { - const char *glyph_name; - unsigned short u; -}; - -extern const struct rufl_glyph_map_entry rufl_glyph_map[]; -extern const size_t rufl_glyph_map_size; - - -#ifndef NDEBUG -#ifdef __CC_NORCROFT -#define __PRETTY_FUNCTION__ __func__ -#endif -#define LOG(format, ...) (fprintf(stderr, __FILE__ " %s %i: ", \ - __PRETTY_FUNCTION__, __LINE__), fprintf(stderr, format, \ - __VA_ARGS__), fprintf(stderr, "\n")) -#else -#define LOG(format, ...) ((void) 0) -#endif diff --git a/rufl_invalidate_cache.c b/rufl_invalidate_cache.c deleted file mode 100644 index 65a3897..0000000 --- a/rufl_invalidate_cache.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2005 James Bursa - */ - -#include "oslib/font.h" -#include "rufl_internal.h" - - -/** - * Clear the internal font handle cache. - * - * Call this function on mode changes or output redirection changes. - */ - -void rufl_invalidate_cache(void) -{ - unsigned int i; - - for (i = 0; i != rufl_CACHE_SIZE; i++) { - if (rufl_cache[i].font != rufl_CACHE_NONE) { - xfont_lose_font(rufl_cache[i].f); - rufl_cache[i].font = rufl_CACHE_NONE; - } - } -} diff --git a/rufl_metrics.c b/rufl_metrics.c deleted file mode 100644 index af4727f..0000000 --- a/rufl_metrics.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2005 John-Mark Bell - */ - -#include -#include -#include - -#include "oslib/font.h" - -#include "rufl_internal.h" - -static int rufl_unicode_map_search_cmp(const void *keyval, const void *datum); - -/** - * Read a font's metrics (sized for a 1pt font) - */ -rufl_code rufl_font_metrics(const char *font_family, rufl_style font_style, - os_box *bbox, int *xkern, int *ykern, int *italic, - int *ascent, int *descent, - int *xheight, int *cap_height, - signed char *uline_position, unsigned char *uline_thickness) -{ - unsigned int font; - font_f f; - int misc_size; - font_metrics_misc_info *misc_info; - rufl_code code; - - code = rufl_find_font_family(font_family, font_style, &font, - NULL, NULL); - if (code != rufl_OK) - return code; - - code = rufl_find_font(font, 16 /* 1pt */, NULL, &f); - if (code != rufl_OK) - return code; - - rufl_fm_error = xfont_read_font_metrics(f, 0, 0, 0, 0, 0, - 0, 0, 0, 0, &misc_size, 0); - if (rufl_fm_error) { - LOG("xfont_read_font_metrics: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - - if (misc_size == 0) { - LOG("no miscellaneous information in metrics for %s", - rufl_font_list[font].identifier); - /** \todo better error code */ - return rufl_FONT_NOT_FOUND; - } - - misc_info = (font_metrics_misc_info *)malloc(misc_size); - if (!misc_info) - return rufl_OUT_OF_MEMORY; - - rufl_fm_error = xfont_read_font_metrics(f, 0, 0, 0, misc_info, 0, - 0, 0, 0, 0, 0, 0); - if (rufl_fm_error) { - LOG("xfont_read_font_metrics: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - free(misc_info); - return rufl_FONT_MANAGER_ERROR; - } - - /* and fill in output */ - if (bbox) { - bbox->x0 = misc_info->x0; - bbox->y0 = misc_info->y0; - bbox->x1 = misc_info->x1; - bbox->y1 = misc_info->y1; - } - - if (xkern) - (*xkern) = misc_info->xkern; - - if (ykern) - (*ykern) = misc_info->ykern; - - if (italic) - (*italic) = misc_info->italic_correction; - - if (ascent) - (*ascent) = misc_info->ascender; - - if (descent) - (*descent) = misc_info->descender; - - if (xheight) - (*xheight) = misc_info->xheight; - - if (cap_height) - (*cap_height) = misc_info->cap_height; - - if (uline_position) - (*uline_position) = misc_info->underline_position; - - if (uline_thickness) - (*uline_thickness) = misc_info->underline_thickness; - - free(misc_info); - - return rufl_OK; -} - -/** - * Read a glyph's metrics - */ -rufl_code rufl_glyph_metrics(const char *font_family, - rufl_style font_style, unsigned int font_size, - const char *string, size_t length, - int *x_bearing, int *y_bearing, - int *width, int *height, - int *x_advance, int *y_advance) -{ - const char *font_encoding = NULL; - unsigned int font, font1, u; - unsigned short u1[2]; - struct rufl_character_set *charset; - struct rufl_unicode_map_entry *umap_entry = NULL; - font_f f; - rufl_code code; - font_scan_block block; - font_string_flags flags; - int xa, ya; - - /* Find font family containing glyph */ - code = rufl_find_font_family(font_family, font_style, - &font, NULL, &charset); - if (code != rufl_OK) - return code; - - rufl_utf8_read(string, length, u); - if (charset && rufl_character_set_test(charset, u)) - font1 = font; - else if (u < 0x10000) - font1 = rufl_substitution_table[u]; - else - font1 = rufl_CACHE_CORPUS; - - /* Old font managers need the font encoding, too */ - if (rufl_old_font_manager && font1 != rufl_CACHE_CORPUS) { - unsigned int i; - unsigned short u16 = (unsigned short) u; - - for (i = 0; i < rufl_font_list[font1].num_umaps; i++) { - struct rufl_unicode_map *map = - rufl_font_list[font1].umap + i; - - umap_entry = bsearch(&u16, map->map, map->entries, - sizeof map->map[0], - rufl_unicode_map_search_cmp); - if (umap_entry) { - font_encoding = map->encoding; - break; - } - } - - assert(umap_entry != NULL); - } - - code = rufl_find_font(font1, font_size, font_encoding, &f); - if (code != rufl_OK) - return code; - - /* - * Glyph Metrics for horizontal text: - * - * ^ x0 x1 - * | Xbearing : x0 - oX - * | +-----+-------- y1 Ybearing : y1 - oY - * | | | Xadvance : aX - oX - * | | | Yadvance : 0 - * o---|-----|---a--> Glyph width : x1 - x0 - * | | | Glyph height : y1 - y0 - * | +-----+-------- y0 Right side bearing: aX - x1 - * | - * - * The rectangle (x0,y0),(x1,y1) is the glyph bounding box. - * - * Glyph Metrics for vertical text: - * - * -------o---------> - * y1--+--|--+ Xbearing : x0 - oX - * | | | Ybearing : oY - y1 - * | | | Xadvance : 0 - * | | | Yadvance : aY - oY - * | | | Glyph width : x1 - x0 - * y0--+-----+ Glyph height : y1 - y0 - * ------a----------- Right side bearing: N/A - * x0 v x1 - * - * The rectangle (x0,y0),(x1,y1) is the glyph bounding box. - * - * - * In order to extract the information we want from the - * Font Manager, a little bit of hackery is required. - * - * Firstly, we can take the origin as being (0,0). This is an - * arbitrary choice but makes the maths simpler. - * - * Secondly, the bounding box returned by Font_CharBBox / - * Font_ScanString / Font_StringBBox represents the ink area of - * the glyph (i.e. the smallest box needed to contain all the - * glyph path segments). This means that, for glyphs with no - * displayed content (such as a space), the bounding box will be 0. - * These SWIs therefore allow us to retrieve the (x0,y0),(x1,y1) - * coordinates marked in the diagrams above. - * - * Finally, we need to retrieve the glyph advance distance. This is - * returned in R3/R4 on exit from Font_ScanString (providing bit 17 - * of the flags word on entry is clear). It is important to note, - * however, that the height will be returned as 0 for fonts with no - * Yadvance values in the font data file. Therefore, in order to - * achieve vertical layout of text, further work will be needed - * (We're also ignoring the fact that the X coordinates of all - * values will be in the wrong place and the Y coordinates will have - * the wrong sign due to the differing definitions of the Y axis for - * horizontal and vertical text.) - * - * Note that all values (that we're interested in, at least) - * returned by the SWIs mentioned above are in _millipoints_. - */ - - block.space.x = block.space.y = 0; - block.letter.x = block.letter.y = 0; - block.split_char = -1; - - flags = font_GIVEN_BLOCK | font_GIVEN_LENGTH | font_GIVEN_FONT | - font_RETURN_BBOX; - - u1[0] = (unsigned short)u; - u1[1] = 0; - - if (font1 == rufl_CACHE_CORPUS) { - /* Fallback Glyph */ - /** \todo implement this properly */ - xa = 1000 * font_size; - ya = 0; - block.bbox.x0 = block.bbox.y0 = 0; - block.bbox.x1 = block.bbox.y1 = xa; - } else if (rufl_old_font_manager) { - /* Old Font Manager */ - char s[2]; - - /* We found the correct umap entry when - * looking for the font encoding */ - s[0] = umap_entry->c; - s[1] = 0; - - rufl_fm_error = xfont_scan_string(f, s, flags, - 0x7fffffff, 0x7fffffff, &block, 0, 1, - 0, &xa, &ya, 0); - if (rufl_fm_error) { - LOG("xfont_scan_string: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - } else { - /* UCS Font Manager */ - rufl_fm_error = xfont_scan_string(f, (const char *)u1, - flags | font_GIVEN16_BIT, - 0x7fffffff, 0x7fffffff, &block, 0, 2, - 0, &xa, &ya, 0); - if (rufl_fm_error) { - LOG("xfont_scan_string: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - } - - /** \todo handle vertical text */ - if (x_bearing) - (*x_bearing) = block.bbox.x0; - - if (y_bearing) - (*y_bearing) = block.bbox.y1; - - if (width) - (*width) = block.bbox.x1 - block.bbox.x0; - - if (height) - (*height) = block.bbox.y1 - block.bbox.y0; - - if (x_advance) - (*x_advance) = xa; - - if (y_advance) - (*y_advance) = ya; - - return rufl_OK; -} - - -int rufl_unicode_map_search_cmp(const void *keyval, const void *datum) -{ - const unsigned short *key = keyval; - const struct rufl_unicode_map_entry *entry = datum; - if (*key < entry->u) - return -1; - else if (entry->u < *key) - return 1; - return 0; -} diff --git a/rufl_paint.c b/rufl_paint.c deleted file mode 100644 index 084fea5..0000000 --- a/rufl_paint.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -#include -#include -#include -#include -#include -#include "oslib/font.h" -#include "rufl_internal.h" - - -typedef enum { rufl_PAINT, rufl_WIDTH, rufl_X_TO_OFFSET, - rufl_SPLIT, rufl_PAINT_CALLBACK, rufl_FONT_BBOX } rufl_action; -#define rufl_PROCESS_CHUNK 200 - -bool rufl_can_background_blend = false; - -static const os_trfm trfm_oblique = - { { { 65536, 0 }, { 13930, 65536 }, { 0, 0 } } }; - - -static rufl_code rufl_process(rufl_action action, - const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string0, size_t length, - int x, int y, unsigned int flags, - int *width, int click_x, size_t *char_offset, int *actual_x, - rufl_callback_t callback, void *context); -static rufl_code rufl_process_span(rufl_action action, - unsigned short *s, unsigned int n, - unsigned int font, unsigned int font_size, unsigned int slant, - int *x, int y, unsigned int flags, - int click_x, size_t *offset, - rufl_callback_t callback, void *context); -static rufl_code rufl_process_span_old(rufl_action action, - unsigned short *s, unsigned int n, - unsigned int font, unsigned int font_size, unsigned int slant, - int *x, int y, unsigned int flags, - int click_x, size_t *offset, - rufl_callback_t callback, void *context); -static int rufl_unicode_map_search_cmp(const void *keyval, const void *datum); -static rufl_code rufl_process_not_available(rufl_action action, - unsigned short *s, unsigned int n, - unsigned int font_size, int *x, int y, - unsigned int flags, - int click_x, size_t *offset, - rufl_callback_t callback, void *context); - - -/** - * Render Unicode text. - */ - -rufl_code rufl_paint(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int x, int y, unsigned int flags) -{ - return rufl_process(rufl_PAINT, - font_family, font_style, font_size, string, - length, x, y, flags, 0, 0, 0, 0, 0, 0); -} - - -/** - * Measure the width of Unicode text. - */ - -rufl_code rufl_width(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int *width) -{ - return rufl_process(rufl_WIDTH, - font_family, font_style, font_size, string, - length, 0, 0, 0, width, 0, 0, 0, 0, 0); -} - - -/** - * Find the nearest character boundary in a string to where an x coordinate - * falls. - */ - -rufl_code rufl_x_to_offset(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int click_x, - size_t *char_offset, int *actual_x) -{ - return rufl_process(rufl_X_TO_OFFSET, - font_family, font_style, font_size, string, - length, 0, 0, 0, 0, - click_x, char_offset, actual_x, 0, 0); -} - - -/** - * Find the prefix of a string that will fit in a specified width. - */ - -rufl_code rufl_split(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int width, - size_t *char_offset, int *actual_x) -{ - return rufl_process(rufl_SPLIT, - font_family, font_style, font_size, string, - length, 0, 0, 0, 0, - width, char_offset, actual_x, 0, 0); -} - - -/** - * Render text, but call a callback instead of each call to Font_Paint. - */ - -rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int x, int y, - rufl_callback_t callback, void *context) -{ - return rufl_process(rufl_PAINT_CALLBACK, - font_family, font_style, font_size, string, - length, x, y, 0, 0, 0, 0, 0, callback, context); -} - - -/** - * Determine the maximum bounding box of a font. - */ - -rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, - unsigned int font_size, - int *bbox) -{ - return rufl_process(rufl_FONT_BBOX, - font_family, font_style, font_size, 0, - 0, 0, 0, 0, bbox, 0, 0, 0, 0, 0); -} - - -/** - * Render, measure, or split Unicode text. - */ - -rufl_code rufl_process(rufl_action action, - const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string0, size_t length, - int x, int y, unsigned int flags, - int *width, int click_x, size_t *char_offset, int *actual_x, - rufl_callback_t callback, void *context) -{ - unsigned short s[rufl_PROCESS_CHUNK]; - unsigned int font; - unsigned int font0, font1; - unsigned int n; - unsigned int u; - size_t offset; - size_t offset_u; - size_t offset_map[rufl_PROCESS_CHUNK]; - unsigned int slant; - const char *string = string0; - struct rufl_character_set *charset; - rufl_code code; - - assert(action == rufl_PAINT || - (action == rufl_WIDTH && width) || - (action == rufl_X_TO_OFFSET && char_offset && - actual_x) || - (action == rufl_SPLIT && char_offset && - actual_x) || - (action == rufl_PAINT_CALLBACK && callback) || - (action == rufl_FONT_BBOX && width)); - - if ((flags & rufl_BLEND_FONT) && !rufl_can_background_blend) { - /* unsuitable FM => clear blending bit */ - flags &= ~rufl_BLEND_FONT; - } - - if (length == 0 && action != rufl_FONT_BBOX) { - if (action == rufl_WIDTH) - *width = 0; - else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { - *char_offset = 0; - *actual_x = 0; - } - return rufl_OK; - } - if ((action == rufl_X_TO_OFFSET || action == rufl_SPLIT) && - click_x <= 0) { - *char_offset = 0; - *actual_x = 0; - return rufl_OK; - } - - code = rufl_find_font_family(font_family, font_style, - &font, &slant, &charset); - if (code != rufl_OK) - return code; - - if (action == rufl_FONT_BBOX) { - if (rufl_old_font_manager) - code = rufl_process_span_old(action, 0, 0, font, - font_size, slant, width, 0, 0, - 0, 0, 0, 0); - else - code = rufl_process_span(action, 0, 0, font, - font_size, slant, width, 0, 0, - 0, 0, 0, 0); - return code; - } - - offset_u = 0; - rufl_utf8_read(string, length, u); - if (u <= 0x001f || (0x007f <= u && u <= 0x009f)) - font1 = NOT_AVAILABLE; - else if (charset && rufl_character_set_test(charset, u)) - font1 = font; - else if (u < 0x10000) - font1 = rufl_substitution_table[u]; - else - font1 = NOT_AVAILABLE; - do { - s[0] = u; - offset_map[0] = offset_u; - n = 1; - font0 = font1; - /* invariant: s[0..n) is in font font0 */ - while (0 < length && n < rufl_PROCESS_CHUNK && font1 == font0) { - offset_u = string - string0; - rufl_utf8_read(string, length, u); - s[n] = u; - offset_map[n] = offset_u; - if (u <= 0x001f || (0x007f <= u && u <= 0x009f)) - font1 = NOT_AVAILABLE; - else if (charset && rufl_character_set_test(charset, u)) - font1 = font; - else if (u < 0x10000) - font1 = rufl_substitution_table[u]; - else - font1 = NOT_AVAILABLE; - if (font1 == font0) - n++; - } - if (n == rufl_PROCESS_CHUNK) - n--; - s[n] = 0; - offset_map[n] = offset_u; - if (length == 0 && font1 == font0) - offset_map[n] = string - string0; - - if (font0 == NOT_AVAILABLE) - code = rufl_process_not_available(action, s, n, - font_size, &x, y, flags, - click_x, &offset, callback, context); - else if (rufl_old_font_manager) - code = rufl_process_span_old(action, s, n, font0, - font_size, slant, &x, y, flags, - click_x, &offset, callback, context); - else - code = rufl_process_span(action, s, n, font0, - font_size, slant, &x, y, flags, - click_x, &offset, callback, context); - - if ((action == rufl_X_TO_OFFSET || action == rufl_SPLIT) && - (offset < n || click_x < x)) - break; - if (code != rufl_OK) - return code; - - } while (!(length == 0 && font1 == font0)); - - if (action == rufl_WIDTH) - *width = x; - else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { - *char_offset = offset_map[offset]; - *actual_x = x; - } - - return rufl_OK; -} - - -/** - * Render a string of characters from a single RISC OS font. - */ - -rufl_code rufl_process_span(rufl_action action, - unsigned short *s, unsigned int n, - unsigned int font, unsigned int font_size, unsigned int slant, - int *x, int y, unsigned int flags, - int click_x, size_t *offset, - rufl_callback_t callback, void *context) -{ - unsigned short *split_point; - int x_out, y_out; - unsigned int i; - char font_name[80]; - bool oblique = slant && !rufl_font_list[font].slant; - font_f f; - rufl_code code; - - code = rufl_find_font(font, font_size, "UTF8", &f); - if (code != rufl_OK) - return code; - - if (action == rufl_FONT_BBOX) { - rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]); - if (rufl_fm_error) - return rufl_FONT_MANAGER_ERROR; - return rufl_OK; - } - - if (action == rufl_PAINT) { - /* paint span */ - rufl_fm_error = xfont_paint(f, (const char *) s, - font_OS_UNITS | - (oblique ? font_GIVEN_TRFM : 0) | - font_GIVEN_LENGTH | - font_GIVEN_FONT | font_KERN | - font_GIVEN16_BIT | - ((flags & rufl_BLEND_FONT) ? - font_BLEND_FONT : 0), - *x, y, 0, &trfm_oblique, n * 2); - if (rufl_fm_error) { - LOG("xfont_paint: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - for (i = 0; i != n; i++) - fprintf(stderr, "0x%x ", s[i]); - fprintf(stderr, " (%u)\n", n); - return rufl_FONT_MANAGER_ERROR; - } - } else if (action == rufl_PAINT_CALLBACK) { - snprintf(font_name, sizeof font_name, "%s\\EUTF8", - rufl_font_list[font].identifier); - callback(context, font_name, font_size, 0, s, n, *x, y); - } - - /* increment x by width of span */ - if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { - rufl_fm_error = xfont_scan_string(f, (const char *) s, - font_GIVEN_LENGTH | font_GIVEN_FONT | - font_KERN | font_GIVEN16_BIT | - ((action == rufl_X_TO_OFFSET) ? - font_RETURN_CARET_POS : 0), - (click_x - *x) * 400, 0x7fffffff, 0, 0, - n * 2, - (char **)(void *)&split_point, - &x_out, &y_out, 0); - *offset = split_point - s; - } else { - rufl_fm_error = xfont_scan_string(f, (const char *) s, - font_GIVEN_LENGTH | font_GIVEN_FONT | - font_KERN | font_GIVEN16_BIT, - 0x7fffffff, 0x7fffffff, 0, 0, n * 2, - 0, &x_out, &y_out, 0); - } - if (rufl_fm_error) { - LOG("xfont_scan_string: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - *x += x_out / 400; - - return rufl_OK; -} - - -/** - * Render a string of characters from a single RISC OS font (old font manager - * version). - */ - -rufl_code rufl_process_span_old(rufl_action action, - unsigned short *s, unsigned int n, - unsigned int font, unsigned int font_size, unsigned int slant, - int *x, int y, unsigned int flags, - int click_x, size_t *offset, - rufl_callback_t callback, void *context) -{ - char s2[rufl_PROCESS_CHUNK]; - char *split_point; - int x_out, y_out; - unsigned int i; - bool oblique = slant && !rufl_font_list[font].slant; - font_f f; - rufl_code code; - - if (action == rufl_FONT_BBOX) { - /* Don't need encoding for bounding box */ - code = rufl_find_font(font, font_size, NULL, &f); - if (code != rufl_OK) - return code; - - rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]); - if (rufl_fm_error) { - LOG("xfont_read_info: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - return rufl_OK; - } - - if (offset) - *offset = 0; - - /* Process the span in map-coherent chunks */ - do { - struct rufl_unicode_map *map; - struct rufl_unicode_map_entry *entry = NULL; - unsigned int j; - - i = 0; - - /* Find map for first character */ - for (j = 0; j < rufl_font_list[font].num_umaps; j++) { - map = rufl_font_list[font].umap + j; - - entry = bsearch(&s[i], map->map, map->entries, - sizeof map->map[0], - rufl_unicode_map_search_cmp); - if (entry) - break; - } - assert(map != NULL); - assert(entry != NULL); - - /* Collect characters: s[0..i) use map */ - do { - entry = bsearch(&s[i], map->map, map->entries, - sizeof map->map[0], - rufl_unicode_map_search_cmp); - - if (entry) - s2[i++] = entry->c; - } while (i != n && entry != NULL); - - s2[i] = 0; - - code = rufl_find_font(font, font_size, map->encoding, &f); - if (code != rufl_OK) - return code; - - if (action == rufl_PAINT) { - /* paint span */ - /* call Font_SetFont to work around broken PS printer - * driver, which doesn't use the font handle from - * Font_Paint */ - rufl_fm_error = xfont_set_font(f); - if (rufl_fm_error) { - LOG("xfont_set_font: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - - rufl_fm_error = xfont_paint(f, s2, font_OS_UNITS | - (oblique ? font_GIVEN_TRFM : 0) | - font_GIVEN_LENGTH | font_GIVEN_FONT | - font_KERN | - ((flags & rufl_BLEND_FONT) ? - font_BLEND_FONT : 0), - *x, y, 0, &trfm_oblique, i); - if (rufl_fm_error) { - LOG("xfont_paint: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - } else if (action == rufl_PAINT_CALLBACK) { - char font_name[80]; - - if (map->encoding) - snprintf(font_name, sizeof font_name, "%s\\E%s", - rufl_font_list[font].identifier, - map->encoding); - else - snprintf(font_name, sizeof font_name, "%s", - rufl_font_list[font].identifier); - - callback(context, font_name, font_size, - s2, 0, i, *x, y); - } - - /* increment x by width of span */ - if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { - rufl_fm_error = xfont_scan_string(f, s2, - font_GIVEN_LENGTH | font_GIVEN_FONT | - font_KERN | - ((action == rufl_X_TO_OFFSET) ? - font_RETURN_CARET_POS : 0), - (click_x - *x) * 400, 0x7fffffff, - 0, 0, i, - &split_point, &x_out, &y_out, 0); - *offset += split_point - s2; - } else { - rufl_fm_error = xfont_scan_string(f, s2, - font_GIVEN_LENGTH | font_GIVEN_FONT | - font_KERN, - 0x7fffffff, 0x7fffffff, 0, 0, i, - 0, &x_out, &y_out, 0); - } - if (rufl_fm_error) { - LOG("xfont_scan_string: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess); - return rufl_FONT_MANAGER_ERROR; - } - *x += x_out / 400; - - /* Now update s and n for the next chunk */ - s += i; - n -= i; - } while (n != 0); - - return rufl_OK; -} - - -int rufl_unicode_map_search_cmp(const void *keyval, const void *datum) -{ - const unsigned short *key = keyval; - const struct rufl_unicode_map_entry *entry = datum; - if (*key < entry->u) - return -1; - else if (entry->u < *key) - return 1; - return 0; -} - - -/** - * Render a string of characters not available in any font as their hex code. - */ - -rufl_code rufl_process_not_available(rufl_action action, - unsigned short *s, unsigned int n, - unsigned int font_size, int *x, int y, - unsigned int flags, - int click_x, size_t *offset, - rufl_callback_t callback, void *context) -{ - char missing[] = "0000"; - int dx = 7 * font_size / 64; - int top_y = y + 5 * font_size / 64; - unsigned int i; - font_f f; - rufl_code code; - - if (action == rufl_WIDTH) { - *x += n * dx; - return rufl_OK; - } else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { - if (click_x - *x < (int) (n * dx)) - *offset = (click_x - *x) / dx; - else - *offset = n; - *x += *offset * dx; - return rufl_OK; - } - - code = rufl_find_font(rufl_CACHE_CORPUS, font_size / 2, "Latin1", &f); - if (code != rufl_OK) - return code; - - for (i = 0; i != n; i++) { - missing[0] = "0123456789abcdef"[(s[i] >> 12) & 0xf]; - missing[1] = "0123456789abcdef"[(s[i] >> 8) & 0xf]; - missing[2] = "0123456789abcdef"[(s[i] >> 4) & 0xf]; - missing[3] = "0123456789abcdef"[(s[i] >> 0) & 0xf]; - - /* first two characters in top row */ - if (action == rufl_PAINT) { - rufl_fm_error = xfont_paint(f, missing, font_OS_UNITS | - font_GIVEN_LENGTH | font_GIVEN_FONT | - font_KERN | - ((flags & rufl_BLEND_FONT) ? - font_BLEND_FONT : 0), - *x, top_y, 0, 0, 2); - if (rufl_fm_error) - return rufl_FONT_MANAGER_ERROR; - } else { - callback(context, "Corpus.Medium\\ELatin1", - font_size / 2, missing, 0, 2, - *x, top_y); - } - - /* last two characters underneath */ - if (action == rufl_PAINT) { - rufl_fm_error = xfont_paint(f, missing + 2, - font_OS_UNITS | - font_GIVEN_LENGTH | font_GIVEN_FONT | - font_KERN | - ((flags & rufl_BLEND_FONT) ? - font_BLEND_FONT : 0), - *x, y, 0, 0, 2); - if (rufl_fm_error) - return rufl_FONT_MANAGER_ERROR; - } else { - callback(context, "Corpus.Medium\\ELatin1", - font_size / 2, missing + 2, 0, 2, - *x, y); - } - - *x += dx; - } - - return rufl_OK; -} diff --git a/rufl_quit.c b/rufl_quit.c deleted file mode 100644 index fc429c0..0000000 --- a/rufl_quit.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -#include -#include "oslib/font.h" -#include "rufl_internal.h" - - -/** - * Free all resources used by the library. - */ - -void rufl_quit(void) -{ - unsigned int i; - - if (!rufl_font_list) - return; - - for (i = 0; i != rufl_font_list_entries; i++) { - free(rufl_font_list[i].identifier); - free(rufl_font_list[i].charset); - } - free(rufl_font_list); - rufl_font_list = 0; - - for (i = 0; i != rufl_family_list_entries; i++) - free((void *) rufl_family_list[i]); - free(rufl_family_list); - free(rufl_family_map); - rufl_family_list = 0; - - for (i = 0; i != rufl_CACHE_SIZE; i++) { - if (rufl_cache[i].font != rufl_CACHE_NONE) { - xfont_lose_font(rufl_cache[i].f); - rufl_cache[i].font = rufl_CACHE_NONE; - } - } - - free(rufl_family_menu); - rufl_family_menu = 0; - - free(rufl_substitution_table); - rufl_substitution_table = 0; -} diff --git a/rufl_test.c b/rufl_test.c deleted file mode 100644 index f07a9b7..0000000 --- a/rufl_test.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -#include -#include -#include -#include "rufl.h" - - -static void try(rufl_code code, const char *context); -static int move_to(os_coord *to, void *user); -static int line_to(os_coord *to, void *user); -static int cubic_to(os_coord *control1, os_coord *control2, os_coord *to, - void *user); -static void callback(void *context, - const char *font_name, unsigned int font_size, - const char *s8, unsigned short *s16, unsigned int n, - int x, int y); - - -int main(void) -{ - char utf8_test[] = "Hello, world! ὕαλον " - "Uherské Hradiště. 𐀀"; - int width; - size_t char_offset; - int x; - int actual_x; - struct rufl_decomp_funcs funcs = { move_to, line_to, cubic_to }; - int bbox[4]; - - try(rufl_init(), "rufl_init"); - rufl_dump_state(); - try(rufl_paint("NewHall", rufl_WEIGHT_400, 240, - utf8_test, sizeof utf8_test - 1, - 1200, 1000, 0), "rufl_paint"); - try(rufl_width("NewHall", rufl_WEIGHT_400, 240, - utf8_test, sizeof utf8_test - 1, - &width), "rufl_width"); - printf("width: %i\n", width); - for (x = 0; x < width + 100; x += 100) { - try(rufl_x_to_offset("NewHall", rufl_WEIGHT_400, 240, - utf8_test, sizeof utf8_test - 1, - x, &char_offset, &actual_x), - "rufl_x_to_offset"); - printf("x to offset: %i -> %i %zi \"%s\"\n", x, actual_x, - char_offset, utf8_test + char_offset); - try(rufl_split("NewHall", rufl_WEIGHT_400, 240, - utf8_test, sizeof utf8_test - 1, - x, &char_offset, &actual_x), - "rufl_split"); - printf("split: %i -> %i %zi \"%s\"\n", x, actual_x, - char_offset, utf8_test + char_offset); - } - try(rufl_decompose_glyph("Homerton", rufl_WEIGHT_400, 1280, - "A", 1, &funcs, 0), - "rufl_decompose_glyph"); - try(rufl_paint_callback("NewHall", rufl_WEIGHT_400, 240, - utf8_test, sizeof utf8_test - 1, - 1200, 1000, callback, 0), "rufl_paint_callback"); - try(rufl_font_bbox("NewHall", rufl_WEIGHT_400, 240, bbox), - "rufl_font_bbox"); - printf("bbox: %i %i %i %i\n", bbox[0], bbox[1], bbox[2], bbox[3]); - rufl_quit(); - - return 0; -} - - -void try(rufl_code code, const char *context) -{ - if (code == rufl_OK) - return; - else if (code == rufl_OUT_OF_MEMORY) - printf("error: %s: out of memory\n", context); - else if (code == rufl_FONT_MANAGER_ERROR) - printf("error: %s: Font Manager error %x %s\n", context, - rufl_fm_error->errnum, - rufl_fm_error->errmess); - else if (code == rufl_FONT_NOT_FOUND) - printf("error: %s: font not found\n", context); - else if (code == rufl_IO_ERROR) - printf("error: %s: io error: %i %s\n", context, errno, - strerror(errno)); - else if (code == rufl_IO_EOF) - printf("error: %s: eof\n", context); - else - printf("error: %s: unknown error\n", context); - rufl_quit(); - exit(1); -} - - -int move_to(os_coord *to, void *user) -{ - printf("Move to (%d,%d)\n", to->x, to->y); - - return 0; -} - - -int line_to(os_coord *to, void *user) -{ - printf("Line to (%d,%d)\n", to->x, to->y); - - return 0; -} - - -int cubic_to(os_coord *control1, os_coord *control2, os_coord *to, - void *user) -{ - printf("Bezier to (%d,%d),(%d,%d),(%d,%d)\n", - control1->x, control1->y, - control2->x, control2->y, - to->x, to->y); - - return 0; -} - - -void callback(void *context, - const char *font_name, unsigned int font_size, - const char *s8, unsigned short *s16, unsigned int n, - int x, int y) -{ - printf("callback: \"%s\", %u, ", font_name, font_size); - if (s8) - printf("s8 \"%.*s\" ", n, s8); - else { - printf("s16 \""); - for (unsigned int i = 0; i != n; i++) - printf("%x ", (unsigned int) s16[i]); - printf("\" "); - } - printf("%i %i\n", x, y); -} diff --git a/ruflmodule.c b/ruflmodule.c deleted file mode 100644 index b62a883..0000000 --- a/ruflmodule.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * This file is part of RUfl - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license - * Copyright 2006 James Bursa - */ - -/* Python module for RUfl. */ - -#include "Python.h" -#include "rufl.h" - - -static char pyrufl_paint__doc__[] = -"paint(font_family, font_style, font_size, string, x, y, flags)\n\n" -"Render Unicode text." -; - -static PyObject * -pyrufl_paint(PyObject *self /* Not used */, PyObject *args) -{ - const char *font_family; - rufl_style font_style; - unsigned int font_size; - const char *string; - int length; - int x; - int y; - unsigned int flags; - - if (!PyArg_ParseTuple(args, "siIs#iiI", - &font_family, &font_style, &font_size, - &string, &length, &x, &y, &flags)) - return NULL; - - rufl_paint(font_family, font_style, font_size, string, length, - x, y, flags); - - Py_INCREF(Py_None); - return Py_None; -} - - -static char pyrufl_width__doc__[] = -"width(font_family, font_style, font_size, string)\n\n" -"Return the width of Unicode text." -; - -static PyObject * -pyrufl_width(PyObject *self /* Not used */, PyObject *args) -{ - const char *font_family; - rufl_style font_style; - unsigned int font_size; - const char *string; - int length; - int width = 0; - - if (!PyArg_ParseTuple(args, "siIs#", - &font_family, &font_style, &font_size, - &string, &length)) - return NULL; - - rufl_width(font_family, font_style, font_size, string, length, - &width); - - return PyInt_FromLong(width); -} - - -static char pyrufl_x_to_offset__doc__[] = -"x_to_offset(font_family, font_style, font_size, string, click_x)\n\n" -"Return a pair of the character offset in string that click_x falls,\n" -"and the actual x coordinate for that character offset." -; - -static PyObject * -pyrufl_x_to_offset(PyObject *self /* Not used */, PyObject *args) -{ - const char *font_family; - rufl_style font_style; - unsigned int font_size; - const char *string; - int length; - int click_x; - size_t char_offset = 0; - int actual_x = 0; - - if (!PyArg_ParseTuple(args, "siIs#i", - &font_family, &font_style, &font_size, - &string, &length, &click_x)) - return NULL; - - rufl_x_to_offset(font_family, font_style, font_size, string, length, - click_x, - &char_offset, &actual_x); - - return Py_BuildValue("ii", (int) char_offset, actual_x); -} - - -static char pyrufl_split__doc__[] = -"split(font_family, font_style, font_size, string, width)\n\n" -"Return a pair of the character offset in string that fits in width,\n" -"and the actual x coordinate for that character offset." -; - -static PyObject * -pyrufl_split(PyObject *self /* Not used */, PyObject *args) -{ - const char *font_family; - rufl_style font_style; - unsigned int font_size; - const char *string; - int length; - int width; - size_t char_offset = 0; - int actual_x = 0; - - if (!PyArg_ParseTuple(args, "siIs#i", - &font_family, &font_style, &font_size, - &string, &length, &width)) - return NULL; - - rufl_split(font_family, font_style, font_size, string, length, - width, - &char_offset, &actual_x); - - return Py_BuildValue("ii", (int) char_offset, actual_x); -} - - -static char pyrufl_invalidate_cache__doc__[] = -"invalidate_cache()\n\n" -"Clear the internal font handle cache.\n" -"Call this function on mode changes or output redirection changes." -; - -static PyObject * -pyrufl_invalidate_cache(PyObject *self /* Not used */, PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) - return NULL; - - rufl_invalidate_cache(); - - Py_INCREF(Py_None); - return Py_None; -} - - -/* List of methods defined in the module */ - -static struct PyMethodDef pyrufl_methods[] = { - {"paint", (PyCFunction)pyrufl_paint, METH_VARARGS, pyrufl_paint__doc__}, - {"width", (PyCFunction)pyrufl_width, METH_VARARGS, pyrufl_width__doc__}, - {"x_to_offset", (PyCFunction)pyrufl_x_to_offset, METH_VARARGS, - pyrufl_x_to_offset__doc__}, - {"split", (PyCFunction)pyrufl_split, METH_VARARGS, pyrufl_split__doc__}, - {"invalidate_cache", (PyCFunction)pyrufl_invalidate_cache, METH_VARARGS, - pyrufl_invalidate_cache__doc__}, - - {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ -}; - - -/* Initialization function for the module (*must* be called initrufl) */ - -static char pyrufl_module_documentation[] = -"This module provides access to the RISC OS Unicode font library\n" -"All string parameters must be in UTF-8." -; - -void -initrufl(void) -{ - PyObject *module; - rufl_code code; - - code = rufl_init(); - if (code != rufl_OK) - Py_FatalError("rufl_init() failed"); - - Py_AtExit(rufl_quit); - - /* Create the module and add the functions */ - module = Py_InitModule4("rufl", pyrufl_methods, - pyrufl_module_documentation, - (PyObject *) NULL, PYTHON_API_VERSION); - - /* Add some symbolic constants to the module */ - PyModule_AddIntConstant(module, "regular", rufl_REGULAR); - PyModule_AddIntConstant(module, "slanted", rufl_SLANTED); - PyModule_AddIntConstant(module, "bold", rufl_BOLD); - PyModule_AddIntConstant(module, "bold_slanted", rufl_BOLD_SLANTED); - - PyModule_AddIntConstant(module, "blend", rufl_BLEND_FONT); - - /* Check for errors */ - if (PyErr_Occurred()) - Py_FatalError("can't initialize module rufl"); -} - diff --git a/src/Glyphs b/src/Glyphs new file mode 100644 index 0000000..d39fa0a --- /dev/null +++ b/src/Glyphs @@ -0,0 +1,1406 @@ +# +# Name: Adobe Glyph List +# Table version: 1.2 +# Date: 22 Oct 1998 +# +# Description: +# +# The Adobe Glyph List (AGL) list relates Unicode values (UVs) to glyph +# names, and should be used only as described in the document "Unicode and +# Glyph Names," at +# http://www.adobe.com/supportservice/devrelations/typeforum/unicodegn.html . +# +# The glyph name to UV relation is one to many. 12 glyph names are mapped to +# two UVs each; each UV has a separate entry. All other glyph names are +# mapped to one UV each. +# +# The Unicode Standard version 2.1 is used for all UVs outside of the Private +# Use area, except for 4 entries (see Revision History for 1.2 below). +# +# There are 1051 entries in this list, 171 of which are in the Corporate Use +# subarea (CUS). Refer to the document "Unicode Corporate Use Subarea as used +# by Adobe Systems," at +# http://www.adobe.com/supportservice/devrelations/typeforum/corporateuse.txt +# for compatibility decompositions for these characters, and to the document +# "Unicode and Glyph Names" for more information the CUS. +# +# Format: Semicolon-delimited fields: +# +# (1) Standard UV or CUS UV. (4 uppercase hexadecimal digits) +# +# (2) Glyph name. (upper- and lowercase letters, digits) +# +# (3) Character names: Unicode character names for standard UVs, and +# descriptive names for CUS UVs. (uppercase letters, hyphen, space) +# +# (4) [optional] Comment. A comment of "Duplicate" indicates one of two +# UVs of a double-mapping. It is the UV that may be given a uni +# override, or the UV that is in the CUS, as described in the document +# "Unicode and Glyph Names." +# +# The entries are sorted by glyph name in increasing ASCII order; entries +# with the same glyph name are sorted in decreasing priority order. +# +# Lines starting with "#" are comments; blank lines should be ignored. +# +# Revision History: +# +# 1.2 [22 Oct 1998] +# +# Some Central European glyph names were remapped and the glyph "dotlessj" +# was added. Some entries in the table below have not changed but are +# included to provide a complete context for other glyphs that have been +# remapped or double-mapped. "-" means that the entry for that UV does not +# exist in the AGL. +# +# -------- ---------------------- ---------------- -------------- +# UV Character name AGL 1.1 AGL 1.2 +# (shortened) glyph name glyph name +# -------- ---------------------- ---------------- -------------- +# 015E/F S/s with cedilla S/scommaaccent S/scedilla +# 0162/3 T/t with cedilla T/tcommaaccent T/tcommaaccent +# 0218/9 S/s with comma below - S/scommaaccent +# 021A/B T/t with comma below - T/tcommaaccent +# 1E9E/F S/s with comma below S/scedilla - +# F6C1/2 S/s with cedilla S/scedilla S/scedilla +# F6BE dotless j - dotlessj +# -------- ---------------------- ---------------- -------------- +# +# The characters at U+1E9E/F in AGL 1.1, LATIN CAPITAL/SMALL LETTER S WITH +# COMMA BELOW, which are proposed new characters (see (b) in the notes for +# AGL 1.1 below), have since been reassigned by the Unicode Standard to new +# proposed values of U+0218/9. These characters, as well as U+021A/B, LATIN +# CAPITAL/SMALL LETTER T WITH COMMA BELOW, are not in the Unicode Standard +# 2.1. +# +# Entries with the same glyph name are now sorted in decreasing priority +# order instead of in increasing UV order. +# +# 1.1 [24 Nov 1997] +# +# a. The "Euro" glyph's UV assignment is changed from U+20A0 (EURO-CURRENCY +# SIGN) to U+20AC (EURO SIGN). While U+20AC is not defined in the +# Unicode Standard 2.0, it has been accepted by the Unicode Technical +# Committee for the next version of the Standard; it has not yet passed +# the ISO approval process as of 7 November '97. +# +# b. Glyphs "Scedilla" and "scedilla", which were assigned in the Corporate +# Use Subarea in AGL 1.0, are now additionally mapped to U+1E9E and +# U+1E9F respectively. These two UVs share the same Unicode approval +# status as the Euro glyph (see a. above). +# +# c. The "fraction" glyph is now additionally mapped to U+2215, to match +# Windows Glyph List 4. +# +# d. The descriptive name for glyph "onefitted", in the Corporate Use +# subarea, is changed from "TABULAR DIGIT ONE" to "PROPORTIONAL DIGIT +# ONE". +# +# 1.0 [17 Jul 1997] Original version +# +0041;A;LATIN CAPITAL LETTER A +00C6;AE;LATIN CAPITAL LETTER AE +01FC;AEacute;LATIN CAPITAL LETTER AE WITH ACUTE +F7E6;AEsmall;LATIN SMALL CAPITAL LETTER AE +00C1;Aacute;LATIN CAPITAL LETTER A WITH ACUTE +F7E1;Aacutesmall;LATIN SMALL CAPITAL LETTER A WITH ACUTE +0102;Abreve;LATIN CAPITAL LETTER A WITH BREVE +00C2;Acircumflex;LATIN CAPITAL LETTER A WITH CIRCUMFLEX +F7E2;Acircumflexsmall;LATIN SMALL CAPITAL LETTER A WITH CIRCUMFLEX +F6C9;Acute;CAPITAL ACUTE ACCENT +F7B4;Acutesmall;SMALL CAPITAL ACUTE ACCENT +00C4;Adieresis;LATIN CAPITAL LETTER A WITH DIAERESIS +F7E4;Adieresissmall;LATIN SMALL CAPITAL LETTER A WITH DIAERESIS +00C0;Agrave;LATIN CAPITAL LETTER A WITH GRAVE +F7E0;Agravesmall;LATIN SMALL CAPITAL LETTER A WITH GRAVE +0391;Alpha;GREEK CAPITAL LETTER ALPHA +0386;Alphatonos;GREEK CAPITAL LETTER ALPHA WITH TONOS +0100;Amacron;LATIN CAPITAL LETTER A WITH MACRON +0104;Aogonek;LATIN CAPITAL LETTER A WITH OGONEK +00C5;Aring;LATIN CAPITAL LETTER A WITH RING ABOVE +01FA;Aringacute;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE +F7E5;Aringsmall;LATIN SMALL CAPITAL LETTER A WITH RING ABOVE +F761;Asmall;LATIN SMALL CAPITAL LETTER A +00C3;Atilde;LATIN CAPITAL LETTER A WITH TILDE +F7E3;Atildesmall;LATIN SMALL CAPITAL LETTER A WITH TILDE +0042;B;LATIN CAPITAL LETTER B +0392;Beta;GREEK CAPITAL LETTER BETA +F6F4;Brevesmall;SMALL CAPITAL BREVE +F762;Bsmall;LATIN SMALL CAPITAL LETTER B +0043;C;LATIN CAPITAL LETTER C +0106;Cacute;LATIN CAPITAL LETTER C WITH ACUTE +F6CA;Caron;CAPITAL CARON +F6F5;Caronsmall;SMALL CAPITAL CARON +010C;Ccaron;LATIN CAPITAL LETTER C WITH CARON +00C7;Ccedilla;LATIN CAPITAL LETTER C WITH CEDILLA +F7E7;Ccedillasmall;LATIN SMALL CAPITAL LETTER C WITH CEDILLA +0108;Ccircumflex;LATIN CAPITAL LETTER C WITH CIRCUMFLEX +010A;Cdotaccent;LATIN CAPITAL LETTER C WITH DOT ABOVE +F7B8;Cedillasmall;SMALL CAPITAL CEDILLA +03A7;Chi;GREEK CAPITAL LETTER CHI +F6F6;Circumflexsmall;SMALL CAPITAL MODIFIER LETTER CIRCUMFLEX ACCENT +F763;Csmall;LATIN SMALL CAPITAL LETTER C +0044;D;LATIN CAPITAL LETTER D +010E;Dcaron;LATIN CAPITAL LETTER D WITH CARON +0110;Dcroat;LATIN CAPITAL LETTER D WITH STROKE +2206;Delta;INCREMENT +0394;Delta;GREEK CAPITAL LETTER DELTA;Duplicate +F6CB;Dieresis;CAPITAL DIAERESIS +F6CC;DieresisAcute;CAPITAL DIAERESIS ACUTE ACCENT +F6CD;DieresisGrave;CAPITAL DIAERESIS GRAVE ACCENT +F7A8;Dieresissmall;SMALL CAPITAL DIAERESIS +F6F7;Dotaccentsmall;SMALL CAPITAL DOT ABOVE +F764;Dsmall;LATIN SMALL CAPITAL LETTER D +0045;E;LATIN CAPITAL LETTER E +00C9;Eacute;LATIN CAPITAL LETTER E WITH ACUTE +F7E9;Eacutesmall;LATIN SMALL CAPITAL LETTER E WITH ACUTE +0114;Ebreve;LATIN CAPITAL LETTER E WITH BREVE +011A;Ecaron;LATIN CAPITAL LETTER E WITH CARON +00CA;Ecircumflex;LATIN CAPITAL LETTER E WITH CIRCUMFLEX +F7EA;Ecircumflexsmall;LATIN SMALL CAPITAL LETTER E WITH CIRCUMFLEX +00CB;Edieresis;LATIN CAPITAL LETTER E WITH DIAERESIS +F7EB;Edieresissmall;LATIN SMALL CAPITAL LETTER E WITH DIAERESIS +0116;Edotaccent;LATIN CAPITAL LETTER E WITH DOT ABOVE +00C8;Egrave;LATIN CAPITAL LETTER E WITH GRAVE +F7E8;Egravesmall;LATIN SMALL CAPITAL LETTER E WITH GRAVE +0112;Emacron;LATIN CAPITAL LETTER E WITH MACRON +014A;Eng;LATIN CAPITAL LETTER ENG +0118;Eogonek;LATIN CAPITAL LETTER E WITH OGONEK +0395;Epsilon;GREEK CAPITAL LETTER EPSILON +0388;Epsilontonos;GREEK CAPITAL LETTER EPSILON WITH TONOS +F765;Esmall;LATIN SMALL CAPITAL LETTER E +0397;Eta;GREEK CAPITAL LETTER ETA +0389;Etatonos;GREEK CAPITAL LETTER ETA WITH TONOS +00D0;Eth;LATIN CAPITAL LETTER ETH +F7F0;Ethsmall;LATIN SMALL CAPITAL LETTER ETH +20AC;Euro;EURO SIGN +0046;F;LATIN CAPITAL LETTER F +F766;Fsmall;LATIN SMALL CAPITAL LETTER F +0047;G;LATIN CAPITAL LETTER G +0393;Gamma;GREEK CAPITAL LETTER GAMMA +011E;Gbreve;LATIN CAPITAL LETTER G WITH BREVE +01E6;Gcaron;LATIN CAPITAL LETTER G WITH CARON +011C;Gcircumflex;LATIN CAPITAL LETTER G WITH CIRCUMFLEX +0122;Gcommaaccent;LATIN CAPITAL LETTER G WITH CEDILLA +0120;Gdotaccent;LATIN CAPITAL LETTER G WITH DOT ABOVE +F6CE;Grave;CAPITAL GRAVE ACCENT +F760;Gravesmall;SMALL CAPITAL GRAVE ACCENT +F767;Gsmall;LATIN SMALL CAPITAL LETTER G +0048;H;LATIN CAPITAL LETTER H +25CF;H18533;BLACK CIRCLE +25AA;H18543;BLACK SMALL SQUARE +25AB;H18551;WHITE SMALL SQUARE +25A1;H22073;WHITE SQUARE +0126;Hbar;LATIN CAPITAL LETTER H WITH STROKE +0124;Hcircumflex;LATIN CAPITAL LETTER H WITH CIRCUMFLEX +F768;Hsmall;LATIN SMALL CAPITAL LETTER H +F6CF;Hungarumlaut;CAPITAL DOUBLE ACUTE ACCENT +F6F8;Hungarumlautsmall;SMALL CAPITAL DOUBLE ACUTE ACCENT +0049;I;LATIN CAPITAL LETTER I +0132;IJ;LATIN CAPITAL LIGATURE IJ +00CD;Iacute;LATIN CAPITAL LETTER I WITH ACUTE +F7ED;Iacutesmall;LATIN SMALL CAPITAL LETTER I WITH ACUTE +012C;Ibreve;LATIN CAPITAL LETTER I WITH BREVE +00CE;Icircumflex;LATIN CAPITAL LETTER I WITH CIRCUMFLEX +F7EE;Icircumflexsmall;LATIN SMALL CAPITAL LETTER I WITH CIRCUMFLEX +00CF;Idieresis;LATIN CAPITAL LETTER I WITH DIAERESIS +F7EF;Idieresissmall;LATIN SMALL CAPITAL LETTER I WITH DIAERESIS +0130;Idotaccent;LATIN CAPITAL LETTER I WITH DOT ABOVE +2111;Ifraktur;BLACK-LETTER CAPITAL I +00CC;Igrave;LATIN CAPITAL LETTER I WITH GRAVE +F7EC;Igravesmall;LATIN SMALL CAPITAL LETTER I WITH GRAVE +012A;Imacron;LATIN CAPITAL LETTER I WITH MACRON +012E;Iogonek;LATIN CAPITAL LETTER I WITH OGONEK +0399;Iota;GREEK CAPITAL LETTER IOTA +03AA;Iotadieresis;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA +038A;Iotatonos;GREEK CAPITAL LETTER IOTA WITH TONOS +F769;Ismall;LATIN SMALL CAPITAL LETTER I +0128;Itilde;LATIN CAPITAL LETTER I WITH TILDE +004A;J;LATIN CAPITAL LETTER J +0134;Jcircumflex;LATIN CAPITAL LETTER J WITH CIRCUMFLEX +F76A;Jsmall;LATIN SMALL CAPITAL LETTER J +004B;K;LATIN CAPITAL LETTER K +039A;Kappa;GREEK CAPITAL LETTER KAPPA +0136;Kcommaaccent;LATIN CAPITAL LETTER K WITH CEDILLA +F76B;Ksmall;LATIN SMALL CAPITAL LETTER K +004C;L;LATIN CAPITAL LETTER L +F6BF;LL;LATIN CAPITAL LETTER LL +0139;Lacute;LATIN CAPITAL LETTER L WITH ACUTE +039B;Lambda;GREEK CAPITAL LETTER LAMDA +013D;Lcaron;LATIN CAPITAL LETTER L WITH CARON +013B;Lcommaaccent;LATIN CAPITAL LETTER L WITH CEDILLA +013F;Ldot;LATIN CAPITAL LETTER L WITH MIDDLE DOT +0141;Lslash;LATIN CAPITAL LETTER L WITH STROKE +F6F9;Lslashsmall;LATIN SMALL CAPITAL LETTER L WITH STROKE +F76C;Lsmall;LATIN SMALL CAPITAL LETTER L +004D;M;LATIN CAPITAL LETTER M +F6D0;Macron;CAPITAL MACRON +F7AF;Macronsmall;SMALL CAPITAL MACRON +F76D;Msmall;LATIN SMALL CAPITAL LETTER M +039C;Mu;GREEK CAPITAL LETTER MU +004E;N;LATIN CAPITAL LETTER N +0143;Nacute;LATIN CAPITAL LETTER N WITH ACUTE +0147;Ncaron;LATIN CAPITAL LETTER N WITH CARON +0145;Ncommaaccent;LATIN CAPITAL LETTER N WITH CEDILLA +F76E;Nsmall;LATIN SMALL CAPITAL LETTER N +00D1;Ntilde;LATIN CAPITAL LETTER N WITH TILDE +F7F1;Ntildesmall;LATIN SMALL CAPITAL LETTER N WITH TILDE +039D;Nu;GREEK CAPITAL LETTER NU +004F;O;LATIN CAPITAL LETTER O +0152;OE;LATIN CAPITAL LIGATURE OE +F6FA;OEsmall;LATIN SMALL CAPITAL LIGATURE OE +00D3;Oacute;LATIN CAPITAL LETTER O WITH ACUTE +F7F3;Oacutesmall;LATIN SMALL CAPITAL LETTER O WITH ACUTE +014E;Obreve;LATIN CAPITAL LETTER O WITH BREVE +00D4;Ocircumflex;LATIN CAPITAL LETTER O WITH CIRCUMFLEX +F7F4;Ocircumflexsmall;LATIN SMALL CAPITAL LETTER O WITH CIRCUMFLEX +00D6;Odieresis;LATIN CAPITAL LETTER O WITH DIAERESIS +F7F6;Odieresissmall;LATIN SMALL CAPITAL LETTER O WITH DIAERESIS +F6FB;Ogoneksmall;SMALL CAPITAL OGONEK +00D2;Ograve;LATIN CAPITAL LETTER O WITH GRAVE +F7F2;Ogravesmall;LATIN SMALL CAPITAL LETTER O WITH GRAVE +01A0;Ohorn;LATIN CAPITAL LETTER O WITH HORN +0150;Ohungarumlaut;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE +014C;Omacron;LATIN CAPITAL LETTER O WITH MACRON +2126;Omega;OHM SIGN +03A9;Omega;GREEK CAPITAL LETTER OMEGA;Duplicate +038F;Omegatonos;GREEK CAPITAL LETTER OMEGA WITH TONOS +039F;Omicron;GREEK CAPITAL LETTER OMICRON +038C;Omicrontonos;GREEK CAPITAL LETTER OMICRON WITH TONOS +00D8;Oslash;LATIN CAPITAL LETTER O WITH STROKE +01FE;Oslashacute;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE +F7F8;Oslashsmall;LATIN SMALL CAPITAL LETTER O WITH STROKE +F76F;Osmall;LATIN SMALL CAPITAL LETTER O +00D5;Otilde;LATIN CAPITAL LETTER O WITH TILDE +F7F5;Otildesmall;LATIN SMALL CAPITAL LETTER O WITH TILDE +0050;P;LATIN CAPITAL LETTER P +03A6;Phi;GREEK CAPITAL LETTER PHI +03A0;Pi;GREEK CAPITAL LETTER PI +03A8;Psi;GREEK CAPITAL LETTER PSI +F770;Psmall;LATIN SMALL CAPITAL LETTER P +0051;Q;LATIN CAPITAL LETTER Q +F771;Qsmall;LATIN SMALL CAPITAL LETTER Q +0052;R;LATIN CAPITAL LETTER R +0154;Racute;LATIN CAPITAL LETTER R WITH ACUTE +0158;Rcaron;LATIN CAPITAL LETTER R WITH CARON +0156;Rcommaaccent;LATIN CAPITAL LETTER R WITH CEDILLA +211C;Rfraktur;BLACK-LETTER CAPITAL R +03A1;Rho;GREEK CAPITAL LETTER RHO +F6FC;Ringsmall;SMALL CAPITAL RING ABOVE +F772;Rsmall;LATIN SMALL CAPITAL LETTER R +0053;S;LATIN CAPITAL LETTER S +250C;SF010000;BOX DRAWINGS LIGHT DOWN AND RIGHT +2514;SF020000;BOX DRAWINGS LIGHT UP AND RIGHT +2510;SF030000;BOX DRAWINGS LIGHT DOWN AND LEFT +2518;SF040000;BOX DRAWINGS LIGHT UP AND LEFT +253C;SF050000;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL +252C;SF060000;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL +2534;SF070000;BOX DRAWINGS LIGHT UP AND HORIZONTAL +251C;SF080000;BOX DRAWINGS LIGHT VERTICAL AND RIGHT +2524;SF090000;BOX DRAWINGS LIGHT VERTICAL AND LEFT +2500;SF100000;BOX DRAWINGS LIGHT HORIZONTAL +2502;SF110000;BOX DRAWINGS LIGHT VERTICAL +2561;SF190000;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE +2562;SF200000;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE +2556;SF210000;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE +2555;SF220000;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE +2563;SF230000;BOX DRAWINGS DOUBLE VERTICAL AND LEFT +2551;SF240000;BOX DRAWINGS DOUBLE VERTICAL +2557;SF250000;BOX DRAWINGS DOUBLE DOWN AND LEFT +255D;SF260000;BOX DRAWINGS DOUBLE UP AND LEFT +255C;SF270000;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE +255B;SF280000;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE +255E;SF360000;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE +255F;SF370000;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE +255A;SF380000;BOX DRAWINGS DOUBLE UP AND RIGHT +2554;SF390000;BOX DRAWINGS DOUBLE DOWN AND RIGHT +2569;SF400000;BOX DRAWINGS DOUBLE UP AND HORIZONTAL +2566;SF410000;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL +2560;SF420000;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT +2550;SF430000;BOX DRAWINGS DOUBLE HORIZONTAL +256C;SF440000;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL +2567;SF450000;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE +2568;SF460000;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE +2564;SF470000;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE +2565;SF480000;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE +2559;SF490000;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE +2558;SF500000;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE +2552;SF510000;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE +2553;SF520000;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE +256B;SF530000;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE +256A;SF540000;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE +015A;Sacute;LATIN CAPITAL LETTER S WITH ACUTE +0160;Scaron;LATIN CAPITAL LETTER S WITH CARON +F6FD;Scaronsmall;LATIN SMALL CAPITAL LETTER S WITH CARON +015E;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA +F6C1;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA;Duplicate +015C;Scircumflex;LATIN CAPITAL LETTER S WITH CIRCUMFLEX +0218;Scommaaccent;LATIN CAPITAL LETTER S WITH COMMA BELOW +03A3;Sigma;GREEK CAPITAL LETTER SIGMA +F773;Ssmall;LATIN SMALL CAPITAL LETTER S +0054;T;LATIN CAPITAL LETTER T +03A4;Tau;GREEK CAPITAL LETTER TAU +0166;Tbar;LATIN CAPITAL LETTER T WITH STROKE +0164;Tcaron;LATIN CAPITAL LETTER T WITH CARON +0162;Tcommaaccent;LATIN CAPITAL LETTER T WITH CEDILLA +021A;Tcommaaccent;LATIN CAPITAL LETTER T WITH COMMA BELOW;Duplicate +0398;Theta;GREEK CAPITAL LETTER THETA +00DE;Thorn;LATIN CAPITAL LETTER THORN +F7FE;Thornsmall;LATIN SMALL CAPITAL LETTER THORN +F6FE;Tildesmall;SMALL CAPITAL SMALL TILDE +F774;Tsmall;LATIN SMALL CAPITAL LETTER T +0055;U;LATIN CAPITAL LETTER U +00DA;Uacute;LATIN CAPITAL LETTER U WITH ACUTE +F7FA;Uacutesmall;LATIN SMALL CAPITAL LETTER U WITH ACUTE +016C;Ubreve;LATIN CAPITAL LETTER U WITH BREVE +00DB;Ucircumflex;LATIN CAPITAL LETTER U WITH CIRCUMFLEX +F7FB;Ucircumflexsmall;LATIN SMALL CAPITAL LETTER U WITH CIRCUMFLEX +00DC;Udieresis;LATIN CAPITAL LETTER U WITH DIAERESIS +F7FC;Udieresissmall;LATIN SMALL CAPITAL LETTER U WITH DIAERESIS +00D9;Ugrave;LATIN CAPITAL LETTER U WITH GRAVE +F7F9;Ugravesmall;LATIN SMALL CAPITAL LETTER U WITH GRAVE +01AF;Uhorn;LATIN CAPITAL LETTER U WITH HORN +0170;Uhungarumlaut;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE +016A;Umacron;LATIN CAPITAL LETTER U WITH MACRON +0172;Uogonek;LATIN CAPITAL LETTER U WITH OGONEK +03A5;Upsilon;GREEK CAPITAL LETTER UPSILON +03D2;Upsilon1;GREEK UPSILON WITH HOOK SYMBOL +03AB;Upsilondieresis;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA +038E;Upsilontonos;GREEK CAPITAL LETTER UPSILON WITH TONOS +016E;Uring;LATIN CAPITAL LETTER U WITH RING ABOVE +F775;Usmall;LATIN SMALL CAPITAL LETTER U +0168;Utilde;LATIN CAPITAL LETTER U WITH TILDE +0056;V;LATIN CAPITAL LETTER V +F776;Vsmall;LATIN SMALL CAPITAL LETTER V +0057;W;LATIN CAPITAL LETTER W +1E82;Wacute;LATIN CAPITAL LETTER W WITH ACUTE +0174;Wcircumflex;LATIN CAPITAL LETTER W WITH CIRCUMFLEX +1E84;Wdieresis;LATIN CAPITAL LETTER W WITH DIAERESIS +1E80;Wgrave;LATIN CAPITAL LETTER W WITH GRAVE +F777;Wsmall;LATIN SMALL CAPITAL LETTER W +0058;X;LATIN CAPITAL LETTER X +039E;Xi;GREEK CAPITAL LETTER XI +F778;Xsmall;LATIN SMALL CAPITAL LETTER X +0059;Y;LATIN CAPITAL LETTER Y +00DD;Yacute;LATIN CAPITAL LETTER Y WITH ACUTE +F7FD;Yacutesmall;LATIN SMALL CAPITAL LETTER Y WITH ACUTE +0176;Ycircumflex;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX +0178;Ydieresis;LATIN CAPITAL LETTER Y WITH DIAERESIS +F7FF;Ydieresissmall;LATIN SMALL CAPITAL LETTER Y WITH DIAERESIS +1EF2;Ygrave;LATIN CAPITAL LETTER Y WITH GRAVE +F779;Ysmall;LATIN SMALL CAPITAL LETTER Y +005A;Z;LATIN CAPITAL LETTER Z +0179;Zacute;LATIN CAPITAL LETTER Z WITH ACUTE +017D;Zcaron;LATIN CAPITAL LETTER Z WITH CARON +F6FF;Zcaronsmall;LATIN SMALL CAPITAL LETTER Z WITH CARON +017B;Zdotaccent;LATIN CAPITAL LETTER Z WITH DOT ABOVE +0396;Zeta;GREEK CAPITAL LETTER ZETA +F77A;Zsmall;LATIN SMALL CAPITAL LETTER Z +0061;a;LATIN SMALL LETTER A +00E1;aacute;LATIN SMALL LETTER A WITH ACUTE +0103;abreve;LATIN SMALL LETTER A WITH BREVE +00E2;acircumflex;LATIN SMALL LETTER A WITH CIRCUMFLEX +00B4;acute;ACUTE ACCENT +0301;acutecomb;COMBINING ACUTE ACCENT +00E4;adieresis;LATIN SMALL LETTER A WITH DIAERESIS +00E6;ae;LATIN SMALL LETTER AE +01FD;aeacute;LATIN SMALL LETTER AE WITH ACUTE +2015;afii00208;HORIZONTAL BAR +0410;afii10017;CYRILLIC CAPITAL LETTER A +0411;afii10018;CYRILLIC CAPITAL LETTER BE +0412;afii10019;CYRILLIC CAPITAL LETTER VE +0413;afii10020;CYRILLIC CAPITAL LETTER GHE +0414;afii10021;CYRILLIC CAPITAL LETTER DE +0415;afii10022;CYRILLIC CAPITAL LETTER IE +0401;afii10023;CYRILLIC CAPITAL LETTER IO +0416;afii10024;CYRILLIC CAPITAL LETTER ZHE +0417;afii10025;CYRILLIC CAPITAL LETTER ZE +0418;afii10026;CYRILLIC CAPITAL LETTER I +0419;afii10027;CYRILLIC CAPITAL LETTER SHORT I +041A;afii10028;CYRILLIC CAPITAL LETTER KA +041B;afii10029;CYRILLIC CAPITAL LETTER EL +041C;afii10030;CYRILLIC CAPITAL LETTER EM +041D;afii10031;CYRILLIC CAPITAL LETTER EN +041E;afii10032;CYRILLIC CAPITAL LETTER O +041F;afii10033;CYRILLIC CAPITAL LETTER PE +0420;afii10034;CYRILLIC CAPITAL LETTER ER +0421;afii10035;CYRILLIC CAPITAL LETTER ES +0422;afii10036;CYRILLIC CAPITAL LETTER TE +0423;afii10037;CYRILLIC CAPITAL LETTER U +0424;afii10038;CYRILLIC CAPITAL LETTER EF +0425;afii10039;CYRILLIC CAPITAL LETTER HA +0426;afii10040;CYRILLIC CAPITAL LETTER TSE +0427;afii10041;CYRILLIC CAPITAL LETTER CHE +0428;afii10042;CYRILLIC CAPITAL LETTER SHA +0429;afii10043;CYRILLIC CAPITAL LETTER SHCHA +042A;afii10044;CYRILLIC CAPITAL LETTER HARD SIGN +042B;afii10045;CYRILLIC CAPITAL LETTER YERU +042C;afii10046;CYRILLIC CAPITAL LETTER SOFT SIGN +042D;afii10047;CYRILLIC CAPITAL LETTER E +042E;afii10048;CYRILLIC CAPITAL LETTER YU +042F;afii10049;CYRILLIC CAPITAL LETTER YA +0490;afii10050;CYRILLIC CAPITAL LETTER GHE WITH UPTURN +0402;afii10051;CYRILLIC CAPITAL LETTER DJE +0403;afii10052;CYRILLIC CAPITAL LETTER GJE +0404;afii10053;CYRILLIC CAPITAL LETTER UKRAINIAN IE +0405;afii10054;CYRILLIC CAPITAL LETTER DZE +0406;afii10055;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I +0407;afii10056;CYRILLIC CAPITAL LETTER YI +0408;afii10057;CYRILLIC CAPITAL LETTER JE +0409;afii10058;CYRILLIC CAPITAL LETTER LJE +040A;afii10059;CYRILLIC CAPITAL LETTER NJE +040B;afii10060;CYRILLIC CAPITAL LETTER TSHE +040C;afii10061;CYRILLIC CAPITAL LETTER KJE +040E;afii10062;CYRILLIC CAPITAL LETTER SHORT U +F6C4;afii10063;CYRILLIC SMALL LETTER GHE VARIANT +F6C5;afii10064;CYRILLIC SMALL LETTER BE VARIANT +0430;afii10065;CYRILLIC SMALL LETTER A +0431;afii10066;CYRILLIC SMALL LETTER BE +0432;afii10067;CYRILLIC SMALL LETTER VE +0433;afii10068;CYRILLIC SMALL LETTER GHE +0434;afii10069;CYRILLIC SMALL LETTER DE +0435;afii10070;CYRILLIC SMALL LETTER IE +0451;afii10071;CYRILLIC SMALL LETTER IO +0436;afii10072;CYRILLIC SMALL LETTER ZHE +0437;afii10073;CYRILLIC SMALL LETTER ZE +0438;afii10074;CYRILLIC SMALL LETTER I +0439;afii10075;CYRILLIC SMALL LETTER SHORT I +043A;afii10076;CYRILLIC SMALL LETTER KA +043B;afii10077;CYRILLIC SMALL LETTER EL +043C;afii10078;CYRILLIC SMALL LETTER EM +043D;afii10079;CYRILLIC SMALL LETTER EN +043E;afii10080;CYRILLIC SMALL LETTER O +043F;afii10081;CYRILLIC SMALL LETTER PE +0440;afii10082;CYRILLIC SMALL LETTER ER +0441;afii10083;CYRILLIC SMALL LETTER ES +0442;afii10084;CYRILLIC SMALL LETTER TE +0443;afii10085;CYRILLIC SMALL LETTER U +0444;afii10086;CYRILLIC SMALL LETTER EF +0445;afii10087;CYRILLIC SMALL LETTER HA +0446;afii10088;CYRILLIC SMALL LETTER TSE +0447;afii10089;CYRILLIC SMALL LETTER CHE +0448;afii10090;CYRILLIC SMALL LETTER SHA +0449;afii10091;CYRILLIC SMALL LETTER SHCHA +044A;afii10092;CYRILLIC SMALL LETTER HARD SIGN +044B;afii10093;CYRILLIC SMALL LETTER YERU +044C;afii10094;CYRILLIC SMALL LETTER SOFT SIGN +044D;afii10095;CYRILLIC SMALL LETTER E +044E;afii10096;CYRILLIC SMALL LETTER YU +044F;afii10097;CYRILLIC SMALL LETTER YA +0491;afii10098;CYRILLIC SMALL LETTER GHE WITH UPTURN +0452;afii10099;CYRILLIC SMALL LETTER DJE +0453;afii10100;CYRILLIC SMALL LETTER GJE +0454;afii10101;CYRILLIC SMALL LETTER UKRAINIAN IE +0455;afii10102;CYRILLIC SMALL LETTER DZE +0456;afii10103;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I +0457;afii10104;CYRILLIC SMALL LETTER YI +0458;afii10105;CYRILLIC SMALL LETTER JE +0459;afii10106;CYRILLIC SMALL LETTER LJE +045A;afii10107;CYRILLIC SMALL LETTER NJE +045B;afii10108;CYRILLIC SMALL LETTER TSHE +045C;afii10109;CYRILLIC SMALL LETTER KJE +045E;afii10110;CYRILLIC SMALL LETTER SHORT U +040F;afii10145;CYRILLIC CAPITAL LETTER DZHE +0462;afii10146;CYRILLIC CAPITAL LETTER YAT +0472;afii10147;CYRILLIC CAPITAL LETTER FITA +0474;afii10148;CYRILLIC CAPITAL LETTER IZHITSA +F6C6;afii10192;CYRILLIC SMALL LETTER DE VARIANT +045F;afii10193;CYRILLIC SMALL LETTER DZHE +0463;afii10194;CYRILLIC SMALL LETTER YAT +0473;afii10195;CYRILLIC SMALL LETTER FITA +0475;afii10196;CYRILLIC SMALL LETTER IZHITSA +F6C7;afii10831;CYRILLIC SMALL LETTER PE VARIANT +F6C8;afii10832;CYRILLIC SMALL LETTER TE VARIANT +04D9;afii10846;CYRILLIC SMALL LETTER SCHWA +200E;afii299;LEFT-TO-RIGHT MARK +200F;afii300;RIGHT-TO-LEFT MARK +200D;afii301;ZERO WIDTH JOINER +066A;afii57381;ARABIC PERCENT SIGN +060C;afii57388;ARABIC COMMA +0660;afii57392;ARABIC-INDIC DIGIT ZERO +0661;afii57393;ARABIC-INDIC DIGIT ONE +0662;afii57394;ARABIC-INDIC DIGIT TWO +0663;afii57395;ARABIC-INDIC DIGIT THREE +0664;afii57396;ARABIC-INDIC DIGIT FOUR +0665;afii57397;ARABIC-INDIC DIGIT FIVE +0666;afii57398;ARABIC-INDIC DIGIT SIX +0667;afii57399;ARABIC-INDIC DIGIT SEVEN +0668;afii57400;ARABIC-INDIC DIGIT EIGHT +0669;afii57401;ARABIC-INDIC DIGIT NINE +061B;afii57403;ARABIC SEMICOLON +061F;afii57407;ARABIC QUESTION MARK +0621;afii57409;ARABIC LETTER HAMZA +0622;afii57410;ARABIC LETTER ALEF WITH MADDA ABOVE +0623;afii57411;ARABIC LETTER ALEF WITH HAMZA ABOVE +0624;afii57412;ARABIC LETTER WAW WITH HAMZA ABOVE +0625;afii57413;ARABIC LETTER ALEF WITH HAMZA BELOW +0626;afii57414;ARABIC LETTER YEH WITH HAMZA ABOVE +0627;afii57415;ARABIC LETTER ALEF +0628;afii57416;ARABIC LETTER BEH +0629;afii57417;ARABIC LETTER TEH MARBUTA +062A;afii57418;ARABIC LETTER TEH +062B;afii57419;ARABIC LETTER THEH +062C;afii57420;ARABIC LETTER JEEM +062D;afii57421;ARABIC LETTER HAH +062E;afii57422;ARABIC LETTER KHAH +062F;afii57423;ARABIC LETTER DAL +0630;afii57424;ARABIC LETTER THAL +0631;afii57425;ARABIC LETTER REH +0632;afii57426;ARABIC LETTER ZAIN +0633;afii57427;ARABIC LETTER SEEN +0634;afii57428;ARABIC LETTER SHEEN +0635;afii57429;ARABIC LETTER SAD +0636;afii57430;ARABIC LETTER DAD +0637;afii57431;ARABIC LETTER TAH +0638;afii57432;ARABIC LETTER ZAH +0639;afii57433;ARABIC LETTER AIN +063A;afii57434;ARABIC LETTER GHAIN +0640;afii57440;ARABIC TATWEEL +0641;afii57441;ARABIC LETTER FEH +0642;afii57442;ARABIC LETTER QAF +0643;afii57443;ARABIC LETTER KAF +0644;afii57444;ARABIC LETTER LAM +0645;afii57445;ARABIC LETTER MEEM +0646;afii57446;ARABIC LETTER NOON +0648;afii57448;ARABIC LETTER WAW +0649;afii57449;ARABIC LETTER ALEF MAKSURA +064A;afii57450;ARABIC LETTER YEH +064B;afii57451;ARABIC FATHATAN +064C;afii57452;ARABIC DAMMATAN +064D;afii57453;ARABIC KASRATAN +064E;afii57454;ARABIC FATHA +064F;afii57455;ARABIC DAMMA +0650;afii57456;ARABIC KASRA +0651;afii57457;ARABIC SHADDA +0652;afii57458;ARABIC SUKUN +0647;afii57470;ARABIC LETTER HEH +06A4;afii57505;ARABIC LETTER VEH +067E;afii57506;ARABIC LETTER PEH +0686;afii57507;ARABIC LETTER TCHEH +0698;afii57508;ARABIC LETTER JEH +06AF;afii57509;ARABIC LETTER GAF +0679;afii57511;ARABIC LETTER TTEH +0688;afii57512;ARABIC LETTER DDAL +0691;afii57513;ARABIC LETTER RREH +06BA;afii57514;ARABIC LETTER NOON GHUNNA +06D2;afii57519;ARABIC LETTER YEH BARREE +06D5;afii57534;ARABIC LETTER AE +20AA;afii57636;NEW SHEQEL SIGN +05BE;afii57645;HEBREW PUNCTUATION MAQAF +05C3;afii57658;HEBREW PUNCTUATION SOF PASUQ +05D0;afii57664;HEBREW LETTER ALEF +05D1;afii57665;HEBREW LETTER BET +05D2;afii57666;HEBREW LETTER GIMEL +05D3;afii57667;HEBREW LETTER DALET +05D4;afii57668;HEBREW LETTER HE +05D5;afii57669;HEBREW LETTER VAV +05D6;afii57670;HEBREW LETTER ZAYIN +05D7;afii57671;HEBREW LETTER HET +05D8;afii57672;HEBREW LETTER TET +05D9;afii57673;HEBREW LETTER YOD +05DA;afii57674;HEBREW LETTER FINAL KAF +05DB;afii57675;HEBREW LETTER KAF +05DC;afii57676;HEBREW LETTER LAMED +05DD;afii57677;HEBREW LETTER FINAL MEM +05DE;afii57678;HEBREW LETTER MEM +05DF;afii57679;HEBREW LETTER FINAL NUN +05E0;afii57680;HEBREW LETTER NUN +05E1;afii57681;HEBREW LETTER SAMEKH +05E2;afii57682;HEBREW LETTER AYIN +05E3;afii57683;HEBREW LETTER FINAL PE +05E4;afii57684;HEBREW LETTER PE +05E5;afii57685;HEBREW LETTER FINAL TSADI +05E6;afii57686;HEBREW LETTER TSADI +05E7;afii57687;HEBREW LETTER QOF +05E8;afii57688;HEBREW LETTER RESH +05E9;afii57689;HEBREW LETTER SHIN +05EA;afii57690;HEBREW LETTER TAV +FB2A;afii57694;HEBREW LETTER SHIN WITH SHIN DOT +FB2B;afii57695;HEBREW LETTER SHIN WITH SIN DOT +FB4B;afii57700;HEBREW LETTER VAV WITH HOLAM +FB1F;afii57705;HEBREW LIGATURE YIDDISH YOD YOD PATAH +05F0;afii57716;HEBREW LIGATURE YIDDISH DOUBLE VAV +05F1;afii57717;HEBREW LIGATURE YIDDISH VAV YOD +05F2;afii57718;HEBREW LIGATURE YIDDISH DOUBLE YOD +FB35;afii57723;HEBREW LETTER VAV WITH DAGESH +05B4;afii57793;HEBREW POINT HIRIQ +05B5;afii57794;HEBREW POINT TSERE +05B6;afii57795;HEBREW POINT SEGOL +05BB;afii57796;HEBREW POINT QUBUTS +05B8;afii57797;HEBREW POINT QAMATS +05B7;afii57798;HEBREW POINT PATAH +05B0;afii57799;HEBREW POINT SHEVA +05B2;afii57800;HEBREW POINT HATAF PATAH +05B1;afii57801;HEBREW POINT HATAF SEGOL +05B3;afii57802;HEBREW POINT HATAF QAMATS +05C2;afii57803;HEBREW POINT SIN DOT +05C1;afii57804;HEBREW POINT SHIN DOT +05B9;afii57806;HEBREW POINT HOLAM +05BC;afii57807;HEBREW POINT DAGESH OR MAPIQ +05BD;afii57839;HEBREW POINT METEG +05BF;afii57841;HEBREW POINT RAFE +05C0;afii57842;HEBREW PUNCTUATION PASEQ +02BC;afii57929;MODIFIER LETTER APOSTROPHE +2105;afii61248;CARE OF +2113;afii61289;SCRIPT SMALL L +2116;afii61352;NUMERO SIGN +202C;afii61573;POP DIRECTIONAL FORMATTING +202D;afii61574;LEFT-TO-RIGHT OVERRIDE +202E;afii61575;RIGHT-TO-LEFT OVERRIDE +200C;afii61664;ZERO WIDTH NON-JOINER +066D;afii63167;ARABIC FIVE POINTED STAR +02BD;afii64937;MODIFIER LETTER REVERSED COMMA +00E0;agrave;LATIN SMALL LETTER A WITH GRAVE +2135;aleph;ALEF SYMBOL +03B1;alpha;GREEK SMALL LETTER ALPHA +03AC;alphatonos;GREEK SMALL LETTER ALPHA WITH TONOS +0101;amacron;LATIN SMALL LETTER A WITH MACRON +0026;ampersand;AMPERSAND +F726;ampersandsmall;SMALL CAPITAL AMPERSAND +2220;angle;ANGLE +2329;angleleft;LEFT-POINTING ANGLE BRACKET +232A;angleright;RIGHT-POINTING ANGLE BRACKET +0387;anoteleia;GREEK ANO TELEIA +0105;aogonek;LATIN SMALL LETTER A WITH OGONEK +2248;approxequal;ALMOST EQUAL TO +00E5;aring;LATIN SMALL LETTER A WITH RING ABOVE +01FB;aringacute;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE +2194;arrowboth;LEFT RIGHT ARROW +21D4;arrowdblboth;LEFT RIGHT DOUBLE ARROW +21D3;arrowdbldown;DOWNWARDS DOUBLE ARROW +21D0;arrowdblleft;LEFTWARDS DOUBLE ARROW +21D2;arrowdblright;RIGHTWARDS DOUBLE ARROW +21D1;arrowdblup;UPWARDS DOUBLE ARROW +2193;arrowdown;DOWNWARDS ARROW +F8E7;arrowhorizex;HORIZONTAL ARROW EXTENDER +2190;arrowleft;LEFTWARDS ARROW +2192;arrowright;RIGHTWARDS ARROW +2191;arrowup;UPWARDS ARROW +2195;arrowupdn;UP DOWN ARROW +21A8;arrowupdnbse;UP DOWN ARROW WITH BASE +F8E6;arrowvertex;VERTICAL ARROW EXTENDER +005E;asciicircum;CIRCUMFLEX ACCENT +007E;asciitilde;TILDE +002A;asterisk;ASTERISK +2217;asteriskmath;ASTERISK OPERATOR +F6E9;asuperior;SUPERSCRIPT LATIN SMALL LETTER A +0040;at;COMMERCIAL AT +00E3;atilde;LATIN SMALL LETTER A WITH TILDE +0062;b;LATIN SMALL LETTER B +005C;backslash;REVERSE SOLIDUS +007C;bar;VERTICAL LINE +03B2;beta;GREEK SMALL LETTER BETA +2588;block;FULL BLOCK +F8F4;braceex;CURLY BRACKET EXTENDER +007B;braceleft;LEFT CURLY BRACKET +F8F3;braceleftbt;LEFT CURLY BRACKET BOTTOM +F8F2;braceleftmid;LEFT CURLY BRACKET MID +F8F1;bracelefttp;LEFT CURLY BRACKET TOP +007D;braceright;RIGHT CURLY BRACKET +F8FE;bracerightbt;RIGHT CURLY BRACKET BOTTOM +F8FD;bracerightmid;RIGHT CURLY BRACKET MID +F8FC;bracerighttp;RIGHT CURLY BRACKET TOP +005B;bracketleft;LEFT SQUARE BRACKET +F8F0;bracketleftbt;LEFT SQUARE BRACKET BOTTOM +F8EF;bracketleftex;LEFT SQUARE BRACKET EXTENDER +F8EE;bracketlefttp;LEFT SQUARE BRACKET TOP +005D;bracketright;RIGHT SQUARE BRACKET +F8FB;bracketrightbt;RIGHT SQUARE BRACKET BOTTOM +F8FA;bracketrightex;RIGHT SQUARE BRACKET EXTENDER +F8F9;bracketrighttp;RIGHT SQUARE BRACKET TOP +02D8;breve;BREVE +00A6;brokenbar;BROKEN BAR +F6EA;bsuperior;SUPERSCRIPT LATIN SMALL LETTER B +2022;bullet;BULLET +0063;c;LATIN SMALL LETTER C +0107;cacute;LATIN SMALL LETTER C WITH ACUTE +02C7;caron;CARON +21B5;carriagereturn;DOWNWARDS ARROW WITH CORNER LEFTWARDS +010D;ccaron;LATIN SMALL LETTER C WITH CARON +00E7;ccedilla;LATIN SMALL LETTER C WITH CEDILLA +0109;ccircumflex;LATIN SMALL LETTER C WITH CIRCUMFLEX +010B;cdotaccent;LATIN SMALL LETTER C WITH DOT ABOVE +00B8;cedilla;CEDILLA +00A2;cent;CENT SIGN +F6DF;centinferior;SUBSCRIPT CENT SIGN +F7A2;centoldstyle;OLDSTYLE CENT SIGN +F6E0;centsuperior;SUPERSCRIPT CENT SIGN +03C7;chi;GREEK SMALL LETTER CHI +25CB;circle;WHITE CIRCLE +2297;circlemultiply;CIRCLED TIMES +2295;circleplus;CIRCLED PLUS +02C6;circumflex;MODIFIER LETTER CIRCUMFLEX ACCENT +2663;club;BLACK CLUB SUIT +003A;colon;COLON +20A1;colonmonetary;COLON SIGN +002C;comma;COMMA +F6C3;commaaccent;COMMA BELOW +F6E1;commainferior;SUBSCRIPT COMMA +F6E2;commasuperior;SUPERSCRIPT COMMA +2245;congruent;APPROXIMATELY EQUAL TO +00A9;copyright;COPYRIGHT SIGN +F8E9;copyrightsans;COPYRIGHT SIGN SANS SERIF +F6D9;copyrightserif;COPYRIGHT SIGN SERIF +00A4;currency;CURRENCY SIGN +F6D1;cyrBreve;CAPITAL CYRILLIC BREVE +F6D2;cyrFlex;CAPITAL CYRILLIC CIRCUMFLEX +F6D4;cyrbreve;CYRILLIC BREVE +F6D5;cyrflex;CYRILLIC CIRCUMFLEX +0064;d;LATIN SMALL LETTER D +2020;dagger;DAGGER +2021;daggerdbl;DOUBLE DAGGER +F6D3;dblGrave;CAPITAL DOUBLE GRAVE ACCENT +F6D6;dblgrave;DOUBLE GRAVE ACCENT +010F;dcaron;LATIN SMALL LETTER D WITH CARON +0111;dcroat;LATIN SMALL LETTER D WITH STROKE +00B0;degree;DEGREE SIGN +03B4;delta;GREEK SMALL LETTER DELTA +2666;diamond;BLACK DIAMOND SUIT +00A8;dieresis;DIAERESIS +F6D7;dieresisacute;DIAERESIS ACUTE ACCENT +F6D8;dieresisgrave;DIAERESIS GRAVE ACCENT +0385;dieresistonos;GREEK DIALYTIKA TONOS +00F7;divide;DIVISION SIGN +2593;dkshade;DARK SHADE +2584;dnblock;LOWER HALF BLOCK +0024;dollar;DOLLAR SIGN +F6E3;dollarinferior;SUBSCRIPT DOLLAR SIGN +F724;dollaroldstyle;OLDSTYLE DOLLAR SIGN +F6E4;dollarsuperior;SUPERSCRIPT DOLLAR SIGN +20AB;dong;DONG SIGN +02D9;dotaccent;DOT ABOVE +0323;dotbelowcomb;COMBINING DOT BELOW +0131;dotlessi;LATIN SMALL LETTER DOTLESS I +F6BE;dotlessj;LATIN SMALL LETTER DOTLESS J +22C5;dotmath;DOT OPERATOR +F6EB;dsuperior;SUPERSCRIPT LATIN SMALL LETTER D +0065;e;LATIN SMALL LETTER E +00E9;eacute;LATIN SMALL LETTER E WITH ACUTE +0115;ebreve;LATIN SMALL LETTER E WITH BREVE +011B;ecaron;LATIN SMALL LETTER E WITH CARON +00EA;ecircumflex;LATIN SMALL LETTER E WITH CIRCUMFLEX +00EB;edieresis;LATIN SMALL LETTER E WITH DIAERESIS +0117;edotaccent;LATIN SMALL LETTER E WITH DOT ABOVE +00E8;egrave;LATIN SMALL LETTER E WITH GRAVE +0038;eight;DIGIT EIGHT +2088;eightinferior;SUBSCRIPT EIGHT +F738;eightoldstyle;OLDSTYLE DIGIT EIGHT +2078;eightsuperior;SUPERSCRIPT EIGHT +2208;element;ELEMENT OF +2026;ellipsis;HORIZONTAL ELLIPSIS +0113;emacron;LATIN SMALL LETTER E WITH MACRON +2014;emdash;EM DASH +2205;emptyset;EMPTY SET +2013;endash;EN DASH +014B;eng;LATIN SMALL LETTER ENG +0119;eogonek;LATIN SMALL LETTER E WITH OGONEK +03B5;epsilon;GREEK SMALL LETTER EPSILON +03AD;epsilontonos;GREEK SMALL LETTER EPSILON WITH TONOS +003D;equal;EQUALS SIGN +2261;equivalence;IDENTICAL TO +212E;estimated;ESTIMATED SYMBOL +F6EC;esuperior;SUPERSCRIPT LATIN SMALL LETTER E +03B7;eta;GREEK SMALL LETTER ETA +03AE;etatonos;GREEK SMALL LETTER ETA WITH TONOS +00F0;eth;LATIN SMALL LETTER ETH +0021;exclam;EXCLAMATION MARK +203C;exclamdbl;DOUBLE EXCLAMATION MARK +00A1;exclamdown;INVERTED EXCLAMATION MARK +F7A1;exclamdownsmall;SMALL CAPITAL INVERTED EXCLAMATION MARK +F721;exclamsmall;SMALL CAPITAL EXCLAMATION MARK +2203;existential;THERE EXISTS +0066;f;LATIN SMALL LETTER F +2640;female;FEMALE SIGN +FB00;ff;LATIN SMALL LIGATURE FF +FB03;ffi;LATIN SMALL LIGATURE FFI +FB04;ffl;LATIN SMALL LIGATURE FFL +FB01;fi;LATIN SMALL LIGATURE FI +2012;figuredash;FIGURE DASH +25A0;filledbox;BLACK SQUARE +25AC;filledrect;BLACK RECTANGLE +0035;five;DIGIT FIVE +215D;fiveeighths;VULGAR FRACTION FIVE EIGHTHS +2085;fiveinferior;SUBSCRIPT FIVE +F735;fiveoldstyle;OLDSTYLE DIGIT FIVE +2075;fivesuperior;SUPERSCRIPT FIVE +FB02;fl;LATIN SMALL LIGATURE FL +0192;florin;LATIN SMALL LETTER F WITH HOOK +0034;four;DIGIT FOUR +2084;fourinferior;SUBSCRIPT FOUR +F734;fouroldstyle;OLDSTYLE DIGIT FOUR +2074;foursuperior;SUPERSCRIPT FOUR +2044;fraction;FRACTION SLASH +2215;fraction;DIVISION SLASH;Duplicate +20A3;franc;FRENCH FRANC SIGN +0067;g;LATIN SMALL LETTER G +03B3;gamma;GREEK SMALL LETTER GAMMA +011F;gbreve;LATIN SMALL LETTER G WITH BREVE +01E7;gcaron;LATIN SMALL LETTER G WITH CARON +011D;gcircumflex;LATIN SMALL LETTER G WITH CIRCUMFLEX +0123;gcommaaccent;LATIN SMALL LETTER G WITH CEDILLA +0121;gdotaccent;LATIN SMALL LETTER G WITH DOT ABOVE +00DF;germandbls;LATIN SMALL LETTER SHARP S +2207;gradient;NABLA +0060;grave;GRAVE ACCENT +0300;gravecomb;COMBINING GRAVE ACCENT +003E;greater;GREATER-THAN SIGN +2265;greaterequal;GREATER-THAN OR EQUAL TO +00AB;guillemotleft;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +00BB;guillemotright;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +2039;guilsinglleft;SINGLE LEFT-POINTING ANGLE QUOTATION MARK +203A;guilsinglright;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK +0068;h;LATIN SMALL LETTER H +0127;hbar;LATIN SMALL LETTER H WITH STROKE +0125;hcircumflex;LATIN SMALL LETTER H WITH CIRCUMFLEX +2665;heart;BLACK HEART SUIT +0309;hookabovecomb;COMBINING HOOK ABOVE +2302;house;HOUSE +02DD;hungarumlaut;DOUBLE ACUTE ACCENT +002D;hyphen;HYPHEN-MINUS +00AD;hyphen;SOFT HYPHEN;Duplicate +F6E5;hypheninferior;SUBSCRIPT HYPHEN-MINUS +F6E6;hyphensuperior;SUPERSCRIPT HYPHEN-MINUS +0069;i;LATIN SMALL LETTER I +00ED;iacute;LATIN SMALL LETTER I WITH ACUTE +012D;ibreve;LATIN SMALL LETTER I WITH BREVE +00EE;icircumflex;LATIN SMALL LETTER I WITH CIRCUMFLEX +00EF;idieresis;LATIN SMALL LETTER I WITH DIAERESIS +00EC;igrave;LATIN SMALL LETTER I WITH GRAVE +0133;ij;LATIN SMALL LIGATURE IJ +012B;imacron;LATIN SMALL LETTER I WITH MACRON +221E;infinity;INFINITY +222B;integral;INTEGRAL +2321;integralbt;BOTTOM HALF INTEGRAL +F8F5;integralex;INTEGRAL EXTENDER +2320;integraltp;TOP HALF INTEGRAL +2229;intersection;INTERSECTION +25D8;invbullet;INVERSE BULLET +25D9;invcircle;INVERSE WHITE CIRCLE +263B;invsmileface;BLACK SMILING FACE +012F;iogonek;LATIN SMALL LETTER I WITH OGONEK +03B9;iota;GREEK SMALL LETTER IOTA +03CA;iotadieresis;GREEK SMALL LETTER IOTA WITH DIALYTIKA +0390;iotadieresistonos;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS +03AF;iotatonos;GREEK SMALL LETTER IOTA WITH TONOS +F6ED;isuperior;SUPERSCRIPT LATIN SMALL LETTER I +0129;itilde;LATIN SMALL LETTER I WITH TILDE +006A;j;LATIN SMALL LETTER J +0135;jcircumflex;LATIN SMALL LETTER J WITH CIRCUMFLEX +006B;k;LATIN SMALL LETTER K +03BA;kappa;GREEK SMALL LETTER KAPPA +0137;kcommaaccent;LATIN SMALL LETTER K WITH CEDILLA +0138;kgreenlandic;LATIN SMALL LETTER KRA +006C;l;LATIN SMALL LETTER L +013A;lacute;LATIN SMALL LETTER L WITH ACUTE +03BB;lambda;GREEK SMALL LETTER LAMDA +013E;lcaron;LATIN SMALL LETTER L WITH CARON +013C;lcommaaccent;LATIN SMALL LETTER L WITH CEDILLA +0140;ldot;LATIN SMALL LETTER L WITH MIDDLE DOT +003C;less;LESS-THAN SIGN +2264;lessequal;LESS-THAN OR EQUAL TO +258C;lfblock;LEFT HALF BLOCK +20A4;lira;LIRA SIGN +F6C0;ll;LATIN SMALL LETTER LL +2227;logicaland;LOGICAL AND +00AC;logicalnot;NOT SIGN +2228;logicalor;LOGICAL OR +017F;longs;LATIN SMALL LETTER LONG S +25CA;lozenge;LOZENGE +0142;lslash;LATIN SMALL LETTER L WITH STROKE +F6EE;lsuperior;SUPERSCRIPT LATIN SMALL LETTER L +2591;ltshade;LIGHT SHADE +006D;m;LATIN SMALL LETTER M +00AF;macron;MACRON +02C9;macron;MODIFIER LETTER MACRON;Duplicate +2642;male;MALE SIGN +2212;minus;MINUS SIGN +2032;minute;PRIME +F6EF;msuperior;SUPERSCRIPT LATIN SMALL LETTER M +00B5;mu;MICRO SIGN +03BC;mu;GREEK SMALL LETTER MU;Duplicate +00D7;multiply;MULTIPLICATION SIGN +266A;musicalnote;EIGHTH NOTE +266B;musicalnotedbl;BEAMED EIGHTH NOTES +006E;n;LATIN SMALL LETTER N +0144;nacute;LATIN SMALL LETTER N WITH ACUTE +0149;napostrophe;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE +0148;ncaron;LATIN SMALL LETTER N WITH CARON +0146;ncommaaccent;LATIN SMALL LETTER N WITH CEDILLA +0039;nine;DIGIT NINE +2089;nineinferior;SUBSCRIPT NINE +F739;nineoldstyle;OLDSTYLE DIGIT NINE +2079;ninesuperior;SUPERSCRIPT NINE +2209;notelement;NOT AN ELEMENT OF +2260;notequal;NOT EQUAL TO +2284;notsubset;NOT A SUBSET OF +207F;nsuperior;SUPERSCRIPT LATIN SMALL LETTER N +00F1;ntilde;LATIN SMALL LETTER N WITH TILDE +03BD;nu;GREEK SMALL LETTER NU +0023;numbersign;NUMBER SIGN +006F;o;LATIN SMALL LETTER O +00F3;oacute;LATIN SMALL LETTER O WITH ACUTE +014F;obreve;LATIN SMALL LETTER O WITH BREVE +00F4;ocircumflex;LATIN SMALL LETTER O WITH CIRCUMFLEX +00F6;odieresis;LATIN SMALL LETTER O WITH DIAERESIS +0153;oe;LATIN SMALL LIGATURE OE +02DB;ogonek;OGONEK +00F2;ograve;LATIN SMALL LETTER O WITH GRAVE +01A1;ohorn;LATIN SMALL LETTER O WITH HORN +0151;ohungarumlaut;LATIN SMALL LETTER O WITH DOUBLE ACUTE +014D;omacron;LATIN SMALL LETTER O WITH MACRON +03C9;omega;GREEK SMALL LETTER OMEGA +03D6;omega1;GREEK PI SYMBOL +03CE;omegatonos;GREEK SMALL LETTER OMEGA WITH TONOS +03BF;omicron;GREEK SMALL LETTER OMICRON +03CC;omicrontonos;GREEK SMALL LETTER OMICRON WITH TONOS +0031;one;DIGIT ONE +2024;onedotenleader;ONE DOT LEADER +215B;oneeighth;VULGAR FRACTION ONE EIGHTH +F6DC;onefitted;PROPORTIONAL DIGIT ONE +00BD;onehalf;VULGAR FRACTION ONE HALF +2081;oneinferior;SUBSCRIPT ONE +F731;oneoldstyle;OLDSTYLE DIGIT ONE +00BC;onequarter;VULGAR FRACTION ONE QUARTER +00B9;onesuperior;SUPERSCRIPT ONE +2153;onethird;VULGAR FRACTION ONE THIRD +25E6;openbullet;WHITE BULLET +00AA;ordfeminine;FEMININE ORDINAL INDICATOR +00BA;ordmasculine;MASCULINE ORDINAL INDICATOR +221F;orthogonal;RIGHT ANGLE +00F8;oslash;LATIN SMALL LETTER O WITH STROKE +01FF;oslashacute;LATIN SMALL LETTER O WITH STROKE AND ACUTE +F6F0;osuperior;SUPERSCRIPT LATIN SMALL LETTER O +00F5;otilde;LATIN SMALL LETTER O WITH TILDE +0070;p;LATIN SMALL LETTER P +00B6;paragraph;PILCROW SIGN +0028;parenleft;LEFT PARENTHESIS +F8ED;parenleftbt;LEFT PAREN BOTTOM +F8EC;parenleftex;LEFT PAREN EXTENDER +208D;parenleftinferior;SUBSCRIPT LEFT PARENTHESIS +207D;parenleftsuperior;SUPERSCRIPT LEFT PARENTHESIS +F8EB;parenlefttp;LEFT PAREN TOP +0029;parenright;RIGHT PARENTHESIS +F8F8;parenrightbt;RIGHT PAREN BOTTOM +F8F7;parenrightex;RIGHT PAREN EXTENDER +208E;parenrightinferior;SUBSCRIPT RIGHT PARENTHESIS +207E;parenrightsuperior;SUPERSCRIPT RIGHT PARENTHESIS +F8F6;parenrighttp;RIGHT PAREN TOP +2202;partialdiff;PARTIAL DIFFERENTIAL +0025;percent;PERCENT SIGN +002E;period;FULL STOP +00B7;periodcentered;MIDDLE DOT +2219;periodcentered;BULLET OPERATOR;Duplicate +F6E7;periodinferior;SUBSCRIPT FULL STOP +F6E8;periodsuperior;SUPERSCRIPT FULL STOP +22A5;perpendicular;UP TACK +2030;perthousand;PER MILLE SIGN +20A7;peseta;PESETA SIGN +03C6;phi;GREEK SMALL LETTER PHI +03D5;phi1;GREEK PHI SYMBOL +03C0;pi;GREEK SMALL LETTER PI +002B;plus;PLUS SIGN +00B1;plusminus;PLUS-MINUS SIGN +211E;prescription;PRESCRIPTION TAKE +220F;product;N-ARY PRODUCT +2282;propersubset;SUBSET OF +2283;propersuperset;SUPERSET OF +221D;proportional;PROPORTIONAL TO +03C8;psi;GREEK SMALL LETTER PSI +0071;q;LATIN SMALL LETTER Q +003F;question;QUESTION MARK +00BF;questiondown;INVERTED QUESTION MARK +F7BF;questiondownsmall;SMALL CAPITAL INVERTED QUESTION MARK +F73F;questionsmall;SMALL CAPITAL QUESTION MARK +0022;quotedbl;QUOTATION MARK +201E;quotedblbase;DOUBLE LOW-9 QUOTATION MARK +201C;quotedblleft;LEFT DOUBLE QUOTATION MARK +201D;quotedblright;RIGHT DOUBLE QUOTATION MARK +2018;quoteleft;LEFT SINGLE QUOTATION MARK +201B;quotereversed;SINGLE HIGH-REVERSED-9 QUOTATION MARK +2019;quoteright;RIGHT SINGLE QUOTATION MARK +201A;quotesinglbase;SINGLE LOW-9 QUOTATION MARK +0027;quotesingle;APOSTROPHE +0072;r;LATIN SMALL LETTER R +0155;racute;LATIN SMALL LETTER R WITH ACUTE +221A;radical;SQUARE ROOT +F8E5;radicalex;RADICAL EXTENDER +0159;rcaron;LATIN SMALL LETTER R WITH CARON +0157;rcommaaccent;LATIN SMALL LETTER R WITH CEDILLA +2286;reflexsubset;SUBSET OF OR EQUAL TO +2287;reflexsuperset;SUPERSET OF OR EQUAL TO +00AE;registered;REGISTERED SIGN +F8E8;registersans;REGISTERED SIGN SANS SERIF +F6DA;registerserif;REGISTERED SIGN SERIF +2310;revlogicalnot;REVERSED NOT SIGN +03C1;rho;GREEK SMALL LETTER RHO +02DA;ring;RING ABOVE +F6F1;rsuperior;SUPERSCRIPT LATIN SMALL LETTER R +2590;rtblock;RIGHT HALF BLOCK +F6DD;rupiah;RUPIAH SIGN +0073;s;LATIN SMALL LETTER S +015B;sacute;LATIN SMALL LETTER S WITH ACUTE +0161;scaron;LATIN SMALL LETTER S WITH CARON +015F;scedilla;LATIN SMALL LETTER S WITH CEDILLA +F6C2;scedilla;LATIN SMALL LETTER S WITH CEDILLA;Duplicate +015D;scircumflex;LATIN SMALL LETTER S WITH CIRCUMFLEX +0219;scommaaccent;LATIN SMALL LETTER S WITH COMMA BELOW +2033;second;DOUBLE PRIME +00A7;section;SECTION SIGN +003B;semicolon;SEMICOLON +0037;seven;DIGIT SEVEN +215E;seveneighths;VULGAR FRACTION SEVEN EIGHTHS +2087;seveninferior;SUBSCRIPT SEVEN +F737;sevenoldstyle;OLDSTYLE DIGIT SEVEN +2077;sevensuperior;SUPERSCRIPT SEVEN +2592;shade;MEDIUM SHADE +03C3;sigma;GREEK SMALL LETTER SIGMA +03C2;sigma1;GREEK SMALL LETTER FINAL SIGMA +223C;similar;TILDE OPERATOR +0036;six;DIGIT SIX +2086;sixinferior;SUBSCRIPT SIX +F736;sixoldstyle;OLDSTYLE DIGIT SIX +2076;sixsuperior;SUPERSCRIPT SIX +002F;slash;SOLIDUS +263A;smileface;WHITE SMILING FACE +0020;space;SPACE +00A0;space;NO-BREAK SPACE;Duplicate +2660;spade;BLACK SPADE SUIT +F6F2;ssuperior;SUPERSCRIPT LATIN SMALL LETTER S +00A3;sterling;POUND SIGN +220B;suchthat;CONTAINS AS MEMBER +2211;summation;N-ARY SUMMATION +263C;sun;WHITE SUN WITH RAYS +0074;t;LATIN SMALL LETTER T +03C4;tau;GREEK SMALL LETTER TAU +0167;tbar;LATIN SMALL LETTER T WITH STROKE +0165;tcaron;LATIN SMALL LETTER T WITH CARON +0163;tcommaaccent;LATIN SMALL LETTER T WITH CEDILLA +021B;tcommaaccent;LATIN SMALL LETTER T WITH COMMA BELOW;Duplicate +2234;therefore;THEREFORE +03B8;theta;GREEK SMALL LETTER THETA +03D1;theta1;GREEK THETA SYMBOL +00FE;thorn;LATIN SMALL LETTER THORN +0033;three;DIGIT THREE +215C;threeeighths;VULGAR FRACTION THREE EIGHTHS +2083;threeinferior;SUBSCRIPT THREE +F733;threeoldstyle;OLDSTYLE DIGIT THREE +00BE;threequarters;VULGAR FRACTION THREE QUARTERS +F6DE;threequartersemdash;THREE QUARTERS EM DASH +00B3;threesuperior;SUPERSCRIPT THREE +02DC;tilde;SMALL TILDE +0303;tildecomb;COMBINING TILDE +0384;tonos;GREEK TONOS +2122;trademark;TRADE MARK SIGN +F8EA;trademarksans;TRADE MARK SIGN SANS SERIF +F6DB;trademarkserif;TRADE MARK SIGN SERIF +25BC;triagdn;BLACK DOWN-POINTING TRIANGLE +25C4;triaglf;BLACK LEFT-POINTING POINTER +25BA;triagrt;BLACK RIGHT-POINTING POINTER +25B2;triagup;BLACK UP-POINTING TRIANGLE +F6F3;tsuperior;SUPERSCRIPT LATIN SMALL LETTER T +0032;two;DIGIT TWO +2025;twodotenleader;TWO DOT LEADER +2082;twoinferior;SUBSCRIPT TWO +F732;twooldstyle;OLDSTYLE DIGIT TWO +00B2;twosuperior;SUPERSCRIPT TWO +2154;twothirds;VULGAR FRACTION TWO THIRDS +0075;u;LATIN SMALL LETTER U +00FA;uacute;LATIN SMALL LETTER U WITH ACUTE +016D;ubreve;LATIN SMALL LETTER U WITH BREVE +00FB;ucircumflex;LATIN SMALL LETTER U WITH CIRCUMFLEX +00FC;udieresis;LATIN SMALL LETTER U WITH DIAERESIS +00F9;ugrave;LATIN SMALL LETTER U WITH GRAVE +01B0;uhorn;LATIN SMALL LETTER U WITH HORN +0171;uhungarumlaut;LATIN SMALL LETTER U WITH DOUBLE ACUTE +016B;umacron;LATIN SMALL LETTER U WITH MACRON +005F;underscore;LOW LINE +2017;underscoredbl;DOUBLE LOW LINE +222A;union;UNION +2200;universal;FOR ALL +0173;uogonek;LATIN SMALL LETTER U WITH OGONEK +2580;upblock;UPPER HALF BLOCK +03C5;upsilon;GREEK SMALL LETTER UPSILON +03CB;upsilondieresis;GREEK SMALL LETTER UPSILON WITH DIALYTIKA +03B0;upsilondieresistonos;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS +03CD;upsilontonos;GREEK SMALL LETTER UPSILON WITH TONOS +016F;uring;LATIN SMALL LETTER U WITH RING ABOVE +0169;utilde;LATIN SMALL LETTER U WITH TILDE +0076;v;LATIN SMALL LETTER V +0077;w;LATIN SMALL LETTER W +1E83;wacute;LATIN SMALL LETTER W WITH ACUTE +0175;wcircumflex;LATIN SMALL LETTER W WITH CIRCUMFLEX +1E85;wdieresis;LATIN SMALL LETTER W WITH DIAERESIS +2118;weierstrass;SCRIPT CAPITAL P +1E81;wgrave;LATIN SMALL LETTER W WITH GRAVE +0078;x;LATIN SMALL LETTER X +03BE;xi;GREEK SMALL LETTER XI +0079;y;LATIN SMALL LETTER Y +00FD;yacute;LATIN SMALL LETTER Y WITH ACUTE +0177;ycircumflex;LATIN SMALL LETTER Y WITH CIRCUMFLEX +00FF;ydieresis;LATIN SMALL LETTER Y WITH DIAERESIS +00A5;yen;YEN SIGN +1EF3;ygrave;LATIN SMALL LETTER Y WITH GRAVE +007A;z;LATIN SMALL LETTER Z +017A;zacute;LATIN SMALL LETTER Z WITH ACUTE +017E;zcaron;LATIN SMALL LETTER Z WITH CARON +017C;zdotaccent;LATIN SMALL LETTER Z WITH DOT ABOVE +0030;zero;DIGIT ZERO +2080;zeroinferior;SUBSCRIPT ZERO +F730;zerooldstyle;OLDSTYLE DIGIT ZERO +2070;zerosuperior;SUPERSCRIPT ZERO +03B6;zeta;GREEK SMALL LETTER ZETA + +# +# Name: ITC Zapf Dingbats encoding, Unicode values, and +# glyph names +# Table version: 1.0 +# Date: 17 July 1997 +# +# Version of ITC Zapf Dingbats: +# +# ITC Zapf Dingbats (PostScript FontName: ZapfDingbats) contains 202 +# of the 379 glyphs in PCL Zapf Dingbats. +# +# Versions of ZapfDingbats previous to 002.000 do not encode 14 out of the +# 202 available glyphs in their PostScript encoding (though these 14 glyphs +# can be accessed on the Macintosh due to the FOND's reencoding of the +# glyphs). ZapfDingbats version 002.000 encodes all of the 202 glyphs in its +# PostScript encoding. +# +# Unicode encoding of ZapfDingbats: +# +# The 188 glyphs in the PostScript encoding of versions of ZapfDingbats +# previous to 002.000 have regular Unicode values (160 in the Dingbats block +# and 28 in other blocks). The remaining 14 glyphs have been assigned +# Unicode values in the Corporate Use subarea, and coincide exactly with +# Apple's MacOS Dingbats assignments in that area. +# +# Format: Four tab-separated columns: +# +# (1) The PostScript encoding. (2 uppercase hexadecimal digits) +# 202 code points are defined. +# Source: Adobe Systems. +# +# (2) The Unicode value. (4 uppercase hexadecimal digits) +# The 14 glyphs at code points 0x80-8D have Corporate Use subarea +# values. +# Source: ftp://unicode.org/pub/UNIX/MAPPINGS/VENDORS/APPLE/DINGBAT.TXT +# [as of 25 February 1997] +# +# (3) The glyph name. (upper- and lowercase letters, digits) +# Source: Adobe Systems. +# +# (4) The Unicode 2.0 character name. (uppercase letters, hyphen, space) +# Source: The Unicode Standard, Version 2.0 +# +# The 14 Corporate Use subarea glyphs obviously don't have a +# Unicode 2.0 character name. A descriptive name (in lowercase +# letters) taken from the source for (2) above is used instead. +# +# The entries are in PostScript encoding order. +# +# Lines starting with "#" are comments; blank lines are to be ignored. +# + +0020;space;SPACE +2701;a1;UPPER BLADE SCISSORS +2702;a2;BLACK SCISSORS +2703;a202;LOWER BLADE SCISSORS +2704;a3;WHITE SCISSORS +260E;a4;BLACK TELEPHONE +2706;a5;TELEPHONE LOCATION SIGN +2707;a119;TAPE DRIVE +2708;a118;AIRPLANE +2709;a117;ENVELOPE +261B;a11;BLACK RIGHT POINTING INDEX +261E;a12;WHITE RIGHT POINTING INDEX +270C;a13;VICTORY HAND +270D;a14;WRITING HAND +270E;a15;LOWER RIGHT PENCIL +270F;a16;PENCIL +2710;a105;UPPER RIGHT PENCIL +2711;a17;WHITE NIB +2712;a18;BLACK NIB +2713;a19;CHECK MARK +2714;a20;HEAVY CHECK MARK +2715;a21;MULTIPLICATION X +2716;a22;HEAVY MULTIPLICATION X +2717;a23;BALLOT X +2718;a24;HEAVY BALLOT X +2719;a25;OUTLINED GREEK CROSS +271A;a26;HEAVY GREEK CROSS +271B;a27;OPEN CENTRE CROSS +271C;a28;HEAVY OPEN CENTRE CROSS +271D;a6;LATIN CROSS +271E;a7;SHADOWED WHITE LATIN CROSS +271F;a8;OUTLINED LATIN CROSS +2720;a9;MALTESE CROSS +2721;a10;STAR OF DAVID +2722;a29;FOUR TEARDROP-SPOKED ASTERISK +2723;a30;FOUR BALLOON-SPOKED ASTERISK +2724;a31;HEAVY FOUR BALLOON-SPOKED ASTERISK +2725;a32;FOUR CLUB-SPOKED ASTERISK +2726;a33;BLACK FOUR POINTED STAR +2727;a34;WHITE FOUR POINTED STAR +2605;a35;BLACK STAR +2729;a36;STRESS OUTLINED WHITE STAR +272A;a37;CIRCLED WHITE STAR +272B;a38;OPEN CENTRE BLACK STAR +272C;a39;BLACK CENTRE WHITE STAR +272D;a40;OUTLINED BLACK STAR +272E;a41;HEAVY OUTLINED BLACK STAR +272F;a42;PINWHEEL STAR +2730;a43;SHADOWED WHITE STAR +2731;a44;HEAVY ASTERISK +2732;a45;OPEN CENTRE ASTERISK +2733;a46;EIGHT SPOKED ASTERISK +2734;a47;EIGHT POINTED BLACK STAR +2735;a48;EIGHT POINTED PINWHEEL STAR +2736;a49;SIX POINTED BLACK STAR +2737;a50;EIGHT POINTED RECTILINEAR BLACK STAR +2738;a51;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR +2739;a52;TWELVE POINTED BLACK STAR +273A;a53;SIXTEEN POINTED ASTERISK +273B;a54;TEARDROP-SPOKED ASTERISK +273C;a55;OPEN CENTRE TEARDROP-SPOKED ASTERISK +273D;a56;HEAVY TEARDROP-SPOKED ASTERISK +273E;a57;SIX PETALLED BLACK AND WHITE FLORETTE +273F;a58;BLACK FLORETTE +2740;a59;WHITE FLORETTE +2741;a60;EIGHT PETALLED OUTLINED BLACK FLORETTE +2742;a61;CIRCLED OPEN CENTRE EIGHT POINTED STAR +2743;a62;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK +2744;a63;SNOWFLAKE +2745;a64;TIGHT TRIFOLIATE SNOWFLAKE +2746;a65;HEAVY CHEVRON SNOWFLAKE +2747;a66;SPARKLE +2748;a67;HEAVY SPARKLE +2749;a68;BALLOON-SPOKED ASTERISK +274A;a69;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK +274B;a70;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK +25CF;a71;BLACK CIRCLE +274D;a72;SHADOWED WHITE CIRCLE +25A0;a73;BLACK SQUARE +274F;a74;LOWER RIGHT DROP-SHADOWED WHITE SQUARE +2750;a203;UPPER RIGHT DROP-SHADOWED WHITE SQUARE +2751;a75;LOWER RIGHT SHADOWED WHITE SQUARE +2752;a204;UPPER RIGHT SHADOWED WHITE SQUARE +25B2;a76;BLACK UP-POINTING TRIANGLE +25BC;a77;BLACK DOWN-POINTING TRIANGLE +25C6;a78;BLACK DIAMOND +2756;a79;BLACK DIAMOND MINUS WHITE X +25D7;a81;RIGHT HALF BLACK CIRCLE +2758;a82;LIGHT VERTICAL BAR +2759;a83;MEDIUM VERTICAL BAR +275A;a84;HEAVY VERTICAL BAR +275B;a97;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT +275C;a98;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT +275D;a99;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT +275E;a100;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT +F8D7;a89;MEDIUM LEFT PARENTHESIS ORNAMENT +F8D8;a90;MEDIUM RIGHT PARENTHESIS ORNAMENT +F8D9;a93;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT +F8DA;a94;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT +F8DB;a91;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT +F8DC;a92;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT +F8DD;a205;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT +F8DE;a85;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT +F8DF;a206;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT +F8E0;a86;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT +F8E1;a87;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT +F8E2;a88;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT +F8E3;a95;MEDIUM LEFT CURLY BRACKET ORNAMENT +F8E4;a96;MEDIUM RIGHT CURLY BRACKET ORNAMENT +2761;a101;CURVED STEM PARAGRAPH SIGN ORNAMENT +2762;a102;HEAVY EXCLAMATION MARK ORNAMENT +2763;a103;HEAVY HEART EXCLAMATION MARK ORNAMENT +2764;a104;HEAVY BLACK HEART +2765;a106;ROTATED HEAVY BLACK HEART BULLET +2766;a107;FLORAL HEART +2767;a108;ROTATED FLORAL HEART BULLET +2663;a112;BLACK CLUB SUIT +2666;a111;BLACK DIAMOND SUIT +2665;a110;BLACK HEART SUIT +2660;a109;BLACK SPADE SUIT +2460;a120;CIRCLED DIGIT ONE +2461;a121;CIRCLED DIGIT TWO +2462;a122;CIRCLED DIGIT THREE +2463;a123;CIRCLED DIGIT FOUR +2464;a124;CIRCLED DIGIT FIVE +2465;a125;CIRCLED DIGIT SIX +2466;a126;CIRCLED DIGIT SEVEN +2467;a127;CIRCLED DIGIT EIGHT +2468;a128;CIRCLED DIGIT NINE +2469;a129;CIRCLED NUMBER TEN +2776;a130;DINGBAT NEGATIVE CIRCLED DIGIT ONE +2777;a131;DINGBAT NEGATIVE CIRCLED DIGIT TWO +2778;a132;DINGBAT NEGATIVE CIRCLED DIGIT THREE +2779;a133;DINGBAT NEGATIVE CIRCLED DIGIT FOUR +277A;a134;DINGBAT NEGATIVE CIRCLED DIGIT FIVE +277B;a135;DINGBAT NEGATIVE CIRCLED DIGIT SIX +277C;a136;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN +277D;a137;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT +277E;a138;DINGBAT NEGATIVE CIRCLED DIGIT NINE +277F;a139;DINGBAT NEGATIVE CIRCLED NUMBER TEN +2780;a140;DINGBAT CIRCLED SANS-SERIF DIGIT ONE +2781;a141;DINGBAT CIRCLED SANS-SERIF DIGIT TWO +2782;a142;DINGBAT CIRCLED SANS-SERIF DIGIT THREE +2783;a143;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR +2784;a144;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE +2785;a145;DINGBAT CIRCLED SANS-SERIF DIGIT SIX +2786;a146;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN +2787;a147;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT +2788;a148;DINGBAT CIRCLED SANS-SERIF DIGIT NINE +2789;a149;DINGBAT CIRCLED SANS-SERIF NUMBER TEN +278A;a150;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE +278B;a151;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO +278C;a152;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE +278D;a153;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR +278E;a154;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE +278F;a155;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX +2790;a156;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN +2791;a157;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT +2792;a158;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE +2793;a159;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN +2794;a160;HEAVY WIDE-HEADED RIGHTWARDS ARROW +2192;a161;RIGHTWARDS ARROW +2194;a163;LEFT RIGHT ARROW +2195;a164;UP DOWN ARROW +2798;a196;HEAVY SOUTH EAST ARROW +2799;a165;HEAVY RIGHTWARDS ARROW +279A;a192;HEAVY NORTH EAST ARROW +279B;a166;DRAFTING POINT RIGHTWARDS ARROW +279C;a167;HEAVY ROUND-TIPPED RIGHTWARDS ARROW +279D;a168;TRIANGLE-HEADED RIGHTWARDS ARROW +279E;a169;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW +279F;a170;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW +27A0;a171;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW +27A1;a172;BLACK RIGHTWARDS ARROW +27A2;a173;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD +27A3;a162;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD +27A4;a174;BLACK RIGHTWARDS ARROWHEAD +27A5;a175;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW +27A6;a176;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW +27A7;a177;SQUAT BLACK RIGHTWARDS ARROW +27A8;a178;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW +27A9;a179;RIGHT-SHADED WHITE RIGHTWARDS ARROW +27AA;a193;LEFT-SHADED WHITE RIGHTWARDS ARROW +27AB;a180;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW +27AC;a199;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW +27AD;a181;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW +27AE;a200;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW +27AF;a182;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW +27B1;a201;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW +27B2;a183;CIRCLED HEAVY WHITE RIGHTWARDS ARROW +27B3;a184;WHITE-FEATHERED RIGHTWARDS ARROW +27B4;a197;BLACK-FEATHERED SOUTH EAST ARROW +27B5;a185;BLACK-FEATHERED RIGHTWARDS ARROW +27B6;a194;BLACK-FEATHERED NORTH EAST ARROW +27B7;a198;HEAVY BLACK-FEATHERED SOUTH EAST ARROW +27B8;a186;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW +27B9;a195;HEAVY BLACK-FEATHERED NORTH EAST ARROW +27BA;a187;TEARDROP-BARBED RIGHTWARDS ARROW +27BB;a188;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW +27BC;a189;WEDGE-TAILED RIGHTWARDS ARROW +27BD;a190;HEAVY WEDGE-TAILED RIGHTWARDS ARROW +27BE;a191;OPEN-OUTLINED RIGHTWARDS ARROW diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..e8a7509 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,12 @@ +# Sources +DIR_SOURCES := rufl_character_set_test.c rufl_decompose.c rufl_dump_state.c \ + rufl_find.c rufl_init.c rufl_invalidate_cache.c \ + rufl_metrics.c rufl_paint.c rufl_quit.c strfuncs.c + +SOURCES := $(SOURCES) $(BUILDDIR)/rufl_glyph_map.c + +$(BUILDDIR)/rufl_glyph_map.c: src/Glyphs + $(VQ)$(ECHO) "MKGLYPHS: $<" + $(Q)$(PERL) build/tools/makeglyphs < $< > $@ + +include build/makefiles/Makefile.subdir diff --git a/src/rufl_character_set_test.c b/src/rufl_character_set_test.c new file mode 100644 index 0000000..45fbcaf --- /dev/null +++ b/src/rufl_character_set_test.c @@ -0,0 +1,37 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2005 James Bursa + */ + +#include "rufl_internal.h" + + +/** + * Test if a character set contains a character. + * + * \param charset character set + * \param c character code + * \return true if present, false if absent + */ + +bool rufl_character_set_test(struct rufl_character_set *charset, + unsigned int c) +{ + unsigned int block = c >> 8; + unsigned int byte = (c >> 3) & 31; + unsigned int bit = c & 7; + + if (256 <= block) + return false; + + if (charset->index[block] == BLOCK_EMPTY) + return false; + else if (charset->index[block] == BLOCK_FULL) + return true; + else { + unsigned char z = charset->block[charset->index[block]][byte]; + return z & (1 << bit); + } +} diff --git a/src/rufl_decompose.c b/src/rufl_decompose.c new file mode 100644 index 0000000..edf9748 --- /dev/null +++ b/src/rufl_decompose.c @@ -0,0 +1,161 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2005 John-Mark Bell + */ + +#include +#include + +#include "oslib/font.h" + +#include "rufl_internal.h" + +/** + * Process a Draw path object + * + * \param path Pointer to path block + * \param funcs Struct of callback functions + * \param user User pointer to be passed to callbacks + * \return Pointer to word after this path, or NULL to terminate processing + */ +static int *process_path(int *path, struct rufl_decomp_funcs *funcs, + void *user) +{ + /* skip forward to style entry */ + path += 9; + + /* skip dash pattern */ + if (path[0] & (1<<7)) + path += path[2] + 2; + + /* and move to start of path components */ + path++; + + while (path[0] != 0) { + switch (path[0]) { + case 2: /* Move to */ + if (funcs->move_to((os_coord *)(path + 1), user)) + return NULL; + path += 3; + break; + case 5: /* Close path */ + path++; + break; + case 6: /* Cubic Bezier to */ + if (funcs->cubic_to((os_coord *)(path + 1), + (os_coord *)(path + 3), + (os_coord *)(path + 5), + user)) + return NULL; + path += 7; + break; + case 8: /* Line to */ + if (funcs->line_to((os_coord *)(path + 1), user)) + return NULL; + path += 3; + break; + default: /* Anything else is broken */ + assert(0); + } + } + + /* + 1 to account for tag 0 - end of path */ + return path + 1; +} + +rufl_code rufl_decompose_glyph(const char *font_family, + rufl_style font_style, unsigned int font_size, + const char *string, size_t len, + struct rufl_decomp_funcs *funcs, void *user) +{ + int *buf, *p, *ep; + int buf_size; + char *buf_end; + rufl_code err; + + /* Get required buffer size */ + rufl_fm_error = xfont_switch_output_to_buffer( + font_NO_OUTPUT | font_ADD_HINTS, (byte *)8, 0); + if (rufl_fm_error) { + LOG("xfont_switch_output_to_buffer: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + + err = rufl_paint(font_family, font_style, font_size, string, len, + 0, 0, rufl_BLEND_FONT); + if (err) { + /* reset font redirection - too bad if this fails */ + xfont_switch_output_to_buffer(0, 0, 0); + return err; + } + + rufl_fm_error = xfont_switch_output_to_buffer(0, NULL, &buf_end); + if (rufl_fm_error) { + LOG("xfont_switch_output_to_buffer: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + buf_size = buf_end - (char *)NULL; + + /* Allocate and initialise buffer */ + buf = malloc(buf_size); + if (!buf) { + LOG("Failed to allocate decompose buffer of size %i", buf_size); + return rufl_OUT_OF_MEMORY; + } + buf[0] = 0; + buf[1] = buf_size - 8; + + /* Populate buffer */ + rufl_fm_error = xfont_switch_output_to_buffer( + font_ADD_HINTS, (byte *)buf, 0); + if (rufl_fm_error) { + LOG("xfont_switch_output_to_buffer: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + free(buf); + return rufl_FONT_MANAGER_ERROR; + } + + err = rufl_paint(font_family, font_style, font_size, string, len, + 0, 0, rufl_BLEND_FONT); + if (err) { + /* reset font redirection - too bad if this fails */ + xfont_switch_output_to_buffer(0, 0, 0); + free(buf); + return err; + } + + rufl_fm_error = xfont_switch_output_to_buffer(0, 0, &buf_end); + if (rufl_fm_error) { + LOG("xfont_switch_output_to_buffer: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + free(buf); + return rufl_FONT_MANAGER_ERROR; + } + ep = (int *)(void *)buf_end; + + /* Parse buffer, calling callbacks as required */ + for (p = buf; p < ep;) { + if (p[0] != 2) { + LOG("Object type %d not known", p[0]); + break; + } + + p = process_path(p, funcs, user); + + /* Have the callbacks asked for us to stop? */ + if (p == NULL) + break; + } + + free(buf); + + return rufl_OK; +} diff --git a/src/rufl_dump_state.c b/src/rufl_dump_state.c new file mode 100644 index 0000000..06a1f22 --- /dev/null +++ b/src/rufl_dump_state.c @@ -0,0 +1,138 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +#include +#include "rufl_internal.h" + + +static void rufl_dump_character_set(struct rufl_character_set *charset); +static void rufl_dump_unicode_map(struct rufl_unicode_map *umap); +static void rufl_dump_substitution_table(void); + + +/** + * Dump the internal library state to stdout. + */ + +void rufl_dump_state(void) +{ + unsigned int i, j; + + printf("rufl_font_list:\n"); + for (i = 0; i != rufl_font_list_entries; i++) { + printf(" %u \"%s\"\n", i, rufl_font_list[i].identifier); + if (rufl_font_list[i].charset) { + printf(" "); + rufl_dump_character_set(rufl_font_list[i].charset); + printf("\n"); + } else { + printf(" (no charset table)\n"); + } + if (rufl_font_list[i].umap) { + for (j = 0; j < rufl_font_list[i].num_umaps; j++) { + struct rufl_unicode_map *map = + rufl_font_list[i].umap + j; + + printf(" "); + rufl_dump_unicode_map(map); + printf("\n"); + } + } + } + + printf("rufl_family_list:\n"); + for (i = 0; i != rufl_family_list_entries; i++) { + printf(" %u \"%s\"\n", i, rufl_family_list[i]); + for (j = 0; j != 9; j++) { + struct rufl_family_map_entry *e = &rufl_family_map[i]; + printf(" %u ", j); + if (e->font[j][0] == NO_FONT) + printf("- "); + else + printf("\"%s\" ", rufl_font_list[e->font[j][0]]. + identifier); + if (e->font[j][1] == NO_FONT) + printf("- "); + else + printf("\"%s\" ", rufl_font_list[e->font[j][1]]. + identifier); + printf("\n"); + } + } + + printf("rufl_substitution_table:\n"); + rufl_dump_substitution_table(); +} + + +/** + * Dump a representation of a character set to stdout. + * + * \param charset character set to print + */ + +void rufl_dump_character_set(struct rufl_character_set *charset) +{ + unsigned int u, t; + + u = 0; + while (u != 0x10000) { + while (u != 0x10000 && !rufl_character_set_test(charset, u)) + u++; + if (u != 0x10000) { + if (!rufl_character_set_test(charset, u + 1)) { + printf("%x ", u); + u++; + } else { + t = u; + while (rufl_character_set_test(charset, u)) + u++; + printf("%x-%x ", t, u - 1); + } + } + } +} + + +/** + * Dump a representation of a unicode map to stdout. + * + * \param umap unicode map to print + */ + +void rufl_dump_unicode_map(struct rufl_unicode_map *umap) +{ + unsigned int i; + + if (umap->encoding) + printf("%s: ", umap->encoding); + + for (i = 0; i != umap->entries; i++) + printf("%x:%x ", umap->map[i].u, umap->map[i].c); +} + + +/** + * Dump a representation of the substitution table to stdout. + */ + +void rufl_dump_substitution_table(void) +{ + unsigned int font; + unsigned int u, t; + + u = 0; + while (u != 0x10000) { + t = u; + font = rufl_substitution_table[t]; + while (u != 0x10000 && font == rufl_substitution_table[u]) + u++; + if (font != NOT_AVAILABLE) + printf(" %x-%x => %u \"%s\"\n", t, u - 1, + font, rufl_font_list[font].identifier); + } +} diff --git a/src/rufl_find.c b/src/rufl_find.c new file mode 100644 index 0000000..a1c2785 --- /dev/null +++ b/src/rufl_find.c @@ -0,0 +1,201 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2005 James Bursa + * Copyright 2005 John-Mark Bell + */ + +#include +#include +#include +#include +#include + +#include "rufl_internal.h" + +static int rufl_family_list_cmp(const void *keyval, const void *datum); +static rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size, + const char *encoding, font_f f); + +/** + * Find a font family. + */ +rufl_code rufl_find_font_family(const char *font_family, + rufl_style font_style, unsigned int *font, + unsigned int *slanted, struct rufl_character_set **charset) +{ + const char **family; + unsigned int f; + unsigned int weight, slant, used_weight; + unsigned int search_direction; + + family = bsearch(font_family, rufl_family_list, + rufl_family_list_entries, + sizeof rufl_family_list[0], rufl_family_list_cmp); + if (!family) + return rufl_FONT_NOT_FOUND; + + weight = (font_style & 0xf) - 1; + assert(weight <= 8); + slant = font_style & rufl_SLANTED ? 1 : 0; + + struct rufl_family_map_entry *e = + &rufl_family_map[family - rufl_family_list]; + used_weight = weight; + if (weight <= 2) + search_direction = -1; + else + search_direction = +1; + while (1) { + if (e->font[used_weight][slant] != NO_FONT) { + /* the weight and slant is available */ + f = e->font[used_weight][slant]; + break; + } + if (e->font[used_weight][1 - slant] != NO_FONT) { + /* slanted, and non-slanted weight exists, or vv. */ + f = e->font[used_weight][1 - slant]; + break; + } + if (used_weight == 0) { + /* searched down without finding a weight: search up */ + used_weight = weight + 1; + search_direction = +1; + } else if (used_weight == 8) { + /* searched up without finding a weight: search down */ + used_weight = weight - 1; + search_direction = -1; + } else { + /* try the next weight in the current direction */ + used_weight += search_direction; + } + } + + if (font) + (*font) = f; + + if (slanted) + (*slanted) = slant; + + if (charset) + (*charset) = rufl_font_list[f].charset; + + return rufl_OK; +} + + +/** + * Find a sized font, placing in the cache if necessary. + */ +rufl_code rufl_find_font(unsigned int font, unsigned int font_size, + const char *encoding, font_f *fhandle) +{ + font_f f; + char font_name[80]; + unsigned int i; + rufl_code code; + + assert(fhandle != NULL); + + for (i = 0; i != rufl_CACHE_SIZE; i++) { + /* Comparing pointers for the encoding is fine, as the + * encoding string passed to us is either: + * + * a) NULL + * or b) statically allocated + * or c) resides in the font's umap, which is constant + * for the lifetime of the application. + */ + if (rufl_cache[i].font == font && + rufl_cache[i].size == font_size && + rufl_cache[i].encoding == encoding) + break; + } + if (i != rufl_CACHE_SIZE) { + /* found in cache */ + f = rufl_cache[i].f; + rufl_cache[i].last_used = rufl_cache_time++; + } else { + /* not found */ + if (font == rufl_CACHE_CORPUS) { + if (encoding) + snprintf(font_name, sizeof font_name, + "Corpus.Medium\\E%s", encoding); + else + snprintf(font_name, sizeof font_name, + "Corpus.Medium"); + } else { + if (encoding) + snprintf(font_name, sizeof font_name, + "%s\\E%s", + rufl_font_list[font].identifier, + encoding); + else + snprintf(font_name, sizeof font_name, "%s", + rufl_font_list[font].identifier); + } + + rufl_fm_error = xfont_find_font(font_name, + font_size, font_size, 0, 0, &f, 0, 0); + if (rufl_fm_error) { + LOG("xfont_find_font: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + /* place in cache */ + code = rufl_place_in_cache(font, font_size, encoding, f); + if (code != rufl_OK) + return code; + } + + (*fhandle) = f; + + return rufl_OK; +} + + +int rufl_family_list_cmp(const void *keyval, const void *datum) +{ + const char *key = keyval; + const char * const *entry = datum; + return strcasecmp(key, *entry); +} + + +/** + * Place a font into the recent-use cache, making space if necessary. + */ + +rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size, + const char *encoding, font_f f) +{ + unsigned int i; + unsigned int max_age = 0; + unsigned int evict = 0; + + for (i = 0; i != rufl_CACHE_SIZE; i++) { + if (rufl_cache[i].font == rufl_CACHE_NONE) { + evict = i; + break; + } else if (max_age < rufl_cache_time - + rufl_cache[i].last_used) { + max_age = rufl_cache_time - + rufl_cache[i].last_used; + evict = i; + } + } + if (rufl_cache[evict].font != rufl_CACHE_NONE) { + rufl_fm_error = xfont_lose_font(rufl_cache[evict].f); + if (rufl_fm_error) + return rufl_FONT_MANAGER_ERROR; + } + rufl_cache[evict].font = font; + rufl_cache[evict].size = font_size; + rufl_cache[evict].encoding = encoding; + rufl_cache[evict].f = f; + rufl_cache[evict].last_used = rufl_cache_time++; + + return rufl_OK; +} diff --git a/src/rufl_init.c b/src/rufl_init.c new file mode 100644 index 0000000..533955a --- /dev/null +++ b/src/rufl_init.c @@ -0,0 +1,1678 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +#define _GNU_SOURCE /* for strndup */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rufl_internal.h" + + +struct rufl_font_list_entry *rufl_font_list = 0; +size_t rufl_font_list_entries = 0; +const char **rufl_family_list = 0; +unsigned int rufl_family_list_entries = 0; +struct rufl_family_map_entry *rufl_family_map = 0; +os_error *rufl_fm_error = 0; +void *rufl_family_menu = 0; +unsigned short *rufl_substitution_table = 0; +struct rufl_cache_entry rufl_cache[rufl_CACHE_SIZE]; +int rufl_cache_time = 0; +bool rufl_old_font_manager = false; +wimp_w rufl_status_w = 0; +char rufl_status_buffer[80]; + +/** An entry in rufl_weight_table. */ +struct rufl_weight_table_entry { + const char *name; + unsigned int weight; +}; + +/** Map from font name part to font weight. Must be case-insensitive sorted by + * name. */ +const struct rufl_weight_table_entry rufl_weight_table[] = { + { "Black", 9 }, + { "Bold", 7 }, + { "Book", 3 }, + { "Demi", 6 }, + { "DemiBold", 6 }, + { "Extra", 8 }, + { "ExtraBlack", 9 }, + { "ExtraBold", 8 }, + { "ExtraLight", 1 }, + { "Heavy", 8 }, + { "Light", 2 }, + { "Medium", 5 }, + { "Regular", 4 }, + { "Semi", 6 }, + { "SemiBold", 6 }, + { "SemiLight", 3 }, + { "UltraBlack", 9 }, + { "UltraBold", 9 }, +}; + + +static rufl_code rufl_init_font_list(void); +static rufl_code rufl_init_add_font(const char *identifier, + const char *local_name); +static int rufl_weight_table_cmp(const void *keyval, const void *datum); +static rufl_code rufl_init_scan_font(unsigned int font); +static rufl_code rufl_init_scan_font_no_enumerate(unsigned int font); +static bool rufl_is_space(unsigned int u); +static rufl_code rufl_init_scan_font_old(unsigned int font_index); +static rufl_code rufl_init_scan_font_in_encoding(const char *font_name, + const char *encoding, struct rufl_character_set *charset, + struct rufl_unicode_map *umap, unsigned int *last); +static rufl_code rufl_init_read_encoding(font_f font, + struct rufl_unicode_map *umap); +static int rufl_glyph_map_cmp(const void *keyval, const void *datum); +static int rufl_unicode_map_cmp(const void *z1, const void *z2); +static rufl_code rufl_init_substitution_table(void); +static rufl_code rufl_save_cache(void); +static rufl_code rufl_load_cache(void); +static int rufl_font_list_cmp(const void *keyval, const void *datum); +static rufl_code rufl_init_family_menu(void); +static void rufl_init_status_open(void); +static void rufl_init_status(const char *status, float progress); +static void rufl_init_status_close(void); + + +/** + * Initialise RUfl. + * + * All available fonts are scanned. May take some time. + */ + +rufl_code rufl_init(void) +{ + bool rufl_broken_font_enumerate_characters = false; + unsigned int changes = 0; + unsigned int i; + int fm_version; + rufl_code code; + font_f font; + os_colour old_sand, old_glass; + + if (rufl_font_list_entries) + /* already initialized */ + return rufl_OK; + + xhourglass_on(); + + rufl_init_status_open(); + + /* determine if the font manager supports Unicode */ + rufl_fm_error = xfont_find_font("Homerton.Medium\\EUTF8", 160, 160, + 0, 0, &font, 0, 0); + if (rufl_fm_error) { + if (rufl_fm_error->errnum == error_FONT_ENCODING_NOT_FOUND) { + rufl_old_font_manager = true; + } else { + LOG("xfont_find_font: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + rufl_quit(); + xhourglass_off(); + return rufl_FONT_MANAGER_ERROR; + } + } else { + /* New font manager; see if character enumeration works */ + int next; + + rufl_fm_error = xfont_enumerate_characters(font, 0, + &next, NULL); + /* Broken if SWI fails or it doesn't return 0x20 as the first + * character to process. Font Managers earlier than 3.64 have + * a bug that means they do not return the first available + * range of characters in a font. We detect this by asking + * for the first character in Homerton.Medium, which we know + * is 0x20 (i.e. space). If the value returned is not this, + * then we assume the font manager is broken and fall back to + * the old code which is significantly slower. + */ + if (rufl_fm_error || next != 0x20) + rufl_broken_font_enumerate_characters = true; + + xfont_lose_font(font); + } + LOG("%s font manager", rufl_old_font_manager ? "old" : "new"); + + /* test if the font manager supports background blending */ + rufl_fm_error = xfont_cache_addr(&fm_version, 0, 0); + if (rufl_fm_error) + return rufl_FONT_MANAGER_ERROR; + if (fm_version >= 335) + rufl_can_background_blend = true; + + code = rufl_init_font_list(); + if (code != rufl_OK) { + rufl_quit(); + xhourglass_off(); + return code; + } + LOG("%zu faces, %u families", rufl_font_list_entries, + rufl_family_list_entries); + + code = rufl_load_cache(); + if (code != rufl_OK) { + LOG("rufl_load_cache: 0x%x", code); + rufl_quit(); + xhourglass_off(); + return code; + } + + xhourglass_leds(1, 0, 0); + for (i = 0; i != rufl_font_list_entries; i++) { + if (rufl_font_list[i].charset) { + /* character set loaded from cache */ + continue; + } + LOG("scanning %u \"%s\"", i, rufl_font_list[i].identifier); + xhourglass_percentage(100 * i / rufl_font_list_entries); + rufl_init_status(rufl_font_list[i].identifier, + (float) i / rufl_font_list_entries); + if (rufl_old_font_manager) + code = rufl_init_scan_font_old(i); + else if (rufl_broken_font_enumerate_characters) + code = rufl_init_scan_font_no_enumerate(i); + else + code = rufl_init_scan_font(i); + if (code != rufl_OK) { + LOG("rufl_init_scan_font: 0x%x", code); + rufl_quit(); + xhourglass_off(); + return code; + } + changes++; + } + + xhourglass_leds(2, 0, 0); + xhourglass_colours(0x0000ff, 0x00ffff, &old_sand, &old_glass); + code = rufl_init_substitution_table(); + if (code != rufl_OK) { + LOG("rufl_init_substitution_table: 0x%x", code); + rufl_quit(); + xhourglass_off(); + return code; + } + xhourglass_colours(old_sand, old_glass, 0, 0); + + if (changes) { + LOG("%u new charsets", changes); + xhourglass_leds(3, 0, 0); + code = rufl_save_cache(); + if (code != rufl_OK) { + LOG("rufl_save_cache: 0x%x", code); + rufl_quit(); + xhourglass_off(); + return code; + } + } + + for (i = 0; i != rufl_CACHE_SIZE; i++) + rufl_cache[i].font = rufl_CACHE_NONE; + + code = rufl_init_family_menu(); + if (code != rufl_OK) { + LOG("rufl_init_substitution_table: 0x%x", code); + rufl_quit(); + xhourglass_off(); + return code; + } + + rufl_init_status_close(); + + xhourglass_off(); + + return rufl_OK; +} + + +/** + * Build list of font in rufl_font_list and list of font families + * in rufl_family_list. + */ + +rufl_code rufl_init_font_list(void) +{ + rufl_code code; + font_list_context context = 0; + char identifier[80], local_name[80]; + + while (context != -1) { + /* read identifier */ + rufl_fm_error = xfont_list_fonts((byte *)identifier, + font_RETURN_FONT_NAME | + font_RETURN_LOCAL_FONT_NAME | + context, + sizeof identifier, + (byte *)local_name, sizeof local_name, 0, + &context, 0, 0); + if (rufl_fm_error) { + LOG("xfont_list_fonts: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + if (context == -1) + break; + + code = rufl_init_add_font(identifier, local_name); + if (code != rufl_OK) + return code; + } + + return rufl_OK; +} + + +rufl_code rufl_init_add_font(const char *identifier, const char *local_name) +{ + int size; + struct rufl_font_list_entry *font_list; + char *dot; + const char **family_list; + const char *family, *part; + unsigned int weight = 0; + unsigned int slant = 0; + bool special = false; + struct rufl_family_map_entry *family_map; + unsigned int i; + struct rufl_weight_table_entry *entry; + + /* Check that: + * a) it's not a RiScript generated font + * b) it's not a TeX font */ + + /* Read required buffer size */ + rufl_fm_error = xosfscontrol_canonicalise_path(identifier, 0, + "Font$Path", 0, 0, &size); + if (rufl_fm_error) { + LOG("xosfscontrol_canonicalise_path(\"%s\", ...): 0x%x: %s", + identifier, + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_OK; + } + /* size is -(space required - 1) so negate and add 1 */ + size = -size + 1; + + /* Create buffer and canonicalise path */ + char fullpath[size]; + rufl_fm_error = xosfscontrol_canonicalise_path(identifier, + fullpath, "Font$Path", 0, size, 0); + if (rufl_fm_error) { + LOG("xosfscontrol_canonicalise_path(\"%s\", ...): 0x%x: %s", + identifier, + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_OK; + } + + /* LOG("%s", fullpath); */ + + if (strstr(fullpath, "RiScript") || strstr(fullpath, "!TeXFonts")) + /* Ignore this font */ + return rufl_OK; + + /* add identifier to rufl_font_list */ + font_list = realloc(rufl_font_list, sizeof rufl_font_list[0] * + (rufl_font_list_entries + 1)); + if (!font_list) + return rufl_OUT_OF_MEMORY; + rufl_font_list = font_list; + rufl_font_list[rufl_font_list_entries].identifier = strdup(identifier); + if (!rufl_font_list[rufl_font_list_entries].identifier) + return rufl_OUT_OF_MEMORY; + rufl_font_list[rufl_font_list_entries].charset = 0; + rufl_font_list[rufl_font_list_entries].umap = 0; + rufl_font_list_entries++; + + /* determine family, weight, and slant */ + dot = strchr(local_name, '.'); + family = local_name; + if (dot) + *dot = 0; + while (dot) { + part = dot + 1; + dot = strchr(part, '.'); + if (dot) + *dot = 0; + if (strcasecmp(part, "Italic") == 0 || + strcasecmp(part, "Oblique") == 0) { + slant = 1; + continue; + } + entry = bsearch(part, rufl_weight_table, + sizeof rufl_weight_table / + sizeof rufl_weight_table[0], + sizeof rufl_weight_table[0], + rufl_weight_table_cmp); + if (entry) + weight = entry->weight; + else + special = true; /* unknown weight or style */ + } + if (!weight) + weight = 4; + weight--; + + if (rufl_family_list_entries == 0 || strcasecmp(family, + rufl_family_list[rufl_family_list_entries - 1]) != 0) { + /* new family */ + family_list = realloc(rufl_family_list, + sizeof rufl_family_list[0] * + (rufl_family_list_entries + 1)); + if (!family_list) + return rufl_OUT_OF_MEMORY; + rufl_family_list = family_list; + + family_map = realloc(rufl_family_map, + sizeof rufl_family_map[0] * + (rufl_family_list_entries + 1)); + if (!family_map) + return rufl_OUT_OF_MEMORY; + rufl_family_map = family_map; + + family = strdup(family); + if (!family) + return rufl_OUT_OF_MEMORY; + + rufl_family_list[rufl_family_list_entries] = family; + for (i = 0; i != 9; i++) + rufl_family_map[rufl_family_list_entries].font[i][0] = + rufl_family_map[rufl_family_list_entries].font[i][1] = + NO_FONT; + rufl_family_list_entries++; + } + + struct rufl_family_map_entry *e = + &rufl_family_map[rufl_family_list_entries - 1]; + /* prefer fonts with no unknown weight or style in their name, so that, + * for example, Alps.Light takes priority over Alps.Cond.Light */ + if (e->font[weight][slant] == NO_FONT || !special) + e->font[weight][slant] = rufl_font_list_entries - 1; + + rufl_font_list[rufl_font_list_entries - 1].family = + rufl_family_list_entries - 1; + rufl_font_list[rufl_font_list_entries - 1].weight = weight; + rufl_font_list[rufl_font_list_entries - 1].slant = slant; + + return rufl_OK; +} + + +int rufl_weight_table_cmp(const void *keyval, const void *datum) +{ + const char *key = keyval; + const struct rufl_weight_table_entry *entry = datum; + return strcasecmp(key, entry->name); +} + +/** + * Scan a font for available characters. + */ + +rufl_code rufl_init_scan_font(unsigned int font_index) +{ + char font_name[80]; + int x_out, y_out; + unsigned int byte, bit; + unsigned int last_used = 0; + unsigned int string[2] = { 0, 0 }; + unsigned int u, next; + struct rufl_character_set *charset; + struct rufl_character_set *charset2; + font_f font; + font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; + + /*LOG("font %u \"%s\"", font_index, + rufl_font_list[font_index].identifier);*/ + + charset = calloc(1, sizeof *charset); + if (!charset) + return rufl_OUT_OF_MEMORY; + for (u = 0; u != 256; u++) + charset->index[u] = BLOCK_EMPTY; + + snprintf(font_name, sizeof font_name, "%s\\EUTF8", + rufl_font_list[font_index].identifier); + + rufl_fm_error = xfont_find_font(font_name, 160, 160, 0, 0, &font, 0, 0); + if (rufl_fm_error) { + LOG("xfont_find_font(\"%s\"): 0x%x: %s", font_name, + rufl_fm_error->errnum, rufl_fm_error->errmess); + free(charset); + return rufl_OK; + } + + /* Scan through mapped characters */ + for (u = 0; u != (unsigned int) -1; u = next) { + unsigned int internal; + + rufl_fm_error = xfont_enumerate_characters(font, u, + (int *) &next, (int *) &internal); + if (rufl_fm_error) { + LOG("xfont_enumerate_characters: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + xfont_lose_font(font); + free(charset); + return rufl_OK; + } + + /* Skip DELETE and C0/C1 controls */ + if (u < 0x0020 || (0x007f <= u && u <= 0x009f)) + continue; + + /* Skip astral characters */ + if (u > 0xffff) + continue; + + /* Skip unmapped characters */ + if (internal == (unsigned int) -1) + continue; + + if (u % 0x200 == 0) + rufl_init_status(0, 0); + + /* Character is mapped, let's see if it's really there */ + string[0] = u; + rufl_fm_error = xfont_scan_string(font, (char *) string, + font_RETURN_BBOX | font_GIVEN32_BIT | + font_GIVEN_FONT | font_GIVEN_LENGTH | + font_GIVEN_BLOCK, + 0x7fffffff, 0x7fffffff, + &block, 0, 4, + 0, &x_out, &y_out, 0); + if (rufl_fm_error) + break; + + if (block.bbox.x0 == 0x20000000) { + /* absent (no definition) */ + } else if (x_out == 0 && y_out == 0 && + block.bbox.x0 == 0 && block.bbox.y0 == 0 && + block.bbox.x1 == 0 && block.bbox.y1 == 0) { + /* absent (empty) */ + } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && + block.bbox.x1 == 0 && block.bbox.y1 == 0 && + !rufl_is_space(u)) { + /* absent (space but not a space character - some + * fonts do this) */ + } else { + /* present */ + if (charset->index[u >> 8] == BLOCK_EMPTY) { + charset->index[u >> 8] = last_used; + last_used++; + if (last_used == 254) + /* too many characters */ + break; + } + + byte = (u >> 3) & 31; + bit = u & 7; + charset->block[charset->index[u >> 8]][byte] |= + 1 << bit; + } + } + + xfont_lose_font(font); + + if (rufl_fm_error) { + free(charset); + LOG("xfont_scan_string: 0x%x: %s", + rufl_fm_error->errnum, rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + + /* Determine which blocks are full, and mark them as such */ + for (u = 0; u != 256; u++) { + if (charset->index[u] == BLOCK_EMPTY) + continue; + + bit = 0xff; + + for (byte = 0; byte != 32; byte++) + bit &= charset->block[u][byte]; + + if (bit == 0xff) { + /* Block is full */ + charset->index[u] = BLOCK_FULL; + + for (byte = 0; byte != 32; byte++) + charset->block[u][byte] = 0; + } + } + + /* shrink-wrap */ + charset->size = offsetof(struct rufl_character_set, block) + + 32 * last_used; + charset2 = realloc(charset, charset->size); + if (!charset2) { + free(charset); + return rufl_OUT_OF_MEMORY; + } + + rufl_font_list[font_index].charset = charset; + + return rufl_OK; +} + +/** + * Scan a font for available characters (version without character enumeration) + */ + +rufl_code rufl_init_scan_font_no_enumerate(unsigned int font_index) +{ + char font_name[80]; + int x_out, y_out; + unsigned int byte, bit; + unsigned int block_count = 0; + unsigned int last_used = 0; + unsigned int string[2] = { 0, 0 }; + unsigned int u; + struct rufl_character_set *charset; + struct rufl_character_set *charset2; + font_f font; + font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; + + /*LOG("font %u \"%s\"", font_index, + rufl_font_list[font_index].identifier);*/ + + charset = calloc(1, sizeof *charset); + if (!charset) + return rufl_OUT_OF_MEMORY; + + snprintf(font_name, sizeof font_name, "%s\\EUTF8", + rufl_font_list[font_index].identifier); + + rufl_fm_error = xfont_find_font(font_name, 160, 160, 0, 0, &font, 0, 0); + if (rufl_fm_error) { + LOG("xfont_find_font(\"%s\"): 0x%x: %s", font_name, + rufl_fm_error->errnum, rufl_fm_error->errmess); + free(charset); + return rufl_OK; + } + + /* scan through all characters */ + for (u = 0x0020; u != 0x10000; u++) { + if (u == 0x007f) { + /* skip DELETE and C1 controls */ + u = 0x009f; + continue; + } + + if (u % 0x200 == 0) + rufl_init_status(0, 0); + + string[0] = u; + rufl_fm_error = xfont_scan_string(font, (char *) string, + font_RETURN_BBOX | font_GIVEN32_BIT | + font_GIVEN_FONT | font_GIVEN_LENGTH | + font_GIVEN_BLOCK, + 0x7fffffff, 0x7fffffff, + &block, 0, 4, + 0, &x_out, &y_out, 0); + if (rufl_fm_error) + break; + + if (block.bbox.x0 == 0x20000000) { + /* absent (no definition) */ + } else if (x_out == 0 && y_out == 0 && + block.bbox.x0 == 0 && block.bbox.y0 == 0 && + block.bbox.x1 == 0 && block.bbox.y1 == 0) { + /* absent (empty) */ + } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && + block.bbox.x1 == 0 && block.bbox.y1 == 0 && + !rufl_is_space(u)) { + /* absent (space but not a space character - some + * fonts do this) */ + } else { + /* present */ + byte = (u >> 3) & 31; + bit = u & 7; + charset->block[last_used][byte] |= 1 << bit; + + block_count++; + } + + if ((u + 1) % 256 == 0) { + /* end of block */ + if (block_count == 0) + charset->index[u >> 8] = BLOCK_EMPTY; + else if (block_count == 256) { + charset->index[u >> 8] = BLOCK_FULL; + for (byte = 0; byte != 32; byte++) + charset->block[last_used][byte] = 0; + } else { + charset->index[u >> 8] = last_used; + last_used++; + if (last_used == 254) + /* too many characters */ + break; + } + block_count = 0; + } + } + + xfont_lose_font(font); + + if (rufl_fm_error) { + free(charset); + LOG("xfont_scan_string: 0x%x: %s", + rufl_fm_error->errnum, rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + + /* shrink-wrap */ + charset->size = offsetof(struct rufl_character_set, block) + + 32 * last_used; + charset2 = realloc(charset, charset->size); + if (!charset2) { + free(charset); + return rufl_OUT_OF_MEMORY; + } + + rufl_font_list[font_index].charset = charset; + + return rufl_OK; +} + +/** + * A character is one of the Unicode space characters. + */ + +bool rufl_is_space(unsigned int u) +{ + return u == 0x0020 || u == 0x00a0 || + (0x2000 <= u && u <= 0x200b) || + u == 0x202f || u == 0x3000; +} + + +/** + * Scan a font for available characters (old font manager version). + */ + +rufl_code rufl_init_scan_font_old(unsigned int font_index) +{ + const char *font_name = rufl_font_list[font_index].identifier; + struct rufl_character_set *charset; + struct rufl_character_set *charset2; + struct rufl_unicode_map *umap = NULL; + unsigned int num_umaps = 0; + unsigned int i; + unsigned int last_used = 0; + rufl_code code; + font_list_context context = 0; + char encoding[80]; + + /*LOG("font %u \"%s\"", font_index, font_name);*/ + + charset = calloc(1, sizeof *charset); + if (!charset) + return rufl_OUT_OF_MEMORY; + for (i = 0; i != 256; i++) + charset->index[i] = BLOCK_EMPTY; + + /* Firstly, search through available encodings (Symbol fonts fail) */ + while (context != -1) { + struct rufl_unicode_map *temp; + + rufl_fm_error = xfont_list_fonts((byte *) encoding, + font_RETURN_FONT_NAME | + 0x400000 /* Return encoding name, instead */ | + context, + sizeof(encoding), NULL, 0, NULL, + &context, NULL, NULL); + if (rufl_fm_error) { + LOG("xfont_list_fonts: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + free(charset); + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + return rufl_FONT_MANAGER_ERROR; + } + if (context == -1) + break; + + temp = realloc(umap, (num_umaps + 1) * sizeof *umap); + if (!temp) { + free(charset); + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + return rufl_OUT_OF_MEMORY; + } + + memset(temp + num_umaps, 0, sizeof *umap); + + umap = temp; + num_umaps++; + + code = rufl_init_scan_font_in_encoding(font_name, encoding, + charset, umap + (num_umaps - 1), &last_used); + if (code != rufl_OK) { + /* Not finding the font isn't fatal */ + if (code != rufl_FONT_MANAGER_ERROR || + (rufl_fm_error->errnum != + error_FONT_NOT_FOUND && + rufl_fm_error->errnum != + error_FILE_NOT_FOUND)) { + free(charset); + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + return code; + } + + /* Ensure we reuse the currently allocated umap */ + num_umaps--; + } else { + /* If this mapping is identical to an existing one, + * then we can discard it */ + for (i = 0; i != num_umaps - 1; i++) { + const struct rufl_unicode_map *a = (umap + i); + const struct rufl_unicode_map *b = + (umap + num_umaps - 1); + + if (a->entries == b->entries && + memcmp(a->map, b->map, + sizeof a->map) == 0) { + /* Found identical map; discard */ + num_umaps--; + break; + } + } + } + } + + if (num_umaps == 0) { + /* This is a symbol font and can only be used + * without an encoding */ + struct rufl_unicode_map *temp; + + temp = realloc(umap, (num_umaps + 1) * sizeof *umap); + if (!temp) { + free(charset); + free(umap); + return rufl_OUT_OF_MEMORY; + } + + memset(temp + num_umaps, 0, sizeof *umap); + + umap = temp; + num_umaps++; + + code = rufl_init_scan_font_in_encoding(font_name, NULL, + charset, umap, &last_used); + if (code != rufl_OK) { + /* Not finding the font isn't fatal */ + if (code != rufl_FONT_MANAGER_ERROR || + (rufl_fm_error->errnum != + error_FONT_NOT_FOUND && + rufl_fm_error->errnum != + error_FILE_NOT_FOUND)) { + free(charset); + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + return code; + } + + num_umaps--; + } + } + + /* shrink-wrap */ + charset->size = offsetof(struct rufl_character_set, block) + + 32 * last_used; + charset2 = realloc(charset, charset->size); + if (!charset2) { + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + free(charset); + return rufl_OUT_OF_MEMORY; + } + + rufl_font_list[font_index].charset = charset; + rufl_font_list[font_index].umap = umap; + rufl_font_list[font_index].num_umaps = num_umaps; + + return rufl_OK; +} + +/** + * Helper function for rufl_init_scan_font_old. + * Scans the given font using the given font encoding (or none, if NULL) + */ + +rufl_code rufl_init_scan_font_in_encoding(const char *font_name, + const char *encoding, struct rufl_character_set *charset, + struct rufl_unicode_map *umap, unsigned int *last) +{ + char string[2] = { 0, 0 }; + int x_out, y_out; + unsigned int byte, bit; + unsigned int i; + unsigned int last_used = *last; + unsigned int u; + rufl_code code; + font_f font; + font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; + char buf[80]; + + if (encoding) + snprintf(buf, sizeof buf, "%s\\E%s", font_name, encoding); + else + snprintf(buf, sizeof buf, "%s", font_name); + + rufl_fm_error = xfont_find_font(buf, 160, 160, 0, 0, &font, 0, 0); + if (rufl_fm_error) { + LOG("xfont_find_font(\"%s\"): 0x%x: %s", buf, + rufl_fm_error->errnum, rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + + code = rufl_init_read_encoding(font, umap); + if (code != rufl_OK) { + xfont_lose_font(font); + return code; + } + + for (i = 0; i != umap->entries; i++) { + u = umap->map[i].u; + string[0] = umap->map[i].c; + rufl_fm_error = xfont_scan_string(font, (char *) string, + font_RETURN_BBOX | font_GIVEN_FONT | + font_GIVEN_LENGTH | font_GIVEN_BLOCK, + 0x7fffffff, 0x7fffffff, + &block, 0, 1, + 0, &x_out, &y_out, 0); + if (rufl_fm_error) + break; + + if (block.bbox.x0 == 0x20000000) { + /* absent (no definition) */ + } else if (x_out == 0 && y_out == 0 && + block.bbox.x0 == 0 && block.bbox.y0 == 0 && + block.bbox.x1 == 0 && block.bbox.y1 == 0) { + /* absent (empty) */ + } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && + block.bbox.x1 == 0 && block.bbox.y1 == 0 && + !rufl_is_space(u)) { + /* absent (space but not a space character - some + * fonts do this) */ + } else { + /* present */ + if (charset->index[u >> 8] == BLOCK_EMPTY) { + charset->index[u >> 8] = last_used; + last_used++; + if (last_used == 254) + /* too many characters */ + break; + } + + byte = (u >> 3) & 31; + bit = u & 7; + charset->block[charset->index[u >> 8]][byte] |= + 1 << bit; + } + } + + xfont_lose_font(font); + + if (rufl_fm_error) { + LOG("xfont_scan_string: 0x%x: %s", + rufl_fm_error->errnum, rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + + if (encoding) { + umap->encoding = strdup(encoding); + if (!umap->encoding) + return rufl_OUT_OF_MEMORY; + } + + *last = last_used; + + return rufl_OK; +} + + +/** + * Parse an encoding file and fill in a rufl_unicode_map. + */ + +rufl_code rufl_init_read_encoding(font_f font, + struct rufl_unicode_map *umap) +{ + unsigned int u = 0; + unsigned int i = 0; + int c; + int n; + char filename[200]; + char s[200]; + struct rufl_glyph_map_entry *entry; + FILE *fp; + + rufl_fm_error = xfont_read_encoding_filename(font, filename, + sizeof filename, 0); + if (rufl_fm_error) { + LOG("xfont_read_encoding_filename: 0x%x: %s", + rufl_fm_error->errnum, rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + + fp = fopen(filename, "r"); + if (!fp) + /* many "symbol" fonts have no encoding file: assume Latin 1 */ + fp = fopen("Resources:$.Fonts.Encodings.Latin1", "r"); + if (!fp) + return rufl_IO_ERROR; + + while (!feof(fp) && u != 256) { + c = fgetc(fp); + if (c == '%') { + /* comment line */ + fgets(s, sizeof s, fp); + } else if (c == '/') { + /* character definition */ + if (i++ < 32) + continue; + n = fscanf(fp, "%100s", s); + if (n != 1) + break; + entry = bsearch(s, rufl_glyph_map, + rufl_glyph_map_size, + sizeof rufl_glyph_map[0], + rufl_glyph_map_cmp); + if (entry) { + /* may be more than one unicode for the glyph + * sentinels stop overshooting array */ + while (strcmp(s, (entry - 1)->glyph_name) == 0) + entry--; + for (; strcmp(s, entry->glyph_name) == 0; + entry++) { + umap->map[u].u = entry->u; + umap->map[u].c = i - 1; + u++; + if (u == 256) + break; + } + } + } + } + + if (fclose(fp) == EOF) + return rufl_IO_ERROR; + + /* sort by unicode */ + qsort(umap->map, u, sizeof umap->map[0], rufl_unicode_map_cmp); + umap->entries = u; + + return rufl_OK; +} + + +int rufl_glyph_map_cmp(const void *keyval, const void *datum) +{ + const char *key = keyval; + const struct rufl_glyph_map_entry *entry = datum; + return strcmp(key, entry->glyph_name); +} + + +int rufl_unicode_map_cmp(const void *z1, const void *z2) +{ + const struct rufl_unicode_map_entry *entry1 = z1; + const struct rufl_unicode_map_entry *entry2 = z2; + if (entry1->u < entry2->u) + return -1; + else if (entry2->u < entry1->u) + return 1; + return 0; +} + + +/** + * Construct the font substitution table. + */ + +rufl_code rufl_init_substitution_table(void) +{ + unsigned char z; + unsigned int i; + unsigned int block, byte, bit; + unsigned int u; + unsigned int index; + const struct rufl_character_set *charset; + + rufl_substitution_table = malloc(65536 * + sizeof rufl_substitution_table[0]); + if (!rufl_substitution_table) { + LOG("malloc(%zu) failed", 65536 * + sizeof rufl_substitution_table[0]); + return rufl_OUT_OF_MEMORY; + } + + for (u = 0; u != 0x10000; u++) + rufl_substitution_table[u] = NOT_AVAILABLE; + + for (i = 0; i != rufl_font_list_entries; i++) { + charset = rufl_font_list[i].charset; + if (!charset) + continue; + for (block = 0; block != 256; block++) { + if (charset->index[block] == BLOCK_EMPTY) + continue; + if (charset->index[block] == BLOCK_FULL) { + for (u = block << 8; u != (block << 8) + 256; + u++) { + if (rufl_substitution_table[u] == + NOT_AVAILABLE) + rufl_substitution_table[u] = i; + } + continue; + } + index = charset->index[block]; + for (byte = 0; byte != 32; byte++) { + z = charset->block[index][byte]; + if (z == 0) + continue; + u = (block << 8) | (byte << 3); + for (bit = 0; bit != 8; bit++, u++) { + if (rufl_substitution_table[u] == + NOT_AVAILABLE && + z & (1 << bit)) + rufl_substitution_table[u] = i; + } + } + } + } + + return rufl_OK; +} + + +/** + * Save character sets to cache. + */ + +rufl_code rufl_save_cache(void) +{ + unsigned int i; + const unsigned int version = rufl_CACHE_VERSION; + size_t len; + FILE *fp; + + fp = fopen(rufl_CACHE, "wb"); + if (!fp) { + LOG("fopen: 0x%x: %s", errno, strerror(errno)); + return rufl_OK; + } + + /* cache format version */ + if (fwrite(&version, sizeof version, 1, fp) != 1) { + LOG("fwrite: 0x%x: %s", errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + + /* font manager type flag */ + if (fwrite(&rufl_old_font_manager, sizeof rufl_old_font_manager, 1, + fp) != 1) { + LOG("fwrite: 0x%x: %s", errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + + for (i = 0; i != rufl_font_list_entries; i++) { + if (!rufl_font_list[i].charset) + continue; + + /* length of font identifier */ + len = strlen(rufl_font_list[i].identifier); + if (fwrite(&len, sizeof len, 1, fp) != 1) { + LOG("fwrite: 0x%x: %s", errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + + /* font identifier */ + if (fwrite(rufl_font_list[i].identifier, len, 1, fp) != 1) { + LOG("fwrite: 0x%x: %s", errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + + /* character set */ + if (fwrite(rufl_font_list[i].charset, + rufl_font_list[i].charset->size, 1, fp) != 1) { + LOG("fwrite: 0x%x: %s", errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + + /* unicode map */ + if (rufl_old_font_manager) { + unsigned int j; + + if (fwrite(&rufl_font_list[i].num_umaps, + sizeof rufl_font_list[i].num_umaps, 1, + fp) != 1) { + LOG("fwrite: 0x%x: %s", errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + + for (j = 0; j < rufl_font_list[i].num_umaps; j++) { + const struct rufl_unicode_map *umap = + rufl_font_list[i].umap + j; + + len = umap->encoding ? + strlen(umap->encoding) : 0; + + if (fwrite(&len, sizeof len, 1, fp) != 1) { + LOG("fwrite: 0x%x: %s", + errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + + if (umap->encoding) { + if (fwrite(umap->encoding, len, 1, + fp) != 1) { + LOG("fwrite: 0x%x: %s", + errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + } + + if (fwrite(&umap->entries, sizeof umap->entries, + 1, fp) != 1) { + LOG("fwrite: 0x%x: %s", + errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + + if (fwrite(umap->map, umap->entries * + sizeof(struct rufl_unicode_map_entry), + 1, fp) != 1) { + LOG("fwrite: 0x%x: %s", + errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + } + } + } + + if (fclose(fp) == EOF) { + LOG("fclose: 0x%x: %s", errno, strerror(errno)); + return rufl_OK; + } + + LOG("%u charsets saved", i); + + return rufl_OK; +} + + +/** + * Load character sets from cache. + */ + +rufl_code rufl_load_cache(void) +{ + unsigned int version; + unsigned int i = 0; + bool old_font_manager; + char *identifier; + size_t len, size; + FILE *fp; + struct rufl_font_list_entry *entry; + struct rufl_character_set *charset; + struct rufl_unicode_map *umap = NULL; + unsigned int num_umaps = 0; + + fp = fopen(rufl_CACHE, "rb"); + if (!fp) { + LOG("fopen: 0x%x: %s", errno, strerror(errno)); + return rufl_OK; + } + + /* cache format version */ + if (fread(&version, sizeof version, 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + if (version != rufl_CACHE_VERSION) { + /* incompatible cache format */ + LOG("cache version %u (now %u)", version, rufl_CACHE_VERSION); + fclose(fp); + return rufl_OK; + } + + /* font manager type flag */ + if (fread(&old_font_manager, sizeof old_font_manager, 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, strerror(errno)); + fclose(fp); + return rufl_OK; + } + if (old_font_manager != rufl_old_font_manager) { + /* font manager type has changed */ + LOG("font manager %u (now %u)", old_font_manager, + rufl_old_font_manager); + fclose(fp); + return rufl_OK; + } + + while (!feof(fp)) { + /* length of font identifier */ + if (fread(&len, sizeof len, 1, fp) != 1) { + /* eof at this point simply means that the whole cache + * file has been loaded */ + if (!feof(fp)) + LOG("fread: 0x%x: %s", errno, strerror(errno)); + break; + } + + identifier = malloc(len + 1); + if (!identifier) { + LOG("malloc(%zu) failed", len + 1); + fclose(fp); + return rufl_OUT_OF_MEMORY; + } + + /* font identifier */ + if (fread(identifier, len, 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, strerror(errno)); + free(identifier); + break; + } + identifier[len] = 0; + + /* character set */ + if (fread(&size, sizeof size, 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, strerror(errno)); + free(identifier); + break; + } + + charset = malloc(size); + if (!charset) { + LOG("malloc(%zu) failed", size); + free(identifier); + fclose(fp); + return rufl_OUT_OF_MEMORY; + } + + charset->size = size; + if (fread(charset->index, size - sizeof size, 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, strerror(errno)); + free(charset); + free(identifier); + break; + } + + /* unicode map */ + if (rufl_old_font_manager) { + rufl_code code = rufl_OK; + unsigned int entry; + + /* Number of maps */ + if (fread(&num_umaps, sizeof num_umaps, 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, + strerror(errno)); + free(charset); + free(identifier); + break; + } + + umap = calloc(num_umaps, sizeof *umap); + if (!umap) { + LOG("malloc(%zu) failed", sizeof *umap); + free(charset); + free(identifier); + fclose(fp); + return rufl_OUT_OF_MEMORY; + } + + /* Load them */ + for (entry = 0; entry < num_umaps; entry++) { + struct rufl_unicode_map *map = umap + entry; + + if (fread(&len, sizeof(len), 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", + "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, + strerror(errno)); + break; + } + + if (len > 0) { + map->encoding = malloc(len + 1); + if (!map->encoding) { + LOG("malloc(%zu) failed", + len + 1); + code = rufl_OUT_OF_MEMORY; + break; + } + + if (fread(map->encoding, len, 1, + fp) != 1) { + if (feof(fp)) + LOG("fread: %s", + "unexpected eof"); + else + LOG("fread: 0x%x: %s", + errno, + strerror(errno)); + break; + } + map->encoding[len] = 0; + } + + if (fread(&map->entries, sizeof(map->entries), + 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", + "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, + strerror(errno)); + break; + } + + if (fread(map->map, map->entries * + sizeof(struct rufl_unicode_map_entry), + 1, fp) != 1) { + if (feof(fp)) + LOG("fread: %s", + "unexpected eof"); + else + LOG("fread: 0x%x: %s", errno, + strerror(errno)); + break; + } + } + + /* Clean up if loading failed */ + if (entry != num_umaps) { + for (num_umaps = 0; num_umaps <= entry; + num_umaps++) { + struct rufl_unicode_map *map = + umap + num_umaps; + + free(map->encoding); + } + free(umap); + free(charset); + free(identifier); + + if (code != rufl_OK) + return code; + + break; + } + } + + /* put in rufl_font_list */ + entry = lfind(identifier, rufl_font_list, + &rufl_font_list_entries, + sizeof rufl_font_list[0], rufl_font_list_cmp); + if (entry) { + entry->charset = charset; + entry->umap = umap; + entry->num_umaps = num_umaps; + i++; + } else { + LOG("\"%s\" not in font list", identifier); + while (num_umaps > 0) { + struct rufl_unicode_map *map = + umap + num_umaps - 1; + + free(map->encoding); + + num_umaps--; + } + free(umap); + free(charset); + } + + free(identifier); + } + fclose(fp); + + LOG("%u charsets loaded", i); + + return rufl_OK; +} + + +int rufl_font_list_cmp(const void *keyval, const void *datum) +{ + const char *key = keyval; + const struct rufl_font_list_entry *entry = datum; + return strcasecmp(key, entry->identifier); +} + + +/** + * Create a menu of font families. + */ + +rufl_code rufl_init_family_menu(void) +{ + wimp_menu *menu; + unsigned int i; + + menu = malloc(wimp_SIZEOF_MENU(rufl_family_list_entries)); + if (!menu) + return rufl_OUT_OF_MEMORY; + menu->title_data.indirected_text.text = (char *) "Fonts"; + menu->title_fg = wimp_COLOUR_BLACK; + menu->title_bg = wimp_COLOUR_LIGHT_GREY; + menu->work_fg = wimp_COLOUR_BLACK; + menu->work_bg = wimp_COLOUR_WHITE; + menu->width = 200; + menu->height = wimp_MENU_ITEM_HEIGHT; + menu->gap = wimp_MENU_ITEM_GAP; + for (i = 0; i != rufl_family_list_entries; i++) { + menu->entries[i].menu_flags = 0; + menu->entries[i].sub_menu = wimp_NO_SUB_MENU; + menu->entries[i].icon_flags = wimp_ICON_TEXT | + wimp_ICON_INDIRECTED | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); + menu->entries[i].data.indirected_text.text = + (char *) rufl_family_list[i]; + menu->entries[i].data.indirected_text.validation = (char *) -1; + menu->entries[i].data.indirected_text.size = + strlen(rufl_family_list[i]); + } + menu->entries[0].menu_flags = wimp_MENU_TITLE_INDIRECTED; + menu->entries[i - 1].menu_flags |= wimp_MENU_LAST; + + rufl_family_menu = menu; + + return rufl_OK; +} + + +/** + * Create and open the init status window. + */ + +void rufl_init_status_open(void) +{ + int xeig_factor, yeig_factor, xwind_limit, ywind_limit, width, height; + wimp_t task; + osbool window_task; + wimp_WINDOW(4) window = { { 0, 0, 0, 0 }, 0, 0, wimp_TOP, + wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_NEW_FORMAT, + wimp_COLOUR_BLACK, wimp_COLOUR_LIGHT_GREY, + wimp_COLOUR_BLACK, wimp_COLOUR_VERY_LIGHT_GREY, + wimp_COLOUR_DARK_GREY, wimp_COLOUR_LIGHT_GREY, + wimp_COLOUR_CREAM, 0, + { 0, -128, 800, 0 }, 0, 0, 0, 0, 0, { "" }, 4, + { { { 12, -56, 788, -12 }, wimp_ICON_TEXT | + wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | + wimp_ICON_INDIRECTED | + wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT | + wimp_COLOUR_VERY_LIGHT_GREY <errnum, error->errmess); + return; + } + if (!task) + return; /* not a Wimp task */ + + error = xtaskwindowtaskinfo_window_task(&window_task); + if (error) { + LOG("xtaskwindowtaskinfo_window_task: 0x%x: %s", + error->errnum, error->errmess); + return; + } + if (window_task) + return; /* in a TaskWindow */ + + xwimp_create_window((const wimp_window *) &window, &rufl_status_w); + state.w = rufl_status_w; + xwimp_get_window_state(&state); + xwimp_open_window((wimp_open *) (void *) &state); +} + + +/** + * Update the status window and multitask. + */ + +void rufl_init_status(const char *status, float progress) +{ + wimp_block block; + static os_t last_t = 0; + os_t t; + + if (!rufl_status_w) + return; + + if (status) { + strncpy(rufl_status_buffer, status, sizeof rufl_status_buffer); + rufl_status_buffer[sizeof rufl_status_buffer - 1] = 0; + xwimp_set_icon_state(rufl_status_w, 3, 0, 0); + } + if (progress) + xwimp_resize_icon(rufl_status_w, 2, 16, -112, + 16 + 768 * progress, -68); + xos_read_monotonic_time(&t); + if (last_t == t) + return; + xwimp_poll(wimp_QUEUE_REDRAW | wimp_MASK_LEAVING | wimp_MASK_ENTERING | + wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_MASK_MESSAGE | + wimp_MASK_RECORDED | wimp_MASK_ACKNOWLEDGE, + &block, 0, 0); + last_t = t; +} + + +/** + * Close and delete the status window. + */ + +void rufl_init_status_close(void) +{ + if (!rufl_status_w) + return; + + xwimp_delete_window(rufl_status_w); + rufl_status_w = 0; +} diff --git a/src/rufl_internal.h b/src/rufl_internal.h new file mode 100644 index 0000000..1c01e36 --- /dev/null +++ b/src/rufl_internal.h @@ -0,0 +1,194 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +#include +#include "oslib/font.h" +#include "rufl.h" +#ifdef __CC_NORCROFT +#include "strfuncs.h" +#endif + + +/** The available characters in a font. The range which can be represented is + * 0x0000 to 0xffff. The size of the structure is 4 + 256 + 32 * blocks. A + * typical * 200 glyph font might have characters in 10 blocks, giving 580 + * bytes. The maximum possible size of the structure is 8388 bytes. Note that + * since two index values are reserved, fonts with 65280-65024 glyphs may be + * unrepresentable, if there are no full blocks. This is unlikely. The primary + * aim of this structure is to make lookup fast. */ +struct rufl_character_set { + /** Size of structure / bytes. */ + size_t size; + + /** Index table. Each entry represents a block of 256 characters, so + * i[k] refers to characters [256*k, 256*(k+1)). The value is either + * BLOCK_EMPTY, BLOCK_FULL, or an offset into the block table. */ + unsigned char index[256]; + /** The block has no characters present. */ +# define BLOCK_EMPTY 254 + /** All characters in the block are present. */ +# define BLOCK_FULL 255 + + /** Block table. Each entry is a 256-bit bitmap indicating which + * characters in the block are present and absent. */ + unsigned char block[254][32]; +}; + + +/** Part of struct rufl_unicode_map. */ +struct rufl_unicode_map_entry { + /** Unicode value. */ + unsigned short u; + /** Corresponding character. */ + unsigned char c; +}; + + +/** Old font manager: mapping from Unicode to character code. This is simply + * an array sorted by Unicode value, suitable for bsearch(). If a font has + * support for multiple encodings, then it will have multiple unicode maps. + * The encoding field contains the name of the encoding to pass to the + * font manager. This will be NULL if the font is a Symbol font. */ +struct rufl_unicode_map { + /** Corresponding encoding name */ + char *encoding; + /** Number of valid entries in map. */ + unsigned int entries; + /** Map from Unicode to character code. */ + struct rufl_unicode_map_entry map[256]; +}; + + +/** An entry in rufl_font_list. */ +struct rufl_font_list_entry { + /** Font identifier (name). */ + char *identifier; + /** Character set of font. */ + struct rufl_character_set *charset; + /** Number of Unicode mapping tables */ + unsigned int num_umaps; + /** Mappings from Unicode to character code. */ + struct rufl_unicode_map *umap; + /** Family that this font belongs to (index in rufl_family_list and + * rufl_family_map). */ + unsigned int family; + /** Font weight (0 to 8). */ + unsigned int weight; + /** Font slant (0 or 1). */ + unsigned int slant; +}; +/** List of all available fonts. */ +extern struct rufl_font_list_entry *rufl_font_list; +/** Number of entries in rufl_font_list. */ +extern size_t rufl_font_list_entries; + + +/** An entry in rufl_family_map. */ +struct rufl_family_map_entry { + /** This style does not exist in this family. */ +# define NO_FONT UINT_MAX + /** Map from weight and slant to index in rufl_font_list, or NO_FONT. */ + unsigned int font[9][2]; +}; +/** Map from font family to fonts, rufl_family_list_entries entries. */ +extern struct rufl_family_map_entry *rufl_family_map; + + +/** No font contains this character. */ +#define NOT_AVAILABLE 65535 +/** Font substitution table. */ +extern unsigned short *rufl_substitution_table; + + +/** Number of slots in recent-use cache. This is the maximum number of RISC OS + * font handles that will be used at any time by the library. */ +#define rufl_CACHE_SIZE 10 + +/** An entry in rufl_cache. */ +struct rufl_cache_entry { + /** Font number (index in rufl_font_list), or rufl_CACHE_*. */ + unsigned int font; + /** No font cached in this slot. */ +#define rufl_CACHE_NONE UINT_MAX + /** Font for rendering hex substitutions in this slot. */ +#define rufl_CACHE_CORPUS (UINT_MAX - 1) + /** Font size. */ + unsigned int size; + /** Font encoding */ + const char *encoding; + /** Value of rufl_cache_time when last used. */ + unsigned int last_used; + /** RISC OS font handle. */ + font_f f; +}; +/** Cache of rufl_CACHE_SIZE most recently used font handles. */ +extern struct rufl_cache_entry rufl_cache[rufl_CACHE_SIZE]; +/** Counter for measuring age of cache entries. */ +extern int rufl_cache_time; + +/** Font manager does not support Unicode. */ +extern bool rufl_old_font_manager; + +/** Font manager supports background blending */ +extern bool rufl_can_background_blend; + +rufl_code rufl_find_font_family(const char *family, rufl_style font_style, + unsigned int *font, unsigned int *slanted, + struct rufl_character_set **charset); +rufl_code rufl_find_font(unsigned int font, unsigned int font_size, + const char *encoding, font_f *fhandle); +bool rufl_character_set_test(struct rufl_character_set *charset, + unsigned int c); + + +#define rufl_utf8_read(s, l, u) \ + if (4 <= l && ((s[0] & 0xf8) == 0xf0) && ((s[1] & 0xc0) == 0x80) && \ + ((s[2] & 0xc0) == 0x80) && ((s[3] & 0xc0) == 0x80)) { \ + u = ((s[0] & 0x7) << 18) | ((s[1] & 0x3f) << 12) | \ + ((s[2] & 0x3f) << 6) | (s[3] & 0x3f); \ + s += 4; l -= 4; \ + } else if (3 <= l && ((s[0] & 0xf0) == 0xe0) && \ + ((s[1] & 0xc0) == 0x80) && \ + ((s[2] & 0xc0) == 0x80)) { \ + u = ((s[0] & 0xf) << 12) | ((s[1] & 0x3f) << 6) | \ + (s[2] & 0x3f); \ + s += 3; l -= 3; \ + } else if (2 <= l && ((s[0] & 0xe0) == 0xc0) && \ + ((s[1] & 0xc0) == 0x80)) { \ + u = ((s[0] & 0x3f) << 6) | (s[1] & 0x3f); \ + s += 2; l -= 2; \ + } else if ((s[0] & 0x80) == 0) { \ + u = s[0]; \ + s++; l--; \ + } else { \ + u = 0xfffd; \ + s++; l--; \ + } + +#define rufl_CACHE ".RUfl_cache" +#define rufl_CACHE_VERSION 3 + + +struct rufl_glyph_map_entry { + const char *glyph_name; + unsigned short u; +}; + +extern const struct rufl_glyph_map_entry rufl_glyph_map[]; +extern const size_t rufl_glyph_map_size; + + +#ifndef NDEBUG +#ifdef __CC_NORCROFT +#define __PRETTY_FUNCTION__ __func__ +#endif +#define LOG(format, ...) (fprintf(stderr, __FILE__ " %s %i: ", \ + __PRETTY_FUNCTION__, __LINE__), fprintf(stderr, format, \ + __VA_ARGS__), fprintf(stderr, "\n")) +#else +#define LOG(format, ...) ((void) 0) +#endif diff --git a/src/rufl_invalidate_cache.c b/src/rufl_invalidate_cache.c new file mode 100644 index 0000000..65a3897 --- /dev/null +++ b/src/rufl_invalidate_cache.c @@ -0,0 +1,28 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2005 James Bursa + */ + +#include "oslib/font.h" +#include "rufl_internal.h" + + +/** + * Clear the internal font handle cache. + * + * Call this function on mode changes or output redirection changes. + */ + +void rufl_invalidate_cache(void) +{ + unsigned int i; + + for (i = 0; i != rufl_CACHE_SIZE; i++) { + if (rufl_cache[i].font != rufl_CACHE_NONE) { + xfont_lose_font(rufl_cache[i].f); + rufl_cache[i].font = rufl_CACHE_NONE; + } + } +} diff --git a/src/rufl_metrics.c b/src/rufl_metrics.c new file mode 100644 index 0000000..af4727f --- /dev/null +++ b/src/rufl_metrics.c @@ -0,0 +1,312 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2005 John-Mark Bell + */ + +#include +#include +#include + +#include "oslib/font.h" + +#include "rufl_internal.h" + +static int rufl_unicode_map_search_cmp(const void *keyval, const void *datum); + +/** + * Read a font's metrics (sized for a 1pt font) + */ +rufl_code rufl_font_metrics(const char *font_family, rufl_style font_style, + os_box *bbox, int *xkern, int *ykern, int *italic, + int *ascent, int *descent, + int *xheight, int *cap_height, + signed char *uline_position, unsigned char *uline_thickness) +{ + unsigned int font; + font_f f; + int misc_size; + font_metrics_misc_info *misc_info; + rufl_code code; + + code = rufl_find_font_family(font_family, font_style, &font, + NULL, NULL); + if (code != rufl_OK) + return code; + + code = rufl_find_font(font, 16 /* 1pt */, NULL, &f); + if (code != rufl_OK) + return code; + + rufl_fm_error = xfont_read_font_metrics(f, 0, 0, 0, 0, 0, + 0, 0, 0, 0, &misc_size, 0); + if (rufl_fm_error) { + LOG("xfont_read_font_metrics: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + + if (misc_size == 0) { + LOG("no miscellaneous information in metrics for %s", + rufl_font_list[font].identifier); + /** \todo better error code */ + return rufl_FONT_NOT_FOUND; + } + + misc_info = (font_metrics_misc_info *)malloc(misc_size); + if (!misc_info) + return rufl_OUT_OF_MEMORY; + + rufl_fm_error = xfont_read_font_metrics(f, 0, 0, 0, misc_info, 0, + 0, 0, 0, 0, 0, 0); + if (rufl_fm_error) { + LOG("xfont_read_font_metrics: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + free(misc_info); + return rufl_FONT_MANAGER_ERROR; + } + + /* and fill in output */ + if (bbox) { + bbox->x0 = misc_info->x0; + bbox->y0 = misc_info->y0; + bbox->x1 = misc_info->x1; + bbox->y1 = misc_info->y1; + } + + if (xkern) + (*xkern) = misc_info->xkern; + + if (ykern) + (*ykern) = misc_info->ykern; + + if (italic) + (*italic) = misc_info->italic_correction; + + if (ascent) + (*ascent) = misc_info->ascender; + + if (descent) + (*descent) = misc_info->descender; + + if (xheight) + (*xheight) = misc_info->xheight; + + if (cap_height) + (*cap_height) = misc_info->cap_height; + + if (uline_position) + (*uline_position) = misc_info->underline_position; + + if (uline_thickness) + (*uline_thickness) = misc_info->underline_thickness; + + free(misc_info); + + return rufl_OK; +} + +/** + * Read a glyph's metrics + */ +rufl_code rufl_glyph_metrics(const char *font_family, + rufl_style font_style, unsigned int font_size, + const char *string, size_t length, + int *x_bearing, int *y_bearing, + int *width, int *height, + int *x_advance, int *y_advance) +{ + const char *font_encoding = NULL; + unsigned int font, font1, u; + unsigned short u1[2]; + struct rufl_character_set *charset; + struct rufl_unicode_map_entry *umap_entry = NULL; + font_f f; + rufl_code code; + font_scan_block block; + font_string_flags flags; + int xa, ya; + + /* Find font family containing glyph */ + code = rufl_find_font_family(font_family, font_style, + &font, NULL, &charset); + if (code != rufl_OK) + return code; + + rufl_utf8_read(string, length, u); + if (charset && rufl_character_set_test(charset, u)) + font1 = font; + else if (u < 0x10000) + font1 = rufl_substitution_table[u]; + else + font1 = rufl_CACHE_CORPUS; + + /* Old font managers need the font encoding, too */ + if (rufl_old_font_manager && font1 != rufl_CACHE_CORPUS) { + unsigned int i; + unsigned short u16 = (unsigned short) u; + + for (i = 0; i < rufl_font_list[font1].num_umaps; i++) { + struct rufl_unicode_map *map = + rufl_font_list[font1].umap + i; + + umap_entry = bsearch(&u16, map->map, map->entries, + sizeof map->map[0], + rufl_unicode_map_search_cmp); + if (umap_entry) { + font_encoding = map->encoding; + break; + } + } + + assert(umap_entry != NULL); + } + + code = rufl_find_font(font1, font_size, font_encoding, &f); + if (code != rufl_OK) + return code; + + /* + * Glyph Metrics for horizontal text: + * + * ^ x0 x1 + * | Xbearing : x0 - oX + * | +-----+-------- y1 Ybearing : y1 - oY + * | | | Xadvance : aX - oX + * | | | Yadvance : 0 + * o---|-----|---a--> Glyph width : x1 - x0 + * | | | Glyph height : y1 - y0 + * | +-----+-------- y0 Right side bearing: aX - x1 + * | + * + * The rectangle (x0,y0),(x1,y1) is the glyph bounding box. + * + * Glyph Metrics for vertical text: + * + * -------o---------> + * y1--+--|--+ Xbearing : x0 - oX + * | | | Ybearing : oY - y1 + * | | | Xadvance : 0 + * | | | Yadvance : aY - oY + * | | | Glyph width : x1 - x0 + * y0--+-----+ Glyph height : y1 - y0 + * ------a----------- Right side bearing: N/A + * x0 v x1 + * + * The rectangle (x0,y0),(x1,y1) is the glyph bounding box. + * + * + * In order to extract the information we want from the + * Font Manager, a little bit of hackery is required. + * + * Firstly, we can take the origin as being (0,0). This is an + * arbitrary choice but makes the maths simpler. + * + * Secondly, the bounding box returned by Font_CharBBox / + * Font_ScanString / Font_StringBBox represents the ink area of + * the glyph (i.e. the smallest box needed to contain all the + * glyph path segments). This means that, for glyphs with no + * displayed content (such as a space), the bounding box will be 0. + * These SWIs therefore allow us to retrieve the (x0,y0),(x1,y1) + * coordinates marked in the diagrams above. + * + * Finally, we need to retrieve the glyph advance distance. This is + * returned in R3/R4 on exit from Font_ScanString (providing bit 17 + * of the flags word on entry is clear). It is important to note, + * however, that the height will be returned as 0 for fonts with no + * Yadvance values in the font data file. Therefore, in order to + * achieve vertical layout of text, further work will be needed + * (We're also ignoring the fact that the X coordinates of all + * values will be in the wrong place and the Y coordinates will have + * the wrong sign due to the differing definitions of the Y axis for + * horizontal and vertical text.) + * + * Note that all values (that we're interested in, at least) + * returned by the SWIs mentioned above are in _millipoints_. + */ + + block.space.x = block.space.y = 0; + block.letter.x = block.letter.y = 0; + block.split_char = -1; + + flags = font_GIVEN_BLOCK | font_GIVEN_LENGTH | font_GIVEN_FONT | + font_RETURN_BBOX; + + u1[0] = (unsigned short)u; + u1[1] = 0; + + if (font1 == rufl_CACHE_CORPUS) { + /* Fallback Glyph */ + /** \todo implement this properly */ + xa = 1000 * font_size; + ya = 0; + block.bbox.x0 = block.bbox.y0 = 0; + block.bbox.x1 = block.bbox.y1 = xa; + } else if (rufl_old_font_manager) { + /* Old Font Manager */ + char s[2]; + + /* We found the correct umap entry when + * looking for the font encoding */ + s[0] = umap_entry->c; + s[1] = 0; + + rufl_fm_error = xfont_scan_string(f, s, flags, + 0x7fffffff, 0x7fffffff, &block, 0, 1, + 0, &xa, &ya, 0); + if (rufl_fm_error) { + LOG("xfont_scan_string: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + } else { + /* UCS Font Manager */ + rufl_fm_error = xfont_scan_string(f, (const char *)u1, + flags | font_GIVEN16_BIT, + 0x7fffffff, 0x7fffffff, &block, 0, 2, + 0, &xa, &ya, 0); + if (rufl_fm_error) { + LOG("xfont_scan_string: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + } + + /** \todo handle vertical text */ + if (x_bearing) + (*x_bearing) = block.bbox.x0; + + if (y_bearing) + (*y_bearing) = block.bbox.y1; + + if (width) + (*width) = block.bbox.x1 - block.bbox.x0; + + if (height) + (*height) = block.bbox.y1 - block.bbox.y0; + + if (x_advance) + (*x_advance) = xa; + + if (y_advance) + (*y_advance) = ya; + + return rufl_OK; +} + + +int rufl_unicode_map_search_cmp(const void *keyval, const void *datum) +{ + const unsigned short *key = keyval; + const struct rufl_unicode_map_entry *entry = datum; + if (*key < entry->u) + return -1; + else if (entry->u < *key) + return 1; + return 0; +} diff --git a/src/rufl_paint.c b/src/rufl_paint.c new file mode 100644 index 0000000..8b9edf1 --- /dev/null +++ b/src/rufl_paint.c @@ -0,0 +1,621 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +#include +#include +#include +#include +#include +#include "oslib/font.h" +#include "rufl_internal.h" + + +typedef enum { rufl_PAINT, rufl_WIDTH, rufl_X_TO_OFFSET, + rufl_SPLIT, rufl_PAINT_CALLBACK, rufl_FONT_BBOX } rufl_action; +#define rufl_PROCESS_CHUNK 200 + +bool rufl_can_background_blend = false; + +static const os_trfm trfm_oblique = + { { { 65536, 0 }, { 13930, 65536 }, { 0, 0 } } }; + + +static rufl_code rufl_process(rufl_action action, + const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string0, size_t length, + int x, int y, unsigned int flags, + int *width, int click_x, size_t *char_offset, int *actual_x, + rufl_callback_t callback, void *context); +static rufl_code rufl_process_span(rufl_action action, + unsigned short *s, unsigned int n, + unsigned int font, unsigned int font_size, unsigned int slant, + int *x, int y, unsigned int flags, + int click_x, size_t *offset, + rufl_callback_t callback, void *context); +static rufl_code rufl_process_span_old(rufl_action action, + unsigned short *s, unsigned int n, + unsigned int font, unsigned int font_size, unsigned int slant, + int *x, int y, unsigned int flags, + int click_x, size_t *offset, + rufl_callback_t callback, void *context); +static int rufl_unicode_map_search_cmp(const void *keyval, const void *datum); +static rufl_code rufl_process_not_available(rufl_action action, + unsigned short *s, unsigned int n, + unsigned int font_size, int *x, int y, + unsigned int flags, + int click_x, size_t *offset, + rufl_callback_t callback, void *context); + + +/** + * Render Unicode text. + */ + +rufl_code rufl_paint(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int x, int y, unsigned int flags) +{ + return rufl_process(rufl_PAINT, + font_family, font_style, font_size, string, + length, x, y, flags, 0, 0, 0, 0, 0, 0); +} + + +/** + * Measure the width of Unicode text. + */ + +rufl_code rufl_width(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int *width) +{ + return rufl_process(rufl_WIDTH, + font_family, font_style, font_size, string, + length, 0, 0, 0, width, 0, 0, 0, 0, 0); +} + + +/** + * Find the nearest character boundary in a string to where an x coordinate + * falls. + */ + +rufl_code rufl_x_to_offset(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int click_x, + size_t *char_offset, int *actual_x) +{ + return rufl_process(rufl_X_TO_OFFSET, + font_family, font_style, font_size, string, + length, 0, 0, 0, 0, + click_x, char_offset, actual_x, 0, 0); +} + + +/** + * Find the prefix of a string that will fit in a specified width. + */ + +rufl_code rufl_split(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int width, + size_t *char_offset, int *actual_x) +{ + return rufl_process(rufl_SPLIT, + font_family, font_style, font_size, string, + length, 0, 0, 0, 0, + width, char_offset, actual_x, 0, 0); +} + + +/** + * Render text, but call a callback instead of each call to Font_Paint. + */ + +rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string, size_t length, + int x, int y, + rufl_callback_t callback, void *context) +{ + return rufl_process(rufl_PAINT_CALLBACK, + font_family, font_style, font_size, string, + length, x, y, 0, 0, 0, 0, 0, callback, context); +} + + +/** + * Determine the maximum bounding box of a font. + */ + +rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, + unsigned int font_size, + int *bbox) +{ + return rufl_process(rufl_FONT_BBOX, + font_family, font_style, font_size, 0, + 0, 0, 0, 0, bbox, 0, 0, 0, 0, 0); +} + + +/** + * Render, measure, or split Unicode text. + */ + +rufl_code rufl_process(rufl_action action, + const char *font_family, rufl_style font_style, + unsigned int font_size, + const char *string0, size_t length, + int x, int y, unsigned int flags, + int *width, int click_x, size_t *char_offset, int *actual_x, + rufl_callback_t callback, void *context) +{ + unsigned short s[rufl_PROCESS_CHUNK]; + unsigned int font; + unsigned int font0, font1; + unsigned int n; + unsigned int u; + size_t offset; + size_t offset_u; + size_t offset_map[rufl_PROCESS_CHUNK]; + unsigned int slant; + const char *string = string0; + struct rufl_character_set *charset; + rufl_code code; + + assert(action == rufl_PAINT || + (action == rufl_WIDTH && width) || + (action == rufl_X_TO_OFFSET && char_offset && + actual_x) || + (action == rufl_SPLIT && char_offset && + actual_x) || + (action == rufl_PAINT_CALLBACK && callback) || + (action == rufl_FONT_BBOX && width)); + + if ((flags & rufl_BLEND_FONT) && !rufl_can_background_blend) { + /* unsuitable FM => clear blending bit */ + flags &= ~rufl_BLEND_FONT; + } + + if (length == 0 && action != rufl_FONT_BBOX) { + if (action == rufl_WIDTH) + *width = 0; + else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { + *char_offset = 0; + *actual_x = 0; + } + return rufl_OK; + } + if ((action == rufl_X_TO_OFFSET || action == rufl_SPLIT) && + click_x <= 0) { + *char_offset = 0; + *actual_x = 0; + return rufl_OK; + } + + code = rufl_find_font_family(font_family, font_style, + &font, &slant, &charset); + if (code != rufl_OK) + return code; + + if (action == rufl_FONT_BBOX) { + if (rufl_old_font_manager) + code = rufl_process_span_old(action, 0, 0, font, + font_size, slant, width, 0, 0, + 0, 0, 0, 0); + else + code = rufl_process_span(action, 0, 0, font, + font_size, slant, width, 0, 0, + 0, 0, 0, 0); + return code; + } + + offset_u = 0; + rufl_utf8_read(string, length, u); + if (u <= 0x001f || (0x007f <= u && u <= 0x009f)) + font1 = NOT_AVAILABLE; + else if (charset && rufl_character_set_test(charset, u)) + font1 = font; + else if (u < 0x10000) + font1 = rufl_substitution_table[u]; + else + font1 = NOT_AVAILABLE; + do { + s[0] = u; + offset_map[0] = offset_u; + n = 1; + font0 = font1; + /* invariant: s[0..n) is in font font0 */ + while (0 < length && n < rufl_PROCESS_CHUNK && font1 == font0) { + offset_u = string - string0; + rufl_utf8_read(string, length, u); + s[n] = u; + offset_map[n] = offset_u; + if (u <= 0x001f || (0x007f <= u && u <= 0x009f)) + font1 = NOT_AVAILABLE; + else if (charset && rufl_character_set_test(charset, u)) + font1 = font; + else if (u < 0x10000) + font1 = rufl_substitution_table[u]; + else + font1 = NOT_AVAILABLE; + if (font1 == font0) + n++; + } + if (n == rufl_PROCESS_CHUNK) + n--; + s[n] = 0; + offset_map[n] = offset_u; + if (length == 0 && font1 == font0) + offset_map[n] = string - string0; + + if (font0 == NOT_AVAILABLE) + code = rufl_process_not_available(action, s, n, + font_size, &x, y, flags, + click_x, &offset, callback, context); + else if (rufl_old_font_manager) + code = rufl_process_span_old(action, s, n, font0, + font_size, slant, &x, y, flags, + click_x, &offset, callback, context); + else + code = rufl_process_span(action, s, n, font0, + font_size, slant, &x, y, flags, + click_x, &offset, callback, context); + + if ((action == rufl_X_TO_OFFSET || action == rufl_SPLIT) && + (offset < n || click_x < x)) + break; + if (code != rufl_OK) + return code; + + } while (!(length == 0 && font1 == font0)); + + if (action == rufl_WIDTH) + *width = x; + else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { + *char_offset = offset_map[offset]; + *actual_x = x; + } + + return rufl_OK; +} + + +/** + * Render a string of characters from a single RISC OS font. + */ + +rufl_code rufl_process_span(rufl_action action, + unsigned short *s, unsigned int n, + unsigned int font, unsigned int font_size, unsigned int slant, + int *x, int y, unsigned int flags, + int click_x, size_t *offset, + rufl_callback_t callback, void *context) +{ + unsigned short *split_point; + int x_out, y_out; + unsigned int i; + char font_name[80]; + bool oblique = slant && !rufl_font_list[font].slant; + font_f f; + rufl_code code; + + code = rufl_find_font(font, font_size, "UTF8", &f); + if (code != rufl_OK) + return code; + + if (action == rufl_FONT_BBOX) { + rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]); + if (rufl_fm_error) + return rufl_FONT_MANAGER_ERROR; + return rufl_OK; + } + + if (action == rufl_PAINT) { + /* paint span */ + rufl_fm_error = xfont_paint(f, (const char *) s, + font_OS_UNITS | + (oblique ? font_GIVEN_TRFM : 0) | + font_GIVEN_LENGTH | + font_GIVEN_FONT | font_KERN | + font_GIVEN16_BIT | + ((flags & rufl_BLEND_FONT) ? + font_BLEND_FONT : 0), + *x, y, 0, &trfm_oblique, n * 2); + if (rufl_fm_error) { + LOG("xfont_paint: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + for (i = 0; i != n; i++) + fprintf(stderr, "0x%x ", s[i]); + fprintf(stderr, " (%u)\n", n); + return rufl_FONT_MANAGER_ERROR; + } + } else if (action == rufl_PAINT_CALLBACK) { + snprintf(font_name, sizeof font_name, "%s\\EUTF8", + rufl_font_list[font].identifier); + callback(context, font_name, font_size, 0, s, n, *x, y); + } + + /* increment x by width of span */ + if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { + rufl_fm_error = xfont_scan_string(f, (const char *) s, + font_GIVEN_LENGTH | font_GIVEN_FONT | + font_KERN | font_GIVEN16_BIT | + ((action == rufl_X_TO_OFFSET) ? + font_RETURN_CARET_POS : 0), + (click_x - *x) * 400, 0x7fffffff, 0, 0, + n * 2, + (char **)(void *)&split_point, + &x_out, &y_out, 0); + *offset = split_point - s; + } else { + rufl_fm_error = xfont_scan_string(f, (const char *) s, + font_GIVEN_LENGTH | font_GIVEN_FONT | + font_KERN | font_GIVEN16_BIT, + 0x7fffffff, 0x7fffffff, 0, 0, n * 2, + 0, &x_out, &y_out, 0); + } + if (rufl_fm_error) { + LOG("xfont_scan_string: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + *x += x_out / 400; + + return rufl_OK; +} + + +/** + * Render a string of characters from a single RISC OS font (old font manager + * version). + */ + +rufl_code rufl_process_span_old(rufl_action action, + unsigned short *s, unsigned int n, + unsigned int font, unsigned int font_size, unsigned int slant, + int *x, int y, unsigned int flags, + int click_x, size_t *offset, + rufl_callback_t callback, void *context) +{ + char s2[rufl_PROCESS_CHUNK]; + char *split_point; + int x_out, y_out; + unsigned int i; + bool oblique = slant && !rufl_font_list[font].slant; + font_f f; + rufl_code code; + + if (action == rufl_FONT_BBOX) { + /* Don't need encoding for bounding box */ + code = rufl_find_font(font, font_size, NULL, &f); + if (code != rufl_OK) + return code; + + rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]); + if (rufl_fm_error) { + LOG("xfont_read_info: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + return rufl_OK; + } + + if (offset) + *offset = 0; + + /* Process the span in map-coherent chunks */ + do { + struct rufl_unicode_map *map = NULL; + struct rufl_unicode_map_entry *entry = NULL; + unsigned int j; + + i = 0; + + /* Find map for first character */ + for (j = 0; j < rufl_font_list[font].num_umaps; j++) { + map = rufl_font_list[font].umap + j; + + entry = bsearch(&s[i], map->map, map->entries, + sizeof map->map[0], + rufl_unicode_map_search_cmp); + if (entry) + break; + } + assert(map != NULL); + assert(entry != NULL); + + /* Collect characters: s[0..i) use map */ + do { + entry = bsearch(&s[i], map->map, map->entries, + sizeof map->map[0], + rufl_unicode_map_search_cmp); + + if (entry) + s2[i++] = entry->c; + } while (i != n && entry != NULL); + + s2[i] = 0; + + code = rufl_find_font(font, font_size, map->encoding, &f); + if (code != rufl_OK) + return code; + + if (action == rufl_PAINT) { + /* paint span */ + /* call Font_SetFont to work around broken PS printer + * driver, which doesn't use the font handle from + * Font_Paint */ + rufl_fm_error = xfont_set_font(f); + if (rufl_fm_error) { + LOG("xfont_set_font: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + + rufl_fm_error = xfont_paint(f, s2, font_OS_UNITS | + (oblique ? font_GIVEN_TRFM : 0) | + font_GIVEN_LENGTH | font_GIVEN_FONT | + font_KERN | + ((flags & rufl_BLEND_FONT) ? + font_BLEND_FONT : 0), + *x, y, 0, &trfm_oblique, i); + if (rufl_fm_error) { + LOG("xfont_paint: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + } else if (action == rufl_PAINT_CALLBACK) { + char font_name[80]; + + if (map->encoding) + snprintf(font_name, sizeof font_name, "%s\\E%s", + rufl_font_list[font].identifier, + map->encoding); + else + snprintf(font_name, sizeof font_name, "%s", + rufl_font_list[font].identifier); + + callback(context, font_name, font_size, + s2, 0, i, *x, y); + } + + /* increment x by width of span */ + if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { + rufl_fm_error = xfont_scan_string(f, s2, + font_GIVEN_LENGTH | font_GIVEN_FONT | + font_KERN | + ((action == rufl_X_TO_OFFSET) ? + font_RETURN_CARET_POS : 0), + (click_x - *x) * 400, 0x7fffffff, + 0, 0, i, + &split_point, &x_out, &y_out, 0); + *offset += split_point - s2; + } else { + rufl_fm_error = xfont_scan_string(f, s2, + font_GIVEN_LENGTH | font_GIVEN_FONT | + font_KERN, + 0x7fffffff, 0x7fffffff, 0, 0, i, + 0, &x_out, &y_out, 0); + } + if (rufl_fm_error) { + LOG("xfont_scan_string: 0x%x: %s", + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } + *x += x_out / 400; + + /* Now update s and n for the next chunk */ + s += i; + n -= i; + } while (n != 0); + + return rufl_OK; +} + + +int rufl_unicode_map_search_cmp(const void *keyval, const void *datum) +{ + const unsigned short *key = keyval; + const struct rufl_unicode_map_entry *entry = datum; + if (*key < entry->u) + return -1; + else if (entry->u < *key) + return 1; + return 0; +} + + +/** + * Render a string of characters not available in any font as their hex code. + */ + +rufl_code rufl_process_not_available(rufl_action action, + unsigned short *s, unsigned int n, + unsigned int font_size, int *x, int y, + unsigned int flags, + int click_x, size_t *offset, + rufl_callback_t callback, void *context) +{ + char missing[] = "0000"; + int dx = 7 * font_size / 64; + int top_y = y + 5 * font_size / 64; + unsigned int i; + font_f f; + rufl_code code; + + if (action == rufl_WIDTH) { + *x += n * dx; + return rufl_OK; + } else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { + if (click_x - *x < (int) (n * dx)) + *offset = (click_x - *x) / dx; + else + *offset = n; + *x += *offset * dx; + return rufl_OK; + } + + code = rufl_find_font(rufl_CACHE_CORPUS, font_size / 2, "Latin1", &f); + if (code != rufl_OK) + return code; + + for (i = 0; i != n; i++) { + missing[0] = "0123456789abcdef"[(s[i] >> 12) & 0xf]; + missing[1] = "0123456789abcdef"[(s[i] >> 8) & 0xf]; + missing[2] = "0123456789abcdef"[(s[i] >> 4) & 0xf]; + missing[3] = "0123456789abcdef"[(s[i] >> 0) & 0xf]; + + /* first two characters in top row */ + if (action == rufl_PAINT) { + rufl_fm_error = xfont_paint(f, missing, font_OS_UNITS | + font_GIVEN_LENGTH | font_GIVEN_FONT | + font_KERN | + ((flags & rufl_BLEND_FONT) ? + font_BLEND_FONT : 0), + *x, top_y, 0, 0, 2); + if (rufl_fm_error) + return rufl_FONT_MANAGER_ERROR; + } else { + callback(context, "Corpus.Medium\\ELatin1", + font_size / 2, missing, 0, 2, + *x, top_y); + } + + /* last two characters underneath */ + if (action == rufl_PAINT) { + rufl_fm_error = xfont_paint(f, missing + 2, + font_OS_UNITS | + font_GIVEN_LENGTH | font_GIVEN_FONT | + font_KERN | + ((flags & rufl_BLEND_FONT) ? + font_BLEND_FONT : 0), + *x, y, 0, 0, 2); + if (rufl_fm_error) + return rufl_FONT_MANAGER_ERROR; + } else { + callback(context, "Corpus.Medium\\ELatin1", + font_size / 2, missing + 2, 0, 2, + *x, y); + } + + *x += dx; + } + + return rufl_OK; +} diff --git a/src/rufl_quit.c b/src/rufl_quit.c new file mode 100644 index 0000000..fc429c0 --- /dev/null +++ b/src/rufl_quit.c @@ -0,0 +1,49 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +#include +#include "oslib/font.h" +#include "rufl_internal.h" + + +/** + * Free all resources used by the library. + */ + +void rufl_quit(void) +{ + unsigned int i; + + if (!rufl_font_list) + return; + + for (i = 0; i != rufl_font_list_entries; i++) { + free(rufl_font_list[i].identifier); + free(rufl_font_list[i].charset); + } + free(rufl_font_list); + rufl_font_list = 0; + + for (i = 0; i != rufl_family_list_entries; i++) + free((void *) rufl_family_list[i]); + free(rufl_family_list); + free(rufl_family_map); + rufl_family_list = 0; + + for (i = 0; i != rufl_CACHE_SIZE; i++) { + if (rufl_cache[i].font != rufl_CACHE_NONE) { + xfont_lose_font(rufl_cache[i].f); + rufl_cache[i].font = rufl_CACHE_NONE; + } + } + + free(rufl_family_menu); + rufl_family_menu = 0; + + free(rufl_substitution_table); + rufl_substitution_table = 0; +} diff --git a/src/strfuncs.c b/src/strfuncs.c new file mode 100644 index 0000000..08b43b2 --- /dev/null +++ b/src/strfuncs.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "strfuncs.h" + +char *strdup(const char *s) +{ + size_t len = strlen(s); + char *new = malloc(len + 1); + if (!new) + return 0; + memcpy(new, s, len); + new[len] = '\0'; + return new; +} + +char *strndup(const char *s, size_t n) +{ + size_t len = strlen(s); + if (n < len) + len = n; + char *new = malloc(len + 1); + if (!new) + return 0; + memcpy(new, s, len); + new[len] = '\0'; + return new; +} + +int strcasecmp(const char *s1, const char *s2) +{ + int i; + while ((i = tolower(*s1)) && i == tolower(*s2)) + s1++, s2++; + return ((unsigned char) tolower(*s1) - (unsigned char) tolower(*s2)); +} diff --git a/src/strfuncs.h b/src/strfuncs.h new file mode 100644 index 0000000..495ea98 --- /dev/null +++ b/src/strfuncs.h @@ -0,0 +1,5 @@ +#include + +char *strdup(const char *s); +char *strndup(const char *s, size_t n); +int strcasecmp(const char *s1, const char *s2); diff --git a/strfuncs.c b/strfuncs.c deleted file mode 100644 index e6c6347..0000000 --- a/strfuncs.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include - -char *strdup(const char *s) -{ - size_t len = strlen(s); - char *new = malloc(len + 1); - if (!new) - return 0; - memcpy(new, s, len); - new[len] = '\0'; - return new; -} - -char *strndup(const char *s, size_t n) -{ - size_t len = strlen(s); - if (n < len) - len = n; - char *new = malloc(len + 1); - if (!new) - return 0; - memcpy(new, s, len); - new[len] = '\0'; - return new; -} - -int strcasecmp(const char *s1, const char *s2) -{ - int i; - while ((i = tolower(*s1)) && i == tolower(*s2)) - s1++, s2++; - return ((unsigned char) tolower(*s1) - (unsigned char) tolower(*s2)); -} diff --git a/strfuncs.h b/strfuncs.h deleted file mode 100644 index 495ea98..0000000 --- a/strfuncs.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -char *strdup(const char *s); -char *strndup(const char *s, size_t n); -int strcasecmp(const char *s1, const char *s2); diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..30e1600 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,4 @@ +# Tests +DIR_TEST_ITEMS := rufl_test:rufl_test.c rufl_chars:rufl_chars.c + +include build/makefiles/Makefile.subdir diff --git a/test/rufl_chars.c b/test/rufl_chars.c new file mode 100644 index 0000000..14a0fb6 --- /dev/null +++ b/test/rufl_chars.c @@ -0,0 +1,315 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +#include +#include +#include +#include +#include +#include "oslib/colourtrans.h" +#include "oslib/wimp.h" +#include "rufl.h" + + +unsigned int font = 0; +unsigned int weight = rufl_WEIGHT_400; +bool italic = false; + + +static rufl_code redraw(int x, int y, int y0, int y1); +static void try(rufl_code code, const char *context); +static void die(const char *error); + + +int main(void) +{ + unsigned int i; + bool quit = false; + const wimp_MESSAGE_LIST(2) messages = { { message_MODE_CHANGE, + message_QUIT } }; + wimp_t task; + wimp_menu *menu; + struct wimp_window_base window = { + { 400, 400, 1700, 1200 }, + 0, 0, + wimp_TOP, + wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON | + wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | + wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | + wimp_WINDOW_SIZE_ICON | wimp_WINDOW_NEW_FORMAT, + wimp_COLOUR_BLACK, wimp_COLOUR_LIGHT_GREY, + wimp_COLOUR_BLACK, wimp_COLOUR_WHITE, + wimp_COLOUR_DARK_GREY, wimp_COLOUR_MID_LIGHT_GREY, + wimp_COLOUR_CREAM, + 0, + { 0, -81928, 1300, 0 }, + wimp_ICON_TEXT | wimp_ICON_HCENTRED, + 0, + 0, + 2, 1, + { "RUfl Chars" }, + 0 }; + wimp_w w; + wimp_window_state state; + wimp_block block; + wimp_event_no event; + wimp_pointer pointer; + osbool more; + os_error *error; + rufl_code code = rufl_OK; + + error = xwimp_initialise(wimp_VERSION_RO3, "RUfl Chars", + (const wimp_message_list *) (const void *) &messages, + 0, &task); + if (error) { + printf("error: xwimp_initialise: 0x%x: %s\n", + error->errnum, error->errmess); + exit(1); + } + + try(rufl_init(), "rufl_init"); + + menu = malloc(wimp_SIZEOF_MENU(10 + rufl_family_list_entries)); + if (!menu) + die("Out of memory"); + strcpy(menu->title_data.text, "Fonts"); + menu->title_fg = wimp_COLOUR_BLACK; + menu->title_bg = wimp_COLOUR_LIGHT_GREY; + menu->work_fg = wimp_COLOUR_RED; + menu->work_bg = wimp_COLOUR_WHITE; + menu->width = 200; + menu->height = wimp_MENU_ITEM_HEIGHT; + menu->gap = wimp_MENU_ITEM_GAP; + for (i = 0; i != 10; i++) { + menu->entries[i].menu_flags = 0; + menu->entries[i].sub_menu = wimp_NO_SUB_MENU; + menu->entries[i].icon_flags = wimp_ICON_TEXT | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); + strcpy(menu->entries[i].data.text, "100"); + menu->entries[i].data.text[0] = '1' + i; + } + menu->entries[9].menu_flags = wimp_MENU_SEPARATE; + menu->entries[9].sub_menu = wimp_NO_SUB_MENU; + menu->entries[9].icon_flags = wimp_ICON_TEXT | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); + strcpy(menu->entries[9].data.text, "Italic"); + for (i = 0; i != rufl_family_list_entries; i++) { + menu->entries[10 + i].menu_flags = 0; + menu->entries[10 + i].sub_menu = wimp_NO_SUB_MENU; + menu->entries[10 + i].icon_flags = wimp_ICON_TEXT | + wimp_ICON_INDIRECTED | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); + menu->entries[10 + i].data.indirected_text.text = + (char *) rufl_family_list[i]; + menu->entries[10 + i].data.indirected_text.validation = + (char *) -1; + menu->entries[10 + i].data.indirected_text.size = + strlen(rufl_family_list[i]); + } + menu->entries[3].menu_flags |= wimp_MENU_TICKED; + menu->entries[10].menu_flags |= wimp_MENU_TICKED; + menu->entries[i + 9].menu_flags |= wimp_MENU_LAST; + + error = xwimp_create_window((wimp_window *) &window, &w); + if (error) + die(error->errmess); + + state.w = w; + error = xwimp_get_window_state(&state); + if (error) + die(error->errmess); + + error = xwimp_open_window((wimp_open *) (void *) &state); + if (error) + die(error->errmess); + + while (!quit) { + error = xwimp_poll(wimp_MASK_NULL, &block, 0, &event); + if (error) + die(error->errmess); + + switch (event) { + case wimp_REDRAW_WINDOW_REQUEST: + error = xwimp_redraw_window(&block.redraw, &more); + if (error) + die(error->errmess); + xcolourtrans_set_font_colours(0, os_COLOUR_WHITE, + os_COLOUR_BLACK, 14, 0, 0, 0); + while (more) { + code = redraw(block.redraw.box.x0 - + block.redraw.xscroll, + block.redraw.box.y1 - + block.redraw.yscroll, + block.redraw.box.y1 - + block.redraw.yscroll - + block.redraw.clip.y1, + block.redraw.box.y1 - + block.redraw.yscroll - + block.redraw.clip.y0); + error = xwimp_get_rectangle(&block.redraw, + &more); + if (error) + die(error->errmess); + } + try(code, "redraw"); + break; + + case wimp_OPEN_WINDOW_REQUEST: + error = xwimp_open_window(&block.open); + if (error) + die(error->errmess); + break; + + case wimp_CLOSE_WINDOW_REQUEST: + quit = true; + break; + + case wimp_MOUSE_CLICK: + if (block.pointer.buttons == wimp_CLICK_MENU) { + error = xwimp_create_menu(menu, + block.pointer.pos.x - 64, + block.pointer.pos.y); + if (error) + die(error->errmess); + } + break; + + case wimp_MENU_SELECTION: + error = xwimp_get_pointer_info(&pointer); + if (error) + die(error->errmess); + if (block.selection.items[0] <= 8) { + menu->entries[weight - 1].menu_flags ^= + wimp_MENU_TICKED; + weight = block.selection.items[0] + 1; + menu->entries[weight - 1].menu_flags ^= + wimp_MENU_TICKED; + } else if (block.selection.items[0] == 9) { + italic = !italic; + menu->entries[9].menu_flags ^= wimp_MENU_TICKED; + } else { + menu->entries[10 + font].menu_flags ^= + wimp_MENU_TICKED; + font = block.selection.items[0] - 10; + menu->entries[10 + font].menu_flags ^= + wimp_MENU_TICKED; + } + error = xwimp_force_redraw(w, + window.extent.x0, window.extent.y0, + window.extent.x1, window.extent.y1); + if (error) + die(error->errmess); + if (pointer.buttons == wimp_CLICK_ADJUST) { + error = xwimp_create_menu(menu, + pointer.pos.x - 64, + pointer.pos.y); + if (error) + die(error->errmess); + } + break; + + case wimp_USER_MESSAGE: + case wimp_USER_MESSAGE_RECORDED: + switch (block.message.action) { + case message_QUIT: + quit = true; + break; + case message_MODE_CHANGE: + rufl_invalidate_cache(); + break; + } + break; + } + } + +/* try(rufl_paint("NewHall.Medium", 240, utf8_test, sizeof utf8_test - 1, */ +/* 1200, 1200), "rufl_paint"); */ + + xwimp_close_down(task); + + rufl_quit(); + + return 0; +} + + +rufl_code redraw(int x, int y, int y0, int y1) +{ + char s[10]; + unsigned int l; + unsigned int u; + rufl_code code; + rufl_style style = weight | (italic ? rufl_SLANTED : 0); + + for (u = y0 / 40 * 32; (int) u != (y1 / 40 + 1) * 32; u++) { + if (u <= 0x7f) + s[0] = u, l = 1; + else if (u <= 0x7ff) + s[0] = 0xc0 | (u >> 6), + s[1] = 0x80 | (u & 0x3f), l = 2; + else if (u <= 0xffff) + s[0] = 0xe0 | (u >> 12), + s[1] = 0x80 | ((u >> 6) & 0x3f), + s[2] = 0x80 | (u & 0x3f), l = 3; + else + break; + s[l] = 0; + + code = rufl_paint(rufl_family_list[font], style, 240, s, l, + x + 10 + 40 * (u % 32), + y - 40 - 40 * (u / 32), + 0); + if (code != rufl_OK) + return code; + } + + return rufl_OK; +} + + +void try(rufl_code code, const char *context) +{ + char s[200]; + if (code == rufl_OK) + return; + else if (code == rufl_OUT_OF_MEMORY) + snprintf(s, sizeof s, "error: %s: out of memory\n", context); + else if (code == rufl_FONT_MANAGER_ERROR) + snprintf(s, sizeof s, "error: %s: Font Manager error %x %s\n", + context, rufl_fm_error->errnum, + rufl_fm_error->errmess); + else if (code == rufl_FONT_NOT_FOUND) + snprintf(s, sizeof s, "error: %s: font not found\n", context); + else if (code == rufl_IO_ERROR) + snprintf(s, sizeof s, "error: %s: io error: %i %s\n", context, + errno, strerror(errno)); + else if (code == rufl_IO_EOF) + snprintf(s, sizeof s, "error: %s: eof\n", context); + else + snprintf(s, sizeof s, "error: %s: unknown error\n", context); + + die(s); +} + + +void die(const char *error) +{ + os_error warn_error; + + warn_error.errnum = 1; + strncpy(warn_error.errmess, error, + sizeof warn_error.errmess - 1); + warn_error.errmess[sizeof warn_error.errmess - 1] = '\0'; + xwimp_report_error(&warn_error, + wimp_ERROR_BOX_OK_ICON, + "RUfl Chars", 0); + rufl_quit(); + exit(EXIT_FAILURE); +} diff --git a/test/rufl_test.c b/test/rufl_test.c new file mode 100644 index 0000000..51a29d6 --- /dev/null +++ b/test/rufl_test.c @@ -0,0 +1,149 @@ +/* + * This file is part of RUfl + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license + * Copyright 2006 James Bursa + */ + +#include +#include +#include +#include "rufl.h" + + +static void try(rufl_code code, const char *context); +static int move_to(os_coord *to, void *user); +static int line_to(os_coord *to, void *user); +static int cubic_to(os_coord *control1, os_coord *control2, os_coord *to, + void *user); +static void callback(void *context, + const char *font_name, unsigned int font_size, + const char *s8, unsigned short *s16, unsigned int n, + int x, int y); + + +int main(void) +{ + char utf8_test[] = "Hello, world! ὕαλον " + "Uherské Hradiště. 𐀀"; + int width; + size_t char_offset; + int x; + int actual_x; + struct rufl_decomp_funcs funcs = { move_to, line_to, cubic_to }; + int bbox[4]; + + try(rufl_init(), "rufl_init"); + rufl_dump_state(); + try(rufl_paint("NewHall", rufl_WEIGHT_400, 240, + utf8_test, sizeof utf8_test - 1, + 1200, 1000, 0), "rufl_paint"); + try(rufl_width("NewHall", rufl_WEIGHT_400, 240, + utf8_test, sizeof utf8_test - 1, + &width), "rufl_width"); + printf("width: %i\n", width); + for (x = 0; x < width + 100; x += 100) { + try(rufl_x_to_offset("NewHall", rufl_WEIGHT_400, 240, + utf8_test, sizeof utf8_test - 1, + x, &char_offset, &actual_x), + "rufl_x_to_offset"); + printf("x to offset: %i -> %i %zi \"%s\"\n", x, actual_x, + char_offset, utf8_test + char_offset); + try(rufl_split("NewHall", rufl_WEIGHT_400, 240, + utf8_test, sizeof utf8_test - 1, + x, &char_offset, &actual_x), + "rufl_split"); + printf("split: %i -> %i %zi \"%s\"\n", x, actual_x, + char_offset, utf8_test + char_offset); + } + try(rufl_decompose_glyph("Homerton", rufl_WEIGHT_400, 1280, + "A", 1, &funcs, 0), + "rufl_decompose_glyph"); + try(rufl_paint_callback("NewHall", rufl_WEIGHT_400, 240, + utf8_test, sizeof utf8_test - 1, + 1200, 1000, callback, 0), "rufl_paint_callback"); + try(rufl_font_bbox("NewHall", rufl_WEIGHT_400, 240, bbox), + "rufl_font_bbox"); + printf("bbox: %i %i %i %i\n", bbox[0], bbox[1], bbox[2], bbox[3]); + rufl_quit(); + + return 0; +} + + +void try(rufl_code code, const char *context) +{ + if (code == rufl_OK) + return; + else if (code == rufl_OUT_OF_MEMORY) + printf("error: %s: out of memory\n", context); + else if (code == rufl_FONT_MANAGER_ERROR) + printf("error: %s: Font Manager error %x %s\n", context, + rufl_fm_error->errnum, + rufl_fm_error->errmess); + else if (code == rufl_FONT_NOT_FOUND) + printf("error: %s: font not found\n", context); + else if (code == rufl_IO_ERROR) + printf("error: %s: io error: %i %s\n", context, errno, + strerror(errno)); + else if (code == rufl_IO_EOF) + printf("error: %s: eof\n", context); + else + printf("error: %s: unknown error\n", context); + rufl_quit(); + exit(1); +} + + +int move_to(os_coord *to, void *user) +{ + (void) user; + + printf("Move to (%d,%d)\n", to->x, to->y); + + return 0; +} + + +int line_to(os_coord *to, void *user) +{ + (void) user; + + printf("Line to (%d,%d)\n", to->x, to->y); + + return 0; +} + + +int cubic_to(os_coord *control1, os_coord *control2, os_coord *to, + void *user) +{ + (void) user; + + printf("Bezier to (%d,%d),(%d,%d),(%d,%d)\n", + control1->x, control1->y, + control2->x, control2->y, + to->x, to->y); + + return 0; +} + + +void callback(void *context, + const char *font_name, unsigned int font_size, + const char *s8, unsigned short *s16, unsigned int n, + int x, int y) +{ + (void) context; + + printf("callback: \"%s\", %u, ", font_name, font_size); + if (s8) + printf("s8 \"%.*s\" ", n, s8); + else { + printf("s16 \""); + for (unsigned int i = 0; i != n; i++) + printf("%x ", (unsigned int) s16[i]); + printf("\" "); + } + printf("%i %i\n", x, y); +} -- cgit v1.2.3