summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/xetexdir/XeTeX_ext.c')
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeX_ext.c845
1 files changed, 629 insertions, 216 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
index a4b467bb10c..d9904176d7e 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
+++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
@@ -37,12 +37,8 @@ authorization from SIL International.
#include "png.h"
#endif
-#include "zlib.h"
-
#define EXTERN extern
-#define Byte my_Byte /* hack to work around typedef conflict with zlib */
#include "xetexd.h"
-#undef Byte
#ifdef XETEX_MAC
#undef input /* this is defined in texmfmp.h, but we don't need it and it confuses the carbon headers */
@@ -54,6 +50,8 @@ authorization from SIL International.
#include <ft2build.h>
#include FT_FREETYPE_H
+#include "zlib.h"
+
#include "TECkit_Engine.h"
#include <kpathsea/c-ctype.h>
@@ -170,11 +168,7 @@ const UInt32 byteMark = 0x00000080UL;
/* if the user specifies a paper size or output driver program */
string papersize;
-#ifdef XETEX_MAC
-string outputdriver = "xdv2pdf"; /* default for backward compatibility on Mac OS X */
-#else
-string outputdriver = "xdvipdfmx -q -E"; /* else default to portable xdvipdfmx driver */
-#endif
+string outputdriver = "xdvipdfmx -q -E"; /* default to portable xdvipdfmx driver */
void initversionstring(char **versions)
@@ -326,11 +320,19 @@ static char* byteBuffer = NULL;
/* now apply the mapping to turn external bytes into Unicode characters in buffer */
cnv = (UConverter*)(f->conversionData);
- outLen = ucnv_toUChars(cnv, &buffer[first], (bufsize - first), byteBuffer, bytesRead, &errorCode);
+#ifdef WORDS_BIGENDIAN
+#define UCNV_UTF32_NativeEndian UCNV_UTF32_BigEndian
+#else
+#define UCNV_UTF32_NativeEndian UCNV_UTF32_LittleEndian
+#endif
+ outLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv,
+ (char*)&buffer[first], sizeof(*buffer) * (bufsize - first),
+ byteBuffer, bytesRead, &errorCode);
if (errorCode != 0) {
fprintf(stderr, "! Unicode conversion failed: error code = %d\n", (int)errorCode);
return false;
}
+ outLen /= sizeof(*buffer);
last = first + outLen;
buffer[last] = ' ';
@@ -439,6 +441,14 @@ getencodingmodeandinfo(integer* info)
}
void
+printcstring(const char* str)
+{
+ if (str != NULL)
+ while (*str)
+ printvisiblechar(*(str++));
+}
+
+void
printutf8str(const unsigned char* str, int len)
{
while (len-- > 0)
@@ -464,7 +474,7 @@ load_mapping_file(const char* s, const char* e)
mapPath = kpse_find_file(buffer, kpse_miscfonts_format, 1);
if (mapPath) {
- FILE* mapFile = fopen(mapPath, "rb");
+ FILE* mapFile = fopen(mapPath, FOPEN_RBIN_MODE);
free(mapPath);
if (mapFile) {
UInt32 mappingSize;
@@ -495,8 +505,43 @@ load_mapping_file(const char* s, const char* e)
return cnv;
}
+double
+read_double(const char** s)
+{
+ int neg = 0;
+ double val = 0.0;
+ const char* cp = *s;
+
+ while (*cp == ' '|| *cp == '\t')
+ ++cp;
+ if (*cp == '-') {
+ neg = 1;
+ ++cp;
+ }
+ else if (*cp == '+') {
+ ++cp;
+ }
+
+ while (*cp >= '0' && *cp <= '9') {
+ val = val * 10.0 + *cp - '0';
+ ++cp;
+ }
+ if (*cp == '.') {
+ double dec = 10.0;
+ ++cp;
+ while (*cp >= '0' && *cp <= '9') {
+ val = val + (*cp - '0') / dec;
+ ++cp;
+ dec = dec * 10.0;
+ }
+ }
+ *s = cp;
+
+ return neg ? -val : val;
+}
+
static UInt32
-read_tag(const char* cp)
+read_tag(const char* cp, char padChar)
{
UInt32 tag = 0;
int i;
@@ -507,7 +552,7 @@ read_tag(const char* cp)
++cp;
}
else
- tag += ' ';
+ tag += padChar;
}
return tag;
}
@@ -543,6 +588,42 @@ read_tag_with_param(const char* cp, SInt32* param)
return tag;
}
+unsigned int
+read_rgb_a(const char** cp)
+{
+ UInt32 rgbValue = 0;
+ UInt32 alpha = 0;
+ int i;
+ for (i = 0; i < 6; ++i) {
+ if ((**cp >= '0') && (**cp <= '9'))
+ rgbValue = (rgbValue << 4) + **cp - '0';
+ else if ((**cp >= 'A') && (**cp <= 'F'))
+ rgbValue = (rgbValue << 4) + **cp - 'A' + 10;
+ else if ((**cp >= 'a') && (**cp <= 'f'))
+ rgbValue = (rgbValue << 4) + **cp - 'a' + 10;
+ else
+ return 0x000000FF;
+ (*cp)++;
+ }
+ rgbValue <<= 8;
+ for (i = 0; i < 2; ++i) {
+ if ((**cp >= '0') && (**cp <= '9'))
+ alpha = (alpha << 4) + **cp - '0';
+ else if ((**cp >= 'A') && (**cp <= 'F'))
+ alpha = (alpha << 4) + **cp - 'A' + 10;
+ else if ((**cp >= 'a') && (**cp <= 'f'))
+ alpha = (alpha << 4) + **cp - 'a' + 10;
+ else
+ break;
+ (*cp)++;
+ }
+ if (i == 2)
+ rgbValue += alpha;
+ else
+ rgbValue += 0xFF;
+ return rgbValue;
+}
+
static void*
loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const char* cp1)
{
@@ -564,6 +645,9 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
UInt32 rgbValue = 0x000000FF;
+ double extend = 1.0;
+ double slant = 0.0;
+
/* scan the feature string (if any) */
if (cp1 != NULL) {
while (*cp1) {
@@ -582,7 +666,7 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
cp3 = cp1 + 6;
if (*cp3 != '=')
goto bad_option;
- scriptTag = read_tag(cp3 + 1);
+ scriptTag = read_tag(cp3 + 1, ' ');
goto next_option;
}
@@ -590,7 +674,7 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
cp3 = cp1 + 8;
if (*cp3 != '=')
goto bad_option;
- languageTag = read_tag(cp3 + 1);
+ languageTag = read_tag(cp3 + 1, ' ');
goto next_option;
}
@@ -602,81 +686,47 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
goto next_option;
}
+ if (strncmp(cp1, "extend", 6) == 0) {
+ cp3 = cp1 + 6;
+ if (*cp3 != '=')
+ goto bad_option;
+ ++cp3;
+ extend = read_double(&cp3);
+ goto next_option;
+ }
+
+ if (strncmp(cp1, "slant", 5) == 0) {
+ cp3 = cp1 + 5;
+ if (*cp3 != '=')
+ goto bad_option;
+ ++cp3;
+ slant = read_double(&cp3);
+ goto next_option;
+ }
+
if (strncmp(cp1, "color", 5) == 0) {
- unsigned alpha = 0;
- int i;
+ const char* s;
cp3 = cp1 + 5;
if (*cp3 != '=')
goto bad_option;
++cp3;
-
- rgbValue = 0;
- for (i = 0; i < 6; ++i) {
- if ((*cp3 >= '0') && (*cp3 <= '9'))
- rgbValue = (rgbValue << 4) + *cp3 - '0';
- else if ((*cp3 >= 'A') && (*cp3 <= 'F'))
- rgbValue = (rgbValue << 4) + *cp3 - 'A' + 10;
- else if ((*cp3 >= 'a') && (*cp3 <= 'f'))
- rgbValue = (rgbValue << 4) + *cp3 - 'a' + 10;
- else
- goto bad_option;
- ++cp3;
- }
- rgbValue <<= 8;
- for (i = 0; i < 2; ++i) {
- if ((*cp3 >= '0') && (*cp3 <= '9'))
- alpha = (alpha << 4) + *cp3 - '0';
- else if ((*cp3 >= 'A') && (*cp3 <= 'F'))
- alpha = (alpha << 4) + *cp3 - 'A' + 10;
- else if ((*cp3 >= 'a') && (*cp3 <= 'f'))
- alpha = (alpha << 4) + *cp3 - 'a' + 10;
- else
- break;
- ++cp3;
- }
- if (i == 2)
- rgbValue += alpha;
+ s = cp3;
+ rgbValue = read_rgb_a(&cp3);
+ if ((cp3 == s+6) || (cp3 == s+8))
+ loadedfontflags |= FONT_FLAGS_COLORED;
else
- rgbValue += 0xFF;
-
- loadedfontflags |= FONT_FLAGS_COLORED;
-
+ goto bad_option;
goto next_option;
}
if (strncmp(cp1, "letterspace", 11) == 0) {
- int sign = 1;
- double val = 0.0;
-
+ double val;
cp3 = cp1 + 11;
if (*cp3 != '=')
goto bad_option;
++cp3;
-
- if (*cp3 == '-') {
- sign = -1;
- ++cp3;
- }
- else if (*cp3 == '+') {
- ++cp3;
- }
-
- while (*cp3 >= '0' && *cp3 <= '9') {
- val = val * 10.0 + *cp3 - '0';
- ++cp3;
- }
- if (*cp3 == '.' || *cp3 == ',') {
- double dec = 10.0;
- ++cp3;
- while (*cp3 >= '0' && *cp3 <= '9') {
- val = val + (*cp3 - '0') / dec;
- ++cp3;
- dec = dec * 10.0;
- }
- }
-
- loadedfontletterspace = sign * (val / 100.0) * scaled_size;
-
+ val = read_double(&cp3);
+ loadedfontletterspace = (val / 100.0) * scaled_size;
goto next_option;
}
@@ -698,7 +748,7 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
}
if (*cp1 == '-') {
- tag = read_tag(cp1 + 1);
+ tag = read_tag(cp1 + 1, ' ');
++nRemoved;
if (nRemoved == 1)
removeFeatures = xmalloc(sizeof(UInt32));
@@ -710,9 +760,9 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
if (strncmp(cp1, "vertical", 8) == 0) {
cp3 = cp2;
- if (*cp3 == ';' || *cp3 == ':')
+ if (*cp3 == ';' || *cp3 == ':' || *cp3 == ',')
--cp3;
- while (*cp3 == ' ' || *cp3 == '\t')
+ while (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t')
--cp3;
if (*cp3)
++cp3;
@@ -746,9 +796,10 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
setFontLayoutDir(font, 1);
engine = createLayoutEngine(fontRef, font, scriptTag, languageTag,
- addFeatures, addParams, removeFeatures, rgbValue);
+ addFeatures, addParams, removeFeatures, rgbValue,
+ extend, slant);
if (engine == 0) {
- deleteFont(font);
+ // only free these if creation failed, otherwise the engine now owns them
if (addFeatures)
free(addFeatures);
if (addParams)
@@ -757,16 +808,210 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
free(removeFeatures);
}
else
- nativefonttypeflag = OT_FONT_FLAG;
+ nativefonttypeflag = OTGR_FONT_FLAG;
+
+ return engine;
+}
+
+static int
+readFeatureNumber(const char* s, const char* e, int* f, int* v)
+{
+ *f = 0;
+ *v = 0;
+ if (*s < '0' || *s > '9')
+ return 0;
+ while (*s >= '0' && *s <= '9')
+ *f = *f * 10 + *s++ - '0';
+ while ((*s == ' ') || (*s == '\t'))
+ ++s;
+ if (*s++ != '=')
+ return 0;
+ if (*s < '0' || *s > '9')
+ return 0;
+ while (*s >= '0' && *s <= '9')
+ *v = *v * 10 + *s++ - '0';
+ while ((*s == ' ') || (*s == '\t'))
+ ++s;
+ if (s != e)
+ return 0;
+ return 1;
+}
+
+#define MAX_GRAPHITE_FEATURES 64
+
+static void*
+loadGraphiteFont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const char* cp1, const char* faceName)
+{
+ XeTeXLayoutEngine engine = NULL;
+
+ const char* cp2;
+ const char* cp3;
+
+ UInt32 tag;
+
+ UInt32 rgbValue = 0x000000FF;
+ UInt32 languageTag = 0;
+
+ double extend = 1.0;
+ double slant = 0.0;
+ int rtl = 0;
+
+ int featureIDs[MAX_GRAPHITE_FEATURES];
+ int featureValues[MAX_GRAPHITE_FEATURES];
+ int nFeatures = 0;
+ int id, val;
+
+ /* create a default engine so we can query the font for Graphite features;
+ because of font caching, it's cheap to discard this and create the real one later */
+ engine = createGraphiteEngine(fontRef, font, faceName, rgbValue, rtl, languageTag,
+ extend, slant, 0, NULL, NULL);
+ if (engine == NULL)
+ return NULL;
+
+ /* scan the feature string (if any) */
+ if (cp1 != NULL) {
+ while (*cp1) {
+ if ((*cp1 == ':') || (*cp1 == ';') || (*cp1 == ','))
+ ++cp1;
+ while ((*cp1 == ' ') || (*cp1 == '\t')) /* skip leading whitespace */
+ ++cp1;
+ if (*cp1 == 0) /* break if end of string */
+ break;
+
+ cp2 = cp1;
+ while (*cp2 && (*cp2 != ':') && (*cp2 != ';') && (*cp2 != ','))
+ ++cp2;
+
+ if (strncmp(cp1, "language", 8) == 0) {
+ cp3 = cp1 + 8;
+ if (*cp3 != '=')
+ goto bad_option;
+ languageTag = read_tag(cp3 + 1, '\0');
+ goto next_option;
+ }
+
+ if (strncmp(cp1, "mapping", 7) == 0) {
+ cp3 = cp1 + 7;
+ if (*cp3 != '=')
+ goto bad_option;
+ loadedfontmapping = load_mapping_file(cp3 + 1, cp2);
+ goto next_option;
+ }
+
+ if (strncmp(cp1, "extend", 6) == 0) {
+ cp3 = cp1 + 6;
+ if (*cp3 != '=')
+ goto bad_option;
+ ++cp3;
+ extend = read_double(&cp3);
+ goto next_option;
+ }
+
+ if (strncmp(cp1, "slant", 5) == 0) {
+ cp3 = cp1 + 5;
+ if (*cp3 != '=')
+ goto bad_option;
+ ++cp3;
+ slant = read_double(&cp3);
+ goto next_option;
+ }
+
+ if (strncmp(cp1, "color", 5) == 0) {
+ const char* s;
+ cp3 = cp1 + 5;
+ if (*cp3 != '=')
+ goto bad_option;
+ ++cp3;
+ s = cp3;
+ rgbValue = read_rgb_a(&cp3);
+ if ((cp3 == s+6) || (cp3 == s+8))
+ loadedfontflags |= FONT_FLAGS_COLORED;
+ else
+ goto bad_option;
+ goto next_option;
+ }
+
+ if (strncmp(cp1, "letterspace", 11) == 0) {
+ double val;
+ cp3 = cp1 + 11;
+ if (*cp3 != '=')
+ goto bad_option;
+ ++cp3;
+ val = read_double(&cp3);
+ loadedfontletterspace = (val / 100.0) * scaled_size;
+ goto next_option;
+ }
+
+ if (readFeatureNumber(cp1, cp2, &id, &val)
+ || findGraphiteFeature(engine, cp1, cp2, &id, &val)) {
+ if (nFeatures < MAX_GRAPHITE_FEATURES) {
+ featureIDs[nFeatures] = id;
+ featureValues[nFeatures] = val;
+ ++nFeatures;
+ }
+ goto next_option;
+ }
+
+ if (strncmp(cp1, "rtl", 3) == 0) {
+ cp3 = cp2;
+ if (*cp3 == ';' || *cp3 == ':')
+ --cp3;
+ while (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t')
+ --cp3;
+ if (*cp3)
+ ++cp3;
+ if (cp3 == cp1 + 3) {
+ rtl = 1;
+ goto next_option;
+ }
+ }
+
+/*
+ if (strncmp(cp1, "vertical", 8) == 0) {
+ cp3 = cp2;
+ if (*cp3 == ';' || *cp3 == ':')
+ --cp3;
+ while (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t')
+ --cp3;
+ if (*cp3)
+ ++cp3;
+ if (cp3 == cp1 + 8) {
+ loadedfontflags |= FONT_FLAGS_VERTICAL;
+ goto next_option;
+ }
+ }
+*/
+
+ bad_option:
+ fontfeaturewarning(cp1, cp2 - cp1, 0, 0);
+
+ next_option:
+ cp1 = cp2;
+ }
+
+ }
+
+ if ((loadedfontflags & FONT_FLAGS_COLORED) == 0)
+ rgbValue = 0x000000FF;
+
+ if ((loadedfontflags & FONT_FLAGS_VERTICAL) != 0)
+ setFontLayoutDir(font, 1);
+
+// deleteLayoutEngine(engine);
+ engine = createGraphiteEngine(fontRef, font, faceName, rgbValue, rtl, languageTag,
+ extend, slant, nFeatures, &featureIDs[0], &featureValues[0]);
+ if (engine != NULL)
+ nativefonttypeflag = OTGR_FONT_FLAG;
return engine;
}
static void
-splitFontName(char* name, char** var, char** feat, char** end)
+splitFontName(char* name, char** var, char** feat, char** end, int* index)
{
*var = NULL;
*feat = NULL;
+ *index = 0;
if (*name == '[') {
int withinFileName = 1;
#ifdef WIN32
@@ -784,8 +1029,12 @@ splitFontName(char* name, char** var, char** feat, char** end)
#ifdef WIN32
&& !((name - start == 1) && isalpha(*start))
#endif
- )
- *var = name;
+ ) {
+ ++name;
+ while (*name >= '0' && *name <= '9')
+ *index = *index * 10 + *name++ - '0';
+ --name;
+ }
else if (!withinFileName && *feat == NULL)
*feat = name;
}
@@ -813,7 +1062,7 @@ void*
findnativefont(unsigned char* uname, integer scaled_size)
/* scaled_size here is in TeX points */
{
- void* rval = 0;
+ void* rval = NULL;
char* nameString;
char* var;
char* feat;
@@ -823,13 +1072,13 @@ findnativefont(unsigned char* uname, integer scaled_size)
char* featString = NULL;
PlatformFontRef fontRef;
XeTeXFont font;
+ int index = 0;
loadedfontmapping = NULL;
loadedfontflags = 0;
loadedfontletterspace = 0;
- splitFontName(name, &var, &feat, &end);
-
+ splitFontName(name, &var, &feat, &end, &index);
nameString = xmalloc(var - name + 1);
strncpy(nameString, name, var - name);
nameString[var - name] = 0;
@@ -854,16 +1103,16 @@ findnativefont(unsigned char* uname, integer scaled_size)
if (path == NULL)
path = kpse_find_file(nameString + 1, kpse_type1_format, 0);
if (path != NULL) {
- int index = 0;
- if (varString != NULL) {
- char* cp;
- for (cp = varString; *cp && isdigit(*cp); ++cp)
- index = index * 10 + *cp - '0';
- }
font = createFontFromFile(path, index, scaled_size);
if (font != NULL) {
- rval = loadOTfont(0, font, scaled_size, featString);
- if (rval == 0)
+ if (varString && strncmp(varString, "/GR", 3) == 0) {
+ rval = loadGraphiteFont(0, font, scaled_size, featString, nameString);
+ if (rval == NULL)
+ graphitewarning();
+ }
+ if (rval == NULL) /* graphite wasn't requested, or failed to initialize */
+ rval = loadOTfont(0, font, scaled_size, featString);
+ if (rval == NULL)
deleteFont(font);
}
}
@@ -892,16 +1141,24 @@ findnativefont(unsigned char* uname, integer scaled_size)
font = createFont(fontRef, scaled_size);
if (font != 0) {
+ if (getReqEngine() == 'G') {
+ rval = loadGraphiteFont(fontRef, font, scaled_size, featString, nameString);
+ if (rval == NULL)
+ graphitewarning();
+ }
+ if (rval == NULL) {
#ifdef XETEX_MAC
- if (getReqEngine() == 'I' || getFontTablePtr(font, kGSUB) != 0 || getFontTablePtr(font, kGPOS) != 0)
+ if (getReqEngine() == 'I' || getReqEngine() == 'G' ||
+ getFontTablePtr(font, kGSUB) != NULL || getFontTablePtr(font, kGPOS) != NULL)
#endif
- rval = loadOTfont(fontRef, font, scaled_size, featString);
- if (rval == 0)
+ rval = loadOTfont(fontRef, font, scaled_size, featString);
+ }
+ if (rval == NULL)
deleteFont(font);
}
#ifdef XETEX_MAC
- if (rval == 0) {
+ if (rval == NULL) {
load_aat:
rval = loadAATfont(fontRef, scaled_size, featString);
}
@@ -939,7 +1196,7 @@ releasefontengine(void* engine, int type_flag)
}
else
#endif
- if (type_flag == OT_FONT_FLAG) {
+ if (type_flag == OTGR_FONT_FLAG) {
deleteLayoutEngine((XeTeXLayoutEngine)engine);
}
}
@@ -956,7 +1213,8 @@ otgetfontmetrics(void* pEngine, scaled* ascent, scaled* descent, scaled* xheight
*ascent = X2Fix(a);
*descent = X2Fix(d);
- *slant = getSlant(getFont(engine));
+ *slant = X2Fix(Fix2X(getSlant(getFont(engine))) * getExtendFactor(engine)
+ + getSlantFactor(engine));
glyphID = mapCharToGlyph(engine, 'x');
if (glyphID != 0) {
@@ -984,7 +1242,11 @@ otfontget(integer what, void* pEngine)
case XeTeX_count_glyphs:
return countGlyphs(fontInst);
break;
-
+
+ case XeTeX_count_features: /* ie Graphite features */
+ return countGraphiteFeatures(engine);
+ break;
+
case XeTeX_OT_count_scripts:
return countScripts(fontInst);
break;
@@ -1006,6 +1268,17 @@ otfontget1(integer what, void* pEngine, integer param)
case XeTeX_OT_script_code:
return getIndScript(fontInst, param);
break;
+
+ /* for graphite fonts...*/
+ case XeTeX_feature_code:
+ return getGraphiteFeatureCode(engine, param);
+ break;
+ case XeTeX_is_exclusive_feature:
+ return 1;
+ break;
+ case XeTeX_count_selectors:
+ return countGraphiteFeatureSettings(engine, param);
+ break;
}
return 0;
}
@@ -1024,6 +1297,14 @@ otfontget2(integer what, void* pEngine, integer param1, integer param2)
case XeTeX_OT_count_features:
return countFeatures(fontInst, param1, param2);
break;
+
+ /* for graphite fonts */
+ case XeTeX_selector_code:
+ return getGraphiteFeatureSettingCode(engine, param1, param2);
+ break;
+ case XeTeX_is_default_selector:
+ return getGraphiteFeatureDefaultSetting(engine, param1) == param2;
+ break;
}
return 0;
@@ -1044,6 +1325,51 @@ otfontget3(integer what, void* pEngine, integer param1, integer param2, integer
return 0;
}
+void
+grprintfontname(integer what, void* pEngine, integer param1, integer param2)
+{
+ unsigned short name[128]; /* graphite API specifies size 128 */
+ int n = 0;
+ XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
+ switch (what) {
+ case XeTeX_feature_name:
+ getGraphiteFeatureLabel(engine, param1, &name[0]);
+ break;
+ case XeTeX_selector_name:
+ getGraphiteFeatureSettingLabel(engine, param1, param2, &name[0]);
+ break;
+ }
+ while (name[n] != 0 && n < 128)
+ ++n;
+ printchars(&name[0], n);
+}
+
+integer
+grfontgetnamed(integer what, void* pEngine)
+{
+ long rval = -1;
+ XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
+ switch (what) {
+ case XeTeX_find_feature_by_name:
+ rval = findGraphiteFeatureNamed(engine, (const char*)nameoffile + 1, namelength);
+ break;
+ }
+ return rval;
+}
+
+integer
+grfontgetnamed1(integer what, void* pEngine, integer param)
+{
+ long rval = -1;
+ XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
+ switch (what) {
+ case XeTeX_find_selector_by_name:
+ rval = findGraphiteFeatureSettingNamed(engine, param, (const char*)nameoffile + 1, namelength);
+ break;
+ }
+ return rval;
+}
+
#define XDV_FLAG_FONTTYPE_ATSUI 0x0001
#define XDV_FLAG_FONTTYPE_ICU 0x0002
@@ -1051,6 +1377,8 @@ otfontget3(integer what, void* pEngine, integer param1, integer param2, integer
#define XDV_FLAG_COLORED 0x0200
#define XDV_FLAG_FEATURES 0x0400
#define XDV_FLAG_VARIATIONS 0x0800
+#define XDV_FLAG_EXTEND 0x1000
+#define XDV_FLAG_SLANT 0x2000
#ifdef XETEX_MAC
static UInt32
@@ -1152,6 +1480,8 @@ makefontdef(integer f)
int fontDefLength;
char* cp;
PlatformFontRef fontRef = 0;
+ float extend = 1.0;
+ float slant = 0.0;
#ifdef XETEX_MAC
ATSUStyle style = NULL;
@@ -1177,11 +1507,16 @@ makefontdef(integer f)
ATSUGetAttribute(style, kATSURGBAlphaColorTag, sizeof(ATSURGBAlphaColor), &atsuColor, 0);
rgba = atsuColorToRGBA32(atsuColor);
+ CGAffineTransform t;
+ ATSUGetAttribute(style, kATSUFontMatrixTag, sizeof(CGAffineTransform), &t, 0);
+ extend = t.a;
+ slant = t.b;
+
ATSUGetAttribute(style, kATSUSizeTag, sizeof(Fixed), &size, 0);
}
else
#endif
- if (fontarea[f] == OT_FONT_FLAG) {
+ if (fontarea[f] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine;
flags = XDV_FLAG_FONTTYPE_ICU;
@@ -1199,6 +1534,9 @@ makefontdef(integer f)
if ((fontflags[f] & FONT_FLAGS_VERTICAL) != 0)
flags |= XDV_FLAG_VERTICAL;
+ extend = getExtendFactor(engine);
+ slant = getSlantFactor(engine);
+
size = X2Fix(getPointSize(engine));
}
else {
@@ -1242,7 +1580,16 @@ makefontdef(integer f)
flags |= XDV_FLAG_VARIATIONS;
}
#endif
-
+
+ if (extend != 1.0) {
+ fontDefLength += 4;
+ flags |= XDV_FLAG_EXTEND;
+ }
+ if (slant != 0.0) {
+ fontDefLength += 4;
+ flags |= XDV_FLAG_SLANT;
+ }
+
if (fontDefLength > xdvBufSize) {
if (xdvbuffer != NULL)
free(xdvbuffer);
@@ -1296,6 +1643,17 @@ makefontdef(integer f)
}
}
#endif
+
+ if (flags & XDV_FLAG_EXTEND) {
+ Fixed f = X2Fix(extend);
+ *(UInt32*)(cp) = SWAP32(f);
+ cp += 4;
+ }
+ if (flags & XDV_FLAG_SLANT) {
+ Fixed f = X2Fix(slant);
+ *(UInt32*)(cp) = SWAP32(f);
+ cp += 4;
+ }
return fontDefLength;
}
@@ -1365,7 +1723,7 @@ getnativecharheightdepth(integer font, integer ch, scaled* height, scaled* depth
}
else
#endif
- if (fontarea[font] == OT_FONT_FLAG) {
+ if (fontarea[font] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font];
int gid = mapCharToGlyph(engine, ch);
getGlyphHeightDepth(engine, gid, &ht, &dp);
@@ -1415,7 +1773,7 @@ getnativecharsidebearings(integer font, integer ch, scaled* lsb, scaled* rsb)
}
else
#endif
- if (fontarea[font] == OT_FONT_FLAG) {
+ if (fontarea[font] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font];
int gid = mapCharToGlyph(engine, ch);
getGlyphSidebearings(engine, gid, &l, &r);
@@ -1452,7 +1810,7 @@ getnativecharwd(integer f, integer c)
}
else
#endif
- if (fontarea[f] == OT_FONT_FLAG) {
+ if (fontarea[f] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f];
int gid = mapCharToGlyph(engine, c);
wd = X2Fix(getGlyphWidthFromEngine(engine, gid));
@@ -1500,46 +1858,104 @@ measure_native_node(void* pNode, int use_glyph_metrics)
}
else
#endif
- if (fontarea[f] == OT_FONT_FLAG) {
- /* using this font in OT Layout mode, so fontlayoutengine[f] is actually a XeTeXLayoutEngine */
-
+ if (fontarea[f] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine = (XeTeXLayoutEngine)(fontlayoutengine[f]);
- /* need to find direction runs within the text, and call layoutChars separately for each */
-
- int nGlyphs;
- UBiDiDirection dir;
- float x, y;
- void* glyph_info = 0;
- static float* positions = 0;
- static UInt32* glyphs = 0;
- static int maxGlyphs = 0;
-
FixedPoint* locations;
UInt16* glyphIDs;
int realGlyphCount = 0;
- UBiDi* pBiDi = ubidi_open();
-
- UErrorCode errorCode = (UErrorCode)0;
- ubidi_setPara(pBiDi, txtPtr, txtLen, getDefaultDirection(engine), NULL, &errorCode);
+ if (usingOpenType(engine)) {
+ /* using this font in OT Layout mode, so fontlayoutengine[f] is actually a XeTeXLayoutEngine */
+
+ /* need to find direction runs within the text, and call layoutChars separately for each */
+
+ int nGlyphs;
+ UBiDiDirection dir;
+ float x, y;
+ void* glyph_info = 0;
+ static float* positions = 0;
+ static UInt32* glyphs = 0;
+ static int maxGlyphs = 0;
+
+ UBiDi* pBiDi = ubidi_open();
+
+ UErrorCode errorCode = (UErrorCode)0;
+ ubidi_setPara(pBiDi, txtPtr, txtLen, getDefaultDirection(engine), NULL, &errorCode);
+
+ dir = ubidi_getDirection(pBiDi);
+ if (dir == UBIDI_MIXED) {
+ /* we actually do the layout twice here, once to count glyphs and then again to get them;
+ // which is inefficient, but i figure that MIXED is a relatively rare occurrence, so i can't be
+ // bothered to deal with the memory reallocation headache of doing it differently
+ */
+ int nRuns = ubidi_countRuns(pBiDi, &errorCode);
+ double wid = 0;
+ long totalGlyphs = 0;
+ int i, runIndex;
+ int32_t logicalStart, length;
+ OSStatus status = 0;
+ for (runIndex = 0; runIndex < nRuns; ++runIndex) {
+ dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length);
+ nGlyphs = layoutChars(engine, (UniChar*)txtPtr, logicalStart, length, txtLen, (dir == UBIDI_RTL), 0.0, 0.0, &status);
+ totalGlyphs += nGlyphs;
+
+ if (nGlyphs >= maxGlyphs) {
+ if (glyphs != 0) {
+ free(glyphs);
+ free(positions);
+ }
+ maxGlyphs = nGlyphs + 20;
+ glyphs = xmalloc(maxGlyphs * sizeof(UInt32));
+ positions = xmalloc((maxGlyphs * 2 + 2) * sizeof(float));
+ }
+
+ getGlyphs(engine, glyphs, &status);
+ for (i = 0; i < nGlyphs; ++i)
+ if (glyphs[i] < 0xfffe)
+ ++realGlyphCount;
+ }
+
+ if (realGlyphCount > 0) {
+ double x, y;
+ glyph_info = xmalloc(realGlyphCount * native_glyph_info_size);
+ locations = (FixedPoint*)glyph_info;
+ glyphIDs = (UInt16*)(locations + realGlyphCount);
+ realGlyphCount = 0;
+
+ x = y = 0.0;
+ for (runIndex = 0; runIndex < nRuns; ++runIndex) {
+ dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length);
+ nGlyphs = layoutChars(engine, (UniChar*)txtPtr, logicalStart, length, txtLen,
+ (dir == UBIDI_RTL), 0, 0, &status);
- dir = ubidi_getDirection(pBiDi);
- if (dir == UBIDI_MIXED) {
- /* we actually do the layout twice here, once to count glyphs and then again to get them;
- // which is inefficient, but i figure that MIXED is a relatively rare occurrence, so i can't be
- // bothered to deal with the memory reallocation headache of doing it differently
- */
- int nRuns = ubidi_countRuns(pBiDi, &errorCode);
- double wid = 0;
- long totalGlyphs = 0;
- int i, runIndex;
- int32_t logicalStart, length;
- OSStatus status = 0;
- for (runIndex = 0; runIndex < nRuns; ++runIndex) {
- dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length);
- nGlyphs = layoutChars(engine, (UniChar*)txtPtr, logicalStart, length, txtLen, (dir == UBIDI_RTL), 0.0, 0.0, &status);
- totalGlyphs += nGlyphs;
+ getGlyphs(engine, glyphs, &status);
+ getGlyphPositions(engine, positions, &status);
+
+ for (i = 0; i < nGlyphs; ++i) {
+ if (glyphs[i] < 0xfffe) {
+ glyphIDs[realGlyphCount] = glyphs[i];
+ locations[realGlyphCount].x = X2Fix(positions[2*i] + x);
+ locations[realGlyphCount].y = X2Fix(positions[2*i+1] + y);
+ ++realGlyphCount;
+ }
+ }
+ x += positions[2*i];
+ y += positions[2*i+1];
+ }
+ wid = x;
+ }
+
+ node_width(node) = X2Fix(wid);
+ native_glyph_count(node) = realGlyphCount;
+ native_glyph_info_ptr(node) = glyph_info;
+ }
+ else {
+ int i;
+ OSStatus status = 0;
+ nGlyphs = layoutChars(engine, (UniChar*)txtPtr, 0, txtLen, txtLen, (dir == UBIDI_RTL), 0.0, 0.0, &status);
+ getGlyphPosition(engine, nGlyphs, &x, &y, &status);
+ node_width(node) = X2Fix(x);
if (nGlyphs >= maxGlyphs) {
if (glyphs != 0) {
@@ -1550,29 +1966,18 @@ measure_native_node(void* pNode, int use_glyph_metrics)
glyphs = xmalloc(maxGlyphs * sizeof(UInt32));
positions = xmalloc((maxGlyphs * 2 + 2) * sizeof(float));
}
-
getGlyphs(engine, glyphs, &status);
+ getGlyphPositions(engine, positions, &status);
+
for (i = 0; i < nGlyphs; ++i)
if (glyphs[i] < 0xfffe)
++realGlyphCount;
- }
-
- if (realGlyphCount > 0) {
- double x, y;
- glyph_info = xmalloc(realGlyphCount * native_glyph_info_size);
- locations = (FixedPoint*)glyph_info;
- glyphIDs = (UInt16*)(locations + realGlyphCount);
- realGlyphCount = 0;
-
- x = y = 0.0;
- for (runIndex = 0; runIndex < nRuns; ++runIndex) {
- dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length);
- nGlyphs = layoutChars(engine, (UniChar*)txtPtr, logicalStart, length, txtLen,
- (dir == UBIDI_RTL), x, y, &status);
- getGlyphs(engine, glyphs, &status);
- getGlyphPositions(engine, positions, &status);
-
+ if (realGlyphCount > 0) {
+ glyph_info = xmalloc(realGlyphCount * native_glyph_info_size);
+ locations = (FixedPoint*)glyph_info;
+ glyphIDs = (UInt16*)(locations + realGlyphCount);
+ realGlyphCount = 0;
for (i = 0; i < nGlyphs; ++i) {
if (glyphs[i] < 0xfffe) {
glyphIDs[realGlyphCount] = glyphs[i];
@@ -1581,60 +1986,39 @@ measure_native_node(void* pNode, int use_glyph_metrics)
++realGlyphCount;
}
}
- x = positions[2*i];
- y = positions[2*i+1];
}
- wid = x;
+
+ native_glyph_count(node) = realGlyphCount;
+ native_glyph_info_ptr(node) = glyph_info;
}
-
- node_width(node) = X2Fix(wid);
- native_glyph_count(node) = realGlyphCount;
- native_glyph_info_ptr(node) = glyph_info;
+
+ ubidi_close(pBiDi);
+
}
- else {
- int i;
- OSStatus status = 0;
- nGlyphs = layoutChars(engine, (UniChar*)txtPtr, 0, txtLen, txtLen, (dir == UBIDI_RTL), 0.0, 0.0, &status);
- getGlyphPosition(engine, nGlyphs, &x, &y, &status);
- node_width(node) = X2Fix(x);
-
- if (nGlyphs >= maxGlyphs) {
- if (glyphs != 0) {
- free(glyphs);
- free(positions);
- }
- maxGlyphs = nGlyphs + 20;
- glyphs = xmalloc(maxGlyphs * sizeof(UInt32));
- positions = xmalloc((maxGlyphs * 2 + 2) * sizeof(float));
- }
- getGlyphs(engine, glyphs, &status);
- getGlyphPositions(engine, positions, &status);
-
- for (i = 0; i < nGlyphs; ++i)
- if (glyphs[i] < 0xfffe)
- ++realGlyphCount;
-
+ else {
+ /* using Graphite */
+ void* glyph_info = NULL;
+ realGlyphCount = makeGraphiteSegment(engine, (UniChar*)txtPtr, txtLen);
+
if (realGlyphCount > 0) {
+ int i;
glyph_info = xmalloc(realGlyphCount * native_glyph_info_size);
locations = (FixedPoint*)glyph_info;
glyphIDs = (UInt16*)(locations + realGlyphCount);
- realGlyphCount = 0;
- for (i = 0; i < nGlyphs; ++i) {
- if (glyphs[i] < 0xfffe) {
- glyphIDs[realGlyphCount] = glyphs[i];
- locations[realGlyphCount].x = X2Fix(positions[2*i]);
- locations[realGlyphCount].y = X2Fix(positions[2*i+1]);
- ++realGlyphCount;
- }
+ for (i = 0; i < realGlyphCount; ++i) {
+ float x, y;
+ getGraphiteGlyphInfo(engine, i, &(glyphIDs[i]), &x, &y);
+ locations[i].x = X2Fix(x);
+ locations[i].y = X2Fix(y);
}
}
+ node_width(node) = X2Fix(graphiteSegmentWidth(engine));
+
native_glyph_count(node) = realGlyphCount;
native_glyph_info_ptr(node) = glyph_info;
}
- ubidi_close(pBiDi);
-
if (fontletterspace[f] != 0) {
Fixed lsDelta = 0;
Fixed lsUnit = fontletterspace[f];
@@ -1681,7 +2065,7 @@ measure_native_node(void* pNode, int use_glyph_metrics)
GetGlyphBBox_AAT((ATSUStyle)(fontlayoutengine[f]), glyphIDs[i], &bbox);
else
#endif
- if (fontarea[f] == OT_FONT_FLAG)
+ if (fontarea[f] == OTGR_FONT_FLAG)
getGlyphBounds((XeTeXLayoutEngine)(fontlayoutengine[f]), glyphIDs[i], &bbox);
cacheGlyphBBox(f, glyphIDs[i], &bbox);
@@ -1715,7 +2099,7 @@ get_native_ital_corr(void* pNode)
return X2Fix(GetGlyphItalCorr_AAT((ATSUStyle)(fontlayoutengine[f]), glyphIDs[n-1]))
+ fontletterspace[f];
#endif
- if (fontarea[f] == OT_FONT_FLAG)
+ if (fontarea[f] == OTGR_FONT_FLAG)
return X2Fix(getGlyphItalCorr((XeTeXLayoutEngine)(fontlayoutengine[f]), glyphIDs[n-1]))
+ fontletterspace[f];
}
@@ -1735,7 +2119,7 @@ get_native_glyph_ital_corr(void* pNode)
if (fontarea[f] == AAT_FONT_FLAG)
return X2Fix(GetGlyphItalCorr_AAT((ATSUStyle)(fontlayoutengine[f]), gid));
#endif
- if (fontarea[f] == OT_FONT_FLAG)
+ if (fontarea[f] == OTGR_FONT_FLAG)
return X2Fix(getGlyphItalCorr((XeTeXLayoutEngine)(fontlayoutengine[f]), gid));
return 0; /* can't actually happen */
@@ -1763,7 +2147,7 @@ measure_native_glyph(void* pNode, int use_glyph_metrics)
}
else
#endif
- if (fontarea[f] == OT_FONT_FLAG) {
+ if (fontarea[f] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f];
XeTeXFont fontInst = getFont(engine);
node_width(node) = X2Fix(getGlyphWidth(fontInst, gid));
@@ -1795,7 +2179,7 @@ mapchartoglyph(integer font, integer ch)
return MapCharToGlyph_AAT((ATSUStyle)(fontlayoutengine[font]), ch);
else
#endif
- if (fontarea[font] == OT_FONT_FLAG)
+ if (fontarea[font] == OTGR_FONT_FLAG)
return mapCharToGlyph((XeTeXLayoutEngine)(fontlayoutengine[font]), ch);
else {
fprintf(stderr, "\n! Internal error: bad native font flag\n");
@@ -1812,7 +2196,7 @@ mapglyphtoindex(integer font)
return MapGlyphToIndex_AAT((ATSUStyle)(fontlayoutengine[font]), (const char*)nameoffile + 1);
else
#endif
- if (fontarea[font] == OT_FONT_FLAG)
+ if (fontarea[font] == OTGR_FONT_FLAG)
return mapGlyphToIndex((XeTeXLayoutEngine)(fontlayoutengine[font]), (const char*)nameoffile + 1);
else {
fprintf(stderr, "\n! Internal error: bad native font flag\n");
@@ -1828,7 +2212,7 @@ getfontcharrange(integer font, int first)
return GetFontCharRange_AAT((ATSUStyle)(fontlayoutengine[font]), first);
else
#endif
- if (fontarea[font] == OT_FONT_FLAG)
+ if (fontarea[font] == OTGR_FONT_FLAG)
return getFontCharRange((XeTeXLayoutEngine)(fontlayoutengine[font]), first);
else {
fprintf(stderr, "\n! Internal error: bad native font flag\n");
@@ -1900,6 +2284,13 @@ atsugetfontmetrics(ATSUStyle style, Fixed* ascent, Fixed* descent, Fixed* xheigh
}
}
+ CGAffineTransform t;
+ ATSUGetAttribute(style, kATSUFontMatrixTag, sizeof(CGAffineTransform), &t, 0);
+ if (t.a != 1.0)
+ *slant = X2Fix(Fix2X(*slant) * t.a);
+ if (t.b != 0.0)
+ *slant += X2Fix(t.b);
+
if (0 && metrics.xHeight != 0.0) {
/* currently not using this, as the values from ATS don't seem quite what I'd expect */
*xheight = X2Fix(metrics.xHeight * floatSize);
@@ -2229,7 +2620,7 @@ printglyphname(integer font, integer gid)
}
else
#endif
- if (fontarea[font] == OT_FONT_FLAG) {
+ if (fontarea[font] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font];
s = (char*)getGlyphName(getFont(engine), gid, &len);
}
@@ -2322,13 +2713,15 @@ open_dvi_output(FILE** fptr)
}
}
-void
+int
dviclose(FILE* fptr)
{
- if (nopdfoutput)
- fclose(fptr);
+ if (nopdfoutput) {
+ if (fclose(fptr) != 0)
+ return errno;
+ }
else
- pclose(fptr);
+ return pclose(fptr);
}
int
@@ -2357,11 +2750,6 @@ get_uni_c(UFILE* f)
case 0: ;
};
rval -= offsetsFromUTF8[extraBytes];
- if (rval > 0xFFFF) {
- rval -= 0x10000;
- f->savedChar = 0xdc00 + rval % 0x0400;
- rval = 0xd800 + rval / 0x0400;
- }
}
break;
@@ -2369,11 +2757,36 @@ get_uni_c(UFILE* f)
rval = getc(f->f);
rval <<= 8;
rval += getc(f->f);
+ if (rval >= 0xd800 && rval <= 0xdbff) {
+ int lo = getc(f->f);
+ lo <<= 8;
+ lo += getc(f->f);
+ if (lo >= 0xdc00 && lo <= 0xdfff)
+ rval = 0x10000 + (rval - 0xd800) * 0x400 + (lo - 0xdc00);
+ else {
+ rval = 0xfffd;
+ f->savedChar = lo;
+ }
+ }
+ else if (rval >= 0xdc00 && rval <= 0xdfff)
+ rval = 0xfffd;
break;
case UTF16LE:
rval = getc(f->f);
rval += (getc(f->f) << 8);
+ if (rval >= 0xd800 && rval <= 0xdbff) {
+ int lo = getc(f->f);
+ lo += (getc(f->f) << 8);
+ if (lo >= 0xdc00 && lo <= 0xdfff)
+ rval = 0x10000 + (rval - 0xd800) * 0x400 + (lo - 0xdc00);
+ else {
+ rval = 0xfffd;
+ f->savedChar = lo;
+ }
+ }
+ else if (rval >= 0xdc00 && rval <= 0xdfff)
+ rval = 0xfffd;
break;
case RAW: