diff options
author | Khaled Hosny <khaledhosny@eglug.org> | 2014-03-14 21:23:32 +0000 |
---|---|---|
committer | Khaled Hosny <khaledhosny@eglug.org> | 2014-03-14 21:23:32 +0000 |
commit | 0af7dc6b7a6b59b735efb25e93dd4e62be2126d5 (patch) | |
tree | c08c1b55d7ae0793a37a9e621a1adebb740f12c8 | |
parent | 97f7834d79c2ef1a3a7a3d0ed038881a2fb1f459 (diff) |
Sync XeTeX
git-svn-id: svn://tug.org/texlive/trunk@33175 c570f23f-e606-0410-a88d-b1316a301751
24 files changed, 6902 insertions, 6926 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp index a6cd3785c4c..cc8267b91bf 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp @@ -35,8 +35,8 @@ authorization from the copyright holders. * * created on: 2005-10-22 * created by: Jonathan Kew - * - * originally based on PortableFontInstance.cpp from ICU + * + * originally based on PortableFontInstance.cpp from ICU */ #ifdef __cplusplus @@ -57,6 +57,8 @@ extern "C" { FT_Library gFreeTypeLibrary = 0; +static hb_font_funcs_t* hbFontFuncs = NULL; + XeTeXFontInst::XeTeXFontInst(const char* pathname, int index, float pointSize, int &status) : fPointSize(pointSize) , fUnitsPerEM(0) @@ -71,17 +73,19 @@ XeTeXFontInst::XeTeXFontInst(const char* pathname, int index, float pointSize, i , hbFont(NULL) , fMath(NULL) { - if (pathname != NULL) - initialize(pathname, index, status); + if (pathname != NULL) + initialize(pathname, index, status); } XeTeXFontInst::~XeTeXFontInst() { - if (ftFace != 0) { - FT_Done_Face(ftFace); - ftFace = 0; - } - hb_font_destroy(hbFont); + if (ftFace != 0) { + FT_Done_Face(ftFace); + ftFace = 0; + } + hb_font_destroy(hbFont); + delete[] fFilename; + free((void*) fMath); } /* HarfBuzz font functions */ @@ -89,198 +93,198 @@ XeTeXFontInst::~XeTeXFontInst() static hb_bool_t _get_glyph(hb_font_t*, void *font_data, hb_codepoint_t ch, hb_codepoint_t vs, hb_codepoint_t *gid, void*) { - FT_Face face = (FT_Face) font_data; - *gid = 0; + FT_Face face = (FT_Face) font_data; + *gid = 0; - if (vs) - *gid = FT_Face_GetCharVariantIndex (face, ch, vs); + if (vs) + *gid = FT_Face_GetCharVariantIndex (face, ch, vs); - if (*gid == 0) - *gid = FT_Get_Char_Index (face, ch); + if (*gid == 0) + *gid = FT_Get_Char_Index (face, ch); - return *gid != 0; + return *gid != 0; } static FT_Fixed _get_glyph_advance(FT_Face face, FT_UInt gid, bool vertical) { - FT_Error error; - FT_Fixed advance; - int flags = FT_LOAD_NO_SCALE; + FT_Error error; + FT_Fixed advance; + int flags = FT_LOAD_NO_SCALE; - if (vertical) - flags |= FT_LOAD_VERTICAL_LAYOUT; + if (vertical) + flags |= FT_LOAD_VERTICAL_LAYOUT; - error = FT_Get_Advance(face, gid, flags, &advance); - if (error) - advance = 0; - else - advance = advance; + error = FT_Get_Advance(face, gid, flags, &advance); + if (error) + advance = 0; + else + advance = advance; - /* FreeType's vertical metrics grows downward */ - if (vertical) - advance = -advance; + /* FreeType's vertical metrics grows downward */ + if (vertical) + advance = -advance; - return advance; + return advance; } static hb_position_t _get_glyph_h_advance(hb_font_t*, void *font_data, hb_codepoint_t gid, void*) { - return _get_glyph_advance((FT_Face) font_data, gid, false); + return _get_glyph_advance((FT_Face) font_data, gid, false); } static hb_position_t _get_glyph_v_advance(hb_font_t*, void *font_data, hb_codepoint_t gid, void*) { - return _get_glyph_advance((FT_Face) font_data, gid, true); + return _get_glyph_advance((FT_Face) font_data, gid, true); } static hb_bool_t _get_glyph_h_origin(hb_font_t*, void *font_data, hb_codepoint_t gid, hb_position_t *x, hb_position_t *y, void*) { - // horizontal origin is (0, 0) - return true; + // horizontal origin is (0, 0) + return true; } static hb_bool_t _get_glyph_v_origin(hb_font_t*, void *font_data, hb_codepoint_t gid, hb_position_t *x, hb_position_t *y, void*) { - // vertical origin is (0, 0) for now - return true; - - // TODO - // Keep the code below for reference, for now we want to keep vertical - // origin at (0, 0) for compatibility with pre-0.9999. - // Reconsider this (e.g. using BASE table) when we get around overhauling - // the text directionality model and implementing real vertical typesetting. - - FT_Face face = (FT_Face) font_data; - FT_Error error; - - error = FT_Load_Glyph (face, gid, FT_LOAD_NO_SCALE); - if (!error) { - *x = face->glyph->metrics.horiBearingX - face->glyph->metrics.vertBearingX; - *y = face->glyph->metrics.horiBearingY - (-face->glyph->metrics.vertBearingY); - } + // vertical origin is (0, 0) for now + return true; + + // TODO + // Keep the code below for reference, for now we want to keep vertical + // origin at (0, 0) for compatibility with pre-0.9999. + // Reconsider this (e.g. using BASE table) when we get around overhauling + // the text directionality model and implementing real vertical typesetting. + + FT_Face face = (FT_Face) font_data; + FT_Error error; + + error = FT_Load_Glyph (face, gid, FT_LOAD_NO_SCALE); + if (!error) { + *x = face->glyph->metrics.horiBearingX - face->glyph->metrics.vertBearingX; + *y = face->glyph->metrics.horiBearingY - (-face->glyph->metrics.vertBearingY); + } - return !error; + return !error; } static hb_position_t _get_glyph_h_kerning(hb_font_t*, void *font_data, hb_codepoint_t gid1, hb_codepoint_t gid2, void*) { - FT_Face face = (FT_Face) font_data; - FT_Error error; - FT_Vector kerning; - hb_position_t ret; + FT_Face face = (FT_Face) font_data; + FT_Error error; + FT_Vector kerning; + hb_position_t ret; - error = FT_Get_Kerning (face, gid1, gid2, FT_KERNING_UNFITTED, &kerning); - if (error) - ret = 0; - else - ret = kerning.x; - return ret; + error = FT_Get_Kerning (face, gid1, gid2, FT_KERNING_UNFITTED, &kerning); + if (error) + ret = 0; + else + ret = kerning.x; + return ret; } static hb_position_t _get_glyph_v_kerning(hb_font_t*, void *font_data, hb_codepoint_t gid1, hb_codepoint_t gid2, void*) { - /* FreeType does not support vertical kerning */ - return 0; + /* FreeType does not support vertical kerning */ + return 0; } static hb_bool_t _get_glyph_extents(hb_font_t*, void *font_data, hb_codepoint_t gid, hb_glyph_extents_t *extents, void*) { - FT_Face face = (FT_Face) font_data; - FT_Error error; - - error = FT_Load_Glyph (face, gid, FT_LOAD_NO_SCALE); - if (!error) { - extents->x_bearing = face->glyph->metrics.horiBearingX; - extents->y_bearing = face->glyph->metrics.horiBearingY; - extents->width = face->glyph->metrics.width; - extents->height = -face->glyph->metrics.height; - } + FT_Face face = (FT_Face) font_data; + FT_Error error; + + error = FT_Load_Glyph (face, gid, FT_LOAD_NO_SCALE); + if (!error) { + extents->x_bearing = face->glyph->metrics.horiBearingX; + extents->y_bearing = face->glyph->metrics.horiBearingY; + extents->width = face->glyph->metrics.width; + extents->height = -face->glyph->metrics.height; + } - return !error; + return !error; } static hb_bool_t _get_glyph_contour_point(hb_font_t*, void *font_data, hb_codepoint_t gid, unsigned int point_index, hb_position_t *x, hb_position_t *y, void*) { - FT_Face face = (FT_Face) font_data; - FT_Error error; - bool ret = false; - - error = FT_Load_Glyph (face, gid, FT_LOAD_NO_SCALE); - if (!error) { - if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - if (point_index < (unsigned int) face->glyph->outline.n_points) { - *x = face->glyph->outline.points[point_index].x; - *y = face->glyph->outline.points[point_index].y; - ret = true; - } - } - } + FT_Face face = (FT_Face) font_data; + FT_Error error; + bool ret = false; + + error = FT_Load_Glyph (face, gid, FT_LOAD_NO_SCALE); + if (!error) { + if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { + if (point_index < (unsigned int) face->glyph->outline.n_points) { + *x = face->glyph->outline.points[point_index].x; + *y = face->glyph->outline.points[point_index].y; + ret = true; + } + } + } - return ret; + return ret; } static hb_bool_t _get_glyph_name(hb_font_t *, void *font_data, hb_codepoint_t gid, char *name, unsigned int size, void *) { - FT_Face face = (FT_Face) font_data; - bool ret = false; + FT_Face face = (FT_Face) font_data; + bool ret = false; - ret = !FT_Get_Glyph_Name (face, gid, name, size); - if (ret && (size && !*name)) - ret = false; + ret = !FT_Get_Glyph_Name (face, gid, name, size); + if (ret && (size && !*name)) + ret = false; - return ret; + return ret; } static hb_font_funcs_t * _get_font_funcs(void) { - static hb_font_funcs_t* funcs = hb_font_funcs_create(); + static hb_font_funcs_t* funcs = hb_font_funcs_create(); - hb_font_funcs_set_glyph_func (funcs, _get_glyph, NULL, NULL); - hb_font_funcs_set_glyph_h_advance_func (funcs, _get_glyph_h_advance, NULL, NULL); - hb_font_funcs_set_glyph_v_advance_func (funcs, _get_glyph_v_advance, NULL, NULL); - hb_font_funcs_set_glyph_h_origin_func (funcs, _get_glyph_h_origin, NULL, NULL); - hb_font_funcs_set_glyph_v_origin_func (funcs, _get_glyph_v_origin, NULL, NULL); - hb_font_funcs_set_glyph_h_kerning_func (funcs, _get_glyph_h_kerning, NULL, NULL); - hb_font_funcs_set_glyph_v_kerning_func (funcs, _get_glyph_v_kerning, NULL, NULL); - hb_font_funcs_set_glyph_extents_func (funcs, _get_glyph_extents, NULL, NULL); - hb_font_funcs_set_glyph_contour_point_func (funcs, _get_glyph_contour_point, NULL, NULL); - hb_font_funcs_set_glyph_name_func (funcs, _get_glyph_name, NULL, NULL); + hb_font_funcs_set_glyph_func (funcs, _get_glyph, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func (funcs, _get_glyph_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func (funcs, _get_glyph_v_advance, NULL, NULL); + hb_font_funcs_set_glyph_h_origin_func (funcs, _get_glyph_h_origin, NULL, NULL); + hb_font_funcs_set_glyph_v_origin_func (funcs, _get_glyph_v_origin, NULL, NULL); + hb_font_funcs_set_glyph_h_kerning_func (funcs, _get_glyph_h_kerning, NULL, NULL); + hb_font_funcs_set_glyph_v_kerning_func (funcs, _get_glyph_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func (funcs, _get_glyph_extents, NULL, NULL); + hb_font_funcs_set_glyph_contour_point_func (funcs, _get_glyph_contour_point, NULL, NULL); + hb_font_funcs_set_glyph_name_func (funcs, _get_glyph_name, NULL, NULL); - return funcs; + return funcs; } static hb_blob_t * _get_table(hb_face_t *, hb_tag_t tag, void *user_data) { - FT_Face face = (FT_Face) user_data; - FT_ULong length = 0; - FT_Byte *table; - FT_Error error; - hb_blob_t* blob = NULL; - - error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &length); - if (!error) { - table = (FT_Byte *) xmalloc(length * sizeof(char)); - if (table != NULL) { - error = FT_Load_Sfnt_Table(face, tag, 0, (FT_Byte*)table, &length); - if (!error) { - blob = hb_blob_create((const char*) table, length, HB_MEMORY_MODE_WRITABLE, table, free); - } else { - free(table); - } - } - } + FT_Face face = (FT_Face) user_data; + FT_ULong length = 0; + FT_Byte *table; + FT_Error error; + hb_blob_t* blob = NULL; + + error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &length); + if (!error) { + table = (FT_Byte *) xmalloc(length * sizeof(char)); + if (table != NULL) { + error = FT_Load_Sfnt_Table(face, tag, 0, (FT_Byte*)table, &length); + if (!error) { + blob = hb_blob_create((const char*) table, length, HB_MEMORY_MODE_WRITABLE, table, free); + } else { + free(table); + } + } + } return blob; } @@ -288,76 +292,79 @@ _get_table(hb_face_t *, hb_tag_t tag, void *user_data) void XeTeXFontInst::initialize(const char* pathname, int index, int &status) { - TT_Postscript *postTable; - TT_OS2* os2Table; - FT_Error error; - hb_face_t *hbFace; - - if (!gFreeTypeLibrary) { - error = FT_Init_FreeType(&gFreeTypeLibrary); - if (error) { - fprintf(stderr, "FreeType initialization failed! (%d)\n", error); - exit(1); - } - } - - error = FT_New_Face(gFreeTypeLibrary, (char*)pathname, index, &ftFace); - if (error) { + TT_Postscript *postTable; + TT_OS2* os2Table; + FT_Error error; + hb_face_t *hbFace; + + if (!gFreeTypeLibrary) { + error = FT_Init_FreeType(&gFreeTypeLibrary); + if (error) { + fprintf(stderr, "FreeType initialization failed! (%d)\n", error); + exit(1); + } + } + + error = FT_New_Face(gFreeTypeLibrary, (char*)pathname, index, &ftFace); + if (error) { + status = 1; + return; + } + + if (!FT_IS_SCALABLE(ftFace)) { status = 1; return; } - if (!FT_IS_SCALABLE(ftFace)) { - status = 1; - return; - } - - /* for non-sfnt-packaged fonts (presumably Type 1), see if there is an AFM file we can attach */ - if (index == 0 && !FT_IS_SFNT(ftFace)) { - char* afm = new char[strlen((const char*)pathname) + 5]; // room to append ".afm" - strcpy(afm, (const char*)pathname); - char* p = strrchr(afm, '.'); - if (p == NULL || strlen(p) != 4 || tolower(*(p+1)) != 'p' || tolower(*(p+2)) != 'f') - strcat(afm, ".afm"); // append .afm if the extension didn't seem to be .pf[ab] - else - strcpy(p, ".afm"); // else replace extension with .afm - FT_Attach_File(ftFace, afm); // ignore error code; AFM might not exist - delete[] afm; - } - - char buf[20]; - if (index > 0) - sprintf(buf, ":%d", index); - else - buf[0] = 0; - fFilename = new char[strlen(pathname) + 2 + strlen(buf) + 1]; - sprintf(fFilename, "[%s%s]", pathname, buf); - fUnitsPerEM = ftFace->units_per_EM; - fAscent = unitsToPoints(ftFace->ascender); - fDescent = unitsToPoints(ftFace->descender); - - postTable = (TT_Postscript *) getFontTable(ft_sfnt_post); - if (postTable != NULL) { - fItalicAngle = Fix2D(postTable->italicAngle); - } - - os2Table = (TT_OS2*) getFontTable(ft_sfnt_os2); - if (os2Table) { - fCapHeight = unitsToPoints(os2Table->sCapHeight); - fXHeight = unitsToPoints(os2Table->sxHeight); - } - - // Set up HarfBuzz font - hbFace = hb_face_create_for_tables(_get_table, ftFace, NULL); - hb_face_set_index(hbFace, index); - hb_face_set_upem(hbFace, fUnitsPerEM); - hbFont = hb_font_create(hbFace); - hb_face_destroy(hbFace); - - hb_font_set_funcs(hbFont, _get_font_funcs(), ftFace, NULL); - hb_font_set_scale(hbFont, fUnitsPerEM, fUnitsPerEM); - // We don’t want device tables adjustments - hb_font_set_ppem(hbFont, 0, 0); + /* for non-sfnt-packaged fonts (presumably Type 1), see if there is an AFM file we can attach */ + if (index == 0 && !FT_IS_SFNT(ftFace)) { + char* afm = new char[strlen((const char*)pathname) + 5]; // room to append ".afm" + strcpy(afm, (const char*)pathname); + char* p = strrchr(afm, '.'); + if (p == NULL || strlen(p) != 4 || tolower(*(p+1)) != 'p' || tolower(*(p+2)) != 'f') + strcat(afm, ".afm"); // append .afm if the extension didn't seem to be .pf[ab] + else + strcpy(p, ".afm"); // else replace extension with .afm + FT_Attach_File(ftFace, afm); // ignore error code; AFM might not exist + delete[] afm; + } + + char buf[20]; + if (index > 0) + sprintf(buf, ":%d", index); + else + buf[0] = 0; + fFilename = new char[strlen(pathname) + 2 + strlen(buf) + 1]; + sprintf(fFilename, "[%s%s]", pathname, buf); + fUnitsPerEM = ftFace->units_per_EM; + fAscent = unitsToPoints(ftFace->ascender); + fDescent = unitsToPoints(ftFace->descender); + + postTable = (TT_Postscript *) getFontTable(ft_sfnt_post); + if (postTable != NULL) { + fItalicAngle = Fix2D(postTable->italicAngle); + } + + os2Table = (TT_OS2*) getFontTable(ft_sfnt_os2); + if (os2Table) { + fCapHeight = unitsToPoints(os2Table->sCapHeight); + fXHeight = unitsToPoints(os2Table->sxHeight); + } + + // Set up HarfBuzz font + hbFace = hb_face_create_for_tables(_get_table, ftFace, NULL); + hb_face_set_index(hbFace, index); + hb_face_set_upem(hbFace, fUnitsPerEM); + hbFont = hb_font_create(hbFace); + hb_face_destroy(hbFace); + + if (hbFontFuncs == NULL) + hbFontFuncs = _get_font_funcs(); + + hb_font_set_funcs(hbFont, hbFontFuncs, ftFace, NULL); + hb_font_set_scale(hbFont, fUnitsPerEM, fUnitsPerEM); + // We don’t want device tables adjustments + hb_font_set_ppem(hbFont, 0, 0); return; } @@ -365,25 +372,25 @@ XeTeXFontInst::initialize(const char* pathname, int index, int &status) void XeTeXFontInst::setLayoutDirVertical(bool vertical) { - fVertical = vertical; + fVertical = vertical; } const void * XeTeXFontInst::getFontTable(OTTag tag) const { - FT_ULong tmpLength = 0; - FT_Error error = FT_Load_Sfnt_Table(ftFace, tag, 0, NULL, &tmpLength); - if (error) - return NULL; - - void* table = xmalloc(tmpLength * sizeof(char)); - if (table != NULL) { - error = FT_Load_Sfnt_Table(ftFace, tag, 0, (FT_Byte*)table, &tmpLength); - if (error) { - free((void *) table); - return NULL; - } - } + FT_ULong tmpLength = 0; + FT_Error error = FT_Load_Sfnt_Table(ftFace, tag, 0, NULL, &tmpLength); + if (error) + return NULL; + + void* table = xmalloc(tmpLength * sizeof(char)); + if (table != NULL) { + error = FT_Load_Sfnt_Table(ftFace, tag, 0, (FT_Byte*)table, &tmpLength); + if (error) { + free((void *) table); + return NULL; + } + } return table; } @@ -391,136 +398,136 @@ XeTeXFontInst::getFontTable(OTTag tag) const const char * XeTeXFontInst::getMathTable() { - if (fMath == NULL) - fMath = (const char*) getFontTable(MATH_TAG); - return fMath; + if (fMath == NULL) + fMath = (const char*) getFontTable(MATH_TAG); + return fMath; } const void * XeTeXFontInst::getFontTable(FT_Sfnt_Tag tag) const { - return FT_Get_Sfnt_Table(ftFace, tag); + return FT_Get_Sfnt_Table(ftFace, tag); } void XeTeXFontInst::getGlyphBounds(GlyphID gid, GlyphBBox* bbox) { - bbox->xMin = bbox->yMin = bbox->xMax = bbox->yMax = 0.0; + bbox->xMin = bbox->yMin = bbox->xMax = bbox->yMax = 0.0; - FT_Error error = FT_Load_Glyph(ftFace, gid, FT_LOAD_NO_SCALE); - if (error) - return; + FT_Error error = FT_Load_Glyph(ftFace, gid, FT_LOAD_NO_SCALE); + if (error) + return; FT_Glyph glyph; error = FT_Get_Glyph(ftFace->glyph, &glyph); - if (error == 0) { - FT_BBox ft_bbox; - FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_UNSCALED, &ft_bbox); - bbox->xMin = unitsToPoints(ft_bbox.xMin); - bbox->yMin = unitsToPoints(ft_bbox.yMin); - bbox->xMax = unitsToPoints(ft_bbox.xMax); - bbox->yMax = unitsToPoints(ft_bbox.yMax); - FT_Done_Glyph(glyph); - } + if (error == 0) { + FT_BBox ft_bbox; + FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_UNSCALED, &ft_bbox); + bbox->xMin = unitsToPoints(ft_bbox.xMin); + bbox->yMin = unitsToPoints(ft_bbox.yMin); + bbox->xMax = unitsToPoints(ft_bbox.xMax); + bbox->yMax = unitsToPoints(ft_bbox.yMax); + FT_Done_Glyph(glyph); + } } GlyphID XeTeXFontInst::mapCharToGlyph(UChar32 ch) const { - return FT_Get_Char_Index(ftFace, ch); + return FT_Get_Char_Index(ftFace, ch); } uint16_t XeTeXFontInst::getNumGlyphs() const { - return ftFace->num_glyphs; + return ftFace->num_glyphs; } float XeTeXFontInst::getGlyphWidth(GlyphID gid) { - return unitsToPoints(_get_glyph_advance(ftFace, gid, false)); + return unitsToPoints(_get_glyph_advance(ftFace, gid, false)); } void XeTeXFontInst::getGlyphHeightDepth(GlyphID gid, float* ht, float* dp) { - GlyphBBox bbox; - getGlyphBounds(gid, &bbox); + GlyphBBox bbox; + getGlyphBounds(gid, &bbox); - if (ht) - *ht = bbox.yMax; - if (dp) - *dp = -bbox.yMin; + if (ht) + *ht = bbox.yMax; + if (dp) + *dp = -bbox.yMin; } void XeTeXFontInst::getGlyphSidebearings(GlyphID gid, float* lsb, float* rsb) { - float width = getGlyphWidth(gid); + float width = getGlyphWidth(gid); - GlyphBBox bbox; - getGlyphBounds(gid, &bbox); + GlyphBBox bbox; + getGlyphBounds(gid, &bbox); - if (lsb) - *lsb = bbox.xMin; - if (rsb) - *rsb = width - bbox.xMax; + if (lsb) + *lsb = bbox.xMin; + if (rsb) + *rsb = width - bbox.xMax; } float XeTeXFontInst::getGlyphItalCorr(GlyphID gid) { - float rval = 0.0; + float rval = 0.0; + + float width = getGlyphWidth(gid); - float width = getGlyphWidth(gid); + GlyphBBox bbox; + getGlyphBounds(gid, &bbox); - GlyphBBox bbox; - getGlyphBounds(gid, &bbox); - - if (bbox.xMax > width) - rval = bbox.xMax - width; - - return rval; + if (bbox.xMax > width) + rval = bbox.xMax - width; + + return rval; } GlyphID XeTeXFontInst::mapGlyphToIndex(const char* glyphName) const { - return FT_Get_Name_Index(ftFace, const_cast<char*>(glyphName)); + return FT_Get_Name_Index(ftFace, const_cast<char*>(glyphName)); } const char* XeTeXFontInst::getGlyphName(GlyphID gid, int& nameLen) { - if (FT_HAS_GLYPH_NAMES(ftFace)) { - static char buffer[256]; - FT_Get_Glyph_Name(ftFace, gid, buffer, 256); - nameLen = strlen(buffer); - return &buffer[0]; - } - else { - nameLen = 0; - return NULL; - } + if (FT_HAS_GLYPH_NAMES(ftFace)) { + static char buffer[256]; + FT_Get_Glyph_Name(ftFace, gid, buffer, 256); + nameLen = strlen(buffer); + return &buffer[0]; + } + else { + nameLen = 0; + return NULL; + } } UChar32 XeTeXFontInst::getFirstCharCode() { - FT_UInt gindex; - return FT_Get_First_Char(ftFace, &gindex); + FT_UInt gindex; + return FT_Get_First_Char(ftFace, &gindex); } UChar32 XeTeXFontInst::getLastCharCode() { - FT_UInt gindex; - UChar32 ch = FT_Get_First_Char(ftFace, &gindex); - UChar32 prev = ch; - while (gindex != 0) { - prev = ch; - ch = FT_Get_Next_Char(ftFace, ch, &gindex); - } - return prev; + FT_UInt gindex; + UChar32 ch = FT_Get_First_Char(ftFace, &gindex); + UChar32 prev = ch; + while (gindex != 0) { + prev = ch; + ch = FT_Get_Next_Char(ftFace, ch, &gindex); + } + return prev; } diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.h b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.h index 119f42808a9..49e0cbe58d9 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.h @@ -35,8 +35,8 @@ authorization from the copyright holders. * * created on: 2005-10-22 * created by: Jonathan Kew - * - * originally based on PortableFontInstance.h from ICU + * + * originally based on PortableFontInstance.h from ICU */ @@ -57,72 +57,72 @@ authorization from the copyright holders. class XeTeXFontInst { protected: - unsigned short fUnitsPerEM; - float fPointSize; - float fAscent; - float fDescent; - float fCapHeight; - float fXHeight; - float fItalicAngle; + unsigned short fUnitsPerEM; + float fPointSize; + float fAscent; + float fDescent; + float fCapHeight; + float fXHeight; + float fItalicAngle; - bool fVertical; // false = horizontal, true = vertical + bool fVertical; // false = horizontal, true = vertical - char *fFilename; // actually holds [filename:index], as used in xetex + char *fFilename; // actually holds [filename:index], as used in xetex - FT_Face ftFace; - hb_font_t* hbFont; - const char *fMath; + FT_Face ftFace; + hb_font_t* hbFont; + const char *fMath; public: - XeTeXFontInst(float pointSize, int &status); - XeTeXFontInst(const char* filename, int index, float pointSize, int &status); + XeTeXFontInst(float pointSize, int &status); + XeTeXFontInst(const char* filename, int index, float pointSize, int &status); + + virtual ~XeTeXFontInst(); - virtual ~XeTeXFontInst(); + void initialize(const char* pathname, int index, int &status); - void initialize(const char* pathname, int index, int &status); + const void *getFontTable(OTTag tableTag) const; + const void *getFontTable(FT_Sfnt_Tag tableTag) const; + const char *getMathTable(); - const void *getFontTable(OTTag tableTag) const; - const void *getFontTable(FT_Sfnt_Tag tableTag) const; - const char *getMathTable(); + const char *getFilename() const { return fFilename; } + hb_font_t *getHbFont() const { return hbFont; } + void setLayoutDirVertical(bool vertical); + bool getLayoutDirVertical() const { return fVertical; }; - const char *getFilename() const { return fFilename; } - hb_font_t *getHbFont() const { return hbFont; } - void setLayoutDirVertical(bool vertical); - bool getLayoutDirVertical() const { return fVertical; }; + float getPointSize() const { return fPointSize; }; + float getAscent() const { return fAscent; } + float getDescent() const { return fDescent; } + float getCapHeight() const { return fCapHeight; } + float getXHeight() const { return fXHeight; } + float getItalicAngle() const { return fItalicAngle; } - float getPointSize() const { return fPointSize; }; - float getAscent() const { return fAscent; } - float getDescent() const { return fDescent; } - float getCapHeight() const { return fCapHeight; } - float getXHeight() const { return fXHeight; } - float getItalicAngle() const { return fItalicAngle; } + GlyphID mapCharToGlyph(UChar32 ch) const; + GlyphID mapGlyphToIndex(const char* glyphName) const; - GlyphID mapCharToGlyph(UChar32 ch) const; - GlyphID mapGlyphToIndex(const char* glyphName) const; + uint16_t getNumGlyphs() const; - uint16_t getNumGlyphs() const; + void getGlyphBounds(GlyphID glyph, GlyphBBox* bbox); - void getGlyphBounds(GlyphID glyph, GlyphBBox* bbox); + float getGlyphWidth(GlyphID glyph); + void getGlyphHeightDepth(GlyphID glyph, float *ht, float* dp); + void getGlyphSidebearings(GlyphID glyph, float* lsb, float* rsb); + float getGlyphItalCorr(GlyphID glyph); - float getGlyphWidth(GlyphID glyph); - void getGlyphHeightDepth(GlyphID glyph, float *ht, float* dp); - void getGlyphSidebearings(GlyphID glyph, float* lsb, float* rsb); - float getGlyphItalCorr(GlyphID glyph); + const char* getGlyphName(GlyphID gid, int& nameLen); - const char* getGlyphName(GlyphID gid, int& nameLen); - - UChar32 getFirstCharCode(); - UChar32 getLastCharCode(); + UChar32 getFirstCharCode(); + UChar32 getLastCharCode(); - float unitsToPoints(float units) const - { - return (units * fPointSize) / (float) fUnitsPerEM; - } + float unitsToPoints(float units) const + { + return (units * fPointSize) / (float) fUnitsPerEM; + } - float pointsToUnits(float points) const - { - return (points * (float) fUnitsPerEM) / fPointSize; - } + float pointsToUnits(float points) const + { + return (points * (float) fUnitsPerEM) / fPointSize; + } }; #endif diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp index 895e5432f36..b79ba144dc7 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp @@ -55,15 +55,15 @@ XeTeXFontInst_Mac::XeTeXFontInst_Mac(CTFontDescriptorRef descriptor, float point , fDescriptor(descriptor) , fFontRef(0) { - initialize(status); + initialize(status); } XeTeXFontInst_Mac::~XeTeXFontInst_Mac() { - if (fDescriptor != 0) - CFRelease(fDescriptor); - if (fFontRef != 0) - CFRelease(fFontRef); + if (fDescriptor != 0) + CFRelease(fDescriptor); + if (fFontRef != 0) + CFRelease(fFontRef); } void @@ -74,29 +74,29 @@ XeTeXFontInst_Mac::initialize(int &status) return; } - if (status != 0) - fDescriptor = 0; + if (status != 0) + fDescriptor = 0; - // Create a copy of original font descriptor with font cascading (fallback) disabled - CFArrayRef emptyCascadeList = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); - const void* values[] = { emptyCascadeList }; - static const void* attributeKeys[] = { kCTFontCascadeListAttribute }; - CFDictionaryRef attributes = CFDictionaryCreate(NULL, attributeKeys, values, 1, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease(emptyCascadeList); + // Create a copy of original font descriptor with font cascading (fallback) disabled + CFArrayRef emptyCascadeList = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); + const void* values[] = { emptyCascadeList }; + static const void* attributeKeys[] = { kCTFontCascadeListAttribute }; + CFDictionaryRef attributes = CFDictionaryCreate(NULL, attributeKeys, values, 1, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease(emptyCascadeList); - fDescriptor = CTFontDescriptorCreateCopyWithAttributes(fDescriptor, attributes); - CFRelease(attributes); - fFontRef = CTFontCreateWithFontDescriptor(fDescriptor, fPointSize * 72.0 / 72.27, NULL); - if (fFontRef) { - char *pathname; - int index; - pathname = getFileNameFromCTFont(fFontRef, &index); + fDescriptor = CTFontDescriptorCreateCopyWithAttributes(fDescriptor, attributes); + CFRelease(attributes); + fFontRef = CTFontCreateWithFontDescriptor(fDescriptor, fPointSize * 72.0 / 72.27, NULL); + if (fFontRef) { + char *pathname; + int index; + pathname = getFileNameFromCTFont(fFontRef, &index); - XeTeXFontInst::initialize(pathname, index, status); - } else { - status = 1; - CFRelease(fDescriptor); - fDescriptor = 0; - } + XeTeXFontInst::initialize(pathname, index, status); + } else { + status = 1; + CFRelease(fDescriptor); + fDescriptor = 0; + } } diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h index 293613a517b..875414b942f 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h @@ -49,15 +49,15 @@ authorization from the copyright holders. class XeTeXFontInst_Mac : public XeTeXFontInst { protected: - CTFontDescriptorRef fDescriptor; - CTFontRef fFontRef; + CTFontDescriptorRef fDescriptor; + CTFontRef fFontRef; public: - XeTeXFontInst_Mac(CTFontDescriptorRef descriptor, float pointSize, int &status); + XeTeXFontInst_Mac(CTFontDescriptorRef descriptor, float pointSize, int &status); - virtual ~XeTeXFontInst_Mac(); + virtual ~XeTeXFontInst_Mac(); - virtual void initialize(int &status); + virtual void initialize(int &status); }; #endif diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp index 27eb5782d2e..dcc4a2fba46 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp @@ -45,17 +45,19 @@ extern "C" { #endif #include "XeTeXFontInst.h" +#include <hb-ot.h> + extern "C" { extern Fixed loadedfontdesignsize; } // functions from the Pascal/WEB side extern "C" { - void zprintnl(int s); - void zprintchar(int c); - void begindiagnostic(); - void zenddiagnostic(int nl); - int gettracingfontsstate(); + void zprintnl(int s); + void zprintchar(int c); + void begindiagnostic(); + void zenddiagnostic(int nl); + int gettracingfontsstate(); }; // see cpascal.h @@ -66,7 +68,7 @@ extern "C" { zprintchar(*(ch_ptr++)); \ } while (0) -XeTeXFontMgr* XeTeXFontMgr::sFontManager = NULL; +XeTeXFontMgr* XeTeXFontMgr::sFontManager = NULL; char XeTeXFontMgr::sReqEngine = 0; /* use our own fmax function because it seems to be missing on certain platforms @@ -74,606 +76,607 @@ char XeTeXFontMgr::sReqEngine = 0; static inline double my_fmax(double x, double y) { - return (x > y) ? x : y; + return (x > y) ? x : y; } XeTeXFontMgr* XeTeXFontMgr::GetFontManager() { - if (sFontManager == NULL) { + if (sFontManager == NULL) { #ifdef XETEX_MAC - sFontManager = new XeTeXFontMgr_Mac; + sFontManager = new XeTeXFontMgr_Mac; #else - sFontManager = new XeTeXFontMgr_FC; + sFontManager = new XeTeXFontMgr_FC; #endif - sFontManager->initialize(); - } - - return sFontManager; + sFontManager->initialize(); + } + + return sFontManager; } void XeTeXFontMgr::Terminate() { - if (sFontManager != NULL) { - sFontManager->terminate(); - // we don't actually deallocate the manager, just ask it to clean up - // any auxiliary data such as the cocoa pool or freetype/fontconfig stuff - // as we still need to access font names after this is called - } + if (sFontManager != NULL) { + sFontManager->terminate(); + // we don't actually deallocate the manager, just ask it to clean up + // any auxiliary data such as the cocoa pool or freetype/fontconfig stuff + // as we still need to access font names after this is called + } } PlatformFontRef XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize) - // ptSize is in TeX points, or negative for 'scaled' factor - // "variant" string will be shortened (in-place) by removal of /B and /I if present + // ptSize is in TeX points, or negative for 'scaled' factor + // "variant" string will be shortened (in-place) by removal of /B and /I if present { - std::string nameStr(name); - Font* font = NULL; - int dsize = 100; - loadedfontdesignsize = 655360L; - - for (int pass = 0; pass < 2; ++pass) { - // try full name as given - std::map<std::string,Font*>::iterator i = nameToFont.find(nameStr); - if (i != nameToFont.end()) { - font = i->second; - if (font->opSizeInfo.designSize != 0) - dsize = font->opSizeInfo.designSize; - break; - } - - // if there's a hyphen, split there and try Family-Style - int hyph = nameStr.find('-'); - if (hyph > 0 && hyph < nameStr.length() - 1) { - std::string family(nameStr.begin(), nameStr.begin() + hyph); - std::map<std::string,Family*>::iterator f = nameToFamily.find(family); - if (f != nameToFamily.end()) { - std::string style(nameStr.begin() + hyph + 1, nameStr.end()); - i = f->second->styles->find(style); - if (i != f->second->styles->end()) { - font = i->second; - if (font->opSizeInfo.designSize != 0) - dsize = font->opSizeInfo.designSize; - break; - } - } - } - - // try as PostScript name - i = psNameToFont.find(nameStr); - if (i != psNameToFont.end()) { - font = i->second; - if (font->opSizeInfo.designSize != 0) - dsize = font->opSizeInfo.designSize; - break; - } - - // try for the name as a family name - std::map<std::string,Family*>::iterator f = nameToFamily.find(nameStr); - - if (f != nameToFamily.end()) { - // look for a family member with the "regular" bit set in OS/2 - int regFonts = 0; - for (i = f->second->styles->begin(); i != f->second->styles->end(); ++i) - if (i->second->isReg) { - if (regFonts == 0) - font = i->second; - ++regFonts; - } - - // families with Ornament or similar fonts may flag those as Regular, - // which confuses the search above... so try some known names - if (font == NULL || regFonts > 1) { - // try for style "Regular", "Plain", "Normal", "Roman" - i = f->second->styles->find("Regular"); - if (i != f->second->styles->end()) - font = i->second; - else { - i = f->second->styles->find("Plain"); - if (i != f->second->styles->end()) - font = i->second; - else { - i = f->second->styles->find("Normal"); - if (i != f->second->styles->end()) - font = i->second; - else { - i = f->second->styles->find("Roman"); - if (i != f->second->styles->end()) - font = i->second; - } - } - } - } - - if (font == NULL) { - // look through the family for the (weight, width, slant) nearest to (80, 100, 0) - font = bestMatchFromFamily(f->second, 80, 100, 0); - } - - if (font != NULL) - break; - } - - if (pass == 0) { - // didn't find it in our caches, so do a platform search (may be relatively expensive); - // this will update the caches with any fonts that seem to match the name given, - // so that the second pass might find it - searchForHostPlatformFonts(nameStr); - } - } - - if (font == NULL) - return 0; - - Family* parent = font->parent; - - // if there are variant requests, try to apply them - // and delete B, I, and S=... codes from the string, just retain /engine option - sReqEngine = 0; - bool reqBold = false; - bool reqItal = false; - if (variant != NULL) { - std::string varString; - char* cp = variant; - while (*cp) { - if (strncmp(cp, "AAT", 3) == 0) { - sReqEngine = 'A'; - cp += 3; - if (varString.length() > 0 && *(varString.end() - 1) != '/') - varString.append("/"); - varString.append("AAT"); - goto skip_to_slash; - } - if (strncmp(cp, "ICU", 3) == 0) { // for backword compatability - sReqEngine = 'O'; - cp += 3; - if (varString.length() > 0 && *(varString.end() - 1) != '/') - varString.append("/"); - varString.append("OT"); - goto skip_to_slash; - } - if (strncmp(cp, "OT", 2) == 0) { - sReqEngine = 'O'; - cp += 2; - if (varString.length() > 0 && *(varString.end() - 1) != '/') - varString.append("/"); - varString.append("OT"); - goto skip_to_slash; - } - if (strncmp(cp, "GR", 2) == 0) { - sReqEngine = 'G'; - cp += 2; - if (varString.length() > 0 && *(varString.end() - 1) != '/') - varString.append("/"); - varString.append("GR"); - goto skip_to_slash; - } - if (*cp == 'S') { - char* start = cp; - ++cp; - if (*cp == '=') - ++cp; - ptSize = 0.0; - while (*cp >= '0' && *cp <= '9') { - ptSize = ptSize * 10 + *cp - '0'; - ++cp; - } - if (*cp == '.') { - double dec = 1.0; - ++cp; - while (*cp >= '0' && *cp <= '9') { - dec = dec * 10.0; - ptSize = ptSize + (*cp - '0') / dec; - ++cp; - } - } - goto skip_to_slash; - } - - /* if the code is "B" or "I", we skip putting it in varString */ - while (1) { - if (*cp == 'B') { - reqBold = true; - ++cp; - continue; - } - if (*cp == 'I') { - reqItal = true; - ++cp; - continue; - } - break; - } - - skip_to_slash: - while (*cp && *cp != '/') - ++cp; - if (*cp == '/') - ++cp; - } - strcpy(variant, varString.c_str()); - - std::map<std::string,Font*>::iterator i; - if (reqItal) { - Font* bestMatch = font; - if (font->slant < parent->maxSlant) - // try for a face with more slant - bestMatch = bestMatchFromFamily(parent, font->weight, font->width, parent->maxSlant); - - if (bestMatch == font && font->slant > parent->minSlant) - // maybe the slant is negated, or maybe this was something like "Times-Italic/I" - bestMatch = bestMatchFromFamily(parent, font->weight, font->width, parent->minSlant); - - if (parent->minWeight == parent->maxWeight && bestMatch->isBold != font->isBold) { - // try again using the bold flag, as we can't trust weight values - Font* newBest = NULL; - for (i = parent->styles->begin(); i != parent->styles->end(); ++i) { - if (i->second->isBold == font->isBold) { - if (newBest == NULL && i->second->isItalic != font->isItalic) { - newBest = i->second; - break; - } - } - } - if (newBest != NULL) - bestMatch = newBest; - } - - if (bestMatch == font) { - // maybe slant values weren't present; try the style bits as a fallback - bestMatch = NULL; - for (i = parent->styles->begin(); i != parent->styles->end(); ++i) - if (i->second->isItalic == !font->isItalic) - if (parent->minWeight != parent->maxWeight) { - // weight info was available, so try to match that - if (bestMatch == NULL || weightAndWidthDiff(i->second, font) < weightAndWidthDiff(bestMatch, font)) - bestMatch = i->second; - } - else { - // no weight info, so try matching style bits - if (bestMatch == NULL && i->second->isBold == font->isBold) { - bestMatch = i->second; - break; // found a match, no need to look further as we can't distinguish! - } - } - } - if (bestMatch != NULL) - font = bestMatch; - } - - if (reqBold) { - // try for more boldness, with the same width and slant - Font* bestMatch = font; - if (font->weight < parent->maxWeight) { - // try to increase weight by 1/2 x (max - min), rounding up - bestMatch = bestMatchFromFamily(parent, - font->weight + (parent->maxWeight - parent->minWeight) / 2 + 1, - font->width, font->slant); - if (parent->minSlant == parent->maxSlant) { - // double-check the italic flag, as we can't trust slant values - Font* newBest = NULL; - for (i = parent->styles->begin(); i != parent->styles->end(); ++i) { - if (i->second->isItalic == font->isItalic) { - if (newBest == NULL || weightAndWidthDiff(i->second, bestMatch) < weightAndWidthDiff(newBest, bestMatch)) - newBest = i->second; - } - } - if (newBest != NULL) - bestMatch = newBest; - } - } - if (bestMatch == font && !font->isBold) { - for (i = parent->styles->begin(); i != parent->styles->end(); ++i) { - if (i->second->isItalic == font->isItalic && i->second->isBold) { - bestMatch = i->second; - break; - } - } - } - font = bestMatch; - } - } - - // if there's optical size info, try to apply it - if (ptSize < 0.0) - ptSize = dsize / 10.0; - if (font != NULL && font->opSizeInfo.subFamilyID != 0 && ptSize > 0.0) { - ptSize = ptSize * 10.0; // convert to decipoints for comparison with the opSize values - double bestMismatch = my_fmax(font->opSizeInfo.minSize - ptSize, ptSize - font->opSizeInfo.maxSize); - if (bestMismatch > 0.0) { - Font* bestMatch = font; - for (std::map<std::string,Font*>::iterator i = parent->styles->begin(); i != parent->styles->end(); ++i) { - if (i->second->opSizeInfo.subFamilyID != font->opSizeInfo.subFamilyID) - continue; - double mismatch = my_fmax(i->second->opSizeInfo.minSize - ptSize, ptSize - i->second->opSizeInfo.maxSize); - if (mismatch < bestMismatch) { - bestMatch = i->second; - bestMismatch = mismatch; - } - if (bestMismatch <= 0.0) - break; - } - font = bestMatch; - } - } - - if (font != NULL && font->opSizeInfo.designSize != 0) - loadedfontdesignsize = (font->opSizeInfo.designSize << 16L) / 10; - - if (gettracingfontsstate() > 0) { - begindiagnostic(); - zprintnl(' '); - printcstring("-> "); - printcstring(getPlatformFontDesc(font->fontRef).c_str()); - zenddiagnostic(0); - } - - return font->fontRef; + std::string nameStr(name); + Font* font = NULL; + int dsize = 100; + loadedfontdesignsize = 655360L; + + for (int pass = 0; pass < 2; ++pass) { + // try full name as given + std::map<std::string,Font*>::iterator i = nameToFont.find(nameStr); + if (i != nameToFont.end()) { + font = i->second; + if (font->opSizeInfo.designSize != 0) + dsize = font->opSizeInfo.designSize; + break; + } + + // if there's a hyphen, split there and try Family-Style + int hyph = nameStr.find('-'); + if (hyph > 0 && hyph < nameStr.length() - 1) { + std::string family(nameStr.begin(), nameStr.begin() + hyph); + std::map<std::string,Family*>::iterator f = nameToFamily.find(family); + if (f != nameToFamily.end()) { + std::string style(nameStr.begin() + hyph + 1, nameStr.end()); + i = f->second->styles->find(style); + if (i != f->second->styles->end()) { + font = i->second; + if (font->opSizeInfo.designSize != 0) + dsize = font->opSizeInfo.designSize; + break; + } + } + } + + // try as PostScript name + i = psNameToFont.find(nameStr); + if (i != psNameToFont.end()) { + font = i->second; + if (font->opSizeInfo.designSize != 0) + dsize = font->opSizeInfo.designSize; + break; + } + + // try for the name as a family name + std::map<std::string,Family*>::iterator f = nameToFamily.find(nameStr); + + if (f != nameToFamily.end()) { + // look for a family member with the "regular" bit set in OS/2 + int regFonts = 0; + for (i = f->second->styles->begin(); i != f->second->styles->end(); ++i) + if (i->second->isReg) { + if (regFonts == 0) + font = i->second; + ++regFonts; + } + + // families with Ornament or similar fonts may flag those as Regular, + // which confuses the search above... so try some known names + if (font == NULL || regFonts > 1) { + // try for style "Regular", "Plain", "Normal", "Roman" + i = f->second->styles->find("Regular"); + if (i != f->second->styles->end()) + font = i->second; + else { + i = f->second->styles->find("Plain"); + if (i != f->second->styles->end()) + font = i->second; + else { + i = f->second->styles->find("Normal"); + if (i != f->second->styles->end()) + font = i->second; + else { + i = f->second->styles->find("Roman"); + if (i != f->second->styles->end()) + font = i->second; + } + } + } + } + + if (font == NULL) { + // look through the family for the (weight, width, slant) nearest to (80, 100, 0) + font = bestMatchFromFamily(f->second, 80, 100, 0); + } + + if (font != NULL) + break; + } + + if (pass == 0) { + // didn't find it in our caches, so do a platform search (may be relatively expensive); + // this will update the caches with any fonts that seem to match the name given, + // so that the second pass might find it + searchForHostPlatformFonts(nameStr); + } + } + + if (font == NULL) + return 0; + + Family* parent = font->parent; + + // if there are variant requests, try to apply them + // and delete B, I, and S=... codes from the string, just retain /engine option + sReqEngine = 0; + bool reqBold = false; + bool reqItal = false; + if (variant != NULL) { + std::string varString; + char* cp = variant; + while (*cp) { + if (strncmp(cp, "AAT", 3) == 0) { + sReqEngine = 'A'; + cp += 3; + if (varString.length() > 0 && *(varString.end() - 1) != '/') + varString.append("/"); + varString.append("AAT"); + goto skip_to_slash; + } + if (strncmp(cp, "ICU", 3) == 0) { // for backword compatability + sReqEngine = 'O'; + cp += 3; + if (varString.length() > 0 && *(varString.end() - 1) != '/') + varString.append("/"); + varString.append("OT"); + goto skip_to_slash; + } + if (strncmp(cp, "OT", 2) == 0) { + sReqEngine = 'O'; + cp += 2; + if (varString.length() > 0 && *(varString.end() - 1) != '/') + varString.append("/"); + varString.append("OT"); + goto skip_to_slash; + } + if (strncmp(cp, "GR", 2) == 0) { + sReqEngine = 'G'; + cp += 2; + if (varString.length() > 0 && *(varString.end() - 1) != '/') + varString.append("/"); + varString.append("GR"); + goto skip_to_slash; + } + if (*cp == 'S') { + char* start = cp; + ++cp; + if (*cp == '=') + ++cp; + ptSize = 0.0; + while (*cp >= '0' && *cp <= '9') { + ptSize = ptSize * 10 + *cp - '0'; + ++cp; + } + if (*cp == '.') { + double dec = 1.0; + ++cp; + while (*cp >= '0' && *cp <= '9') { + dec = dec * 10.0; + ptSize = ptSize + (*cp - '0') / dec; + ++cp; + } + } + goto skip_to_slash; + } + + /* if the code is "B" or "I", we skip putting it in varString */ + while (1) { + if (*cp == 'B') { + reqBold = true; + ++cp; + continue; + } + if (*cp == 'I') { + reqItal = true; + ++cp; + continue; + } + break; + } + + skip_to_slash: + while (*cp && *cp != '/') + ++cp; + if (*cp == '/') + ++cp; + } + strcpy(variant, varString.c_str()); + + std::map<std::string,Font*>::iterator i; + if (reqItal) { + Font* bestMatch = font; + if (font->slant < parent->maxSlant) + // try for a face with more slant + bestMatch = bestMatchFromFamily(parent, font->weight, font->width, parent->maxSlant); + + if (bestMatch == font && font->slant > parent->minSlant) + // maybe the slant is negated, or maybe this was something like "Times-Italic/I" + bestMatch = bestMatchFromFamily(parent, font->weight, font->width, parent->minSlant); + + if (parent->minWeight == parent->maxWeight && bestMatch->isBold != font->isBold) { + // try again using the bold flag, as we can't trust weight values + Font* newBest = NULL; + for (i = parent->styles->begin(); i != parent->styles->end(); ++i) { + if (i->second->isBold == font->isBold) { + if (newBest == NULL && i->second->isItalic != font->isItalic) { + newBest = i->second; + break; + } + } + } + if (newBest != NULL) + bestMatch = newBest; + } + + if (bestMatch == font) { + // maybe slant values weren't present; try the style bits as a fallback + bestMatch = NULL; + for (i = parent->styles->begin(); i != parent->styles->end(); ++i) { + if (i->second->isItalic == !font->isItalic) { + if (parent->minWeight != parent->maxWeight) { + // weight info was available, so try to match that + if (bestMatch == NULL || weightAndWidthDiff(i->second, font) < weightAndWidthDiff(bestMatch, font)) + bestMatch = i->second; + } else { + // no weight info, so try matching style bits + if (bestMatch == NULL && i->second->isBold == font->isBold) { + bestMatch = i->second; + break; // found a match, no need to look further as we can't distinguish! + } + } + } + } + } + if (bestMatch != NULL) + font = bestMatch; + } + + if (reqBold) { + // try for more boldness, with the same width and slant + Font* bestMatch = font; + if (font->weight < parent->maxWeight) { + // try to increase weight by 1/2 x (max - min), rounding up + bestMatch = bestMatchFromFamily(parent, + font->weight + (parent->maxWeight - parent->minWeight) / 2 + 1, + font->width, font->slant); + if (parent->minSlant == parent->maxSlant) { + // double-check the italic flag, as we can't trust slant values + Font* newBest = NULL; + for (i = parent->styles->begin(); i != parent->styles->end(); ++i) { + if (i->second->isItalic == font->isItalic) { + if (newBest == NULL || weightAndWidthDiff(i->second, bestMatch) < weightAndWidthDiff(newBest, bestMatch)) + newBest = i->second; + } + } + if (newBest != NULL) + bestMatch = newBest; + } + } + if (bestMatch == font && !font->isBold) { + for (i = parent->styles->begin(); i != parent->styles->end(); ++i) { + if (i->second->isItalic == font->isItalic && i->second->isBold) { + bestMatch = i->second; + break; + } + } + } + font = bestMatch; + } + } + + // if there's optical size info, try to apply it + if (ptSize < 0.0) + ptSize = dsize / 10.0; + if (font != NULL && font->opSizeInfo.subFamilyID != 0 && ptSize > 0.0) { + ptSize = ptSize * 10.0; // convert to decipoints for comparison with the opSize values + double bestMismatch = my_fmax(font->opSizeInfo.minSize - ptSize, ptSize - font->opSizeInfo.maxSize); + if (bestMismatch > 0.0) { + Font* bestMatch = font; + for (std::map<std::string,Font*>::iterator i = parent->styles->begin(); i != parent->styles->end(); ++i) { + if (i->second->opSizeInfo.subFamilyID != font->opSizeInfo.subFamilyID) + continue; + double mismatch = my_fmax(i->second->opSizeInfo.minSize - ptSize, ptSize - i->second->opSizeInfo.maxSize); + if (mismatch < bestMismatch) { + bestMatch = i->second; + bestMismatch = mismatch; + } + if (bestMismatch <= 0.0) + break; + } + font = bestMatch; + } + } + + if (font != NULL && font->opSizeInfo.designSize != 0) + loadedfontdesignsize = (font->opSizeInfo.designSize << 16L) / 10; + + if (gettracingfontsstate() > 0) { + begindiagnostic(); + zprintnl(' '); + printcstring("-> "); + printcstring(getPlatformFontDesc(font->fontRef).c_str()); + zenddiagnostic(0); + } + + return font->fontRef; } const char* XeTeXFontMgr::getFullName(PlatformFontRef font) const { - std::map<PlatformFontRef,Font*>::const_iterator i = platformRefToFont.find(font); - if (i == platformRefToFont.end()) - die("internal error %d in XeTeXFontMgr", 2); - if (i->second->fullName != NULL) - return i->second->fullName->c_str(); - else - return i->second->psName->c_str(); + std::map<PlatformFontRef,Font*>::const_iterator i = platformRefToFont.find(font); + if (i == platformRefToFont.end()) + die("internal error %d in XeTeXFontMgr", 2); + if (i->second->fullName != NULL) + return i->second->fullName->c_str(); + else + return i->second->psName->c_str(); } void XeTeXFontMgr::getNames(PlatformFontRef font, const char** psName, - const char** famName, const char** styName) const + const char** famName, const char** styName) const { - std::map<PlatformFontRef,Font*>::const_iterator i = platformRefToFont.find(font); - if (i == platformRefToFont.end()) - die("internal error %d in XeTeXFontMgr", 3); - *psName = i->second->psName->c_str(); - *famName = i->second->familyName->c_str(); - *styName = i->second->styleName->c_str(); + std::map<PlatformFontRef,Font*>::const_iterator i = platformRefToFont.find(font); + if (i == platformRefToFont.end()) + die("internal error %d in XeTeXFontMgr", 3); + *psName = xstrdup(i->second->psName->c_str()); + *famName = xstrdup(i->second->familyName->c_str()); + *styName = xstrdup(i->second->styleName->c_str()); } int XeTeXFontMgr::weightAndWidthDiff(const Font* a, const Font* b) const { - if (a->weight == 0 && a->width == 0) { - // assume there was no OS/2 info - if (a->isBold == b->isBold) - return 0; - else - return 10000; - } - - int widDiff = labs(a->width - b->width); - if (widDiff < 10) - widDiff *= 50; - - return labs(a->weight - b->weight) + widDiff; + if (a->weight == 0 && a->width == 0) { + // assume there was no OS/2 info + if (a->isBold == b->isBold) + return 0; + else + return 10000; + } + + int widDiff = labs(a->width - b->width); + if (widDiff < 10) + widDiff *= 50; + + return labs(a->weight - b->weight) + widDiff; } int XeTeXFontMgr::styleDiff(const Font* a, int wt, int wd, int slant) const { - int widDiff = labs(a->width - wd); - if (widDiff < 10) - widDiff *= 200; - - return labs(labs(a->slant) - labs(slant)) * 2 + labs(a->weight - wt) + widDiff; + int widDiff = labs(a->width - wd); + if (widDiff < 10) + widDiff *= 200; + + return labs(labs(a->slant) - labs(slant)) * 2 + labs(a->weight - wt) + widDiff; } XeTeXFontMgr::Font* XeTeXFontMgr::bestMatchFromFamily(const Family* fam, int wt, int wd, int slant) const { - Font* bestMatch = NULL; - for (std::map<std::string,Font*>::iterator s = fam->styles->begin(); s != fam->styles->end(); ++s) - if (bestMatch == NULL || styleDiff(s->second, wt, wd, slant) < styleDiff(bestMatch, wt, wd, slant)) - bestMatch = s->second; - return bestMatch; + Font* bestMatch = NULL; + for (std::map<std::string,Font*>::iterator s = fam->styles->begin(); s != fam->styles->end(); ++s) + if (bestMatch == NULL || styleDiff(s->second, wt, wd, slant) < styleDiff(bestMatch, wt, wd, slant)) + bestMatch = s->second; + return bestMatch; } const XeTeXFontMgr::OpSizeRec* XeTeXFontMgr::getOpSize(XeTeXFont font) { - hb_font_t* hbFont = ((XeTeXFontInst*)font)->getHbFont(); - if (hbFont != NULL) { - hb_face_t* face = hb_font_get_face(hbFont); - OpSizeRec* pSizeRec = (OpSizeRec*) xmalloc(sizeof(OpSizeRec)); - - bool ok = hb_ot_layout_get_size_params(face, - &pSizeRec->designSize, - &pSizeRec->subFamilyID, - &pSizeRec->nameCode, - &pSizeRec->minSize, - &pSizeRec->maxSize); - - if (ok) - return pSizeRec; - - free(pSizeRec); - return NULL; - } - - return NULL; + hb_font_t* hbFont = ((XeTeXFontInst*)font)->getHbFont(); + if (hbFont != NULL) { + hb_face_t* face = hb_font_get_face(hbFont); + OpSizeRec* pSizeRec = (OpSizeRec*) xmalloc(sizeof(OpSizeRec)); + + bool ok = hb_ot_layout_get_size_params(face, + &pSizeRec->designSize, + &pSizeRec->subFamilyID, + &pSizeRec->nameCode, + &pSizeRec->minSize, + &pSizeRec->maxSize); + + if (ok) + return pSizeRec; + + free(pSizeRec); + return NULL; + } + + return NULL; } double XeTeXFontMgr::getDesignSize(XeTeXFont font) { - const OpSizeRec* pSizeRec = getOpSize(font); - if (pSizeRec != NULL) - return pSizeRec->designSize / 10.0; - else - return 10.0; + const OpSizeRec* pSizeRec = getOpSize(font); + if (pSizeRec != NULL) + return pSizeRec->designSize / 10.0; + else + return 10.0; } void XeTeXFontMgr::getOpSizeRecAndStyleFlags(Font* theFont) { - XeTeXFont font = createFont(theFont->fontRef, 655360); - XeTeXFontInst* fontInst = (XeTeXFontInst*) font; - if (font != 0) { - const OpSizeRec* pSizeRec = getOpSize(font); - if (pSizeRec != NULL) { - theFont->opSizeInfo.designSize = pSizeRec->designSize; - if (pSizeRec->subFamilyID == 0 - && pSizeRec->nameCode == 0 - && pSizeRec->minSize == 0 - && pSizeRec->maxSize == 0) - goto done_size; // feature is valid, but no 'size' range - theFont->opSizeInfo.subFamilyID = pSizeRec->subFamilyID; - theFont->opSizeInfo.nameCode = pSizeRec->nameCode; - theFont->opSizeInfo.minSize = pSizeRec->minSize; - theFont->opSizeInfo.maxSize = pSizeRec->maxSize; - } - done_size: - - const TT_OS2* os2Table = (TT_OS2*) fontInst->getFontTable(ft_sfnt_os2); - if (os2Table != NULL) { - theFont->weight = os2Table->usWeightClass; - theFont->width = os2Table->usWidthClass; - uint16_t sel = os2Table->fsSelection; - theFont->isReg = (sel & (1 << 6)) != 0; - theFont->isBold = (sel & (1 << 5)) != 0; - theFont->isItalic = (sel & (1 << 0)) != 0; - } - - const TT_Header* headTable = (TT_Header*) fontInst->getFontTable(ft_sfnt_head); - if (headTable != NULL) { - uint16_t ms = headTable->Mac_Style; - if ((ms & (1 << 0)) != 0) - theFont->isBold = true; - if ((ms & (1 << 1)) != 0) - theFont->isItalic = true; - } - - const TT_Postscript* postTable = (const TT_Postscript*) fontInst->getFontTable(ft_sfnt_post); - if (postTable != NULL) { - theFont->slant = (int)(1000 * (tan(Fix2D(-postTable->italicAngle) * M_PI / 180.0))); - } - deleteFont(font); - } + XeTeXFont font = createFont(theFont->fontRef, 655360); + XeTeXFontInst* fontInst = (XeTeXFontInst*) font; + if (font != 0) { + const OpSizeRec* pSizeRec = getOpSize(font); + if (pSizeRec != NULL) { + theFont->opSizeInfo.designSize = pSizeRec->designSize; + if (pSizeRec->subFamilyID == 0 + && pSizeRec->nameCode == 0 + && pSizeRec->minSize == 0 + && pSizeRec->maxSize == 0) + goto done_size; // feature is valid, but no 'size' range + theFont->opSizeInfo.subFamilyID = pSizeRec->subFamilyID; + theFont->opSizeInfo.nameCode = pSizeRec->nameCode; + theFont->opSizeInfo.minSize = pSizeRec->minSize; + theFont->opSizeInfo.maxSize = pSizeRec->maxSize; + } + done_size: + + const TT_OS2* os2Table = (TT_OS2*) fontInst->getFontTable(ft_sfnt_os2); + if (os2Table != NULL) { + theFont->weight = os2Table->usWeightClass; + theFont->width = os2Table->usWidthClass; + uint16_t sel = os2Table->fsSelection; + theFont->isReg = (sel & (1 << 6)) != 0; + theFont->isBold = (sel & (1 << 5)) != 0; + theFont->isItalic = (sel & (1 << 0)) != 0; + } + + const TT_Header* headTable = (TT_Header*) fontInst->getFontTable(ft_sfnt_head); + if (headTable != NULL) { + uint16_t ms = headTable->Mac_Style; + if ((ms & (1 << 0)) != 0) + theFont->isBold = true; + if ((ms & (1 << 1)) != 0) + theFont->isItalic = true; + } + + const TT_Postscript* postTable = (const TT_Postscript*) fontInst->getFontTable(ft_sfnt_post); + if (postTable != NULL) { + theFont->slant = (int)(1000 * (tan(Fix2D(-postTable->italicAngle) * M_PI / 180.0))); + } + deleteFont(font); + } } // append a name but only if it's not already in the list void XeTeXFontMgr::appendToList(std::list<std::string>* list, const char* str) { - for (std::list<std::string>::const_iterator i = list->begin(); i != list->end(); ++i) - if (*i == str) - return; - list->push_back(str); + for (std::list<std::string>::const_iterator i = list->begin(); i != list->end(); ++i) + if (*i == str) + return; + list->push_back(str); } // prepend a name, removing it from later in the list if present void XeTeXFontMgr::prependToList(std::list<std::string>* list, const char* str) { - for (std::list<std::string>::iterator i = list->begin(); i != list->end(); ++i) - if (*i == str) { - list->erase(i); - break; - } - list->push_front(str); + for (std::list<std::string>::iterator i = list->begin(); i != list->end(); ++i) + if (*i == str) { + list->erase(i); + break; + } + list->push_front(str); } void XeTeXFontMgr::addToMaps(PlatformFontRef platformFont, const NameCollection* names) { - if (platformRefToFont.find(platformFont) != platformRefToFont.end()) - return; // this font has already been cached - - if (names->psName.length() == 0) - return; // can't use a font that lacks a PostScript name - - if (psNameToFont.find(names->psName) != psNameToFont.end()) - return; // duplicates an earlier PS name, so skip - - Font* thisFont = new Font(platformFont); - thisFont->psName = new std::string(names->psName); - getOpSizeRecAndStyleFlags(thisFont); - - psNameToFont[names->psName] = thisFont; - platformRefToFont[platformFont] = thisFont; - - if (names->fullNames.size() > 0) - thisFont->fullName = new std::string(*(names->fullNames.begin())); - - if (names->familyNames.size() > 0) - thisFont->familyName = new std::string(*(names->familyNames.begin())); - else - thisFont->familyName = new std::string(names->psName); - - if (names->styleNames.size() > 0) - thisFont->styleName = new std::string(*(names->styleNames.begin())); - else - thisFont->styleName = new std::string; - - std::list<std::string>::const_iterator i; - for (i = names->familyNames.begin(); i != names->familyNames.end(); ++i) { - std::map<std::string,Family*>::iterator iFam = nameToFamily.find(*i); - Family* family; - if (iFam == nameToFamily.end()) { - family = new Family; - nameToFamily[*i] = family; - family->minWeight = thisFont->weight; - family->maxWeight = thisFont->weight; - family->minWidth = thisFont->width; - family->maxWidth = thisFont->width; - family->minSlant = thisFont->slant; - family->maxSlant = thisFont->slant; - } else { - family = iFam->second; - if (thisFont->weight < family->minWeight) - family->minWeight = thisFont->weight; - if (thisFont->weight > family->maxWeight) - family->maxWeight = thisFont->weight; - if (thisFont->width < family->minWidth) - family->minWidth = thisFont->width; - if (thisFont->width > family->maxWidth) - family->maxWidth = thisFont->width; - if (thisFont->slant < family->minSlant) - family->minSlant = thisFont->slant; - if (thisFont->slant > family->maxSlant) - family->maxSlant = thisFont->slant; - } - - if (thisFont->parent == NULL) - thisFont->parent = family; - - // ensure all style names in the family point to thisFont - for (std::list<std::string>::const_iterator j = names->styleNames.begin(); j != names->styleNames.end(); ++j) { - std::map<std::string,Font*>::iterator iFont = family->styles->find(*j); - if (iFont == family->styles->end()) - (*family->styles)[*j] = thisFont; + if (platformRefToFont.find(platformFont) != platformRefToFont.end()) + return; // this font has already been cached + + if (names->psName.length() == 0) + return; // can't use a font that lacks a PostScript name + + if (psNameToFont.find(names->psName) != psNameToFont.end()) + return; // duplicates an earlier PS name, so skip + + Font* thisFont = new Font(platformFont); + thisFont->psName = new std::string(names->psName); + getOpSizeRecAndStyleFlags(thisFont); + + psNameToFont[names->psName] = thisFont; + platformRefToFont[platformFont] = thisFont; + + if (names->fullNames.size() > 0) + thisFont->fullName = new std::string(*(names->fullNames.begin())); + + if (names->familyNames.size() > 0) + thisFont->familyName = new std::string(*(names->familyNames.begin())); + else + thisFont->familyName = new std::string(names->psName); + + if (names->styleNames.size() > 0) + thisFont->styleName = new std::string(*(names->styleNames.begin())); + else + thisFont->styleName = new std::string; + + std::list<std::string>::const_iterator i; + for (i = names->familyNames.begin(); i != names->familyNames.end(); ++i) { + std::map<std::string,Family*>::iterator iFam = nameToFamily.find(*i); + Family* family; + if (iFam == nameToFamily.end()) { + family = new Family; + nameToFamily[*i] = family; + family->minWeight = thisFont->weight; + family->maxWeight = thisFont->weight; + family->minWidth = thisFont->width; + family->maxWidth = thisFont->width; + family->minSlant = thisFont->slant; + family->maxSlant = thisFont->slant; + } else { + family = iFam->second; + if (thisFont->weight < family->minWeight) + family->minWeight = thisFont->weight; + if (thisFont->weight > family->maxWeight) + family->maxWeight = thisFont->weight; + if (thisFont->width < family->minWidth) + family->minWidth = thisFont->width; + if (thisFont->width > family->maxWidth) + family->maxWidth = thisFont->width; + if (thisFont->slant < family->minSlant) + family->minSlant = thisFont->slant; + if (thisFont->slant > family->maxSlant) + family->maxSlant = thisFont->slant; + } + + if (thisFont->parent == NULL) + thisFont->parent = family; + + // ensure all style names in the family point to thisFont + for (std::list<std::string>::const_iterator j = names->styleNames.begin(); j != names->styleNames.end(); ++j) { + std::map<std::string,Font*>::iterator iFont = family->styles->find(*j); + if (iFont == family->styles->end()) + (*family->styles)[*j] = thisFont; /* - else if (iFont->second != thisFont) - fprintf(stderr, "# Font name warning: ambiguous Style \"%s\" in Family \"%s\" (PSNames \"%s\" and \"%s\")\n", - j->c_str(), i->c_str(), iFont->second->psName->c_str(), thisFont->psName->c_str()); + else if (iFont->second != thisFont) + fprintf(stderr, "# Font name warning: ambiguous Style \"%s\" in Family \"%s\" (PSNames \"%s\" and \"%s\")\n", + j->c_str(), i->c_str(), iFont->second->psName->c_str(), thisFont->psName->c_str()); */ - } - } - - for (i = names->fullNames.begin(); i != names->fullNames.end(); ++i) { - std::map<std::string,Font*>::iterator iFont = nameToFont.find(*i); - if (iFont == nameToFont.end()) - nameToFont[*i] = thisFont; + } + } + + for (i = names->fullNames.begin(); i != names->fullNames.end(); ++i) { + std::map<std::string,Font*>::iterator iFont = nameToFont.find(*i); + if (iFont == nameToFont.end()) + nameToFont[*i] = thisFont; /* - else if (iFont->second != thisFont) - fprintf(stderr, "# Font name warning: ambiguous FullName \"%s\" (PSNames \"%s\" and \"%s\")\n", - i->c_str(), iFont->second->psName->c_str(), thisFont->psName->c_str()); + else if (iFont->second != thisFont) + fprintf(stderr, "# Font name warning: ambiguous FullName \"%s\" (PSNames \"%s\" and \"%s\")\n", + i->c_str(), iFont->second->psName->c_str(), thisFont->psName->c_str()); */ - } + } } void XeTeXFontMgr::die(const char*s, int i) const { - fprintf(stderr, s, i); - fprintf(stderr, " - exiting\n"); - exit(3); + fprintf(stderr, s, i); + fprintf(stderr, " - exiting\n"); + exit(3); } void diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h index 599fbe97d47..1535eff9db3 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h @@ -41,14 +41,14 @@ typedef CTFontDescriptorRef PlatformFontRef; #include <fontconfig/fontconfig.h> #include <ft2build.h> #include FT_FREETYPE_H -typedef FcPattern* PlatformFontRef; +typedef FcPattern* PlatformFontRef; #endif #include "XeTeX_ext.h" #include "XeTeXLayoutInterface.h" -#ifdef __cplusplus /* allow inclusion in plain C files just to get the typedefs above */ +#ifdef __cplusplus /* allow inclusion in plain C files just to get the typedefs above */ #include <string> #include <map> @@ -58,151 +58,151 @@ typedef FcPattern* PlatformFontRef; class XeTeXFontMgr { public: - static XeTeXFontMgr* GetFontManager(); - // returns the global fontmanager (creating it if necessary) - static void Terminate(); - // clean up (may be required if using the cocoa implementation) + static XeTeXFontMgr* GetFontManager(); + // returns the global fontmanager (creating it if necessary) + static void Terminate(); + // clean up (may be required if using the cocoa implementation) - PlatformFontRef findFont(const char* name, char* variant, double ptSize); - // 1st arg is name as specified by user (C string, UTF-8) - // 2nd is /B/I/AAT/OT/ICU/GR/S=## qualifiers - // 1. try name given as "full name" - // 2. if there's a hyphen, split and try "family-style" - // 3. try as PostScript name - // 4. try name as family with "Regular/Plain/Normal" style - // apply style qualifiers and optical sizing if present + PlatformFontRef findFont(const char* name, char* variant, double ptSize); + // 1st arg is name as specified by user (C string, UTF-8) + // 2nd is /B/I/AAT/OT/ICU/GR/S=## qualifiers + // 1. try name given as "full name" + // 2. if there's a hyphen, split and try "family-style" + // 3. try as PostScript name + // 4. try name as family with "Regular/Plain/Normal" style + // apply style qualifiers and optical sizing if present - // SIDE EFFECT: sets sReqEngine to 'A' or 'O' or 'G' if appropriate, - // else clears it to 0 + // SIDE EFFECT: sets sReqEngine to 'A' or 'O' or 'G' if appropriate, + // else clears it to 0 - // SIDE EFFECT: updates TeX variables /nameoffile/ and /namelength/, - // to match the actual font found + // SIDE EFFECT: updates TeX variables /nameoffile/ and /namelength/, + // to match the actual font found - // SIDE EFFECT: edits /variant/ string in-place removing /B or /I - - const char* getFullName(PlatformFontRef font) const; - // return the full name of the font, suitable for use in XeTeX source - // without requiring style qualifiers + // SIDE EFFECT: edits /variant/ string in-place removing /B or /I - void getNames(PlatformFontRef font, const char** psName, - const char** famName, const char** styName) const; - // return Postscript, family, and style names, for use in .xdv + const char* getFullName(PlatformFontRef font) const; + // return the full name of the font, suitable for use in XeTeX source + // without requiring style qualifiers - double getDesignSize(XeTeXFont font); + void getNames(PlatformFontRef font, const char** psName, + const char** famName, const char** styName) const; + // return Postscript, family, and style names, for use in .xdv - char getReqEngine() const { return sReqEngine; }; - // return the requested rendering technology for the most recent findFont - // or 0 if no specific technology was requested + double getDesignSize(XeTeXFont font); - void setReqEngine(char reqEngine) const { sReqEngine = reqEngine; }; + char getReqEngine() const { return sReqEngine; }; + // return the requested rendering technology for the most recent findFont + // or 0 if no specific technology was requested + + void setReqEngine(char reqEngine) const { sReqEngine = reqEngine; }; protected: - static XeTeXFontMgr* sFontManager; - static char sReqEngine; - - XeTeXFontMgr() - { } - virtual ~XeTeXFontMgr() - { } - - virtual void initialize() = 0; - virtual void terminate(); - - virtual std::string getPlatformFontDesc(PlatformFontRef font) const = 0; - - class Font; - class Family; - - struct OpSizeRec { - unsigned int designSize; - unsigned int subFamilyID; - unsigned int nameCode; - unsigned int minSize; - unsigned int maxSize; - }; - - class Font { - public: - Font(PlatformFontRef ref) - : fullName(NULL), psName(NULL), familyName(NULL), styleName(NULL) - , parent(NULL) - , fontRef(ref), weight(0), width(0), slant(0) - , isReg(false), isBold(false), isItalic(false) - { opSizeInfo.subFamilyID = 0; - opSizeInfo.designSize = 100; } /* default to 10bp */ - ~Font() - { delete fullName; delete psName; } - - std::string* fullName; - std::string* psName; - std::string* familyName; // default family and style names that should locate this font - std::string* styleName; - Family* parent; - PlatformFontRef fontRef; - OpSizeRec opSizeInfo; - uint16_t weight; - uint16_t width; - int16_t slant; - bool isReg; - bool isBold; - bool isItalic; - }; - - class Family { - public: - Family() - : minWeight(0), maxWeight(0) - , minWidth(0), maxWidth(0) - , minSlant(0), maxSlant(0) - { - styles = new std::map<std::string,Font*>; - } - ~Family() - { - delete styles; - } - - std::map<std::string,Font*>* styles; - uint16_t minWeight; - uint16_t maxWeight; - uint16_t minWidth; - uint16_t maxWidth; - int16_t minSlant; - int16_t maxSlant; - }; - - class NameCollection { - public: - std::list<std::string> familyNames; - std::list<std::string> styleNames; - std::list<std::string> fullNames; - std::string psName; - std::string subFamily; - }; - - std::map<std::string,Font*> nameToFont; // maps full name (as used in TeX source) to font record - std::map<std::string,Family*> nameToFamily; - std::map<PlatformFontRef,Font*> platformRefToFont; - std::map<std::string,Font*> psNameToFont; // maps PS name (as used in .xdv) to font record - - int weightAndWidthDiff(const Font* a, const Font* b) const; - int styleDiff(const Font* a, int wt, int wd, int slant) const; - Font* bestMatchFromFamily(const Family* fam, int wt, int wd, int slant) const; - void appendToList(std::list<std::string>* list, const char* str); - void prependToList(std::list<std::string>* list, const char* str); - void addToMaps(PlatformFontRef platformFont, const NameCollection* names); - - const OpSizeRec* getOpSize(XeTeXFont font); - - virtual void getOpSizeRecAndStyleFlags(Font* theFont); - virtual void searchForHostPlatformFonts(const std::string& name) = 0; - - virtual NameCollection* readNames(PlatformFontRef fontRef) = 0; - - void die(const char*s, int i) const; /* for fatal internal errors! */ + static XeTeXFontMgr* sFontManager; + static char sReqEngine; + + XeTeXFontMgr() + { } + virtual ~XeTeXFontMgr() + { } + + virtual void initialize() = 0; + virtual void terminate(); + + virtual std::string getPlatformFontDesc(PlatformFontRef font) const = 0; + + class Font; + class Family; + + struct OpSizeRec { + unsigned int designSize; + unsigned int subFamilyID; + unsigned int nameCode; + unsigned int minSize; + unsigned int maxSize; + }; + + class Font { + public: + Font(PlatformFontRef ref) + : fullName(NULL), psName(NULL), familyName(NULL), styleName(NULL) + , parent(NULL) + , fontRef(ref), weight(0), width(0), slant(0) + , isReg(false), isBold(false), isItalic(false) + { opSizeInfo.subFamilyID = 0; + opSizeInfo.designSize = 100; } /* default to 10bp */ + ~Font() + { delete fullName; delete psName; } + + std::string* fullName; + std::string* psName; + std::string* familyName; // default family and style names that should locate this font + std::string* styleName; + Family* parent; + PlatformFontRef fontRef; + OpSizeRec opSizeInfo; + uint16_t weight; + uint16_t width; + int16_t slant; + bool isReg; + bool isBold; + bool isItalic; + }; + + class Family { + public: + Family() + : minWeight(0), maxWeight(0) + , minWidth(0), maxWidth(0) + , minSlant(0), maxSlant(0) + { + styles = new std::map<std::string,Font*>; + } + ~Family() + { + delete styles; + } + + std::map<std::string,Font*>* styles; + uint16_t minWeight; + uint16_t maxWeight; + uint16_t minWidth; + uint16_t maxWidth; + int16_t minSlant; + int16_t maxSlant; + }; + + class NameCollection { + public: + std::list<std::string> familyNames; + std::list<std::string> styleNames; + std::list<std::string> fullNames; + std::string psName; + std::string subFamily; + }; + + std::map<std::string,Font*> nameToFont; // maps full name (as used in TeX source) to font record + std::map<std::string,Family*> nameToFamily; + std::map<PlatformFontRef,Font*> platformRefToFont; + std::map<std::string,Font*> psNameToFont; // maps PS name (as used in .xdv) to font record + + int weightAndWidthDiff(const Font* a, const Font* b) const; + int styleDiff(const Font* a, int wt, int wd, int slant) const; + Font* bestMatchFromFamily(const Family* fam, int wt, int wd, int slant) const; + void appendToList(std::list<std::string>* list, const char* str); + void prependToList(std::list<std::string>* list, const char* str); + void addToMaps(PlatformFontRef platformFont, const NameCollection* names); + + const OpSizeRec* getOpSize(XeTeXFont font); + + virtual void getOpSizeRecAndStyleFlags(Font* theFont); + virtual void searchForHostPlatformFonts(const std::string& name) = 0; + + virtual NameCollection* readNames(PlatformFontRef fontRef) = 0; + + void die(const char*s, int i) const; /* for fatal internal errors! */ }; -#endif /* __cplusplus */ +#endif /* __cplusplus */ -#endif /* __XETEX_FONT_MANAGER_H */ +#endif /* __XETEX_FONT_MANAGER_H */ diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_FC.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_FC.cpp index f7c64d16f4b..f7253f1faa3 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_FC.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_FC.cpp @@ -50,318 +50,320 @@ extern "C" { #include <unicode/ucnv.h> -#define kFontFamilyName 1 -#define kFontStyleName 2 -#define kFontFullName 4 -#define kPreferredFamilyName 16 -#define kPreferredSubfamilyName 17 +#define kFontFamilyName 1 +#define kFontStyleName 2 +#define kFontFullName 4 +#define kPreferredFamilyName 16 +#define kPreferredSubfamilyName 17 -static UConverter* macRomanConv = NULL; -static UConverter* utf16beConv = NULL; -static UConverter* utf8Conv = NULL; +static UConverter* macRomanConv = NULL; +static UConverter* utf16beConv = NULL; +static UConverter* utf8Conv = NULL; static char* convertToUtf8(UConverter* conv, const unsigned char* name, int len) { - char* buffer1 = NULL; - char* buffer2 = NULL; - int bufSize = -1; - - if (2 * (len + 1) > bufSize) { - if (buffer1 != NULL) { - delete[] buffer1; - delete[] buffer2; - } - bufSize = 2 * len + 100; - buffer1 = new char[bufSize]; - buffer2 = new char[bufSize]; - } - - UErrorCode status = U_ZERO_ERROR; - len = ucnv_toUChars(conv, (UChar*)buffer1, bufSize, (const char*)name, len, &status); - len = ucnv_fromUChars(utf8Conv, buffer2, bufSize, (UChar*)buffer1, len, &status); - buffer2[len] = 0; - - return buffer2; + char* buffer1 = NULL; + char* buffer2 = NULL; + int bufSize = -1; + + if (2 * (len + 1) > bufSize) { + if (buffer1 != NULL) { + delete[] buffer1; + delete[] buffer2; + } + bufSize = 2 * len + 100; + buffer1 = new char[bufSize]; + buffer2 = new char[bufSize]; + } + + UErrorCode status = U_ZERO_ERROR; + len = ucnv_toUChars(conv, (UChar*)buffer1, bufSize, (const char*)name, len, &status); + len = ucnv_fromUChars(utf8Conv, buffer2, bufSize, (UChar*)buffer1, len, &status); + buffer2[len] = 0; + + delete[] buffer1; + return buffer2; } XeTeXFontMgr::NameCollection* XeTeXFontMgr_FC::readNames(FcPattern* pat) { - NameCollection* names = new NameCollection; - - char* pathname; - if (FcPatternGetString(pat, FC_FILE, 0, (FcChar8**)&pathname) != FcResultMatch) - return names; - int index; - if (FcPatternGetInteger(pat, FC_INDEX, 0, &index) != FcResultMatch) - return names; - - FT_Face face; - if (FT_New_Face(gFreeTypeLibrary, pathname, index, &face) != 0) - return names; - - const char* name = FT_Get_Postscript_Name(face); - if (name == NULL) - return names; - names->psName = name; - - // for sfnt containers, we'll read the name table ourselves, not rely on Fontconfig - if (FT_IS_SFNT(face)) { - std::list<std::string> familyNames; - std::list<std::string> subFamilyNames; - FT_SfntName nameRec; - for (index = 0; index < FT_Get_Sfnt_Name_Count(face); ++index) { - char* utf8name = NULL; - if (FT_Get_Sfnt_Name(face, index, &nameRec) != 0) - continue; - switch (nameRec.name_id) { - case kFontFullName: - case kFontFamilyName: - case kFontStyleName: - case kPreferredFamilyName: - case kPreferredSubfamilyName: - { - bool preferredName = false; - if (nameRec.platform_id == TT_PLATFORM_MACINTOSH - && nameRec.encoding_id == TT_MAC_ID_ROMAN && nameRec.language_id == 0) { - utf8name = convertToUtf8(macRomanConv, nameRec.string, nameRec.string_len); - preferredName = true; - } - else if ((nameRec.platform_id == TT_PLATFORM_APPLE_UNICODE) - || (nameRec.platform_id == TT_PLATFORM_MICROSOFT)) - utf8name = convertToUtf8(utf16beConv, nameRec.string, nameRec.string_len); - - if (utf8name != NULL) { - std::list<std::string>* nameList = NULL; - switch (nameRec.name_id) { - case kFontFullName: - nameList = &names->fullNames; - break; - case kFontFamilyName: - nameList = &names->familyNames; - break; - case kFontStyleName: - nameList = &names->styleNames; - break; - case kPreferredFamilyName: - nameList = &familyNames; - break; - case kPreferredSubfamilyName: - nameList = &subFamilyNames; - break; - } - if (preferredName) - prependToList(nameList, utf8name); - else - appendToList(nameList, utf8name); - } - } - break; - } - } - if (familyNames.size() > 0) - names->familyNames = familyNames; - if (subFamilyNames.size() > 0) - names->styleNames = subFamilyNames; - } else { - index = 0; - while (FcPatternGetString(pat, FC_FULLNAME, index++, (FcChar8**)&name) == FcResultMatch) - appendToList(&names->fullNames, name); - index = 0; - while (FcPatternGetString(pat, FC_FAMILY, index++, (FcChar8**)&name) == FcResultMatch) - appendToList(&names->familyNames, name); - index = 0; - while (FcPatternGetString(pat, FC_STYLE, index++, (FcChar8**)&name) == FcResultMatch) - appendToList(&names->styleNames, name); - - if (names->fullNames.size() == 0) { - std::string fullName(names->familyNames.front()); - if (names->styleNames.size() > 0) { - fullName += " "; - fullName += names->styleNames.front(); - } - names->fullNames.push_back(fullName); - } - } - - FT_Done_Face(face); - - return names; + NameCollection* names = new NameCollection; + + char* pathname; + if (FcPatternGetString(pat, FC_FILE, 0, (FcChar8**)&pathname) != FcResultMatch) + return names; + int index; + if (FcPatternGetInteger(pat, FC_INDEX, 0, &index) != FcResultMatch) + return names; + + FT_Face face; + if (FT_New_Face(gFreeTypeLibrary, pathname, index, &face) != 0) + return names; + + const char* name = FT_Get_Postscript_Name(face); + if (name == NULL) + return names; + names->psName = name; + + // for sfnt containers, we'll read the name table ourselves, not rely on Fontconfig + if (FT_IS_SFNT(face)) { + std::list<std::string> familyNames; + std::list<std::string> subFamilyNames; + FT_SfntName nameRec; + for (index = 0; index < FT_Get_Sfnt_Name_Count(face); ++index) { + char* utf8name = NULL; + if (FT_Get_Sfnt_Name(face, index, &nameRec) != 0) + continue; + switch (nameRec.name_id) { + case kFontFullName: + case kFontFamilyName: + case kFontStyleName: + case kPreferredFamilyName: + case kPreferredSubfamilyName: + { + bool preferredName = false; + if (nameRec.platform_id == TT_PLATFORM_MACINTOSH + && nameRec.encoding_id == TT_MAC_ID_ROMAN && nameRec.language_id == 0) { + utf8name = convertToUtf8(macRomanConv, nameRec.string, nameRec.string_len); + preferredName = true; + } + else if ((nameRec.platform_id == TT_PLATFORM_APPLE_UNICODE) + || (nameRec.platform_id == TT_PLATFORM_MICROSOFT)) + utf8name = convertToUtf8(utf16beConv, nameRec.string, nameRec.string_len); + + if (utf8name != NULL) { + std::list<std::string>* nameList = NULL; + switch (nameRec.name_id) { + case kFontFullName: + nameList = &names->fullNames; + break; + case kFontFamilyName: + nameList = &names->familyNames; + break; + case kFontStyleName: + nameList = &names->styleNames; + break; + case kPreferredFamilyName: + nameList = &familyNames; + break; + case kPreferredSubfamilyName: + nameList = &subFamilyNames; + break; + } + if (preferredName) + prependToList(nameList, utf8name); + else + appendToList(nameList, utf8name); + delete[] utf8name; + } + } + break; + } + } + if (familyNames.size() > 0) + names->familyNames = familyNames; + if (subFamilyNames.size() > 0) + names->styleNames = subFamilyNames; + } else { + index = 0; + while (FcPatternGetString(pat, FC_FULLNAME, index++, (FcChar8**)&name) == FcResultMatch) + appendToList(&names->fullNames, name); + index = 0; + while (FcPatternGetString(pat, FC_FAMILY, index++, (FcChar8**)&name) == FcResultMatch) + appendToList(&names->familyNames, name); + index = 0; + while (FcPatternGetString(pat, FC_STYLE, index++, (FcChar8**)&name) == FcResultMatch) + appendToList(&names->styleNames, name); + + if (names->fullNames.size() == 0) { + std::string fullName(names->familyNames.front()); + if (names->styleNames.size() > 0) { + fullName += " "; + fullName += names->styleNames.front(); + } + names->fullNames.push_back(fullName); + } + } + + FT_Done_Face(face); + + return names; } void XeTeXFontMgr_FC::getOpSizeRecAndStyleFlags(Font* theFont) { - XeTeXFontMgr::getOpSizeRecAndStyleFlags(theFont); - - if (theFont->weight == 0 && theFont->width == 0) { - // try to get values from FontConfig, as it apparently wasn't an sfnt - FcPattern* pat = theFont->fontRef; - int value; - if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &value) == FcResultMatch) - theFont->weight = value; - if (FcPatternGetInteger(pat, FC_WIDTH, 0, &value) == FcResultMatch) - theFont->width = value; - if (FcPatternGetInteger(pat, FC_SLANT, 0, &value) == FcResultMatch) - theFont->slant = value; - } + XeTeXFontMgr::getOpSizeRecAndStyleFlags(theFont); + + if (theFont->weight == 0 && theFont->width == 0) { + // try to get values from FontConfig, as it apparently wasn't an sfnt + FcPattern* pat = theFont->fontRef; + int value; + if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &value) == FcResultMatch) + theFont->weight = value; + if (FcPatternGetInteger(pat, FC_WIDTH, 0, &value) == FcResultMatch) + theFont->width = value; + if (FcPatternGetInteger(pat, FC_SLANT, 0, &value) == FcResultMatch) + theFont->slant = value; + } } void XeTeXFontMgr_FC::cacheFamilyMembers(const std::list<std::string>& familyNames) { - if (familyNames.size() == 0) - return; - for (int f = 0; f < allFonts->nfont; ++f) { - FcPattern* pat = allFonts->fonts[f]; - if (platformRefToFont.find(pat) != platformRefToFont.end()) - continue; - char* s; - for (int i = 0; FcPatternGetString(pat, FC_FAMILY, i, (FcChar8**)&s) == FcResultMatch; ++i) { - for (std::list<std::string>::const_iterator j = familyNames.begin(); j != familyNames.end(); ++j) { - if (*j == s) { - NameCollection* names = readNames(pat); - addToMaps(pat, names); - delete names; - goto cached; - } - } - } - cached: - ; - } + if (familyNames.size() == 0) + return; + for (int f = 0; f < allFonts->nfont; ++f) { + FcPattern* pat = allFonts->fonts[f]; + if (platformRefToFont.find(pat) != platformRefToFont.end()) + continue; + char* s; + for (int i = 0; FcPatternGetString(pat, FC_FAMILY, i, (FcChar8**)&s) == FcResultMatch; ++i) { + for (std::list<std::string>::const_iterator j = familyNames.begin(); j != familyNames.end(); ++j) { + if (*j == s) { + NameCollection* names = readNames(pat); + addToMaps(pat, names); + delete names; + goto cached; + } + } + } + cached: + ; + } } void XeTeXFontMgr_FC::searchForHostPlatformFonts(const std::string& name) { - if (cachedAll) // we've already loaded everything on an earlier search - return; - - std::string famName; - int hyph = name.find('-'); - if (hyph > 0 && hyph < name.length() - 1) - famName.assign(name.begin(), name.begin() + hyph); - else - hyph = 0; - - bool found = false; - while (1) { - for (int f = 0; f < allFonts->nfont; ++f) { - restart: - FcPattern* pat = allFonts->fonts[f]; - if (platformRefToFont.find(pat) != platformRefToFont.end()) - continue; - - if (cachedAll) { - // failed to find it via FC; add everything to our maps (potentially slow) as a last resort - NameCollection* names = readNames(pat); - addToMaps(pat, names); - delete names; - continue; - } - - char* s; - int i; - for (i = 0; FcPatternGetString(pat, FC_FULLNAME, i, (FcChar8**)&s) == FcResultMatch; ++i) { - if (name == s) { - NameCollection* names = readNames(pat); - addToMaps(pat, names); - cacheFamilyMembers(names->familyNames); - delete names; - found = true; - goto next_font; - } - } - - for (i = 0; FcPatternGetString(pat, FC_FAMILY, i, (FcChar8**)&s) == FcResultMatch; ++i) { - if (name == s || (hyph && famName == s)) { - NameCollection* names = readNames(pat); - addToMaps(pat, names); - cacheFamilyMembers(names->familyNames); - delete names; - found = true; - goto next_font; - } - char* t; - for (int j = 0; FcPatternGetString(pat, FC_STYLE, j, (FcChar8**)&t) == FcResultMatch; ++j) { - std::string full(s); - full += " "; - full += t; - if (name == full) { - NameCollection* names = readNames(pat); - addToMaps(pat, names); - cacheFamilyMembers(names->familyNames); - delete names; - found = true; - goto next_font; - } - } - } - - next_font: - ; - } - - if (found || cachedAll) - break; - cachedAll = true; - } + if (cachedAll) // we've already loaded everything on an earlier search + return; + + std::string famName; + int hyph = name.find('-'); + if (hyph > 0 && hyph < name.length() - 1) + famName.assign(name.begin(), name.begin() + hyph); + else + hyph = 0; + + bool found = false; + while (1) { + for (int f = 0; f < allFonts->nfont; ++f) { + restart: + FcPattern* pat = allFonts->fonts[f]; + if (platformRefToFont.find(pat) != platformRefToFont.end()) + continue; + + if (cachedAll) { + // failed to find it via FC; add everything to our maps (potentially slow) as a last resort + NameCollection* names = readNames(pat); + addToMaps(pat, names); + delete names; + continue; + } + + char* s; + int i; + for (i = 0; FcPatternGetString(pat, FC_FULLNAME, i, (FcChar8**)&s) == FcResultMatch; ++i) { + if (name == s) { + NameCollection* names = readNames(pat); + addToMaps(pat, names); + cacheFamilyMembers(names->familyNames); + delete names; + found = true; + goto next_font; + } + } + + for (i = 0; FcPatternGetString(pat, FC_FAMILY, i, (FcChar8**)&s) == FcResultMatch; ++i) { + if (name == s || (hyph && famName == s)) { + NameCollection* names = readNames(pat); + addToMaps(pat, names); + cacheFamilyMembers(names->familyNames); + delete names; + found = true; + goto next_font; + } + char* t; + for (int j = 0; FcPatternGetString(pat, FC_STYLE, j, (FcChar8**)&t) == FcResultMatch; ++j) { + std::string full(s); + full += " "; + full += t; + if (name == full) { + NameCollection* names = readNames(pat); + addToMaps(pat, names); + cacheFamilyMembers(names->familyNames); + delete names; + found = true; + goto next_font; + } + } + } + + next_font: + ; + } + + if (found || cachedAll) + break; + cachedAll = true; + } } void XeTeXFontMgr_FC::initialize() { - if (FcInit() == FcFalse) { - fprintf(stderr, "fontconfig initialization failed!\n"); - exit(9); - } - - if (gFreeTypeLibrary == 0 && FT_Init_FreeType(&gFreeTypeLibrary) != 0) { - fprintf(stderr, "FreeType initialization failed!\n"); - exit(9); - } - - UErrorCode err = U_ZERO_ERROR; - macRomanConv = ucnv_open("macintosh", &err); - utf16beConv = ucnv_open("UTF16BE", &err); - utf8Conv = ucnv_open("UTF8", &err); - if (err != 0) { - fprintf(stderr, "internal error; cannot read font names\n"); - exit(3); - } - - FcPattern* pat = FcNameParse((const FcChar8*)":outline=true"); - FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_FILE, FC_INDEX, - FC_FULLNAME, FC_WEIGHT, FC_WIDTH, FC_SLANT, FC_FONTFORMAT, NULL); - allFonts = FcFontList(FcConfigGetCurrent(), pat, os); - FcObjectSetDestroy(os); - FcPatternDestroy(pat); - - cachedAll = false; + if (FcInit() == FcFalse) { + fprintf(stderr, "fontconfig initialization failed!\n"); + exit(9); + } + + if (gFreeTypeLibrary == 0 && FT_Init_FreeType(&gFreeTypeLibrary) != 0) { + fprintf(stderr, "FreeType initialization failed!\n"); + exit(9); + } + + UErrorCode err = U_ZERO_ERROR; + macRomanConv = ucnv_open("macintosh", &err); + utf16beConv = ucnv_open("UTF16BE", &err); + utf8Conv = ucnv_open("UTF8", &err); + if (err != 0) { + fprintf(stderr, "internal error; cannot read font names\n"); + exit(3); + } + + FcPattern* pat = FcNameParse((const FcChar8*)":outline=true"); + FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_FILE, FC_INDEX, + FC_FULLNAME, FC_WEIGHT, FC_WIDTH, FC_SLANT, FC_FONTFORMAT, NULL); + allFonts = FcFontList(FcConfigGetCurrent(), pat, os); + FcObjectSetDestroy(os); + FcPatternDestroy(pat); + + cachedAll = false; } void XeTeXFontMgr_FC::terminate() { - if (macRomanConv != NULL) - ucnv_close(macRomanConv); - if (utf16beConv != NULL) - ucnv_close(utf16beConv); - if (utf8Conv != NULL) - ucnv_close(utf8Conv); + if (macRomanConv != NULL) + ucnv_close(macRomanConv); + if (utf16beConv != NULL) + ucnv_close(utf16beConv); + if (utf8Conv != NULL) + ucnv_close(utf8Conv); } std::string XeTeXFontMgr_FC::getPlatformFontDesc(PlatformFontRef font) const { - std::string path; - FcChar8* s; - if (FcPatternGetString(font, FC_FILE, 0, (FcChar8**)&s) == FcResultMatch) - path = (char*)s; - else - path = "[unknown]"; - return path; + std::string path; + FcChar8* s; + if (FcPatternGetString(font, FC_FILE, 0, (FcChar8**)&s) == FcResultMatch) + path = (char*)s; + else + path = "[unknown]"; + return path; } diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_FC.h b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_FC.h index 6187523027e..72889b3c971 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_FC.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_FC.h @@ -36,30 +36,30 @@ authorization from the copyright holders. #include "XeTeXFontMgr.h" class XeTeXFontMgr_FC - : public XeTeXFontMgr + : public XeTeXFontMgr { public: - XeTeXFontMgr_FC() - { } - virtual ~XeTeXFontMgr_FC() - { } + XeTeXFontMgr_FC() + { } + virtual ~XeTeXFontMgr_FC() + { } protected: - - virtual void initialize(); - virtual void terminate(); - virtual void getOpSizeRecAndStyleFlags(Font* theFont); - virtual void searchForHostPlatformFonts(const std::string& name); - - virtual NameCollection* readNames(FcPattern* pat); + virtual void initialize(); + virtual void terminate(); - std::string getPlatformFontDesc(PlatformFontRef font) const; - - void cacheFamilyMembers(const std::list<std::string>& familyNames); + virtual void getOpSizeRecAndStyleFlags(Font* theFont); + virtual void searchForHostPlatformFonts(const std::string& name); - FcFontSet* allFonts; - bool cachedAll; + virtual NameCollection* readNames(FcPattern* pat); + + std::string getPlatformFontDesc(PlatformFontRef font) const; + + void cacheFamilyMembers(const std::list<std::string>& familyNames); + + FcFontSet* allFonts; + bool cachedAll; }; -#endif /* __XETEX_FONT_MGR_FC_H */ +#endif /* __XETEX_FONT_MGR_FC_H */ diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Mac.h b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Mac.h index fe19cef7c97..f6f8a824a7d 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Mac.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Mac.h @@ -39,35 +39,35 @@ authorization from the copyright holders. #include <CoreFoundation/CoreFoundation.h> class XeTeXFontMgr_Mac - : public XeTeXFontMgr + : public XeTeXFontMgr { public: - XeTeXFontMgr_Mac() - { } - virtual ~XeTeXFontMgr_Mac() - { } + XeTeXFontMgr_Mac() + { } + virtual ~XeTeXFontMgr_Mac() + { } protected: - - virtual void initialize(); - virtual void terminate(); - virtual void searchForHostPlatformFonts(const std::string& name); - - virtual NameCollection* readNames(CTFontDescriptorRef fontRef); + virtual void initialize(); + virtual void terminate(); - virtual std::string getPlatformFontDesc(PlatformFontRef font) const; + virtual void searchForHostPlatformFonts(const std::string& name); + + virtual NameCollection* readNames(CTFontDescriptorRef fontRef); + + virtual std::string getPlatformFontDesc(PlatformFontRef font) const; private: - void addFontsToCaches(CFArrayRef fonts); + void addFontsToCaches(CFArrayRef fonts); - void addFamilyToCaches(CTFontDescriptorRef familyRef); + void addFamilyToCaches(CTFontDescriptorRef familyRef); - void addFontAndSiblingsToCaches(CTFontDescriptorRef fontRef); + void addFontAndSiblingsToCaches(CTFontDescriptorRef fontRef); - void appendNameToList(CTFontRef font, - std::list<std::string>* nameList, - CFStringRef nameKey); + void appendNameToList(CTFontRef font, + std::list<std::string>* nameList, + CFStringRef nameKey); }; -#endif /* __XETEX_FONT_MGR_MAC_H */ +#endif /* __XETEX_FONT_MGR_MAC_H */ diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Mac.mm b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Mac.mm index 6d818a0f386..92b11245a7e 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Mac.mm +++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr_Mac.mm @@ -45,168 +45,168 @@ extern "C" { CTFontDescriptorRef findFontWithName(CFStringRef name, CFStringRef key) { - CFStringRef keys[] = { key }; - CFTypeRef values[] = { name }; - CFDictionaryRef attributes = CFDictionaryCreate(NULL, (const void **) &keys, (const void **) &values, 1, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CTFontDescriptorRef descriptor = CTFontDescriptorCreateWithAttributes(attributes); - CFRelease(attributes); - - CFSetRef mandatoryAttributes = CFSetCreate(NULL, (const void **) &keys, 1, &kCFTypeSetCallBacks); - CFArrayRef matches = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, mandatoryAttributes); - CFRelease(mandatoryAttributes); - CFRelease(descriptor); - - CTFontDescriptorRef matched = NULL; - if (matches) { - if (CFArrayGetCount(matches)) { - matched = (CTFontDescriptorRef) CFArrayGetValueAtIndex(matches, 0); - CFRetain(matched); - } - CFRelease(matches); - } - return matched; + CFStringRef keys[] = { key }; + CFTypeRef values[] = { name }; + CFDictionaryRef attributes = CFDictionaryCreate(NULL, (const void **) &keys, (const void **) &values, 1, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CTFontDescriptorRef descriptor = CTFontDescriptorCreateWithAttributes(attributes); + CFRelease(attributes); + + CFSetRef mandatoryAttributes = CFSetCreate(NULL, (const void **) &keys, 1, &kCFTypeSetCallBacks); + CFArrayRef matches = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, mandatoryAttributes); + CFRelease(mandatoryAttributes); + CFRelease(descriptor); + + CTFontDescriptorRef matched = NULL; + if (matches) { + if (CFArrayGetCount(matches)) { + matched = (CTFontDescriptorRef) CFArrayGetValueAtIndex(matches, 0); + CFRetain(matched); + } + CFRelease(matches); + } + return matched; } void XeTeXFontMgr_Mac::appendNameToList(CTFontRef font, - std::list<std::string>* nameList, - CFStringRef nameKey) + std::list<std::string>* nameList, + CFStringRef nameKey) { - CFStringRef name = CTFontCopyName(font, nameKey); - if (name) { - appendToList(nameList, [(NSString *) name UTF8String]); - CFRelease(name); - } - CFStringRef language; - name = CTFontCopyLocalizedName(font, nameKey, &language); - if (name) { - appendToList(nameList, [(NSString *) name UTF8String]); - CFRelease(name); - } + CFStringRef name = CTFontCopyName(font, nameKey); + if (name) { + appendToList(nameList, [(NSString *) name UTF8String]); + CFRelease(name); + } + CFStringRef language; + name = CTFontCopyLocalizedName(font, nameKey, &language); + if (name) { + appendToList(nameList, [(NSString *) name UTF8String]); + CFRelease(name); + } } XeTeXFontMgr::NameCollection* XeTeXFontMgr_Mac::readNames(CTFontDescriptorRef fontRef) { - NameCollection* names = new NameCollection; + NameCollection* names = new NameCollection; - CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(fontRef, kCTFontNameAttribute); - if (!psName) - return names; + CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(fontRef, kCTFontNameAttribute); + if (!psName) + return names; - NSAutoreleasePool *pool = [NSAutoreleasePool new]; + NSAutoreleasePool *pool = [NSAutoreleasePool new]; - names->psName = [(NSString *) psName UTF8String]; - CFRelease(psName); + names->psName = [(NSString *) psName UTF8String]; + CFRelease(psName); - CTFontRef font = CTFontCreateWithFontDescriptor(fontRef, 0.0, 0); - appendNameToList(font, &names->fullNames, kCTFontFullNameKey); - appendNameToList(font, &names->familyNames, kCTFontFamilyNameKey); - appendNameToList(font, &names->styleNames, kCTFontStyleNameKey); - CFRelease(font); + CTFontRef font = CTFontCreateWithFontDescriptor(fontRef, 0.0, 0); + appendNameToList(font, &names->fullNames, kCTFontFullNameKey); + appendNameToList(font, &names->familyNames, kCTFontFamilyNameKey); + appendNameToList(font, &names->styleNames, kCTFontStyleNameKey); + CFRelease(font); - [pool release]; + [pool release]; - return names; + return names; } void XeTeXFontMgr_Mac::addFontsToCaches(CFArrayRef fonts) { - NSEnumerator* enumerator = [(NSArray*)fonts objectEnumerator]; - while (id aFont = [enumerator nextObject]) { - CTFontDescriptorRef fontRef = findFontWithName((CFStringRef)[aFont objectAtIndex: 0], kCTFontNameAttribute); - NameCollection* names = readNames(fontRef); - addToMaps(fontRef, names); - delete names; - } + NSEnumerator* enumerator = [(NSArray*)fonts objectEnumerator]; + while (id aFont = [enumerator nextObject]) { + CTFontDescriptorRef fontRef = findFontWithName((CFStringRef)[aFont objectAtIndex: 0], kCTFontNameAttribute); + NameCollection* names = readNames(fontRef); + addToMaps(fontRef, names); + delete names; + } } void XeTeXFontMgr_Mac::addFamilyToCaches(CTFontDescriptorRef familyRef) { - CFStringRef nameStr = (CFStringRef) CTFontDescriptorCopyAttribute(familyRef, kCTFontFamilyNameAttribute); - if (nameStr) { - NSArray* members = [[NSFontManager sharedFontManager] - availableMembersOfFontFamily: (NSString*)nameStr]; - CFRelease(nameStr); - addFontsToCaches((CFArrayRef)members); - } + CFStringRef nameStr = (CFStringRef) CTFontDescriptorCopyAttribute(familyRef, kCTFontFamilyNameAttribute); + if (nameStr) { + NSArray* members = [[NSFontManager sharedFontManager] + availableMembersOfFontFamily: (NSString*)nameStr]; + CFRelease(nameStr); + addFontsToCaches((CFArrayRef)members); + } } void XeTeXFontMgr_Mac::addFontAndSiblingsToCaches(CTFontDescriptorRef fontRef) { - CFStringRef name = (CFStringRef) CTFontDescriptorCopyAttribute(fontRef, kCTFontNameAttribute); - if (name) { - NSFont* font = [NSFont fontWithName:(NSString*)name size:10.0]; - CFRelease(name); - NSArray* members = [[NSFontManager sharedFontManager] - availableMembersOfFontFamily: [font familyName]]; - addFontsToCaches((CFArrayRef)members); - } + CFStringRef name = (CFStringRef) CTFontDescriptorCopyAttribute(fontRef, kCTFontNameAttribute); + if (name) { + NSFont* font = [NSFont fontWithName:(NSString*)name size:10.0]; + CFRelease(name); + NSArray* members = [[NSFontManager sharedFontManager] + availableMembersOfFontFamily: [font familyName]]; + addFontsToCaches((CFArrayRef)members); + } } void XeTeXFontMgr_Mac::searchForHostPlatformFonts(const std::string& name) { - // the name might be: - // FullName - // Family-Style (if there's a hyphen) - // PSName - // Family - // ...so we need to try it as each of these - - CFStringRef nameStr = CFStringCreateWithCString(kCFAllocatorDefault, name.c_str(), kCFStringEncodingUTF8); - CTFontDescriptorRef matched = findFontWithName(nameStr, kCTFontDisplayNameAttribute); - if (matched) { - // found it, so locate the family, and add all members to the caches - addFontAndSiblingsToCaches(matched); - CFRelease(matched); - return; - } - - int hyph = name.find('-'); - if (hyph > 0 && hyph < name.length() - 1) { - std::string family(name.begin(), name.begin() + hyph); - CFStringRef familyStr = CFStringCreateWithCString(kCFAllocatorDefault, family.c_str(), kCFStringEncodingUTF8); - - NSArray* familyMembers = [[NSFontManager sharedFontManager] - availableMembersOfFontFamily: (NSString*)familyStr]; - if ([familyMembers count] > 0) { - addFontsToCaches((CFArrayRef)familyMembers); - return; - } - - matched = findFontWithName(familyStr, kCTFontFamilyNameAttribute); - if (matched) { - addFamilyToCaches(matched); - CFRelease(matched); - return; - } - } - - matched = findFontWithName(nameStr, kCTFontNameAttribute); - if (matched) { - addFontAndSiblingsToCaches(matched); - CFRelease(matched); - return; - } - - NSArray* familyMembers = [[NSFontManager sharedFontManager] - availableMembersOfFontFamily: (NSString*)nameStr]; - if ([familyMembers count] > 0) { - addFontsToCaches((CFArrayRef)familyMembers); - return; - } - - matched = findFontWithName(nameStr, kCTFontFamilyNameAttribute); - if (matched) { - addFamilyToCaches(matched); - CFRelease(matched); - return; - } + // the name might be: + // FullName + // Family-Style (if there's a hyphen) + // PSName + // Family + // ...so we need to try it as each of these + + CFStringRef nameStr = CFStringCreateWithCString(kCFAllocatorDefault, name.c_str(), kCFStringEncodingUTF8); + CTFontDescriptorRef matched = findFontWithName(nameStr, kCTFontDisplayNameAttribute); + if (matched) { + // found it, so locate the family, and add all members to the caches + addFontAndSiblingsToCaches(matched); + CFRelease(matched); + return; + } + + int hyph = name.find('-'); + if (hyph > 0 && hyph < name.length() - 1) { + std::string family(name.begin(), name.begin() + hyph); + CFStringRef familyStr = CFStringCreateWithCString(kCFAllocatorDefault, family.c_str(), kCFStringEncodingUTF8); + + NSArray* familyMembers = [[NSFontManager sharedFontManager] + availableMembersOfFontFamily: (NSString*)familyStr]; + if ([familyMembers count] > 0) { + addFontsToCaches((CFArrayRef)familyMembers); + return; + } + + matched = findFontWithName(familyStr, kCTFontFamilyNameAttribute); + if (matched) { + addFamilyToCaches(matched); + CFRelease(matched); + return; + } + } + + matched = findFontWithName(nameStr, kCTFontNameAttribute); + if (matched) { + addFontAndSiblingsToCaches(matched); + CFRelease(matched); + return; + } + + NSArray* familyMembers = [[NSFontManager sharedFontManager] + availableMembersOfFontFamily: (NSString*)nameStr]; + if ([familyMembers count] > 0) { + addFontsToCaches((CFArrayRef)familyMembers); + return; + } + + matched = findFontWithName(nameStr, kCTFontFamilyNameAttribute); + if (matched) { + addFamilyToCaches(matched); + CFRelease(matched); + return; + } } NSAutoreleasePool* pool = NULL; @@ -214,44 +214,44 @@ NSAutoreleasePool* pool = NULL; void XeTeXFontMgr_Mac::initialize() { - pool = [[NSAutoreleasePool alloc] init]; + pool = [[NSAutoreleasePool alloc] init]; } void XeTeXFontMgr_Mac::terminate() { - if (pool != NULL) { - [pool release]; - } + if (pool != NULL) { + [pool release]; + } } std::string XeTeXFontMgr_Mac::getPlatformFontDesc(PlatformFontRef descriptor) const { - std::string path; - CTFontRef ctFont = CTFontCreateWithFontDescriptor(descriptor, 0.0, 0); - if (ctFont) { - CFURLRef url = NULL; + std::string path; + CTFontRef ctFont = CTFontCreateWithFontDescriptor(descriptor, 0.0, 0); + if (ctFont) { + CFURLRef url = NULL; #if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 - /* kCTFontURLAttribute was not avialable before 10.6 */ - FSRef fsref; - ATSFontRef atsFont = CTFontGetPlatformFont(ctFont, NULL); - OSStatus status = ATSFontGetFileReference(atsFont, &fsref); - if (status == noErr) - url = CFURLCreateFromFSRef(NULL, &fsref); + /* kCTFontURLAttribute was not avialable before 10.6 */ + FSRef fsref; + ATSFontRef atsFont = CTFontGetPlatformFont(ctFont, NULL); + OSStatus status = ATSFontGetFileReference(atsFont, &fsref); + if (status == noErr) + url = CFURLCreateFromFSRef(NULL, &fsref); #else - url = (CFURLRef) CTFontCopyAttribute(ctFont, kCTFontURLAttribute); + url = (CFURLRef) CTFontCopyAttribute(ctFont, kCTFontURLAttribute); #endif - if (url) { - UInt8 posixPath[PATH_MAX]; - if (CFURLGetFileSystemRepresentation(url, true, posixPath, PATH_MAX)) { - path = (char*)posixPath; - } - CFRelease(url); - } - CFRelease(ctFont); - } - if (path.length() == 0) - path = "[unknown]"; - return path; + if (url) { + UInt8 posixPath[PATH_MAX]; + if (CFURLGetFileSystemRepresentation(url, true, posixPath, PATH_MAX)) { + path = (char*)posixPath; + } + CFRelease(url); + } + CFRelease(ctFont); + } + if (path.length() == 0) + path = "[unknown]"; + return path; } diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp index 0e99efa88ec..dc1d1067f3e 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp @@ -39,10 +39,16 @@ extern "C" { } #endif -#include <unicode/platform.h> // We need this first +#include <unicode/platform.h> // We need this first #include <unicode/ubidi.h> #include <unicode/utext.h> +#include <graphite2/Font.h> +#include <graphite2/Segment.h> +#include <hb-graphite2.h> +#include <hb-icu.h> +#include <hb-ot.h> + #include "XeTeXLayoutInterface.h" #include "XeTeXFontInst.h" #ifdef XETEX_MAC @@ -50,21 +56,28 @@ extern "C" { #endif #include "XeTeXFontMgr.h" +typedef void* voidptr; + +extern "C" { + extern voidptr* fontlayoutengine; + extern integer* fontarea; +} + struct XeTeXLayoutEngine_rec { - XeTeXFontInst* font; - PlatformFontRef fontRef; - hb_tag_t script; - hb_tag_t language; - hb_feature_t* features; - char** ShaperList; // the requested shapers - char* shaper; // the actually used shaper - int nFeatures; - uint32_t rgbValue; - float extend; - float slant; - float embolden; - hb_buffer_t* hbBuffer; + XeTeXFontInst* font; + PlatformFontRef fontRef; + hb_tag_t script; + hb_language_t language; + hb_feature_t* features; + char** ShaperList; // the requested shapers + char* shaper; // the actually used shaper + int nFeatures; + uint32_t rgbValue; + float extend; + float slant; + float embolden; + hb_buffer_t* hbBuffer; }; /*******************************************************************/ @@ -74,815 +87,860 @@ struct XeTeXLayoutEngine_rec // key is combined value representing (font_id << 16) + glyph // value is glyph bounding box in TeX points -static std::map<uint32_t,GlyphBBox> sGlyphBoxes; +static std::map<uint32_t,GlyphBBox> sGlyphBoxes; int getCachedGlyphBBox(uint16_t fontID, uint16_t glyphID, GlyphBBox* bbox) { - uint32_t key = ((uint32_t)fontID << 16) + glyphID; - std::map<uint32_t,GlyphBBox>::const_iterator i = sGlyphBoxes.find(key); - if (i == sGlyphBoxes.end()) { - return 0; - } - *bbox = i->second; - return 1; + uint32_t key = ((uint32_t)fontID << 16) + glyphID; + std::map<uint32_t,GlyphBBox>::const_iterator i = sGlyphBoxes.find(key); + if (i == sGlyphBoxes.end()) { + return 0; + } + *bbox = i->second; + return 1; } void cacheGlyphBBox(uint16_t fontID, uint16_t glyphID, const GlyphBBox* bbox) { - uint32_t key = ((uint32_t)fontID << 16) + glyphID; - sGlyphBoxes[key] = *bbox; + uint32_t key = ((uint32_t)fontID << 16) + glyphID; + sGlyphBoxes[key] = *bbox; } /*******************************************************************/ void terminatefontmanager() { - XeTeXFontMgr::Terminate(); + XeTeXFontMgr::Terminate(); } XeTeXFont createFont(PlatformFontRef fontRef, Fixed pointSize) { - int status = 0; + int status = 0; #ifdef XETEX_MAC - XeTeXFontInst* font = new XeTeXFontInst_Mac(fontRef, Fix2D(pointSize), status); + XeTeXFontInst* font = new XeTeXFontInst_Mac(fontRef, Fix2D(pointSize), status); #else - FcChar8* pathname = 0; - FcPatternGetString(fontRef, FC_FILE, 0, &pathname); - int index; - FcPatternGetInteger(fontRef, FC_INDEX, 0, &index); - XeTeXFontInst* font = new XeTeXFontInst((const char*)pathname, index, Fix2D(pointSize), status); + FcChar8* pathname = 0; + FcPatternGetString(fontRef, FC_FILE, 0, &pathname); + int index; + FcPatternGetInteger(fontRef, FC_INDEX, 0, &index); + XeTeXFontInst* font = new XeTeXFontInst((const char*)pathname, index, Fix2D(pointSize), status); #endif - if (status != 0) { - delete font; - return NULL; - } - return (XeTeXFont)font; + if (status != 0) { + delete font; + return NULL; + } + return (XeTeXFont)font; } XeTeXFont createFontFromFile(const char* filename, int index, Fixed pointSize) { - int status = 0; - XeTeXFontInst* font = new XeTeXFontInst(filename, index, Fix2D(pointSize), status); - if (status != 0) { - delete font; - return NULL; - } - return (XeTeXFont)font; + int status = 0; + XeTeXFontInst* font = new XeTeXFontInst(filename, index, Fix2D(pointSize), status); + if (status != 0) { + delete font; + return NULL; + } + return (XeTeXFont)font; } void setFontLayoutDir(XeTeXFont font, int vertical) { - ((XeTeXFontInst*)font)->setLayoutDirVertical(vertical != 0); + ((XeTeXFontInst*)font)->setLayoutDirVertical(vertical != 0); } PlatformFontRef findFontByName(const char* name, char* var, double size) { - return (XeTeXFontMgr::GetFontManager()->findFont(name, var, size)); + return (XeTeXFontMgr::GetFontManager()->findFont(name, var, size)); } char getReqEngine() { - return XeTeXFontMgr::GetFontManager()->getReqEngine(); + return XeTeXFontMgr::GetFontManager()->getReqEngine(); } void setReqEngine(char reqEngine) { - XeTeXFontMgr::GetFontManager()->setReqEngine(reqEngine); + XeTeXFontMgr::GetFontManager()->setReqEngine(reqEngine); } const char* getFullName(PlatformFontRef fontRef) { - return XeTeXFontMgr::GetFontManager()->getFullName(fontRef); + return XeTeXFontMgr::GetFontManager()->getFullName(fontRef); } double getDesignSize(XeTeXFont font) { - return XeTeXFontMgr::GetFontManager()->getDesignSize(font); + return XeTeXFontMgr::GetFontManager()->getDesignSize(font); } const char* getFontFilename(XeTeXLayoutEngine engine) { - return engine->font->getFilename(); + return engine->font->getFilename(); } void getNames(PlatformFontRef fontRef, const char** psName, const char** famName, const char** styName) { - XeTeXFontMgr::GetFontManager()->getNames(fontRef, psName, famName, styName); + XeTeXFontMgr::GetFontManager()->getNames(fontRef, psName, famName, styName); } PlatformFontRef getFontRef(XeTeXLayoutEngine engine) { - return engine->fontRef; + return engine->fontRef; } void deleteFont(XeTeXFont font) { - delete (XeTeXFontInst*)font; + delete (XeTeXFontInst*)font; } void* getFontTablePtr(XeTeXFont font, uint32_t tableTag) { - return const_cast<void*>(((XeTeXFontInst*)font)->getFontTable(tableTag)); + return const_cast<void*>(((XeTeXFontInst*)font)->getFontTable(tableTag)); } Fixed getSlant(XeTeXFont font) { - float italAngle = ((XeTeXFontInst*)font)->getItalicAngle(); - return D2Fix(tan(-italAngle * M_PI / 180.0)); + float italAngle = ((XeTeXFontInst*)font)->getItalicAngle(); + return D2Fix(tan(-italAngle * M_PI / 180.0)); } static unsigned int getLargerScriptListTable(XeTeXFont font, hb_tag_t** scriptList) { - unsigned int rval = 0; + unsigned int rval = 0; - hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); - hb_tag_t* scriptListSub = NULL; - hb_tag_t* scriptListPos = NULL; + hb_tag_t* scriptListSub = NULL; + hb_tag_t* scriptListPos = NULL; - unsigned int scriptCountSub = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, NULL, NULL); - scriptListSub = (hb_tag_t*) xmalloc(scriptCountSub * sizeof(hb_tag_t*)); - hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCountSub, scriptListSub); + unsigned int scriptCountSub = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, NULL, NULL); + scriptListSub = (hb_tag_t*) xcalloc(scriptCountSub, sizeof(hb_tag_t*)); + hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCountSub, scriptListSub); - unsigned int scriptCountPos = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GPOS, 0, NULL, NULL); - scriptListPos = (hb_tag_t*) xmalloc(scriptCountPos * sizeof(hb_tag_t*)); - hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCountPos, scriptListPos); + unsigned int scriptCountPos = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GPOS, 0, NULL, NULL); + scriptListPos = (hb_tag_t*) xcalloc(scriptCountPos, sizeof(hb_tag_t*)); + hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCountPos, scriptListPos); - if (scriptCountSub > scriptCountPos) { - if (scriptList != NULL) - *scriptList = scriptListSub; - rval = scriptCountSub; - } else { - if (scriptList != NULL) - *scriptList = scriptListPos; - rval = scriptCountPos; - } + if (scriptCountSub > scriptCountPos) { + if (scriptList != NULL) + *scriptList = scriptListSub; + rval = scriptCountSub; + } else { + if (scriptList != NULL) + *scriptList = scriptListPos; + rval = scriptCountPos; + } - return rval; + return rval; } unsigned int countScripts(XeTeXFont font) { - return getLargerScriptListTable(font, NULL); + return getLargerScriptListTable(font, NULL); } hb_tag_t getIndScript(XeTeXFont font, unsigned int index) { - hb_tag_t rval = 0; + hb_tag_t rval = 0; - hb_tag_t* scriptList; + hb_tag_t* scriptList; - unsigned int scriptCount = getLargerScriptListTable(font, &scriptList); - if (scriptList != NULL) { - if (index < scriptCount) - rval = scriptList[index]; - } + unsigned int scriptCount = getLargerScriptListTable(font, &scriptList); + if (scriptList != NULL) { + if (index < scriptCount) + rval = scriptList[index]; + } - return rval; + return rval; } unsigned int countLanguages(XeTeXFont font, hb_tag_t script) { - unsigned int rval = 0; + unsigned int rval = 0; - hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); - hb_tag_t* scriptList; + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); + hb_tag_t* scriptList; - unsigned int scriptCount = getLargerScriptListTable(font, &scriptList); - if (scriptList != NULL) { - for (int i = 0; i < scriptCount; i++) { - if (scriptList[i] == script) { - rval += hb_ot_layout_script_get_language_tags (face, HB_OT_TAG_GSUB, i, 0, NULL, NULL); - rval += hb_ot_layout_script_get_language_tags (face, HB_OT_TAG_GPOS, i, 0, NULL, NULL); - break; - } - } - } + unsigned int scriptCount = getLargerScriptListTable(font, &scriptList); + if (scriptList != NULL) { + for (int i = 0; i < scriptCount; i++) { + if (scriptList[i] == script) { + rval += hb_ot_layout_script_get_language_tags (face, HB_OT_TAG_GSUB, i, 0, NULL, NULL); + rval += hb_ot_layout_script_get_language_tags (face, HB_OT_TAG_GPOS, i, 0, NULL, NULL); + break; + } + } + } - return rval; + return rval; } hb_tag_t getIndLanguage(XeTeXFont font, hb_tag_t script, unsigned int index) { - hb_tag_t rval = 0; + hb_tag_t rval = 0; - hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); - hb_tag_t* scriptList; + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); + hb_tag_t* scriptList; - unsigned int scriptCount = getLargerScriptListTable(font, &scriptList); - if (scriptList != NULL) { - for (int i = 0; i < scriptCount; i++) { - if (scriptList[i] == script) { - unsigned int langCount; - hb_tag_t* langList; + unsigned int scriptCount = getLargerScriptListTable(font, &scriptList); + if (scriptList != NULL) { + for (int i = 0; i < scriptCount; i++) { + if (scriptList[i] == script) { + unsigned int langCount; + hb_tag_t* langList; - langCount = hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, NULL, NULL); - langList = (hb_tag_t*) xcalloc(langCount, sizeof(hb_tag_t*)); - hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, &langCount, langList); + langCount = hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, NULL, NULL); + langList = (hb_tag_t*) xcalloc(langCount, sizeof(hb_tag_t*)); + hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, &langCount, langList); - if (index < langCount) { - rval = langList[index]; - break; - } + if (index < langCount) { + rval = langList[index]; + break; + } - free(langList); + free(langList); - langCount = hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GPOS, i, 0, NULL, NULL); - langList = (hb_tag_t*) xcalloc(langCount, sizeof(hb_tag_t*)); - hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GPOS, i, 0, &langCount, langList); + langCount = hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GPOS, i, 0, NULL, NULL); + langList = (hb_tag_t*) xcalloc(langCount, sizeof(hb_tag_t*)); + hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GPOS, i, 0, &langCount, langList); - if (index < langCount) { - rval = langList[index]; - break; - } + if (index < langCount) { + rval = langList[index]; + break; + } - free(langList); - } - } - } + free(langList); + } + } + } - return rval; + return rval; } unsigned int countFeatures(XeTeXFont font, hb_tag_t script, hb_tag_t language) { - unsigned int rval = 0; + unsigned int rval = 0; - hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); - for (int i = 0; i < 2; ++i) { - unsigned int scriptIndex, langIndex = 0; - hb_tag_t tableTag = i == 0 ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; - if (hb_ot_layout_table_find_script(face, tableTag, script, &scriptIndex)) { - if (hb_ot_layout_script_find_language(face, tableTag, scriptIndex, language, &langIndex) || language == 0) { - rval += hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, NULL, NULL); - } - } - } + for (int i = 0; i < 2; ++i) { + unsigned int scriptIndex, langIndex = 0; + hb_tag_t tableTag = i == 0 ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; + if (hb_ot_layout_table_find_script(face, tableTag, script, &scriptIndex)) { + if (hb_ot_layout_script_find_language(face, tableTag, scriptIndex, language, &langIndex) || language == 0) { + rval += hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, NULL, NULL); + } + } + } - return rval; + return rval; } hb_tag_t getIndFeature(XeTeXFont font, hb_tag_t script, hb_tag_t language, unsigned int index) { - hb_tag_t rval = 0; + hb_tag_t rval = 0; - hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); + hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); - for (int i = 0; i < 2; ++i) { - unsigned int scriptIndex, langIndex = 0; - hb_tag_t tableTag = i == 0 ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; - if (hb_ot_layout_table_find_script(face, tableTag, script, &scriptIndex)) { - if (hb_ot_layout_script_find_language(face, tableTag, scriptIndex, language, &langIndex) || language == 0) { - unsigned int featCount = hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, NULL, NULL); - hb_tag_t* featList = (hb_tag_t*) xmalloc(featCount * sizeof(hb_tag_t*)); - hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, &featCount, featList); + for (int i = 0; i < 2; ++i) { + unsigned int scriptIndex, langIndex = 0; + hb_tag_t tableTag = i == 0 ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; + if (hb_ot_layout_table_find_script(face, tableTag, script, &scriptIndex)) { + if (hb_ot_layout_script_find_language(face, tableTag, scriptIndex, language, &langIndex) || language == 0) { + unsigned int featCount = hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, NULL, NULL); + hb_tag_t* featList = (hb_tag_t*) xcalloc(featCount, sizeof(hb_tag_t*)); + hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, &featCount, featList); - if (index < featCount) { - rval = featList[index]; - break; - } + if (index < featCount) { + rval = featList[index]; + break; + } - index -= featCount; - } - } - } + index -= featCount; + } + } + } - return rval; + return rval; } uint32_t countGraphiteFeatures(XeTeXLayoutEngine engine) { - uint32_t rval = 0; + uint32_t rval = 0; - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) - rval = gr_face_n_fref(grFace); + if (grFace != NULL) + rval = gr_face_n_fref(grFace); - return rval; + return rval; } uint32_t getGraphiteFeatureCode(XeTeXLayoutEngine engine, uint32_t index) { - uint32_t rval = 0; + uint32_t rval = 0; - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) { - const gr_feature_ref* feature = gr_face_fref(grFace, index); - rval = gr_fref_id(feature); - } + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_fref(grFace, index); + rval = gr_fref_id(feature); + } - return rval; + return rval; } uint32_t countGraphiteFeatureSettings(XeTeXLayoutEngine engine, uint32_t featureID) { - uint32_t rval = 0; + uint32_t rval = 0; - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) { - const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); - rval = gr_fref_n_values(feature); - } + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + rval = gr_fref_n_values(feature); + } - return rval; + return rval; } uint32_t getGraphiteFeatureSettingCode(XeTeXLayoutEngine engine, uint32_t featureID, uint32_t index) { - uint32_t rval = 0; + uint32_t rval = 0; - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) { - const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); - rval = gr_fref_value(feature, index); - } + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + rval = gr_fref_value(feature, index); + } - return rval; + return rval; } +#define tag_from_lang(x) hb_tag_from_string(hb_language_to_string(x), strlen(hb_language_to_string(x))) + uint32_t getGraphiteFeatureDefaultSetting(XeTeXLayoutEngine engine, uint32_t featureID) { - uint32_t rval = 0; + uint32_t rval = 0; - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) { - const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); - gr_feature_val *featureValues = gr_face_featureval_for_lang (grFace, engine->language); + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + gr_feature_val *featureValues = gr_face_featureval_for_lang (grFace, tag_from_lang(engine->language)); - rval = gr_fref_feature_value(feature, featureValues); - } + rval = gr_fref_feature_value(feature, featureValues); + } - return rval; + return rval; } char * getGraphiteFeatureLabel(XeTeXLayoutEngine engine, uint32_t featureID) { - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) { - const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); - uint32_t len = 0; - uint16_t langID = 0x409; + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + uint32_t len = 0; + uint16_t langID = 0x409; - return (char *) gr_fref_label(feature, &langID, gr_utf8, &len); - } + return (char *) gr_fref_label(feature, &langID, gr_utf8, &len); + } - return NULL; + return NULL; } char * getGraphiteFeatureSettingLabel(XeTeXLayoutEngine engine, uint32_t featureID, uint32_t settingID) { - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) { - const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); - for (int i = 0; i < gr_fref_n_values(feature); i++) { - if (settingID == gr_fref_value(feature, i)) { - uint32_t len = 0; - uint16_t langID = 0x409; + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, featureID); + for (int i = 0; i < gr_fref_n_values(feature); i++) { + if (settingID == gr_fref_value(feature, i)) { + uint32_t len = 0; + uint16_t langID = 0x409; - return (char *) gr_fref_value_label(feature, i, &langID, gr_utf8, &len); - } - } - } + return (char *) gr_fref_value_label(feature, i, &langID, gr_utf8, &len); + } + } + } - return NULL; + return NULL; } bool findGraphiteFeature(XeTeXLayoutEngine engine, const char* s, const char* e, hb_tag_t* f, int* v) - /* s...e is a "feature=setting" string; look for this in the font */ + /* s...e is a "feature=setting" string; look for this in the font */ { - *f = 0; - *v = 0; - while (*s == ' ' || *s == '\t') - ++s; - const char* cp = s; - while (cp < e && *cp != '=') - ++cp; + *f = 0; + *v = 0; + while (*s == ' ' || *s == '\t') + ++s; + const char* cp = s; + while (cp < e && *cp != '=') + ++cp; - *f = findGraphiteFeatureNamed(engine, s, cp - s); - if (*f == -1) - return false; + *f = findGraphiteFeatureNamed(engine, s, cp - s); + if (*f == -1) + return false; - ++cp; - while (cp < e && (*cp == ' ' || *cp == '\t')) - ++cp; + ++cp; + while (cp < e && (*cp == ' ' || *cp == '\t')) + ++cp; - if (cp == e) - /* no setting was specified */ - return false; + if (cp == e) + /* no setting was specified */ + return false; - *v = findGraphiteFeatureSettingNamed(engine, *f, cp, e - cp); - if (*v == -1) - return false; + *v = findGraphiteFeatureSettingNamed(engine, *f, cp, e - cp); + if (*v == -1) + return false; - return true; + return true; } long findGraphiteFeatureNamed(XeTeXLayoutEngine engine, const char* name, int namelength) { - long rval = -1; + long rval = -1; - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) { - for (int i = 0; i < gr_face_n_fref(grFace); i++) { - const gr_feature_ref* feature = gr_face_fref(grFace, i); - uint32_t len = 0; - uint16_t langID = 0x409; + if (grFace != NULL) { + for (int i = 0; i < gr_face_n_fref(grFace); i++) { + const gr_feature_ref* feature = gr_face_fref(grFace, i); + uint32_t len = 0; + uint16_t langID = 0x409; - // the first call is to get the length of the string - gr_fref_label(feature, &langID, gr_utf8, &len); - char* label = (char*) xmalloc(len); - label = (char*) gr_fref_label(feature, &langID, gr_utf8, &len); + // the first call is to get the length of the string + gr_fref_label(feature, &langID, gr_utf8, &len); + char* label = (char*) xmalloc(len); + label = (char*) gr_fref_label(feature, &langID, gr_utf8, &len); - if (strncmp(label, name, namelength) == 0) { - rval = gr_fref_id(feature); - gr_label_destroy(label); - break; - } + if (strncmp(label, name, namelength) == 0) { + rval = gr_fref_id(feature); + gr_label_destroy(label); + break; + } - gr_label_destroy(label); - } - } + gr_label_destroy(label); + } + } - return rval; + return rval; } long findGraphiteFeatureSettingNamed(XeTeXLayoutEngine engine, uint32_t id, const char* name, int namelength) { - long rval = -1; + long rval = -1; - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - if (grFace != NULL) { - const gr_feature_ref* feature = gr_face_find_fref(grFace, id); - for (int i = 0; i < gr_fref_n_values(feature); i++) { - uint32_t len = 0; - uint16_t langID = 0x409; + if (grFace != NULL) { + const gr_feature_ref* feature = gr_face_find_fref(grFace, id); + for (int i = 0; i < gr_fref_n_values(feature); i++) { + uint32_t len = 0; + uint16_t langID = 0x409; - // the first call is to get the length of the string - gr_fref_value_label(feature, i, &langID, gr_utf8, &len); - char* label = (char*) xmalloc(len); - label = (char*) gr_fref_value_label(feature, i, &langID, gr_utf8, &len); + // the first call is to get the length of the string + gr_fref_value_label(feature, i, &langID, gr_utf8, &len); + char* label = (char*) xmalloc(len); + label = (char*) gr_fref_value_label(feature, i, &langID, gr_utf8, &len); - if (strncmp(label, name, namelength) == 0) { - rval = gr_fref_value(feature, i); - gr_label_destroy(label); - break; - } + if (strncmp(label, name, namelength) == 0) { + rval = gr_fref_value(feature, i); + gr_label_destroy(label); + break; + } - gr_label_destroy(label); - } - } + gr_label_destroy(label); + } + } - return rval; + return rval; } float getGlyphWidth(XeTeXFont font, uint32_t gid) { - return ((XeTeXFontInst*)font)->getGlyphWidth(gid); + return ((XeTeXFontInst*)font)->getGlyphWidth(gid); } unsigned int countGlyphs(XeTeXFont font) { - return ((XeTeXFontInst*)font)->getNumGlyphs(); + return ((XeTeXFontInst*)font)->getNumGlyphs(); } XeTeXFont getFont(XeTeXLayoutEngine engine) { - return (XeTeXFont)(engine->font); + return (XeTeXFont)(engine->font); } float getExtendFactor(XeTeXLayoutEngine engine) { - return engine->extend; + return engine->extend; } float getSlantFactor(XeTeXLayoutEngine engine) { - return engine->slant; + return engine->slant; } float getEmboldenFactor(XeTeXLayoutEngine engine) { - return engine->embolden; + return engine->embolden; } XeTeXLayoutEngine -createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, hb_tag_t script, hb_tag_t language, - hb_feature_t* features, int nFeatures, char **shapers, uint32_t rgbValue, - float extend, float slant, float embolden) -{ - XeTeXLayoutEngine result = new XeTeXLayoutEngine_rec; - result->fontRef = fontRef; - result->font = (XeTeXFontInst*)font; - result->script = script; - result->language = language; - result->features = features; - result->ShaperList = shapers; - result->shaper = NULL; - result->nFeatures = nFeatures; - result->rgbValue = rgbValue; - result->extend = extend; - result->slant = slant; - result->embolden = embolden; - result->hbBuffer = hb_buffer_create(); - - return result; +createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, hb_tag_t script, char *language, + hb_feature_t* features, int nFeatures, char **shapers, uint32_t rgbValue, + float extend, float slant, float embolden) +{ + XeTeXLayoutEngine result = new XeTeXLayoutEngine_rec; + result->fontRef = fontRef; + result->font = (XeTeXFontInst*)font; + result->script = script; + result->features = features; + result->ShaperList = shapers; + result->shaper = NULL; + result->nFeatures = nFeatures; + result->rgbValue = rgbValue; + result->extend = extend; + result->slant = slant; + result->embolden = embolden; + result->hbBuffer = hb_buffer_create(); + + // For Graphite fonts treat the language as BCP 47 tag, for OpenType we + // treat it as a OT language tag for backward compatibility with pre-0.9999 + // XeTeX. + if (getReqEngine() == 'G') + result->language = hb_language_from_string(language, -1); + else + result->language = hb_ot_tag_to_language(hb_tag_from_string(language, -1)); + + free(language); + + return result; } void deleteLayoutEngine(XeTeXLayoutEngine engine) { - hb_buffer_destroy(engine->hbBuffer); - delete engine->font; + hb_buffer_destroy(engine->hbBuffer); + delete engine->font; + free(engine->shaper); +} + +static unsigned int +_decompose_compat(hb_unicode_funcs_t* ufuncs, + hb_codepoint_t u, + hb_codepoint_t* decomposed, + void* user_data) +{ + return 0; +} + +static hb_unicode_funcs_t* +_get_unicode_funcs(void) +{ + static hb_unicode_funcs_t* ufuncs = hb_unicode_funcs_create(hb_icu_get_unicode_funcs()); + hb_unicode_funcs_set_decompose_compatibility_func(ufuncs, _decompose_compat, NULL, NULL); + return ufuncs; } +static hb_unicode_funcs_t* hbUnicodeFuncs = NULL; + int layoutChars(XeTeXLayoutEngine engine, uint16_t chars[], int32_t offset, int32_t count, int32_t max, - bool rightToLeft) -{ - bool res; - hb_script_t script = HB_SCRIPT_INVALID; - hb_language_t language = HB_LANGUAGE_INVALID; - hb_direction_t direction = HB_DIRECTION_LTR; - hb_segment_properties_t segment_props; - hb_shape_plan_t *shape_plan; - hb_font_t* hbFont = engine->font->getHbFont(); - hb_face_t* hbFace = hb_font_get_face(hbFont); - - if (engine->font->getLayoutDirVertical()) - direction = HB_DIRECTION_TTB; - else if (rightToLeft) - direction = HB_DIRECTION_RTL; - - script = hb_ot_tag_to_script (engine->script); - language = hb_ot_tag_to_language (engine->language); - - hb_buffer_reset(engine->hbBuffer); - hb_buffer_add_utf16(engine->hbBuffer, chars, max, offset, count); - hb_buffer_set_direction(engine->hbBuffer, direction); - hb_buffer_set_script(engine->hbBuffer, script); - hb_buffer_set_language(engine->hbBuffer, language); - - hb_buffer_guess_segment_properties(engine->hbBuffer); - hb_buffer_get_segment_properties(engine->hbBuffer, &segment_props); - - shape_plan = hb_shape_plan_create_cached(hbFace, &segment_props, engine->features, engine->nFeatures, engine->ShaperList); - res = hb_shape_plan_execute(shape_plan, hbFont, engine->hbBuffer, engine->features, engine->nFeatures); - - if (res) { - engine->shaper = strdup(hb_shape_plan_get_shaper(shape_plan)); - hb_buffer_set_content_type(engine->hbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); - } else { - // all selected shapers failed, retrying with default - // we don't use _cached here as the cached plain will always fail. - hb_shape_plan_destroy(shape_plan); - shape_plan = hb_shape_plan_create(hbFace, &segment_props, engine->features, engine->nFeatures, NULL); - res = hb_shape_plan_execute(shape_plan, hbFont, engine->hbBuffer, engine->features, engine->nFeatures); - - if (res) { - engine->shaper = strdup(hb_shape_plan_get_shaper(shape_plan)); - hb_buffer_set_content_type(engine->hbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); - } else { - fprintf(stderr, "\nERROR: all shapers failed\n"); - exit(3); - } - } + bool rightToLeft) +{ + bool res; + hb_script_t script = HB_SCRIPT_INVALID; + hb_direction_t direction = HB_DIRECTION_LTR; + hb_segment_properties_t segment_props; + hb_shape_plan_t *shape_plan; + hb_font_t* hbFont = engine->font->getHbFont(); + hb_face_t* hbFace = hb_font_get_face(hbFont); + + if (engine->font->getLayoutDirVertical()) + direction = HB_DIRECTION_TTB; + else if (rightToLeft) + direction = HB_DIRECTION_RTL; + + script = hb_ot_tag_to_script (engine->script); + + if (hbUnicodeFuncs == NULL) + hbUnicodeFuncs = _get_unicode_funcs(); + + hb_buffer_reset(engine->hbBuffer); + hb_buffer_set_unicode_funcs(engine->hbBuffer, hbUnicodeFuncs); + hb_buffer_add_utf16(engine->hbBuffer, chars, max, offset, count); + hb_buffer_set_direction(engine->hbBuffer, direction); + hb_buffer_set_script(engine->hbBuffer, script); + hb_buffer_set_language(engine->hbBuffer, engine->language); + + hb_buffer_guess_segment_properties(engine->hbBuffer); + hb_buffer_get_segment_properties(engine->hbBuffer, &segment_props); + + if (engine->ShaperList == NULL) { + // HarfBuzz gives graphite2 shaper a priority, so that for hybrid + // Graphite/OpenType fonts, Graphite will be used. However, pre-0.9999 + // XeTeX preferred OpenType over Graphite, so we are doing the same + // here for sake of backward compatibility. + engine->ShaperList = (char**) xcalloc(4, sizeof(char*)); + engine->ShaperList[0] = (char*) "ot"; + engine->ShaperList[1] = (char*) "graphite2"; + engine->ShaperList[2] = (char*) "fallback"; + engine->ShaperList[3] = NULL; + } - hb_shape_plan_destroy(shape_plan); + shape_plan = hb_shape_plan_create_cached(hbFace, &segment_props, engine->features, engine->nFeatures, engine->ShaperList); + res = hb_shape_plan_execute(shape_plan, hbFont, engine->hbBuffer, engine->features, engine->nFeatures); + + if (res) { + engine->shaper = strdup(hb_shape_plan_get_shaper(shape_plan)); + hb_buffer_set_content_type(engine->hbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); + } else { + // all selected shapers failed, retrying with default + // we don't use _cached here as the cached plain will always fail. + hb_shape_plan_destroy(shape_plan); + shape_plan = hb_shape_plan_create(hbFace, &segment_props, engine->features, engine->nFeatures, NULL); + res = hb_shape_plan_execute(shape_plan, hbFont, engine->hbBuffer, engine->features, engine->nFeatures); + + if (res) { + engine->shaper = strdup(hb_shape_plan_get_shaper(shape_plan)); + hb_buffer_set_content_type(engine->hbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); + } else { + fprintf(stderr, "\nERROR: all shapers failed\n"); + exit(3); + } + } + + hb_shape_plan_destroy(shape_plan); - int glyphCount = hb_buffer_get_length(engine->hbBuffer); + int glyphCount = hb_buffer_get_length(engine->hbBuffer); #ifdef DEBUG - char buf[1024]; - unsigned int consumed; + char buf[1024]; + unsigned int consumed; - printf ("shaper: %s\n", engine->shaper); + printf ("shaper: %s\n", engine->shaper); - hb_buffer_serialize_flags_t flags = HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; - hb_buffer_serialize_format_t format = HB_BUFFER_SERIALIZE_FORMAT_JSON; + hb_buffer_serialize_flags_t flags = HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; + hb_buffer_serialize_format_t format = HB_BUFFER_SERIALIZE_FORMAT_JSON; - hb_buffer_serialize_glyphs (engine->hbBuffer, 0, glyphCount, buf, sizeof(buf), &consumed, hbFont, format, flags); - if (consumed) - printf ("buffer glyphs: %s\n", buf); + hb_buffer_serialize_glyphs (engine->hbBuffer, 0, glyphCount, buf, sizeof(buf), &consumed, hbFont, format, flags); + if (consumed) + printf ("buffer glyphs: %s\n", buf); #endif - return glyphCount; + return glyphCount; } void getGlyphs(XeTeXLayoutEngine engine, uint32_t glyphs[]) { - int glyphCount = hb_buffer_get_length(engine->hbBuffer); - hb_glyph_info_t *hbGlyphs = hb_buffer_get_glyph_infos(engine->hbBuffer, NULL); + int glyphCount = hb_buffer_get_length(engine->hbBuffer); + hb_glyph_info_t *hbGlyphs = hb_buffer_get_glyph_infos(engine->hbBuffer, NULL); - for (int i = 0; i < glyphCount; i++) - glyphs[i] = hbGlyphs[i].codepoint; + for (int i = 0; i < glyphCount; i++) + glyphs[i] = hbGlyphs[i].codepoint; } void getGlyphAdvances(XeTeXLayoutEngine engine, float advances[]) { - int glyphCount = hb_buffer_get_length(engine->hbBuffer); - hb_glyph_position_t *hbPositions = hb_buffer_get_glyph_positions(engine->hbBuffer, NULL); + int glyphCount = hb_buffer_get_length(engine->hbBuffer); + hb_glyph_position_t *hbPositions = hb_buffer_get_glyph_positions(engine->hbBuffer, NULL); - for (int i = 0; i < glyphCount; i++) { - if (engine->font->getLayoutDirVertical()) - advances[i] = engine->font->unitsToPoints(hbPositions[i].y_advance); - else - advances[i] = engine->font->unitsToPoints(hbPositions[i].x_advance); - } + for (int i = 0; i < glyphCount; i++) { + if (engine->font->getLayoutDirVertical()) + advances[i] = engine->font->unitsToPoints(hbPositions[i].y_advance); + else + advances[i] = engine->font->unitsToPoints(hbPositions[i].x_advance); + } } void getGlyphPositions(XeTeXLayoutEngine engine, float positions[]) { - int glyphCount = hb_buffer_get_length(engine->hbBuffer); - hb_glyph_position_t *hbPositions = hb_buffer_get_glyph_positions(engine->hbBuffer, NULL); - - int i = 0; - float x = 0, y = 0; - - if (engine->font->getLayoutDirVertical()) { - for (i = 0; i < glyphCount; i++) { - positions[2*i] = - engine->font->unitsToPoints(x + hbPositions[i].y_offset); /* negative is forwards */ - positions[2*i+1] = engine->font->unitsToPoints(y - hbPositions[i].x_offset); - x += hbPositions[i].y_advance; - y += hbPositions[i].x_advance; - } - positions[2*i] = - engine->font->unitsToPoints(x); - positions[2*i+1] = engine->font->unitsToPoints(y); - } else { - for (i = 0; i < glyphCount; i++) { - positions[2*i] = engine->font->unitsToPoints(x + hbPositions[i].x_offset); - positions[2*i+1] = - engine->font->unitsToPoints(y + hbPositions[i].y_offset); /* negative is upwards */ - x += hbPositions[i].x_advance; - y += hbPositions[i].y_advance; - } - positions[2*i] = engine->font->unitsToPoints(x); - positions[2*i+1] = - engine->font->unitsToPoints(y); - } + int glyphCount = hb_buffer_get_length(engine->hbBuffer); + hb_glyph_position_t *hbPositions = hb_buffer_get_glyph_positions(engine->hbBuffer, NULL); + + int i = 0; + float x = 0, y = 0; + + if (engine->font->getLayoutDirVertical()) { + for (i = 0; i < glyphCount; i++) { + positions[2*i] = - engine->font->unitsToPoints(x + hbPositions[i].y_offset); /* negative is forwards */ + positions[2*i+1] = engine->font->unitsToPoints(y - hbPositions[i].x_offset); + x += hbPositions[i].y_advance; + y += hbPositions[i].x_advance; + } + positions[2*i] = - engine->font->unitsToPoints(x); + positions[2*i+1] = engine->font->unitsToPoints(y); + } else { + for (i = 0; i < glyphCount; i++) { + positions[2*i] = engine->font->unitsToPoints(x + hbPositions[i].x_offset); + positions[2*i+1] = - engine->font->unitsToPoints(y + hbPositions[i].y_offset); /* negative is upwards */ + x += hbPositions[i].x_advance; + y += hbPositions[i].y_advance; + } + positions[2*i] = engine->font->unitsToPoints(x); + positions[2*i+1] = - engine->font->unitsToPoints(y); + } - if (engine->extend != 1.0 || engine->slant != 0.0) - for (int i = 0; i <= glyphCount; ++i) - positions[2*i] = positions[2*i] * engine->extend - positions[2*i+1] * engine->slant; + if (engine->extend != 1.0 || engine->slant != 0.0) + for (int i = 0; i <= glyphCount; ++i) + positions[2*i] = positions[2*i] * engine->extend - positions[2*i+1] * engine->slant; } float getPointSize(XeTeXLayoutEngine engine) { - return engine->font->getPointSize(); + return engine->font->getPointSize(); } void getAscentAndDescent(XeTeXLayoutEngine engine, float* ascent, float* descent) { - *ascent = engine->font->getAscent(); - *descent = engine->font->getDescent(); + *ascent = engine->font->getAscent(); + *descent = engine->font->getDescent(); } void getCapAndXHeight(XeTeXLayoutEngine engine, float* capheight, float* xheight) { - *capheight = engine->font->getCapHeight(); - *xheight = engine->font->getXHeight(); + *capheight = engine->font->getCapHeight(); + *xheight = engine->font->getXHeight(); } int getDefaultDirection(XeTeXLayoutEngine engine) { - hb_script_t script = hb_buffer_get_script(engine->hbBuffer); - if (hb_script_get_horizontal_direction (script) == HB_DIRECTION_RTL) - return UBIDI_DEFAULT_RTL; - else - return UBIDI_DEFAULT_LTR; + hb_script_t script = hb_buffer_get_script(engine->hbBuffer); + if (hb_script_get_horizontal_direction (script) == HB_DIRECTION_RTL) + return UBIDI_DEFAULT_RTL; + else + return UBIDI_DEFAULT_LTR; } uint32_t getRgbValue(XeTeXLayoutEngine engine) { - return engine->rgbValue; + return engine->rgbValue; } void getGlyphBounds(XeTeXLayoutEngine engine, uint32_t glyphID, GlyphBBox* bbox) { - engine->font->getGlyphBounds(glyphID, bbox); - if (engine->extend != 0.0) { - bbox->xMin *= engine->extend; - bbox->xMax *= engine->extend; + engine->font->getGlyphBounds(glyphID, bbox); + if (engine->extend != 0.0) { + bbox->xMin *= engine->extend; + bbox->xMax *= engine->extend; } } float getGlyphWidthFromEngine(XeTeXLayoutEngine engine, uint32_t glyphID) { - return engine->extend * engine->font->getGlyphWidth(glyphID); + return engine->extend * engine->font->getGlyphWidth(glyphID); } void getGlyphHeightDepth(XeTeXLayoutEngine engine, uint32_t glyphID, float* height, float* depth) { - engine->font->getGlyphHeightDepth(glyphID, height, depth); + engine->font->getGlyphHeightDepth(glyphID, height, depth); } void getGlyphSidebearings(XeTeXLayoutEngine engine, uint32_t glyphID, float* lsb, float* rsb) { - engine->font->getGlyphSidebearings(glyphID, lsb, rsb); - if (engine->extend != 0.0) { - *lsb *= engine->extend; - *rsb *= engine->extend; - } + engine->font->getGlyphSidebearings(glyphID, lsb, rsb); + if (engine->extend != 0.0) { + *lsb *= engine->extend; + *rsb *= engine->extend; + } } float getGlyphItalCorr(XeTeXLayoutEngine engine, uint32_t glyphID) { - return engine->extend * engine->font->getGlyphItalCorr(glyphID); + return engine->extend * engine->font->getGlyphItalCorr(glyphID); } uint32_t mapCharToGlyph(XeTeXLayoutEngine engine, uint32_t charCode) { - return engine->font->mapCharToGlyph(charCode); + return engine->font->mapCharToGlyph(charCode); } int getFontCharRange(XeTeXLayoutEngine engine, int reqFirst) { - if (reqFirst) - return engine->font->getFirstCharCode(); - else - return engine->font->getLastCharCode(); + if (reqFirst) + return engine->font->getFirstCharCode(); + else + return engine->font->getLastCharCode(); } const char* getGlyphName(XeTeXFont font, uint16_t gid, int* len) { - return ((XeTeXFontInst*)font)->getGlyphName(gid, *len); + return ((XeTeXFontInst*)font)->getGlyphName(gid, *len); } int mapGlyphToIndex(XeTeXLayoutEngine engine, const char* glyphName) { - return engine->font->mapGlyphToIndex(glyphName); + return engine->font->mapGlyphToIndex(glyphName); } static gr_segment* grSegment = NULL; @@ -892,95 +950,110 @@ static int grTextLen; bool initGraphiteBreaking(XeTeXLayoutEngine engine, const uint16_t* txtPtr, int txtLen) { - hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); - gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); - gr_font* grFont = hb_graphite2_font_get_gr_font(engine->font->getHbFont()); - if (grFace != NULL && grFont != NULL) { - if (grSegment != NULL) { - gr_seg_destroy(grSegment); - grSegment = NULL; - grPrevSlot = NULL; - } - - gr_feature_val *grFeatureValues = gr_face_featureval_for_lang (grFace, engine->language); - - int nFeatures = engine->nFeatures; - hb_feature_t *features = engine->features; - while (nFeatures--) { - const gr_feature_ref *fref = gr_face_find_fref (grFace, features->tag); - if (fref) - gr_fref_set_feature_value (fref, features->value, grFeatureValues); - features++; - } - - grSegment = gr_make_seg(grFont, grFace, engine->script, grFeatureValues, gr_utf16, txtPtr, txtLen, 0); - grPrevSlot = gr_seg_first_slot(grSegment); - grTextLen = txtLen; - - return true; - } + hb_face_t* hbFace = hb_font_get_face(engine->font->getHbFont()); + gr_face* grFace = hb_graphite2_face_get_gr_face(hbFace); + gr_font* grFont = hb_graphite2_font_get_gr_font(engine->font->getHbFont()); + if (grFace != NULL && grFont != NULL) { + if (grSegment != NULL) { + gr_seg_destroy(grSegment); + grSegment = NULL; + grPrevSlot = NULL; + } + + gr_feature_val *grFeatureValues = gr_face_featureval_for_lang (grFace, tag_from_lang(engine->language)); + + int nFeatures = engine->nFeatures; + hb_feature_t *features = engine->features; + while (nFeatures--) { + const gr_feature_ref *fref = gr_face_find_fref (grFace, features->tag); + if (fref) + gr_fref_set_feature_value (fref, features->value, grFeatureValues); + features++; + } + + grSegment = gr_make_seg(grFont, grFace, engine->script, grFeatureValues, gr_utf16, txtPtr, txtLen, 0); + grPrevSlot = gr_seg_first_slot(grSegment); + grTextLen = txtLen; + + return true; + } - return false; + return false; } int findNextGraphiteBreak(void) { - int ret = -1; - - if (grSegment != NULL) { - if (grPrevSlot && grPrevSlot != gr_seg_last_slot(grSegment)) { - for (const gr_slot* s = gr_slot_next_in_segment(grPrevSlot); s != NULL; s = gr_slot_next_in_segment(s)) { - const gr_char_info* ci = NULL; - int bw; - - ci = gr_seg_cinfo(grSegment, gr_slot_index(s)); - bw = gr_cinfo_break_weight(ci); - if (bw < gr_breakNone && bw >= gr_breakBeforeWord) { - grPrevSlot = s; - ret = gr_cinfo_base(ci); - } else if (bw > gr_breakNone && bw <= gr_breakWord) { - grPrevSlot = gr_slot_next_in_segment(s); - ret = gr_cinfo_base(ci) + 1; - } - - if (ret != -1) - break; - } - - if (ret == -1) { - grPrevSlot = gr_seg_last_slot(grSegment); - ret = grTextLen; - } - } - } + int ret = -1; + + if (grSegment != NULL) { + if (grPrevSlot && grPrevSlot != gr_seg_last_slot(grSegment)) { + for (const gr_slot* s = gr_slot_next_in_segment(grPrevSlot); s != NULL; s = gr_slot_next_in_segment(s)) { + const gr_char_info* ci = NULL; + int bw; + + ci = gr_seg_cinfo(grSegment, gr_slot_index(s)); + bw = gr_cinfo_break_weight(ci); + if (bw < gr_breakNone && bw >= gr_breakBeforeWord) { + grPrevSlot = s; + ret = gr_cinfo_base(ci); + } else if (bw > gr_breakNone && bw <= gr_breakWord) { + grPrevSlot = gr_slot_next_in_segment(s); + ret = gr_cinfo_base(ci) + 1; + } + + if (ret != -1) + break; + } + + if (ret == -1) { + grPrevSlot = gr_seg_last_slot(grSegment); + ret = grTextLen; + } + } + } - return ret; + return ret; } bool -usingGraphite(XeTeXLayoutEngine engine) +usingGraphite(int font) { - if (engine->shaper != NULL && (strcmp("graphite2", engine->shaper) == 0)) - return true; - else - return false; + bool ret = false; + if (fontarea[font] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; + if (engine->shaper != NULL && (strcmp("graphite2", engine->shaper) == 0)) { + ret = true; + } + } + + return ret; } bool -usingOpenType(XeTeXLayoutEngine engine) +usingOpenType(int font) { - if (engine->shaper == NULL || (strcmp("ot", engine->shaper) == 0)) - return true; - else - return false; + bool ret = false; + if (fontarea[font] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; + if (engine->shaper == NULL || (strcmp("ot", engine->shaper) == 0)) { + ret = true; + } + } + + return ret; } bool -isOpenTypeMathFont(XeTeXLayoutEngine engine) +isOpenTypeMathFont(int font) { - if (engine->font->getMathTable() != NULL) - return true; - else - return false; + bool ret = false; + if (fontarea[font] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; + if (engine->font->getMathTable() != NULL) { + ret = true; + } + } + + return ret; } diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h index 4b2b8e2dde3..d7f598f8f58 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h @@ -48,12 +48,6 @@ typedef struct XeTeXLayoutEngine_rec* XeTeXLayoutEngine; #include FT_TRUETYPE_TABLES_H #include <hb.h> -#include <hb-ot.h> -#include <hb-icu.h> - -#include <graphite2/Font.h> -#include <graphite2/Segment.h> -#include <hb-graphite2.h> #include "XeTeX_ext.h" #include "XeTeXFontMgr.h" @@ -62,7 +56,7 @@ typedef struct XeTeXLayoutEngine_rec* XeTeXLayoutEngine; extern "C" { #endif -extern char gPrefEngine; +extern char gPrefEngine; int getCachedGlyphBBox(uint16_t fontID, uint16_t glyphID, GlyphBBox* bbox); void cacheGlyphBBox(uint16_t fontID, uint16_t glyphID, const GlyphBBox* bbox); @@ -102,9 +96,9 @@ hb_tag_t getIndFeature(XeTeXFont font, hb_tag_t script, hb_tag_t language, unsig float getGlyphWidth(XeTeXFont font, uint32_t gid); -XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, hb_tag_t script, hb_tag_t language, - hb_feature_t* features, int nFeatures, char **shapers, uint32_t rgbValue, - float extend, float slant, float embolden); +XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef, XeTeXFont font, hb_tag_t script, char *language, + hb_feature_t* features, int nFeatures, char **shapers, uint32_t rgbValue, + float extend, float slant, float embolden); void deleteLayoutEngine(XeTeXLayoutEngine engine); @@ -116,7 +110,7 @@ float getSlantFactor(XeTeXLayoutEngine engine); float getEmboldenFactor(XeTeXLayoutEngine engine); int layoutChars(XeTeXLayoutEngine engine, uint16_t* chars, int32_t offset, int32_t count, int32_t max, - bool rightToLeft); + bool rightToLeft); void getGlyphs(XeTeXLayoutEngine engine, uint32_t* glyphs); void getGlyphAdvances(XeTeXLayoutEngine engine, float *advances); @@ -143,7 +137,7 @@ float getGlyphItalCorr(XeTeXLayoutEngine engine, uint32_t glyphID); uint32_t mapCharToGlyph(XeTeXLayoutEngine engine, uint32_t charCode); -int mapGlyphToIndex(XeTeXLayoutEngine engine, const char* glyphName); +int mapGlyphToIndex(XeTeXLayoutEngine engine, const char* glyphName); const char* getGlyphName(XeTeXFont font, uint16_t gid, int* len); @@ -153,9 +147,9 @@ int getFontCharRange(XeTeXLayoutEngine engine, int reqFirst); bool initGraphiteBreaking(XeTeXLayoutEngine engine, const uint16_t* txtPtr, int txtLen); int findNextGraphiteBreak(void); -bool usingOpenType(XeTeXLayoutEngine engine); -bool usingGraphite(XeTeXLayoutEngine engine); -bool isOpenTypeMathFont(XeTeXLayoutEngine engine); +bool usingOpenType(int); +bool usingGraphite(int); +bool isOpenTypeMathFont(int); bool findGraphiteFeature(XeTeXLayoutEngine engine, const char* s, const char* e, hb_tag_t* f, int* v); diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTMath.cpp b/Build/source/texk/web2c/xetexdir/XeTeXOTMath.cpp index 3f43d6272c5..f66a23c6fe6 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXOTMath.cpp +++ b/Build/source/texk/web2c/xetexdir/XeTeXOTMath.cpp @@ -48,455 +48,455 @@ extern "C" { #include "XeTeXFontInst.h" #include "XeTeXswap.h" -typedef void* voidptr; +typedef void* voidptr; extern "C" { - extern voidptr* fontlayoutengine; - extern integer* fontarea; - extern integer* fontsize; + extern voidptr* fontlayoutengine; + extern integer* fontarea; + extern integer* fontsize; } static int32_t getCoverage(const Coverage* coverage, GlyphID g) { - if (SWAP(coverage->format) == 1) { - const CoverageFormat1 *table = (const CoverageFormat1 *) coverage; - for (int i = 0; i < SWAP(table->glyphCount); i++) { - if (SWAP(table->glyphArray[i]) == g) - return i; - } - } else if (SWAP(coverage->format) == 2) { - const CoverageFormat2 *table = (const CoverageFormat2 *) coverage; - for (int i = 0; i < SWAP(table->rangeCount); i++) { - if (SWAP(table->rangeArray[i].start) <= g && SWAP(table->rangeArray[i].end) >= g) - return SWAP(table->rangeArray[i].startCoverageIndex) + (g - SWAP(table->rangeArray[i].start)); - } - } - - return -1; + if (SWAP(coverage->format) == 1) { + const CoverageFormat1 *table = (const CoverageFormat1 *) coverage; + for (int i = 0; i < SWAP(table->glyphCount); i++) { + if (SWAP(table->glyphArray[i]) == g) + return i; + } + } else if (SWAP(coverage->format) == 2) { + const CoverageFormat2 *table = (const CoverageFormat2 *) coverage; + for (int i = 0; i < SWAP(table->rangeCount); i++) { + if (SWAP(table->rangeArray[i].start) <= g && SWAP(table->rangeArray[i].end) >= g) + return SWAP(table->rangeArray[i].startCoverageIndex) + (g - SWAP(table->rangeArray[i].start)); + } + } + + return -1; } static int16_t getMathConstant(XeTeXFontInst* fontInst, mathConstantIndex whichConstant) { - const char* table = fontInst->getMathTable(); - if (table == NULL) - return 0; - - const uint16_t* constants = (const uint16_t*)(table + SWAP(((const MathTableHeader*)table)->mathConstants)); - - if (whichConstant < firstMathValueRecord) { - /* it's a simple 16-bit value */ - return SWAP(constants[whichConstant]); - } - else if (whichConstant <= lastMathValueRecord) { - const MathValueRecord* valueRecords = (const MathValueRecord*) - ((char*)constants + firstMathValueRecord * sizeof(uint16_t) - firstMathValueRecord * sizeof(MathValueRecord)); - return SWAP(valueRecords[whichConstant].value); - } - else if (whichConstant <= lastMathConstant) { - return SWAP(constants[whichConstant + (lastMathValueRecord - firstMathValueRecord + 1)]); - } - else - return 0; /* or abort, with "internal error" or something */ + const char* table = fontInst->getMathTable(); + if (table == NULL) + return 0; + + const uint16_t* constants = (const uint16_t*)(table + SWAP(((const MathTableHeader*)table)->mathConstants)); + + if (whichConstant < firstMathValueRecord) { + /* it's a simple 16-bit value */ + return SWAP(constants[whichConstant]); + } + else if (whichConstant <= lastMathValueRecord) { + const MathValueRecord* valueRecords = (const MathValueRecord*) + ((char*)constants + firstMathValueRecord * sizeof(uint16_t) - firstMathValueRecord * sizeof(MathValueRecord)); + return SWAP(valueRecords[whichConstant].value); + } + else if (whichConstant <= lastMathConstant) { + return SWAP(constants[whichConstant + (lastMathValueRecord - firstMathValueRecord + 1)]); + } + else + return 0; /* or abort, with "internal error" or something */ } int get_ot_math_constant(int f, int n) { - int rval = 0; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - rval = getMathConstant(font, (mathConstantIndex)n); - /* scale according to font size, except the ones that are percentages */ - if (n > scriptScriptPercentScaleDown && n < radicalDegreeBottomRaisePercent) - rval = D2Fix(font->unitsToPoints(rval)); - } - return rval; + int rval = 0; + + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + rval = getMathConstant(font, (mathConstantIndex)n); + /* scale according to font size, except the ones that are percentages */ + if (n > scriptScriptPercentScaleDown && n < radicalDegreeBottomRaisePercent) + rval = D2Fix(font->unitsToPoints(rval)); + } + return rval; } /* fontdimen IDs for math symbols font (family 2) */ -#define math_x_height 5 -#define math_quad 6 -#define num1 8 /* numerator shift-up in display styles */ -#define num2 9 /* numerator shift-up in non-display, non-\.{\\atop} */ -#define num3 10 /* numerator shift-up in non-display \.{\\atop} */ -#define denom1 11 /* denominator shift-down in display styles */ -#define denom2 12 /* denominator shift-down in non-display styles */ -#define sup1 13 /* superscript shift-up in uncramped display style */ -#define sup2 14 /* superscript shift-up in uncramped non-display */ -#define sup3 15 /* superscript shift-up in cramped styles */ -#define sub1 16 /* subscript shift-down if superscript is absent */ -#define sub2 17 /* subscript shift-down if superscript is present */ -#define sup_drop 18 /* superscript baseline below top of large box */ -#define sub_drop 19 /* subscript baseline below bottom of large box */ -#define delim1 20 /* size of \.{\\atopwithdelims} delimiters */ -#define delim2 21 /* size of \.{\\atopwithdelims} delimiters in non-displays */ -#define axis_height 22 /* height of fraction lines above the baseline */ +#define math_x_height 5 +#define math_quad 6 +#define num1 8 /* numerator shift-up in display styles */ +#define num2 9 /* numerator shift-up in non-display, non-\.{\\atop} */ +#define num3 10 /* numerator shift-up in non-display \.{\\atop} */ +#define denom1 11 /* denominator shift-down in display styles */ +#define denom2 12 /* denominator shift-down in non-display styles */ +#define sup1 13 /* superscript shift-up in uncramped display style */ +#define sup2 14 /* superscript shift-up in uncramped non-display */ +#define sup3 15 /* superscript shift-up in cramped styles */ +#define sub1 16 /* subscript shift-down if superscript is absent */ +#define sub2 17 /* subscript shift-down if superscript is present */ +#define sup_drop 18 /* superscript baseline below top of large box */ +#define sub_drop 19 /* subscript baseline below bottom of large box */ +#define delim1 20 /* size of \.{\\atopwithdelims} delimiters */ +#define delim2 21 /* size of \.{\\atopwithdelims} delimiters in non-displays */ +#define axis_height 22 /* height of fraction lines above the baseline */ const mathConstantIndex TeX_sym_to_OT_map[] = { - unknown, - unknown, - unknown, - unknown, - unknown, - accentBaseHeight, // x-height - unknown, // quad - unknown, - fractionNumeratorDisplayStyleShiftUp, - fractionNumeratorShiftUp, - stackTopShiftUp, - fractionDenominatorDisplayStyleShiftDown, - fractionDenominatorShiftDown, - superscriptShiftUp, // ?? - superscriptShiftUp, // ?? - superscriptShiftUpCramped, - subscriptShiftDown, // ?? - subscriptShiftDown, // ?? - superscriptBaselineDropMax, // ?? - subscriptBaselineDropMin, // ?? - delimitedSubFormulaMinHeight, - unknown, // using quad instead for now - axisHeight + unknown, + unknown, + unknown, + unknown, + unknown, + accentBaseHeight, // x-height + unknown, // quad + unknown, + fractionNumeratorDisplayStyleShiftUp, + fractionNumeratorShiftUp, + stackTopShiftUp, + fractionDenominatorDisplayStyleShiftDown, + fractionDenominatorShiftDown, + superscriptShiftUp, // ?? + superscriptShiftUp, // ?? + superscriptShiftUpCramped, + subscriptShiftDown, // ?? + subscriptShiftDown, // ?? + superscriptBaselineDropMax, // ?? + subscriptBaselineDropMin, // ?? + delimitedSubFormulaMinHeight, + unknown, // using quad instead for now + axisHeight }; int get_native_mathsy_param(int f, int n) { - int rval = 0; - - if (n == math_quad || n == delim2) - rval = fontsize[f]; - else { - if (n < sizeof(TeX_sym_to_OT_map) / sizeof(mathConstantIndex)) { - mathConstantIndex ot_index = TeX_sym_to_OT_map[n]; - if (ot_index != unknown) - rval = get_ot_math_constant(f, (int)ot_index); - } - } -// fprintf(stderr, " math_sy(%d, %d) returns %.3f\n", f, n, Fix2D(rval)); - - return rval; + int rval = 0; + + if (n == math_quad || n == delim2) + rval = fontsize[f]; + else { + if (n < sizeof(TeX_sym_to_OT_map) / sizeof(mathConstantIndex)) { + mathConstantIndex ot_index = TeX_sym_to_OT_map[n]; + if (ot_index != unknown) + rval = get_ot_math_constant(f, (int)ot_index); + } + } +// fprintf(stderr, " math_sy(%d, %d) returns %.3f\n", f, n, Fix2D(rval)); + + return rval; } /* fontdimen IDs for math extension font (family 3) */ -#define default_rule_thickness 8 /* thickness of \.{\\over} bars */ -#define big_op_spacing1 9 /* minimum clearance above a displayed op */ -#define big_op_spacing2 10 /* minimum clearance below a displayed op */ -#define big_op_spacing3 11 /* minimum baselineskip above displayed op */ -#define big_op_spacing4 12 /* minimum baselineskip below displayed op */ -#define big_op_spacing5 13 /* padding above and below displayed limits */ +#define default_rule_thickness 8 /* thickness of \.{\\over} bars */ +#define big_op_spacing1 9 /* minimum clearance above a displayed op */ +#define big_op_spacing2 10 /* minimum clearance below a displayed op */ +#define big_op_spacing3 11 /* minimum baselineskip above displayed op */ +#define big_op_spacing4 12 /* minimum baselineskip below displayed op */ +#define big_op_spacing5 13 /* padding above and below displayed limits */ const mathConstantIndex TeX_ext_to_OT_map[] = { - unknown, - unknown, - unknown, - unknown, - unknown, - accentBaseHeight, // x-height - unknown, // quad - unknown, - fractionRuleThickness, // default_rule_thickness - upperLimitGapMin, // big_op_spacing1 - lowerLimitGapMin, // big_op_spacing2 - upperLimitBaselineRiseMin, // big_op_spacing3 - lowerLimitBaselineDropMin, // big_op_spacing4 - stackGapMin // big_op_spacing5 + unknown, + unknown, + unknown, + unknown, + unknown, + accentBaseHeight, // x-height + unknown, // quad + unknown, + fractionRuleThickness, // default_rule_thickness + upperLimitGapMin, // big_op_spacing1 + lowerLimitGapMin, // big_op_spacing2 + upperLimitBaselineRiseMin, // big_op_spacing3 + lowerLimitBaselineDropMin, // big_op_spacing4 + stackGapMin // big_op_spacing5 }; int get_native_mathex_param(int f, int n) { - int rval = 0; - - if (n == math_quad) - rval = fontsize[f]; - else { - if (n < sizeof(TeX_ext_to_OT_map) / sizeof(mathConstantIndex)) { - mathConstantIndex ot_index = TeX_ext_to_OT_map[n]; - if (ot_index != unknown) - rval = get_ot_math_constant(f, (int)ot_index); - } - } -// fprintf(stderr, " math_ex(%d, %d) returns %.3f\n", f, n, Fix2D(rval)); - - return rval; + int rval = 0; + + if (n == math_quad) + rval = fontsize[f]; + else { + if (n < sizeof(TeX_ext_to_OT_map) / sizeof(mathConstantIndex)) { + mathConstantIndex ot_index = TeX_ext_to_OT_map[n]; + if (ot_index != unknown) + rval = get_ot_math_constant(f, (int)ot_index); + } + } +// fprintf(stderr, " math_ex(%d, %d) returns %.3f\n", f, n, Fix2D(rval)); + + return rval; } int get_ot_math_variant(int f, int g, int v, integer* adv, int horiz) { - int rval = g; - *adv = -1; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - - const char* table = font->getMathTable(); - if (table == NULL) - return rval; - - uint16_t offset = SWAP(((const MathTableHeader*)table)->mathVariants); - if (offset == 0) - return rval; - const MathVariants* variants = (const MathVariants*)(table + offset); - - offset = horiz ? SWAP(variants->horizGlyphCoverage) : SWAP(variants->vertGlyphCoverage); - if (offset == 0) - return rval; - const Coverage* coverage = (const Coverage*)(((const char*)variants) + offset); - - int32_t index = getCoverage(coverage, g); - if (index >= 0) { - if (horiz) - index += SWAP(variants->vertGlyphCount); - const MathGlyphConstruction* construction = (const MathGlyphConstruction*)(((const char*)variants) - + SWAP(variants->vertGlyphConstruction[index])); - if (v < SWAP(construction->variantCount)) { - rval = SWAP(construction->mathGlyphVariantRecord[v].variantGlyph); - *adv = D2Fix(font->unitsToPoints(SWAP(construction->mathGlyphVariantRecord[v].advanceMeasurement))); - } - } - } - - return rval; + int rval = g; + *adv = -1; + + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = font->getMathTable(); + if (table == NULL) + return rval; + + uint16_t offset = SWAP(((const MathTableHeader*)table)->mathVariants); + if (offset == 0) + return rval; + const MathVariants* variants = (const MathVariants*)(table + offset); + + offset = horiz ? SWAP(variants->horizGlyphCoverage) : SWAP(variants->vertGlyphCoverage); + if (offset == 0) + return rval; + const Coverage* coverage = (const Coverage*)(((const char*)variants) + offset); + + int32_t index = getCoverage(coverage, g); + if (index >= 0) { + if (horiz) + index += SWAP(variants->vertGlyphCount); + const MathGlyphConstruction* construction = (const MathGlyphConstruction*)(((const char*)variants) + + SWAP(variants->vertGlyphConstruction[index])); + if (v < SWAP(construction->variantCount)) { + rval = SWAP(construction->mathGlyphVariantRecord[v].variantGlyph); + *adv = D2Fix(font->unitsToPoints(SWAP(construction->mathGlyphVariantRecord[v].advanceMeasurement))); + } + } + } + + return rval; } void* get_ot_assembly_ptr(int f, int g, int horiz) { - void* rval = NULL; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - - const char* table = font->getMathTable(); - if (table == NULL) - return rval; - - uint16_t offset = SWAP(((const MathTableHeader*)table)->mathVariants); - if (offset == 0) - return rval; - const MathVariants* variants = (const MathVariants*)(table + offset); - - offset = horiz ? SWAP(variants->horizGlyphCoverage) : SWAP(variants->vertGlyphCoverage); - if (offset == 0) - return rval; - const Coverage* coverage = (const Coverage*)(((const char*)variants) + offset); - - int32_t index = getCoverage(coverage, g); - if (index >= 0) { - if (horiz) - index += SWAP(variants->vertGlyphCount); - const MathGlyphConstruction* construction = (const MathGlyphConstruction*)(((const char*)variants) - + SWAP(variants->vertGlyphConstruction[index])); - offset = SWAP(construction->glyphAssembly); - if (offset != 0) - rval = (void*)(((const char*)construction) + offset); - } - } - - return rval; + void* rval = NULL; + + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = font->getMathTable(); + if (table == NULL) + return rval; + + uint16_t offset = SWAP(((const MathTableHeader*)table)->mathVariants); + if (offset == 0) + return rval; + const MathVariants* variants = (const MathVariants*)(table + offset); + + offset = horiz ? SWAP(variants->horizGlyphCoverage) : SWAP(variants->vertGlyphCoverage); + if (offset == 0) + return rval; + const Coverage* coverage = (const Coverage*)(((const char*)variants) + offset); + + int32_t index = getCoverage(coverage, g); + if (index >= 0) { + if (horiz) + index += SWAP(variants->vertGlyphCount); + const MathGlyphConstruction* construction = (const MathGlyphConstruction*)(((const char*)variants) + + SWAP(variants->vertGlyphConstruction[index])); + offset = SWAP(construction->glyphAssembly); + if (offset != 0) + rval = (void*)(((const char*)construction) + offset); + } + } + + return rval; } int get_ot_math_ital_corr(int f, int g) { - int rval = 0; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - - const char* table = font->getMathTable(); - if (table == NULL) - return rval; - - uint16_t offset = SWAP(((const MathTableHeader*)table)->mathGlyphInfo); - if (offset == 0) - return rval; - const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset); - - offset = SWAP(glyphInfo->mathItalicsCorrectionInfo); - if (offset == 0) - return rval; - const MathItalicsCorrectionInfo* italCorrInfo = (const MathItalicsCorrectionInfo*)(((const char*)glyphInfo) + offset); - - offset = SWAP(italCorrInfo->coverage); - if (offset == 0) - return rval; - const Coverage* coverage = (const Coverage*)(((const char*)italCorrInfo) + offset); - - int32_t index = getCoverage(coverage, g); - if (index >= 0 && index < SWAP(italCorrInfo->italicsCorrectionCount)) - rval = D2Fix(font->unitsToPoints(SWAP(italCorrInfo->italicsCorrection[index].value))); - } - - return rval; + int rval = 0; + + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = font->getMathTable(); + if (table == NULL) + return rval; + + uint16_t offset = SWAP(((const MathTableHeader*)table)->mathGlyphInfo); + if (offset == 0) + return rval; + const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset); + + offset = SWAP(glyphInfo->mathItalicsCorrectionInfo); + if (offset == 0) + return rval; + const MathItalicsCorrectionInfo* italCorrInfo = (const MathItalicsCorrectionInfo*)(((const char*)glyphInfo) + offset); + + offset = SWAP(italCorrInfo->coverage); + if (offset == 0) + return rval; + const Coverage* coverage = (const Coverage*)(((const char*)italCorrInfo) + offset); + + int32_t index = getCoverage(coverage, g); + if (index >= 0 && index < SWAP(italCorrInfo->italicsCorrectionCount)) + rval = D2Fix(font->unitsToPoints(SWAP(italCorrInfo->italicsCorrection[index].value))); + } + + return rval; } int get_ot_math_accent_pos(int f, int g) { - int rval = 0x7fffffffUL; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - - const char* table = font->getMathTable(); - if (table == NULL) - return rval; - - uint16_t offset = SWAP(((const MathTableHeader*)table)->mathGlyphInfo); - if (offset == 0) - return rval; - const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset); - - offset = SWAP(glyphInfo->mathTopAccentAttachment); - if (offset == 0) - return rval; - const MathTopAccentAttachment* accentAttachment = (const MathTopAccentAttachment*)(((const char*)glyphInfo) + offset); - - offset = SWAP(accentAttachment->coverage); - if (offset == 0) - return rval; - const Coverage* coverage = (const Coverage*)(((const char*)accentAttachment) + offset); - - int32_t index = getCoverage(coverage, g); - if (index >= 0 && index < SWAP(accentAttachment->topAccentAttachmentCount)) { - rval = (int16_t)SWAP(accentAttachment->topAccentAttachment[index].value); - rval = D2Fix(font->unitsToPoints(rval)); - } - } - - return rval; + int rval = 0x7fffffffUL; + + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = font->getMathTable(); + if (table == NULL) + return rval; + + uint16_t offset = SWAP(((const MathTableHeader*)table)->mathGlyphInfo); + if (offset == 0) + return rval; + const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset); + + offset = SWAP(glyphInfo->mathTopAccentAttachment); + if (offset == 0) + return rval; + const MathTopAccentAttachment* accentAttachment = (const MathTopAccentAttachment*)(((const char*)glyphInfo) + offset); + + offset = SWAP(accentAttachment->coverage); + if (offset == 0) + return rval; + const Coverage* coverage = (const Coverage*)(((const char*)accentAttachment) + offset); + + int32_t index = getCoverage(coverage, g); + if (index >= 0 && index < SWAP(accentAttachment->topAccentAttachmentCount)) { + rval = (int16_t)SWAP(accentAttachment->topAccentAttachment[index].value); + rval = D2Fix(font->unitsToPoints(rval)); + } + } + + return rval; } int ot_min_connector_overlap(int f) { - int rval = 0; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + int rval = 0; - const char* table = font->getMathTable(); - if (table == NULL) - return rval; + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - uint16_t offset = SWAP(((const MathTableHeader*)table)->mathVariants); - if (offset == 0) - return rval; - const MathVariants* variants = (const MathVariants*)(table + offset); + const char* table = font->getMathTable(); + if (table == NULL) + return rval; - rval = D2Fix(font->unitsToPoints(SWAP(variants->minConnectorOverlap))); - } + uint16_t offset = SWAP(((const MathTableHeader*)table)->mathVariants); + if (offset == 0) + return rval; + const MathVariants* variants = (const MathVariants*)(table + offset); - return rval; + rval = D2Fix(font->unitsToPoints(SWAP(variants->minConnectorOverlap))); + } + + return rval; } typedef enum { - topRight, - topLeft, - bottomRight, - bottomLeft, + topRight, + topLeft, + bottomRight, + bottomLeft, } MathKernSide; static int getMathKernAt(int f, int g, MathKernSide side, int height) { - int rval = 0; - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - - const char* table = font->getMathTable(); - if (table == NULL) - return rval; - - uint16_t offset = SWAP(((const MathTableHeader*)table)->mathGlyphInfo); - if (offset == 0) - return rval; - - const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset); - - offset = SWAP(glyphInfo->mathKernInfo); - if (offset == 0) - return rval; - - const MathKernInfo* mathKernInfo = (const MathKernInfo*)(((const char*)glyphInfo) + offset); - - offset = SWAP(mathKernInfo->coverage); - if (offset == 0) - return rval; - - const Coverage* coverage = (const Coverage*)(((const char*)mathKernInfo) + offset); - - int32_t index = getCoverage(coverage, g); - if (index >= 0 && index < SWAP(mathKernInfo->kernInfoCount)) { - if (side == topRight) - offset = SWAP(mathKernInfo->kernInfo[index].topRight); - else if (side == bottomRight) - offset = SWAP(mathKernInfo->kernInfo[index].bottomRight); - else if (side == topLeft) - offset = SWAP(mathKernInfo->kernInfo[index].topLeft); - else if (side == bottomLeft) - offset = SWAP(mathKernInfo->kernInfo[index].bottomLeft); - else - assert(0); // we should not reach here - - if (offset == 0) - return rval; - - const MathKernTable* kernTable = (const MathKernTable*)(((const char*)mathKernInfo) + offset); - - uint16_t count = SWAP(kernTable->heightCount); - - // XXX: the following makes no sense WRT my understanding of the - // spec! it is just how things worked for me. - if (count == 0) - rval = SWAP(kernTable->kern[-1].value); - else if (height < SWAP(kernTable->height[0].value)) - rval = SWAP(kernTable->kern[1].value); - else if (height > SWAP(kernTable->height[count].value)) - rval = SWAP(kernTable->kern[count+1].value); - else { - for (int i = 0; i < count; i++) { - if (height > SWAP(kernTable->height[i].value)) { - rval = SWAP(kernTable->kern[i+1].value); - break; - } - } - } - - //fprintf(stderr, " kern: %f %f\n", font->unitsToPoints(height), font->unitsToPoints(rval)); - } - } - - return rval; + int rval = 0; + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + + const char* table = font->getMathTable(); + if (table == NULL) + return rval; + + uint16_t offset = SWAP(((const MathTableHeader*)table)->mathGlyphInfo); + if (offset == 0) + return rval; + + const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset); + + offset = SWAP(glyphInfo->mathKernInfo); + if (offset == 0) + return rval; + + const MathKernInfo* mathKernInfo = (const MathKernInfo*)(((const char*)glyphInfo) + offset); + + offset = SWAP(mathKernInfo->coverage); + if (offset == 0) + return rval; + + const Coverage* coverage = (const Coverage*)(((const char*)mathKernInfo) + offset); + + int32_t index = getCoverage(coverage, g); + if (index >= 0 && index < SWAP(mathKernInfo->kernInfoCount)) { + if (side == topRight) + offset = SWAP(mathKernInfo->kernInfo[index].topRight); + else if (side == bottomRight) + offset = SWAP(mathKernInfo->kernInfo[index].bottomRight); + else if (side == topLeft) + offset = SWAP(mathKernInfo->kernInfo[index].topLeft); + else if (side == bottomLeft) + offset = SWAP(mathKernInfo->kernInfo[index].bottomLeft); + else + assert(0); // we should not reach here + + if (offset == 0) + return rval; + + const MathKernTable* kernTable = (const MathKernTable*)(((const char*)mathKernInfo) + offset); + + uint16_t count = SWAP(kernTable->heightCount); + + // XXX: the following makes no sense WRT my understanding of the + // spec! it is just how things worked for me. + if (count == 0) + rval = SWAP(kernTable->kern[-1].value); + else if (height < SWAP(kernTable->height[0].value)) + rval = SWAP(kernTable->kern[1].value); + else if (height > SWAP(kernTable->height[count].value)) + rval = SWAP(kernTable->kern[count+1].value); + else { + for (int i = 0; i < count; i++) { + if (height > SWAP(kernTable->height[i].value)) { + rval = SWAP(kernTable->kern[i+1].value); + break; + } + } + } + + //fprintf(stderr, " kern: %f %f\n", font->unitsToPoints(height), font->unitsToPoints(rval)); + } + } + + return rval; } static float glyph_height(int f, int g) { - float rval = 0.0; + float rval = 0.0; - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f]; - getGlyphHeightDepth(engine, g, &rval, NULL); - } + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f]; + getGlyphHeightDepth(engine, g, &rval, NULL); + } - return rval; + return rval; } static float glyph_depth(int f, int g) { - float rval = 0.0; + float rval = 0.0; - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f]; - getGlyphHeightDepth(engine, g, NULL, &rval); - } + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f]; + getGlyphHeightDepth(engine, g, NULL, &rval); + } - return rval; + return rval; } // keep in sync with xetex.web @@ -506,104 +506,104 @@ glyph_depth(int f, int g) int get_ot_math_kern(int f, int g, int sf, int sg, int cmd, int shift) { - int rval = 0; + int rval = 0; - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - int kern = 0, skern = 0; - float corr_height_top = 0.0, corr_height_bot = 0.0; + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + int kern = 0, skern = 0; + float corr_height_top = 0.0, corr_height_bot = 0.0; - shift = Fix2D(shift); + shift = Fix2D(shift); - if (cmd == sup_cmd) { // superscript - corr_height_top = font->pointsToUnits(glyph_height(f, g)); - corr_height_bot = -font->pointsToUnits(glyph_depth(sf, sg) + shift); + if (cmd == sup_cmd) { // superscript + corr_height_top = font->pointsToUnits(glyph_height(f, g)); + corr_height_bot = -font->pointsToUnits(glyph_depth(sf, sg) + shift); - kern = getMathKernAt(f, g, topRight, corr_height_top); - skern = getMathKernAt(sf, sg, bottomLeft, corr_height_top); - rval = kern + skern; + kern = getMathKernAt(f, g, topRight, corr_height_top); + skern = getMathKernAt(sf, sg, bottomLeft, corr_height_top); + rval = kern + skern; - kern = getMathKernAt(f, g, topRight, corr_height_bot); - skern = getMathKernAt(sf, sg, bottomLeft, corr_height_bot); - if ((kern + skern) < rval) - rval = kern + skern; + kern = getMathKernAt(f, g, topRight, corr_height_bot); + skern = getMathKernAt(sf, sg, bottomLeft, corr_height_bot); + if ((kern + skern) < rval) + rval = kern + skern; - } else if (cmd == sub_cmd) { // subscript - corr_height_top = font->pointsToUnits(glyph_height(sf, sg) - shift); - corr_height_bot = -font->pointsToUnits(glyph_depth(f, g)); + } else if (cmd == sub_cmd) { // subscript + corr_height_top = font->pointsToUnits(glyph_height(sf, sg) - shift); + corr_height_bot = -font->pointsToUnits(glyph_depth(f, g)); - kern = getMathKernAt(f, g, bottomRight, corr_height_top); - skern = getMathKernAt(sf, sg, topLeft, corr_height_top); - rval = kern + skern; + kern = getMathKernAt(f, g, bottomRight, corr_height_top); + skern = getMathKernAt(sf, sg, topLeft, corr_height_top); + rval = kern + skern; - kern = getMathKernAt(f, g, bottomRight, corr_height_bot); - skern = getMathKernAt(sf, sg, topLeft, corr_height_bot); - if ((kern + skern) < rval) - rval = kern + skern; + kern = getMathKernAt(f, g, bottomRight, corr_height_bot); + skern = getMathKernAt(sf, sg, topLeft, corr_height_bot); + if ((kern + skern) < rval) + rval = kern + skern; - } else { - assert(0); // we should not reach here - } + } else { + assert(0); // we should not reach here + } - rval = D2Fix(font->unitsToPoints(rval)); - } + rval = D2Fix(font->unitsToPoints(rval)); + } - return rval; + return rval; } int ot_part_count(const GlyphAssembly* a) { - return SWAP(a->partCount); + return SWAP(a->partCount); } int ot_part_glyph(const GlyphAssembly* a, int i) { - return SWAP(a->partRecords[i].glyph); + return SWAP(a->partRecords[i].glyph); } int ot_part_is_extender(const GlyphAssembly* a, int i) { - return (SWAP(a->partRecords[i].partFlags) & fExtender) != 0; + return (SWAP(a->partRecords[i].partFlags) & fExtender) != 0; } int ot_part_start_connector(int f, const GlyphAssembly* a, int i) { - int rval = 0; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - rval = D2Fix(font->unitsToPoints(SWAP(a->partRecords[i].startConnectorLength))); - } - - return rval; + int rval = 0; + + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + rval = D2Fix(font->unitsToPoints(SWAP(a->partRecords[i].startConnectorLength))); + } + + return rval; } int ot_part_end_connector(int f, const GlyphAssembly* a, int i) { - int rval = 0; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - rval = D2Fix(font->unitsToPoints(SWAP(a->partRecords[i].endConnectorLength))); - } - - return rval; + int rval = 0; + + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + rval = D2Fix(font->unitsToPoints(SWAP(a->partRecords[i].endConnectorLength))); + } + + return rval; } int ot_part_full_advance(int f, const GlyphAssembly* a, int i) { - int rval = 0; - - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); - rval = D2Fix(font->unitsToPoints(SWAP(a->partRecords[i].fullAdvance))); - } - - return rval; + int rval = 0; + + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXFontInst* font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]); + rval = D2Fix(font->unitsToPoints(SWAP(a->partRecords[i].fullAdvance))); + } + + return rval; } diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTMath.h b/Build/source/texk/web2c/xetexdir/XeTeXOTMath.h index 1304c84e76e..ba2cc873041 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeXOTMath.h +++ b/Build/source/texk/web2c/xetexdir/XeTeXOTMath.h @@ -40,21 +40,21 @@ authorization from the copyright holders. #ifdef __cplusplus extern "C" { #endif - int get_native_mathsy_param(int f, int n); - int get_native_mathex_param(int f, int n); - int get_ot_math_constant(int f, int n); - int get_ot_math_variant(int f, int g, int v, integer* adv, int horiz); - void* get_ot_assembly_ptr(int f, int g, int horiz); - int get_ot_math_ital_corr(int f, int g); - int get_ot_math_accent_pos(int f, int g); - int get_ot_math_kern(int f, int g, int sf, int sg, int cmd, int shift); - int ot_part_count(const GlyphAssembly* a); - int ot_part_glyph(const GlyphAssembly* a, int i); - int ot_part_is_extender(const GlyphAssembly* a, int i); - int ot_part_start_connector(int f, const GlyphAssembly* a, int i); - int ot_part_end_connector(int f, const GlyphAssembly* a, int i); - int ot_part_full_advance(int f, const GlyphAssembly* a, int i); - int ot_min_connector_overlap(int f); + int get_native_mathsy_param(int f, int n); + int get_native_mathex_param(int f, int n); + int get_ot_math_constant(int f, int n); + int get_ot_math_variant(int f, int g, int v, integer* adv, int horiz); + void* get_ot_assembly_ptr(int f, int g, int horiz); + int get_ot_math_ital_corr(int f, int g); + int get_ot_math_accent_pos(int f, int g); + int get_ot_math_kern(int f, int g, int sf, int sg, int cmd, int shift); + int ot_part_count(const GlyphAssembly* a); + int ot_part_glyph(const GlyphAssembly* a, int i); + int ot_part_is_extender(const GlyphAssembly* a, int i); + int ot_part_start_connector(int f, const GlyphAssembly* a, int i); + int ot_part_end_connector(int f, const GlyphAssembly* a, int i); + int ot_part_full_advance(int f, const GlyphAssembly* a, int i); + int ot_min_connector_overlap(int f); #ifdef __cplusplus }; #endif diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c index afbce0bd4f1..721ab678724 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c @@ -38,12 +38,10 @@ authorization from the copyright holders. #include <w2c/config.h> -#ifdef XETEX_OTHER -#include "poppler-config.h" -#include "png.h" -#endif - -#include "zlib.h" +#include <poppler-config.h> +#include <png.h> +#include <zlib.h> +#include <graphite2/Font.h> #ifdef _MSC_VER #undef timezone @@ -90,45 +88,45 @@ authorization from the copyright holders. #include <assert.h> -/* tables/values used in UTF-8 interpretation - +/* tables/values used in UTF-8 interpretation - code is based on ConvertUTF.[ch] sample code published by the Unicode consortium */ const uint32_t -offsetsFromUTF8[6] = { - 0x00000000UL, - 0x00003080UL, - 0x000E2080UL, - 0x03C82080UL, - 0xFA082080UL, - 0x82082080UL +offsetsFromUTF8[6] = { + 0x00000000UL, + 0x00003080UL, + 0x000E2080UL, + 0x03C82080UL, + 0xFA082080UL, + 0x82082080UL }; const uint8_t bytesFromUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; const uint8_t firstByteMark[7] = { - 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC + 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; -const int halfShift = 10; -const uint32_t halfBase = 0x0010000UL; -const uint32_t halfMask = 0x3FFUL; -const uint32_t kSurrogateHighStart = 0xD800UL; -const uint32_t kSurrogateHighEnd = 0xDBFFUL; -const uint32_t kSurrogateLowStart = 0xDC00UL; -const uint32_t kSurrogateLowEnd = 0xDFFFUL; -const uint32_t byteMask = 0x000000BFUL; -const uint32_t byteMark = 0x00000080UL; +const int halfShift = 10; +const uint32_t halfBase = 0x0010000UL; +const uint32_t halfMask = 0x3FFUL; +const uint32_t kSurrogateHighStart = 0xD800UL; +const uint32_t kSurrogateHighEnd = 0xDBFFUL; +const uint32_t kSurrogateLowStart = 0xDC00UL; +const uint32_t kSurrogateLowEnd = 0xDFFFUL; +const uint32_t byteMask = 0x000000BFUL; +const uint32_t byteMark = 0x00000080UL; /* if the user specifies a paper size or output driver program */ @@ -138,184 +136,184 @@ const char *outputdriver = "xdvipdfmx -q -E"; /* default to portable xdvipdfmx d void initversionstring(char **versions) { -#ifdef XETEX_OTHER - int fc_version = FcGetVersion(); +#ifndef XETEX_MAC + int fc_version = FcGetVersion(); #endif - FT_Int ftMajor, ftMinor, ftPatch; - int grMajor, grMinor, grBugfix; - UVersionInfo icuVersion; - char icu_version[U_MAX_VERSION_STRING_LENGTH] = ""; - - const_string fmt = - "Compiled with ICU version %s; using %s\n" - "Compiled with zlib version %s; using %s\n" - "Compiled with FreeType2 version %d.%d.%d; using %d.%d.%d\n" - "Compiled with Graphite2 version %d.%d.%d; using %d.%d.%d\n" - "Compiled with HarfBuzz version %s; using %s\n" + FT_Int ftMajor, ftMinor, ftPatch; + int grMajor, grMinor, grBugfix; + UVersionInfo icuVersion; + char icu_version[U_MAX_VERSION_STRING_LENGTH] = ""; + + const_string fmt = + "Compiled with ICU version %s; using %s\n" + "Compiled with zlib version %s; using %s\n" + "Compiled with FreeType2 version %d.%d.%d; using %d.%d.%d\n" + "Compiled with Graphite2 version %d.%d.%d; using %d.%d.%d\n" + "Compiled with HarfBuzz version %s; using %s\n" + "Compiled with libpng version %s; using %s\n" + "Compiled with poppler version %s\n" #ifdef XETEX_MAC - "Using Mac OS X Core Text, Cocoa & ImageIO frameworks\n" + "Using Mac OS X Core Text and Cocoa frameworks\n" #else - "Compiled with fontconfig version %d.%d.%d; using %d.%d.%d\n" - "Compiled with libpng version %s; using %s\n" - "Compiled with poppler version %s\n" + "Compiled with fontconfig version %d.%d.%d; using %d.%d.%d\n" #endif - ; - - int len = strlen(fmt) - + strlen(U_ICU_VERSION) - + strlen(icu_version) - + strlen(ZLIB_VERSION) - + strlen(zlib_version) - + strlen(HB_VERSION_STRING) - + strlen(hb_version_string()) -#ifdef XETEX_OTHER - + strlen(PNG_LIBPNG_VER_STRING) - + strlen(png_libpng_ver) - + strlen(POPPLER_VERSION) - + 6 * 3 /* for fontconfig version #s (won't really need 3 digits per field!) */ + ; + + int len = strlen(fmt) + + strlen(U_ICU_VERSION) + + strlen(icu_version) + + strlen(ZLIB_VERSION) + + strlen(zlib_version) + + strlen(HB_VERSION_STRING) + + strlen(hb_version_string()) + + strlen(PNG_LIBPNG_VER_STRING) + + strlen(png_libpng_ver) + + strlen(POPPLER_VERSION) +#ifndef XETEX_MAC + + 6 * 3 /* for fontconfig version #s (won't really need 3 digits per field!) */ #endif - + 6 * 3 /* for graphite2 version #s (ditto) */ - + 6 * 3; /* for freetype version #s (ditto) */ + + 6 * 3 /* for graphite2 version #s (ditto) */ + + 6 * 3; /* for freetype version #s (ditto) */ - *versions = xmalloc(len + 1); - /* len will be more than enough, because of the placeholder chars in fmt - that get replaced by the arguments */ + *versions = (char *) xmalloc(len + 1); + /* len will be more than enough, because of the placeholder chars in fmt + that get replaced by the arguments */ - u_getVersion(icuVersion); - u_versionToString(icuVersion, icu_version); + u_getVersion(icuVersion); + u_versionToString(icuVersion, icu_version); - if (gFreeTypeLibrary == 0 && FT_Init_FreeType(&gFreeTypeLibrary) != 0) { - fprintf(stderr, "FreeType initialization failed!\n"); - exit(9); - } - FT_Library_Version(gFreeTypeLibrary, &ftMajor, &ftMinor, &ftPatch); + if (gFreeTypeLibrary == 0 && FT_Init_FreeType(&gFreeTypeLibrary) != 0) { + fprintf(stderr, "FreeType initialization failed!\n"); + exit(9); + } + FT_Library_Version(gFreeTypeLibrary, &ftMajor, &ftMinor, &ftPatch); - gr_engine_version(&grMajor, &grMinor, &grBugfix); + gr_engine_version(&grMajor, &grMinor, &grBugfix); (void)sprintf(*versions, fmt, - U_ICU_VERSION, icu_version, - ZLIB_VERSION, zlib_version, - FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH, - ftMajor, ftMinor, ftPatch, - GR2_VERSION_MAJOR, GR2_VERSION_MINOR, GR2_VERSION_BUGFIX, - grMajor, grMinor, grBugfix, - HB_VERSION_STRING, hb_version_string() -#ifdef XETEX_OTHER - , - FC_VERSION / 10000, (FC_VERSION % 10000) / 100, FC_VERSION % 100, - fc_version / 10000, (fc_version % 10000) / 100, fc_version % 100, - PNG_LIBPNG_VER_STRING, png_libpng_ver, POPPLER_VERSION + U_ICU_VERSION, icu_version, + ZLIB_VERSION, zlib_version, + FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH, + ftMajor, ftMinor, ftPatch, + GR2_VERSION_MAJOR, GR2_VERSION_MINOR, GR2_VERSION_BUGFIX, + grMajor, grMinor, grBugfix, + HB_VERSION_STRING, hb_version_string(), + PNG_LIBPNG_VER_STRING, png_libpng_ver, POPPLER_VERSION +#ifndef XETEX_MAC + , + FC_VERSION / 10000, (FC_VERSION % 10000) / 100, FC_VERSION % 100, + fc_version / 10000, (fc_version % 10000) / 100, fc_version % 100 #endif - ); + ); } void setinputfileencoding(UFILE* f, integer mode, integer encodingData) { - if ((f->encodingMode == ICUMAPPING) && (f->conversionData != NULL)) - ucnv_close((UConverter*)(f->conversionData)); - f->conversionData = 0; - - switch (mode) { - case UTF8: - case UTF16BE: - case UTF16LE: - case RAW: - f->encodingMode = mode; - break; - - case ICUMAPPING: - { - char* name = gettexstring(encodingData); - UErrorCode err = 0; - UConverter* cnv = ucnv_open(name, &err); - if (cnv == NULL) { - begindiagnostic(); - printnl('E'); - printcstring("rror "); - printint(err); - printcstring(" creating Unicode converter for `"); - printcstring(name); - printcstring("'; reading as raw bytes"); - enddiagnostic(1); - f->encodingMode = RAW; - } else { - f->encodingMode = ICUMAPPING; - f->conversionData = cnv; - } - free(name); - } - break; - } + if ((f->encodingMode == ICUMAPPING) && (f->conversionData != NULL)) + ucnv_close((UConverter*)(f->conversionData)); + f->conversionData = 0; + + switch (mode) { + case UTF8: + case UTF16BE: + case UTF16LE: + case RAW: + f->encodingMode = mode; + break; + + case ICUMAPPING: + { + char* name = gettexstring(encodingData); + UErrorCode err = U_ZERO_ERROR; + UConverter* cnv = ucnv_open(name, &err); + if (cnv == NULL) { + begindiagnostic(); + printnl('E'); + printcstring("rror "); + printint(err); + printcstring(" creating Unicode converter for `"); + printcstring(name); + printcstring("'; reading as raw bytes"); + enddiagnostic(1); + f->encodingMode = RAW; + } else { + f->encodingMode = ICUMAPPING; + f->conversionData = cnv; + } + free(name); + } + break; + } } void uclose(UFILE* f) { - if (f != 0) { - fclose(f->f); - if ((f->encodingMode == ICUMAPPING) && (f->conversionData != NULL)) - ucnv_close((UConverter*)(f->conversionData)); - free((void*)f); - } + if (f != 0) { + fclose(f->f); + if ((f->encodingMode == ICUMAPPING) && (f->conversionData != NULL)) + ucnv_close((UConverter*)(f->conversionData)); + free((void*)f); + } } static void buffer_overflow() { - fprintf (stderr, "! Unable to read an entire line---bufsize=%u.\n", - (unsigned) bufsize); - fputs ("Please increase buf_size in texmf.cnf.\n", stderr); - uexit (1); + fprintf (stderr, "! Unable to read an entire line---bufsize=%u.\n", + (unsigned) bufsize); + fputs ("Please increase buf_size in texmf.cnf.\n", stderr); + uexit (1); } static void conversion_error(int errcode) { - begindiagnostic(); - printnl('U'); - printcstring("nicode conversion failed (ICU error code = "); - printint(errcode); - printcstring(") discarding any remaining text"); - enddiagnostic(1); + begindiagnostic(); + printnl('U'); + printcstring("nicode conversion failed (ICU error code = "); + printint(errcode); + printcstring(") discarding any remaining text"); + enddiagnostic(1); } #ifdef WORDS_BIGENDIAN -#define NATIVE_UTF32 kForm_UTF32BE +#define NATIVE_UTF32 kForm_UTF32BE #else -#define NATIVE_UTF32 kForm_UTF32LE +#define NATIVE_UTF32 kForm_UTF32LE #endif static void apply_normalization(uint32_t* buf, int len, int norm) { - static TECkit_Converter normalizers[2] = { NULL, NULL }; - - TECkit_Status status; - UInt32 inUsed, outUsed; - TECkit_Converter *normPtr = &normalizers[norm - 1]; - if (*normPtr == NULL) { - status = TECkit_CreateConverter(NULL, 0, 1, - NATIVE_UTF32, NATIVE_UTF32 | (norm == 1 ? kForm_NFC : kForm_NFD), - &*normPtr); - if (status != kStatus_NoError) { - fprintf(stderr, "! Failed to create normalizer: error code = %d\n", (int)status); - uexit (1); - } - } + static TECkit_Converter normalizers[2] = { NULL, NULL }; + + TECkit_Status status; + UInt32 inUsed, outUsed; + TECkit_Converter *normPtr = &normalizers[norm - 1]; + if (*normPtr == NULL) { + status = TECkit_CreateConverter(NULL, 0, 1, + NATIVE_UTF32, NATIVE_UTF32 | (norm == 1 ? kForm_NFC : kForm_NFD), + &*normPtr); + if (status != kStatus_NoError) { + fprintf(stderr, "! Failed to create normalizer: error code = %d\n", (int)status); + uexit (1); + } + } - status = TECkit_ConvertBuffer(*normPtr, (Byte*)buf, len * sizeof(UInt32), &inUsed, - (Byte*)&buffer[first], sizeof(*buffer) * (bufsize - first), &outUsed, 1); - if (status != kStatus_NoError) - buffer_overflow(); - last = first + outUsed / sizeof(*buffer); + status = TECkit_ConvertBuffer(*normPtr, (Byte*)buf, len * sizeof(UInt32), &inUsed, + (Byte*)&buffer[first], sizeof(*buffer) * (bufsize - first), &outUsed, 1); + if (status != kStatus_NoError) + buffer_overflow(); + last = first + outUsed / sizeof(*buffer); } #ifdef WORDS_BIGENDIAN -#define UCNV_UTF32_NativeEndian UCNV_UTF32_BigEndian +#define UCNV_UTF32_NativeEndian UCNV_UTF32_BigEndian #else -#define UCNV_UTF32_NativeEndian UCNV_UTF32_LittleEndian +#define UCNV_UTF32_NativeEndian UCNV_UTF32_LittleEndian #endif int @@ -323,267 +321,265 @@ input_line(UFILE* f) { static char* byteBuffer = NULL; static uint32_t *utf32Buf = NULL; - int i, tmpLen; - int norm = getinputnormalizationstate(); + int i, tmpLen; + int norm = getinputnormalizationstate(); #ifdef WIN32 - const int fd = fileno(f->f); - if (fd == _fileno(stdin) && _isatty(fd)) { - f->encodingMode = WIN32CONSOLE; - } + const int fd = fileno(f->f); + if (fd == _fileno(stdin) && _isatty(fd)) { + f->encodingMode = WIN32CONSOLE; + } #endif - last = first; - - if (f->encodingMode == ICUMAPPING) { - uint32_t bytesRead = 0; - UConverter* cnv; - int outLen; - UErrorCode errorCode = 0; - - if (byteBuffer == NULL) - byteBuffer = xmalloc(bufsize + 1); - - /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */ - i = getc(f->f); - if (f->skipNextLF) { - f->skipNextLF = 0; - if (i == '\n') - i = getc(f->f); - } - - if (i != EOF && i != '\n' && i != '\r') - byteBuffer[bytesRead++] = i; - if (i != EOF && i != '\n' && i != '\r') - while (bytesRead < bufsize && (i = getc(f->f)) != EOF && i != '\n' && i != '\r') - byteBuffer[bytesRead++] = i; - - if (i == EOF && errno != EINTR && bytesRead == 0) - return false; - - if (i != EOF && i != '\n' && i != '\r') - buffer_overflow(); - - /* now apply the mapping to turn external bytes into Unicode characters in buffer */ - cnv = (UConverter*)(f->conversionData); - switch (norm) { - case 1: // NFC - case 2: // NFD - if (utf32Buf == NULL) - utf32Buf = (uint32_t*)xmalloc(bufsize * sizeof(*utf32Buf)); - tmpLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv, - (char*)utf32Buf, bufsize * sizeof(*utf32Buf), - byteBuffer, bytesRead, &errorCode); - if (errorCode != 0) { - conversion_error((int)errorCode); - return false; - } - apply_normalization(utf32Buf, tmpLen / sizeof(*utf32Buf), norm); // sets 'last' correctly - break; - - default: // none - outLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv, - (char*)&buffer[first], sizeof(*buffer) * (bufsize - first), - byteBuffer, bytesRead, &errorCode); - if (errorCode != 0) { - conversion_error((int)errorCode); - return false; - } - outLen /= sizeof(*buffer); - last = first + outLen; - break; - } - } else { - /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */ - i = get_uni_c(f); - if (f->skipNextLF) { - f->skipNextLF = 0; - if (i == '\n') - i = get_uni_c(f); - } - - switch (norm) { - case 1: // NFC - case 2: // NFD - // read Unicode chars into utf32Buf as UTF32 - if (utf32Buf == NULL) - utf32Buf = xmalloc(bufsize * sizeof(*utf32Buf)); - tmpLen = 0; - if (i != EOF && i != '\n' && i != '\r') - utf32Buf[tmpLen++] = i; - if (i != EOF && i != '\n' && i != '\r') - while (tmpLen < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r') - utf32Buf[tmpLen++] = i; - - if (i == EOF && errno != EINTR && tmpLen == 0) - return false; - - /* We didn't get the whole line because our buffer was too small. */ - if (i != EOF && i != '\n' && i != '\r') - buffer_overflow(); - apply_normalization(utf32Buf, tmpLen, norm); - break; - - default: // none - if (last < bufsize && i != EOF && i != '\n' && i != '\r') - buffer[last++] = i; - if (i != EOF && i != '\n' && i != '\r') - while (last < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r') - buffer[last++] = i; - - if (i == EOF && errno != EINTR && last == first) - return false; - - /* We didn't get the whole line because our buffer was too small. */ - if (i != EOF && i != '\n' && i != '\r') - buffer_overflow(); - break; - } - } - - /* If line ended with CR, remember to skip following LF. */ - if (i == '\r') - f->skipNextLF = 1; - - buffer[last] = ' '; - if (last >= maxbufstack) - maxbufstack = last; - - /* Trim trailing whitespace. */ - while (last > first && ISBLANK(buffer[last - 1])) - --last; - - return true; + last = first; + + if (f->encodingMode == ICUMAPPING) { + uint32_t bytesRead = 0; + UConverter* cnv; + int outLen; + UErrorCode errorCode = U_ZERO_ERROR; + + if (byteBuffer == NULL) + byteBuffer = (char*) xmalloc(bufsize + 1); + + /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */ + i = getc(f->f); + if (f->skipNextLF) { + f->skipNextLF = 0; + if (i == '\n') + i = getc(f->f); + } + + if (i != EOF && i != '\n' && i != '\r') + byteBuffer[bytesRead++] = i; + if (i != EOF && i != '\n' && i != '\r') + while (bytesRead < bufsize && (i = getc(f->f)) != EOF && i != '\n' && i != '\r') + byteBuffer[bytesRead++] = i; + + if (i == EOF && errno != EINTR && bytesRead == 0) + return false; + + if (i != EOF && i != '\n' && i != '\r') + buffer_overflow(); + + /* now apply the mapping to turn external bytes into Unicode characters in buffer */ + cnv = (UConverter*)(f->conversionData); + switch (norm) { + case 1: // NFC + case 2: // NFD + if (utf32Buf == NULL) + utf32Buf = (uint32_t*) xcalloc(bufsize, sizeof(uint32_t)); + tmpLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv, + (char*)utf32Buf, bufsize * sizeof(*utf32Buf), + byteBuffer, bytesRead, &errorCode); + if (errorCode != 0) { + conversion_error((int)errorCode); + return false; + } + apply_normalization(utf32Buf, tmpLen / sizeof(*utf32Buf), norm); // sets 'last' correctly + break; + + default: // none + outLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv, + (char*)&buffer[first], sizeof(*buffer) * (bufsize - first), + byteBuffer, bytesRead, &errorCode); + if (errorCode != 0) { + conversion_error((int)errorCode); + return false; + } + outLen /= sizeof(*buffer); + last = first + outLen; + break; + } + } else { + /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */ + i = get_uni_c(f); + if (f->skipNextLF) { + f->skipNextLF = 0; + if (i == '\n') + i = get_uni_c(f); + } + + switch (norm) { + case 1: // NFC + case 2: // NFD + // read Unicode chars into utf32Buf as UTF32 + if (utf32Buf == NULL) + utf32Buf = (uint32_t*) xcalloc(bufsize, sizeof(uint32_t)); + tmpLen = 0; + if (i != EOF && i != '\n' && i != '\r') + utf32Buf[tmpLen++] = i; + if (i != EOF && i != '\n' && i != '\r') + while (tmpLen < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r') + utf32Buf[tmpLen++] = i; + + if (i == EOF && errno != EINTR && tmpLen == 0) + return false; + + /* We didn't get the whole line because our buffer was too small. */ + if (i != EOF && i != '\n' && i != '\r') + buffer_overflow(); + apply_normalization(utf32Buf, tmpLen, norm); + break; + + default: // none + if (last < bufsize && i != EOF && i != '\n' && i != '\r') + buffer[last++] = i; + if (i != EOF && i != '\n' && i != '\r') + while (last < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r') + buffer[last++] = i; + + if (i == EOF && errno != EINTR && last == first) + return false; + + /* We didn't get the whole line because our buffer was too small. */ + if (i != EOF && i != '\n' && i != '\r') + buffer_overflow(); + break; + } + } + + /* If line ended with CR, remember to skip following LF. */ + if (i == '\r') + f->skipNextLF = 1; + + buffer[last] = ' '; + if (last >= maxbufstack) + maxbufstack = last; + + /* Trim trailing whitespace. */ + while (last > first && ISBLANK(buffer[last - 1])) + --last; + + return true; } static void die(const_string s, int i) { - fprintf(stderr, s, i); - fprintf(stderr, " - exiting\n"); - exit(3); + fprintf(stderr, s, i); + fprintf(stderr, " - exiting\n"); + exit(3); } -static UBreakIterator* brkIter = NULL; -static int brkLocaleStrNum = 0; +static UBreakIterator* brkIter = NULL; +static int brkLocaleStrNum = 0; void linebreakstart(int f, integer localeStrNum, const uint16_t* text, integer textLength) { - UErrorCode status; - char* locale = (char*)gettexstring(localeStrNum); - - if (fontarea[f] == OTGR_FONT_FLAG && strcmp(locale, "G") == 0) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine) fontlayoutengine[f]; - if (initGraphiteBreaking(engine, text, textLength)) - /* user asked for Graphite line breaking and the font supports it */ - return; - } - - status = 0; - - if ((localeStrNum != brkLocaleStrNum) && (brkIter != NULL)) { - ubrk_close(brkIter); - brkIter = NULL; - } - - if (brkIter == NULL) { - brkIter = ubrk_open(UBRK_LINE, locale, NULL, 0, &status); - if (U_FAILURE(status)) { - begindiagnostic(); - printnl('E'); - printcstring("rror "); - printint(status); - printcstring(" creating linebreak iterator for locale `"); - printcstring(locale); - printcstring("'; trying default locale `en_us'."); - enddiagnostic(1); - if (brkIter != NULL) - ubrk_close(brkIter); - status = 0; - brkIter = ubrk_open(UBRK_LINE, "en_us", NULL, 0, &status); - } - free(locale); - brkLocaleStrNum = localeStrNum; - } - - if (brkIter == NULL) { - die("! failed to create linebreak iterator, status=%d", (int)status); - } - - ubrk_setText(brkIter, text, textLength, &status); + UErrorCode status = U_ZERO_ERROR; + char* locale = (char*)gettexstring(localeStrNum); + + if (fontarea[f] == OTGR_FONT_FLAG && strcmp(locale, "G") == 0) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine) fontlayoutengine[f]; + if (initGraphiteBreaking(engine, text, textLength)) + /* user asked for Graphite line breaking and the font supports it */ + return; + } + + if ((localeStrNum != brkLocaleStrNum) && (brkIter != NULL)) { + ubrk_close(brkIter); + brkIter = NULL; + } + + if (brkIter == NULL) { + brkIter = ubrk_open(UBRK_LINE, locale, NULL, 0, &status); + if (U_FAILURE(status)) { + begindiagnostic(); + printnl('E'); + printcstring("rror "); + printint(status); + printcstring(" creating linebreak iterator for locale `"); + printcstring(locale); + printcstring("'; trying default locale `en_us'."); + enddiagnostic(1); + if (brkIter != NULL) + ubrk_close(brkIter); + status = U_ZERO_ERROR; + brkIter = ubrk_open(UBRK_LINE, "en_us", NULL, 0, &status); + } + free(locale); + brkLocaleStrNum = localeStrNum; + } + + if (brkIter == NULL) { + die("! failed to create linebreak iterator, status=%d", (int)status); + } + + ubrk_setText(brkIter, (UChar*) text, textLength, &status); } int linebreaknext() { - if (brkIter != NULL) - return ubrk_next((UBreakIterator*)brkIter); - else - return findNextGraphiteBreak(); + if (brkIter != NULL) + return ubrk_next((UBreakIterator*)brkIter); + else + return findNextGraphiteBreak(); } int getencodingmodeandinfo(integer* info) { - /* \XeTeXinputencoding "enc-name" - * -> name is packed in |nameoffile| as a C string, starting at [1] - * Check if it's a built-in name; if not, try to open an ICU converter by that name - */ - UErrorCode err = 0; - UConverter* cnv; - char* name = (char*)nameoffile + 1; - *info = 0; - if (strcasecmp(name, "auto") == 0) { - return AUTO; - } - if (strcasecmp(name, "utf8") == 0) { - return UTF8; - } - if (strcasecmp(name, "utf16") == 0) { /* depends on host platform */ + /* \XeTeXinputencoding "enc-name" + * -> name is packed in |nameoffile| as a C string, starting at [1] + * Check if it's a built-in name; if not, try to open an ICU converter by that name + */ + UErrorCode err = U_ZERO_ERROR; + UConverter* cnv; + char* name = (char*)nameoffile + 1; + *info = 0; + if (strcasecmp(name, "auto") == 0) { + return AUTO; + } + if (strcasecmp(name, "utf8") == 0) { + return UTF8; + } + if (strcasecmp(name, "utf16") == 0) { /* depends on host platform */ #ifdef WORDS_BIGENDIAN - return UTF16BE; + return UTF16BE; #else - return UTF16LE; + return UTF16LE; #endif - } - if (strcasecmp(name, "utf16be") == 0) { - return UTF16BE; - } - if (strcasecmp(name, "utf16le") == 0) { - return UTF16LE; - } - if (strcasecmp(name, "bytes") == 0) { - return RAW; - } - - /* try for an ICU converter */ - cnv = ucnv_open(name, &err); - if (cnv == NULL) { - begindiagnostic(); - printnl('U'); /* ensure message starts on a new line */ - printcstring("nknown encoding `"); - printcstring(name); - printcstring("'; reading as raw bytes"); - enddiagnostic(1); - return RAW; - } else { - ucnv_close(cnv); - *info = maketexstring(name); - return ICUMAPPING; - } + } + if (strcasecmp(name, "utf16be") == 0) { + return UTF16BE; + } + if (strcasecmp(name, "utf16le") == 0) { + return UTF16LE; + } + if (strcasecmp(name, "bytes") == 0) { + return RAW; + } + + /* try for an ICU converter */ + cnv = ucnv_open(name, &err); + if (cnv == NULL) { + begindiagnostic(); + printnl('U'); /* ensure message starts on a new line */ + printcstring("nknown encoding `"); + printcstring(name); + printcstring("'; reading as raw bytes"); + enddiagnostic(1); + return RAW; + } else { + ucnv_close(cnv); + *info = maketexstring(name); + return ICUMAPPING; + } } void printutf8str(const unsigned char* str, int len) { - while (len-- > 0) - printrawchar(*(str++), true); /* bypass utf-8 encoding done in print_char() */ + while (len-- > 0) + printrawchar(*(str++), true); /* bypass utf-8 encoding done in print_char() */ } void printchars(const unsigned short* str, int len) { - while (len-- > 0) - printchar(*(str++)); + while (len-- > 0) + printchar(*(str++)); } #ifdef WORDS_BIGENDIAN @@ -595,1728 +591,1737 @@ printchars(const unsigned short* str, int len) static void* load_mapping_file(const char* s, const char* e, char byteMapping) { - char* mapPath; - TECkit_Converter cnv = 0; - char* buffer = xmalloc(e - s + 5); - strncpy(buffer, s, e - s); - buffer[e - s] = 0; - strcat(buffer, ".tec"); - mapPath = kpse_find_file(buffer, kpse_miscfonts_format, 1); - - if (mapPath) { - FILE* mapFile = fopen(mapPath, FOPEN_RBIN_MODE); - free(mapPath); - if (mapFile) { - uint32_t mappingSize; - Byte* mapping; - TECkit_Status status; - fseek(mapFile, 0, SEEK_END); - mappingSize = ftell(mapFile); - fseek(mapFile, 0, SEEK_SET); - mapping = xmalloc(mappingSize); - fread(mapping, 1, mappingSize, mapFile); - fclose(mapFile); - if (byteMapping != 0) - status = TECkit_CreateConverter(mapping, mappingSize, - false, - UTF16_NATIVE, kForm_Bytes, - &cnv); - else - status = TECkit_CreateConverter(mapping, mappingSize, - true, - UTF16_NATIVE, UTF16_NATIVE, - &cnv); - free(mapping); - } - if (cnv == NULL) - fontmappingwarning(buffer, strlen(buffer), 2); /* not loadable */ - else if (gettracingfontsstate() > 1) - fontmappingwarning(buffer, strlen(buffer), 0); /* tracing */ - } else { - fontmappingwarning(buffer, strlen(buffer), 1); /* not found */ - } - - free(buffer); - - return cnv; + char* mapPath; + TECkit_Converter cnv = 0; + char* buffer = (char*) xmalloc(e - s + 5); + strncpy(buffer, s, e - s); + buffer[e - s] = 0; + strcat(buffer, ".tec"); + mapPath = kpse_find_file(buffer, kpse_miscfonts_format, 1); + + if (mapPath) { + FILE* mapFile = fopen(mapPath, FOPEN_RBIN_MODE); + free(mapPath); + if (mapFile) { + uint32_t mappingSize; + Byte* mapping; + TECkit_Status status; + fseek(mapFile, 0, SEEK_END); + mappingSize = ftell(mapFile); + fseek(mapFile, 0, SEEK_SET); + mapping = (Byte*) xmalloc(mappingSize); + fread(mapping, 1, mappingSize, mapFile); + fclose(mapFile); + if (byteMapping != 0) + status = TECkit_CreateConverter(mapping, mappingSize, + false, + UTF16_NATIVE, kForm_Bytes, + &cnv); + else + status = TECkit_CreateConverter(mapping, mappingSize, + true, + UTF16_NATIVE, UTF16_NATIVE, + &cnv); + free(mapping); + } + if (cnv == NULL) + fontmappingwarning(buffer, strlen(buffer), 2); /* not loadable */ + else if (gettracingfontsstate() > 1) + fontmappingwarning(buffer, strlen(buffer), 0); /* tracing */ + } else { + fontmappingwarning(buffer, strlen(buffer), 1); /* not found */ + } + + free(buffer); + + return cnv; } char *saved_mapping_name = NULL; void checkfortfmfontmapping() { - char* cp = strstr((char*)nameoffile + 1, ":mapping="); - if (saved_mapping_name != NULL) { - free(saved_mapping_name); - saved_mapping_name = NULL; - } - if (cp != NULL) { - *cp = 0; - cp += 9; - while (*cp && *cp <= ' ') - ++cp; - if (*cp) - saved_mapping_name = xstrdup(cp); - } + char* cp = strstr((char*)nameoffile + 1, ":mapping="); + if (saved_mapping_name != NULL) { + free(saved_mapping_name); + saved_mapping_name = NULL; + } + if (cp != NULL) { + *cp = 0; + cp += 9; + while (*cp && *cp <= ' ') + ++cp; + if (*cp) + saved_mapping_name = xstrdup(cp); + } } void* loadtfmfontmapping() { - void* rval = NULL; - if (saved_mapping_name != NULL) { - rval = load_mapping_file(saved_mapping_name, - saved_mapping_name + strlen(saved_mapping_name), 1); - free(saved_mapping_name); - saved_mapping_name = NULL; - } - return rval; + void* rval = NULL; + if (saved_mapping_name != NULL) { + rval = load_mapping_file(saved_mapping_name, + saved_mapping_name + strlen(saved_mapping_name), 1); + free(saved_mapping_name); + saved_mapping_name = NULL; + } + return rval; } int applytfmfontmapping(void* cnv, int c) { - UniChar in = c; - Byte out[2]; - UInt32 inUsed, outUsed; - TECkit_Status status = TECkit_ConvertBuffer((TECkit_Converter)cnv, - (const Byte*)&in, sizeof(in), &inUsed, out, sizeof(out), &outUsed, 1); - if (outUsed < 1) - return 0; - else - return out[0]; + UniChar in = c; + Byte out[2]; + UInt32 inUsed, outUsed; + TECkit_Status status = TECkit_ConvertBuffer((TECkit_Converter)cnv, + (const Byte*)&in, sizeof(in), &inUsed, out, sizeof(out), &outUsed, 1); + if (outUsed < 1) + return 0; + else + return out[0]; } 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; + 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 hb_tag_t read_tag_with_param(const char* cp, int* param) { - const char* cp2; - hb_tag_t tag; - - cp2 = cp; - while (*cp2 && (*cp2 != ':') && (*cp2 != ';') && (*cp2 != ',') && (*cp2 != '=')) - ++cp2; - - tag = hb_tag_from_string(cp, cp2 - cp); - - cp = cp2; - if (*cp == '=') { - int neg = 0; - ++cp; - if (*cp == '-') { - ++neg; - ++cp; - } - while (*cp >= '0' && *cp <= '9') { - *param = *param * 10 + *cp - '0'; - ++cp; - } - if (neg) - *param = -(*param); - } + const char* cp2; + hb_tag_t tag; + + cp2 = cp; + while (*cp2 && (*cp2 != ':') && (*cp2 != ';') && (*cp2 != ',') && (*cp2 != '=')) + ++cp2; + + tag = hb_tag_from_string(cp, cp2 - cp); + + cp = cp2; + if (*cp == '=') { + int neg = 0; + ++cp; + if (*cp == '-') { + ++neg; + ++cp; + } + while (*cp >= '0' && *cp <= '9') { + *param = *param * 10 + *cp - '0'; + ++cp; + } + if (neg) + *param = -(*param); + } - return tag; + return tag; } unsigned int read_rgb_a(const char** cp) { - uint32_t rgbValue = 0; - uint32_t 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; + uint32_t rgbValue = 0; + uint32_t 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; } int readCommonFeatures(const char* feat, const char* end, float* extend, float* slant, float* embolden, float* letterspace, uint32_t* rgbValue) - // returns 1 to go to next_option, -1 for bad_option, 0 to continue -{ - const char* sep; - if (strncmp(feat, "mapping", 7) == 0) { - sep = feat + 7; - if (*sep != '=') - return -1; - loadedfontmapping = load_mapping_file(sep + 1, end, 0); - return 1; - } - - if (strncmp(feat, "extend", 6) == 0) { - sep = feat + 6; - if (*sep != '=') - return -1; - ++sep; - *extend = read_double(&sep); - return 1; - } - - if (strncmp(feat, "slant", 5) == 0) { - sep = feat + 5; - if (*sep != '=') - return -1; - ++sep; - *slant = read_double(&sep); - return 1; - } - - if (strncmp(feat, "embolden", 8) == 0) { - sep = feat + 8; - if (*sep != '=') - return -1; - ++sep; - *embolden = read_double(&sep); - return 1; - } - - if (strncmp(feat, "letterspace", 11) == 0) { - sep = feat + 11; - if (*sep != '=') - return -1; - ++sep; - *letterspace = read_double(&sep); - return 1; - } - - if (strncmp(feat, "color", 5) == 0) { - const char* s; - sep = feat + 5; - if (*sep != '=') - return -1; - ++sep; - s = sep; - *rgbValue = read_rgb_a(&sep); - if ((sep == s+6) || (sep == s+8)) - loadedfontflags |= FONT_FLAGS_COLORED; - else - return -1; - return 1; - } - - return 0; + // returns 1 to go to next_option, -1 for bad_option, 0 to continue +{ + const char* sep; + if (strncmp(feat, "mapping", 7) == 0) { + sep = feat + 7; + if (*sep != '=') + return -1; + loadedfontmapping = load_mapping_file(sep + 1, end, 0); + return 1; + } + + if (strncmp(feat, "extend", 6) == 0) { + sep = feat + 6; + if (*sep != '=') + return -1; + ++sep; + *extend = read_double(&sep); + return 1; + } + + if (strncmp(feat, "slant", 5) == 0) { + sep = feat + 5; + if (*sep != '=') + return -1; + ++sep; + *slant = read_double(&sep); + return 1; + } + + if (strncmp(feat, "embolden", 8) == 0) { + sep = feat + 8; + if (*sep != '=') + return -1; + ++sep; + *embolden = read_double(&sep); + return 1; + } + + if (strncmp(feat, "letterspace", 11) == 0) { + sep = feat + 11; + if (*sep != '=') + return -1; + ++sep; + *letterspace = read_double(&sep); + return 1; + } + + if (strncmp(feat, "color", 5) == 0) { + const char* s; + sep = feat + 5; + if (*sep != '=') + return -1; + ++sep; + s = sep; + *rgbValue = read_rgb_a(&sep); + if ((sep == s+6) || (sep == s+8)) + loadedfontflags |= FONT_FLAGS_COLORED; + else + return -1; + return 1; + } + + return 0; } static bool readFeatureNumber(const char* s, const char* e, hb_tag_t* f, int* v) - /* s...e is a "id=setting" string; */ -{ - *f = 0; - *v = 0; - if (*s < '0' || *s > '9') - return false; - while (*s >= '0' && *s <= '9') - *f = *f * 10 + *s++ - '0'; - while ((*s == ' ') || (*s == '\t')) - ++s; - if (*s++ != '=') - /* no setting was specified */ - return false; - - if (*s < '0' || *s > '9') - return false; - while (*s >= '0' && *s <= '9') - *v = *v * 10 + *s++ - '0'; - while ((*s == ' ') || (*s == '\t')) - ++s; - if (s != e) - return false; - return true; + /* s...e is a "id=setting" string; */ +{ + *f = 0; + *v = 0; + if (*s < '0' || *s > '9') + return false; + while (*s >= '0' && *s <= '9') + *f = *f * 10 + *s++ - '0'; + while ((*s == ' ') || (*s == '\t')) + ++s; + if (*s++ != '=') + /* no setting was specified */ + return false; + + if (*s < '0' || *s > '9') + return false; + while (*s >= '0' && *s <= '9') + *v = *v * 10 + *s++ - '0'; + while ((*s == ' ') || (*s == '\t')) + ++s; + if (s != e) + return false; + return true; } static void* loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const char* cp1) { - XeTeXLayoutEngine engine; - hb_tag_t script = HB_TAG_NONE; - hb_tag_t language = HB_TAG_NONE; - hb_feature_t* features = NULL; - char** shapers = NULL; /* NULL-terminated array */ - int nFeatures = 0; - int nShapers = 0; - - const char* cp2; - const char* cp3; - - hb_tag_t tag; - - uint32_t rgbValue = 0x000000FF; - - float extend = 1.0; - float slant = 0.0; - float embolden = 0.0; - float letterspace = 0.0; - - int i; - - char reqEngine = getReqEngine(); - - if (reqEngine == 'O' || reqEngine == 'G') { - shapers = xrealloc(shapers, (nShapers + 1) * sizeof(char *)); - if (reqEngine == 'O') - shapers[nShapers] = strdup("ot"); - else if (reqEngine == 'G') - shapers[nShapers] = strdup("graphite2"); - nShapers++; - } - - if (reqEngine == 'G') { - char* tmpShapers[] = {shapers[0]}; - /* 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 = createLayoutEngine(fontRef, font, script, language, - features, nFeatures, tmpShapers, rgbValue, extend, slant, embolden); - - 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, "script", 6) == 0) { - cp3 = cp1 + 6; - if (*cp3 != '=') - goto bad_option; - ++cp3; - script = hb_tag_from_string(cp3, cp2 - cp3); - goto next_option; - } - - if (strncmp(cp1, "language", 8) == 0) { - cp3 = cp1 + 8; - if (*cp3 != '=') - goto bad_option; - ++cp3; - language = hb_tag_from_string(cp3, cp2 - cp3); - goto next_option; - } - - if (strncmp(cp1, "shaper", 6) == 0) { - cp3 = cp1 + 6; - if (*cp3 != '=') - goto bad_option; - ++cp3; - shapers = xrealloc(shapers, (nShapers + 1) * sizeof(char *)); - /* some dumb systems have no strndup() */ - shapers[nShapers] = strdup(cp3); - shapers[nShapers][cp2 - cp3] = '\0'; - nShapers++; - goto next_option; - } - - i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden, &letterspace, &rgbValue); - if (i == 1) - goto next_option; - else if (i == -1) - goto bad_option; - - if (reqEngine == 'G') { - int value = 0; - if (readFeatureNumber(cp1, cp2, &tag, &value) - || findGraphiteFeature(engine, cp1, cp2, &tag, &value)) { - features = xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t)); - features[nFeatures].tag = tag; - features[nFeatures].value = value; - features[nFeatures].start = 0; - features[nFeatures].end = (unsigned int) -1; - nFeatures++; - goto next_option; - } - } - - if (*cp1 == '+') { - int param = 0; - tag = read_tag_with_param(cp1 + 1, ¶m); - features = xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t)); - features[nFeatures].tag = tag; - features[nFeatures].start = 0; - features[nFeatures].end = (unsigned int) -1; - // for backward compatibility with pre-0.9999 where feature - // indices started from 0 - if (param >= 0) - param++; - features[nFeatures].value = param; - nFeatures++; - goto next_option; - } - - if (*cp1 == '-') { - ++cp1; - tag = hb_tag_from_string(cp1, cp2 - cp1); - features = xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t)); - features[nFeatures].tag = tag; - features[nFeatures].start = 0; - features[nFeatures].end = (unsigned int) -1; - features[nFeatures].value = 0; - nFeatures++; - goto next_option; - } - - if (strncmp(cp1, "vertical", 8) == 0) { - cp3 = cp2; - if (*cp3 == ';' || *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 (shapers != NULL) { - shapers = xrealloc(shapers, (nShapers + 1) * sizeof(char *)); - shapers[nShapers] = NULL; - } - - if (embolden != 0.0) - embolden = embolden * Fix2D(scaled_size) / 100.0; - - if (letterspace != 0.0) - loadedfontletterspace = (letterspace / 100.0) * scaled_size; - - if ((loadedfontflags & FONT_FLAGS_COLORED) == 0) - rgbValue = 0x000000FF; - - if ((loadedfontflags & FONT_FLAGS_VERTICAL) != 0) - setFontLayoutDir(font, 1); - - engine = createLayoutEngine(fontRef, font, script, language, - features, nFeatures, shapers, rgbValue, extend, slant, embolden); - - if (engine == 0) { - // only free these if creation failed, otherwise the engine now owns them - free(features); - free(shapers); - } else { - nativefonttypeflag = OTGR_FONT_FLAG; - } - - return engine; + XeTeXLayoutEngine engine; + hb_tag_t script = HB_TAG_NONE; + char * language = NULL; + hb_feature_t* features = NULL; + char** shapers = NULL; /* NULL-terminated array */ + int nFeatures = 0; + int nShapers = 0; + + const char* cp2; + const char* cp3; + + hb_tag_t tag; + + uint32_t rgbValue = 0x000000FF; + + float extend = 1.0; + float slant = 0.0; + float embolden = 0.0; + float letterspace = 0.0; + + int i; + + char reqEngine = getReqEngine(); + + if (reqEngine == 'O' || reqEngine == 'G') { + shapers = (char**) xrealloc(shapers, (nShapers + 1) * sizeof(char *)); + if (reqEngine == 'O') + shapers[nShapers] = "ot"; + else if (reqEngine == 'G') + shapers[nShapers] = "graphite2"; + nShapers++; + } + + if (reqEngine == 'G') { + char* tmpShapers[] = {shapers[0]}; + /* 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 = createLayoutEngine(fontRef, font, script, language, + features, nFeatures, tmpShapers, rgbValue, extend, slant, embolden); + + 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, "script", 6) == 0) { + cp3 = cp1 + 6; + if (*cp3 != '=') + goto bad_option; + ++cp3; + script = hb_tag_from_string(cp3, cp2 - cp3); + goto next_option; + } + + if (strncmp(cp1, "language", 8) == 0) { + cp3 = cp1 + 8; + if (*cp3 != '=') + goto bad_option; + ++cp3; + language = (char*)xmalloc(cp2 - cp3 + 1); + language[cp2 - cp3] = '\0'; + memcpy(language, cp3, cp2 - cp3); + goto next_option; + } + + if (strncmp(cp1, "shaper", 6) == 0) { + cp3 = cp1 + 6; + if (*cp3 != '=') + goto bad_option; + ++cp3; + shapers = (char**) xrealloc(shapers, (nShapers + 1) * sizeof(char *)); + /* some dumb systems have no strndup() */ + shapers[nShapers] = strdup(cp3); + shapers[nShapers][cp2 - cp3] = '\0'; + nShapers++; + goto next_option; + } + + i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden, &letterspace, &rgbValue); + if (i == 1) + goto next_option; + else if (i == -1) + goto bad_option; + + if (reqEngine == 'G') { + int value = 0; + if (readFeatureNumber(cp1, cp2, &tag, &value) + || findGraphiteFeature(engine, cp1, cp2, &tag, &value)) { + features = (hb_feature_t*) xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t)); + features[nFeatures].tag = tag; + features[nFeatures].value = value; + features[nFeatures].start = 0; + features[nFeatures].end = (unsigned int) -1; + nFeatures++; + goto next_option; + } + } + + if (*cp1 == '+') { + int param = 0; + tag = read_tag_with_param(cp1 + 1, ¶m); + features = (hb_feature_t*) xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t)); + features[nFeatures].tag = tag; + features[nFeatures].start = 0; + features[nFeatures].end = (unsigned int) -1; + // for backward compatibility with pre-0.9999 where feature + // indices started from 0 + if (param >= 0) + param++; + features[nFeatures].value = param; + nFeatures++; + goto next_option; + } + + if (*cp1 == '-') { + ++cp1; + tag = hb_tag_from_string(cp1, cp2 - cp1); + features = (hb_feature_t*) xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t)); + features[nFeatures].tag = tag; + features[nFeatures].start = 0; + features[nFeatures].end = (unsigned int) -1; + features[nFeatures].value = 0; + nFeatures++; + goto next_option; + } + + if (strncmp(cp1, "vertical", 8) == 0) { + cp3 = cp2; + if (*cp3 == ';' || *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((void*) cp1, cp2 - cp1, 0, 0); + + next_option: + cp1 = cp2; + } + } + + if (shapers != NULL) { + shapers = (char**) xrealloc(shapers, (nShapers + 1) * sizeof(char *)); + shapers[nShapers] = NULL; + } + + if (embolden != 0.0) + embolden = embolden * Fix2D(scaled_size) / 100.0; + + if (letterspace != 0.0) + loadedfontletterspace = (letterspace / 100.0) * scaled_size; + + if ((loadedfontflags & FONT_FLAGS_COLORED) == 0) + rgbValue = 0x000000FF; + + if ((loadedfontflags & FONT_FLAGS_VERTICAL) != 0) + setFontLayoutDir(font, 1); + + engine = createLayoutEngine(fontRef, font, script, language, + features, nFeatures, shapers, rgbValue, extend, slant, embolden); + + if (engine == 0) { + // only free these if creation failed, otherwise the engine now owns them + free(features); + free(shapers); + } else { + nativefonttypeflag = OTGR_FONT_FLAG; + } + + return engine; } static void splitFontName(char* name, char** var, char** feat, char** end, int* index) { - *var = NULL; - *feat = NULL; - *index = 0; - if (*name == '[') { - int withinFileName = 1; + *var = NULL; + *feat = NULL; + *index = 0; + if (*name == '[') { + int withinFileName = 1; #ifdef WIN32 - char* start = name + 1; + char* start = name + 1; #endif - ++name; - while (*name) { - if (withinFileName && *name == ']') { - withinFileName = 0; - if (*var == NULL) - *var = name; - } else if (*name == ':') { - if (withinFileName && *var == NULL + ++name; + while (*name) { + if (withinFileName && *name == ']') { + withinFileName = 0; + if (*var == NULL) + *var = name; + } else if (*name == ':') { + if (withinFileName && *var == NULL #ifdef WIN32 - && !((name - start == 1) && isalpha(*start)) + && !((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; - } - ++name; - } - *end = name; - } else { - while (*name) { - if (*name == '/' && *var == NULL && *feat == NULL) - *var = name; - else if (*name == ':' && *feat == NULL) - *feat = name; - ++name; - } - *end = name; - } - if (*feat == NULL) - *feat = name; - if (*var == NULL) - *var = *feat; + ) { + *var = name; + ++name; + while (*name >= '0' && *name <= '9') + *index = *index * 10 + *name++ - '0'; + --name; + } else if (!withinFileName && *feat == NULL) + *feat = name; + } + ++name; + } + *end = name; + } else { + while (*name) { + if (*name == '/' && *var == NULL && *feat == NULL) + *var = name; + else if (*name == ':' && *feat == NULL) + *feat = name; + ++name; + } + *end = name; + } + if (*feat == NULL) + *feat = name; + if (*var == NULL) + *var = *feat; } void* findnativefont(unsigned char* uname, integer scaled_size) - /* scaled_size here is in TeX points, or is a negative integer for 'scaled' */ -{ - void* rval = NULL; - char* nameString; - char* var; - char* feat; - char* end; - char* name = (char*)uname; - char* varString = NULL; - char* featString = NULL; - PlatformFontRef fontRef; - XeTeXFont font = NULL; - int index = 0; - - loadedfontmapping = NULL; - loadedfontflags = 0; - loadedfontletterspace = 0; - - splitFontName(name, &var, &feat, &end, &index); - nameString = xmalloc(var - name + 1); - strncpy(nameString, name, var - name); - nameString[var - name] = 0; - - if (feat > var) { - varString = xmalloc(feat - var); - strncpy(varString, var + 1, feat - var - 1); - varString[feat - var - 1] = 0; - } - - if (end > feat) { - featString = xmalloc(end - feat); - strncpy(featString, feat + 1, end - feat - 1); - featString[end - feat - 1] = 0; - } - - // check for "[filename]" form, don't search maps in this case - if (nameString[0] == '[') { - char* path = kpse_find_file(nameString + 1, kpse_opentype_format, 0); - if (path == NULL) - path = kpse_find_file(nameString + 1, kpse_truetype_format, 0); - if (path == NULL) - path = kpse_find_file(nameString + 1, kpse_type1_format, 0); - if (path != NULL) { - if (scaled_size < 0) { - font = createFontFromFile(path, index, 655360L); - if (font != NULL) { - Fixed dsize = D2Fix(getDesignSize(font)); - if (scaled_size == -1000) - scaled_size = dsize; - else - scaled_size = zxnoverd(dsize, -scaled_size, 1000); - deleteFont(font); - } - } - font = createFontFromFile(path, index, scaled_size); - if (font != NULL) { - loadedfontdesignsize = D2Fix(getDesignSize(font)); - - /* This is duplicated in XeTeXFontMgr::findFont! */ - setReqEngine(0); - if (varString) { - if (strncmp(varString, "/AAT", 4) == 0) - setReqEngine('A'); - else if ((strncmp(varString, "/OT", 3) == 0) || (strncmp(varString, "/ICU", 4) == 0)) - setReqEngine('O'); - else if (strncmp(varString, "/GR", 3) == 0) - setReqEngine('G'); - } - - rval = loadOTfont(0, font, scaled_size, featString); - if (rval == NULL) - deleteFont(font); - if (rval != NULL && gettracingfontsstate() > 0) { - begindiagnostic(); - zprintnl(' '); - printcstring("-> "); - printcstring(path); - zenddiagnostic(0); - } - } - } - } else { - fontRef = findFontByName(nameString, varString, Fix2D(scaled_size)); - - if (fontRef != 0) { - /* update nameoffile to the full name of the font, for error messages during font loading */ - const char* fullName = getFullName(fontRef); - namelength = strlen(fullName); - if (featString != NULL) - namelength += strlen(featString) + 1; - if (varString != NULL) - namelength += strlen(varString) + 1; - free(nameoffile); - nameoffile = xmalloc(namelength + 4); /* +2 would be correct: initial space, final NUL */ - nameoffile[0] = ' '; - strcpy((char*)nameoffile + 1, fullName); - - if (scaled_size < 0) { - font = createFont(fontRef, scaled_size); - if (font != NULL) { - Fixed dsize = D2Fix(getDesignSize(font)); - if (scaled_size == -1000) - scaled_size = dsize; - else - scaled_size = zxnoverd(dsize, -scaled_size, 1000); - deleteFont(font); - } - } - - font = createFont(fontRef, scaled_size); - if (font != NULL) { + /* scaled_size here is in TeX points, or is a negative integer for 'scaled' */ +{ + void* rval = NULL; + char* nameString; + char* var; + char* feat; + char* end; + char* name = (char*)uname; + char* varString = NULL; + char* featString = NULL; + PlatformFontRef fontRef; + XeTeXFont font = NULL; + int index = 0; + + loadedfontmapping = NULL; + loadedfontflags = 0; + loadedfontletterspace = 0; + + splitFontName(name, &var, &feat, &end, &index); + nameString = (char*) xmalloc(var - name + 1); + strncpy(nameString, name, var - name); + nameString[var - name] = 0; + + if (feat > var) { + varString = (char*) xmalloc(feat - var); + strncpy(varString, var + 1, feat - var - 1); + varString[feat - var - 1] = 0; + } + + if (end > feat) { + featString = (char*) xmalloc(end - feat); + strncpy(featString, feat + 1, end - feat - 1); + featString[end - feat - 1] = 0; + } + + // check for "[filename]" form, don't search maps in this case + if (nameString[0] == '[') { + char* path = kpse_find_file(nameString + 1, kpse_opentype_format, 0); + if (path == NULL) + path = kpse_find_file(nameString + 1, kpse_truetype_format, 0); + if (path == NULL) + path = kpse_find_file(nameString + 1, kpse_type1_format, 0); + if (path != NULL) { + if (scaled_size < 0) { + font = createFontFromFile(path, index, 655360L); + if (font != NULL) { + Fixed dsize = D2Fix(getDesignSize(font)); + if (scaled_size == -1000) + scaled_size = dsize; + else + scaled_size = zxnoverd(dsize, -scaled_size, 1000); + deleteFont(font); + } + } + font = createFontFromFile(path, index, scaled_size); + if (font != NULL) { + loadedfontdesignsize = D2Fix(getDesignSize(font)); + + /* This is duplicated in XeTeXFontMgr::findFont! */ + setReqEngine(0); + if (varString) { + if (strncmp(varString, "/AAT", 4) == 0) + setReqEngine('A'); + else if ((strncmp(varString, "/OT", 3) == 0) || (strncmp(varString, "/ICU", 4) == 0)) + setReqEngine('O'); + else if (strncmp(varString, "/GR", 3) == 0) + setReqEngine('G'); + } + + rval = loadOTfont(0, font, scaled_size, featString); + if (rval == NULL) + deleteFont(font); + if (rval != NULL && gettracingfontsstate() > 0) { + begindiagnostic(); + zprintnl(' '); + printcstring("-> "); + printcstring(path); + zenddiagnostic(0); + } + } + } + } else { + fontRef = findFontByName(nameString, varString, Fix2D(scaled_size)); + + if (fontRef != 0) { + /* update nameoffile to the full name of the font, for error messages during font loading */ + const char* fullName = getFullName(fontRef); + namelength = strlen(fullName); + if (featString != NULL) + namelength += strlen(featString) + 1; + if (varString != NULL) + namelength += strlen(varString) + 1; + free(nameoffile); + nameoffile = xmalloc(namelength + 4); /* +2 would be correct: initial space, final NUL */ + nameoffile[0] = ' '; + strcpy((char*)nameoffile + 1, fullName); + + if (scaled_size < 0) { + font = createFont(fontRef, scaled_size); + if (font != NULL) { + Fixed dsize = D2Fix(getDesignSize(font)); + if (scaled_size == -1000) + scaled_size = dsize; + else + scaled_size = zxnoverd(dsize, -scaled_size, 1000); + deleteFont(font); + } + } + + font = createFont(fontRef, scaled_size); + if (font != NULL) { #ifdef XETEX_MAC - /* decide whether to use AAT or OpenType rendering with this font */ - if (getReqEngine() == 'A') { - rval = loadAATfont(fontRef, scaled_size, featString); - if (rval == NULL) - deleteFont(font); - } else { - if (getReqEngine() == 'O' || getReqEngine() == 'G' || - getFontTablePtr(font, kGSUB) != NULL || getFontTablePtr(font, kGPOS) != NULL) - rval = loadOTfont(fontRef, font, scaled_size, featString); - - /* loadOTfont failed or the above check was false */ - if (rval == NULL) - rval = loadAATfont(fontRef, scaled_size, featString); - - if (rval == NULL) - deleteFont(font); - } + /* decide whether to use AAT or OpenType rendering with this font */ + if (getReqEngine() == 'A') { + rval = loadAATfont(fontRef, scaled_size, featString); + if (rval == NULL) + deleteFont(font); + } else { + if (getReqEngine() == 'O' || getReqEngine() == 'G' || + getFontTablePtr(font, kGSUB) != NULL || getFontTablePtr(font, kGPOS) != NULL) + rval = loadOTfont(fontRef, font, scaled_size, featString); + + /* loadOTfont failed or the above check was false */ + if (rval == NULL) + rval = loadAATfont(fontRef, scaled_size, featString); + + if (rval == NULL) + deleteFont(font); + } #else - rval = loadOTfont(fontRef, font, scaled_size, featString); - if (rval == NULL) - deleteFont(font); + rval = loadOTfont(fontRef, font, scaled_size, featString); + if (rval == NULL) + deleteFont(font); #endif - } - - /* append the style and feature strings, so that \show\fontID will give a full result */ - if (varString != NULL && *varString != 0) { - strcat((char*)nameoffile + 1, "/"); - strcat((char*)nameoffile + 1, varString); - } - if (featString != NULL && *featString != 0) { - strcat((char*)nameoffile + 1, ":"); - strcat((char*)nameoffile + 1, featString); - } - namelength = strlen((char*)nameoffile + 1); - } - } - - if (varString != NULL) - free(varString); - - if (featString != NULL) - free(featString); - - free(nameString); - - return rval; + } + + /* append the style and feature strings, so that \show\fontID will give a full result */ + if (varString != NULL && *varString != 0) { + strcat((char*)nameoffile + 1, "/"); + strcat((char*)nameoffile + 1, varString); + } + if (featString != NULL && *featString != 0) { + strcat((char*)nameoffile + 1, ":"); + strcat((char*)nameoffile + 1, featString); + } + namelength = strlen((char*)nameoffile + 1); + } + } + + if (varString != NULL) + free(varString); + + if (featString != NULL) + free(featString); + + free(nameString); + + return rval; } void releasefontengine(void* engine, int type_flag) { #ifdef XETEX_MAC - if (type_flag == AAT_FONT_FLAG) { - CFRelease((CFDictionaryRef)engine); - } else + if (type_flag == AAT_FONT_FLAG) { + CFRelease((CFDictionaryRef)engine); + } else #endif - if (type_flag == OTGR_FONT_FLAG) { - deleteLayoutEngine((XeTeXLayoutEngine)engine); - } + if (type_flag == OTGR_FONT_FLAG) { + deleteLayoutEngine((XeTeXLayoutEngine)engine); + } } /* params are given as 'integer' in the header file, but are really TeX scaled integers */ void otgetfontmetrics(void* pEngine, scaled* ascent, scaled* descent, scaled* xheight, scaled* capheight, scaled* slant) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; - float a, d; - - getAscentAndDescent(engine, &a, &d); - *ascent = D2Fix(a); - *descent = D2Fix(d); - - *slant = D2Fix(Fix2D(getSlant(getFont(engine))) * getExtendFactor(engine) - + getSlantFactor(engine)); - - /* get cap and x height from OS/2 table */ - getCapAndXHeight(engine, &a, &d); - *capheight = D2Fix(a); - *xheight = D2Fix(d); - - /* fallback in case the font does not have OS/2 table */ - if (*xheight == 0) { - int glyphID = mapCharToGlyph(engine, 'x'); - if (glyphID != 0) { - getGlyphHeightDepth(engine, glyphID, &a, &d); - *xheight = D2Fix(a); - } else { - *xheight = *ascent / 2; /* arbitrary figure if there's no 'x' in the font */ - } - } - - if (*capheight == 0) { - int glyphID = mapCharToGlyph(engine, 'X'); - if (glyphID != 0) { - getGlyphHeightDepth(engine, glyphID, &a, &d); - *capheight = D2Fix(a); - } else { - *capheight = *ascent; /* arbitrary figure if there's no 'X' in the font */ - } - } + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; + float a, d; + + getAscentAndDescent(engine, &a, &d); + *ascent = D2Fix(a); + *descent = D2Fix(d); + + *slant = D2Fix(Fix2D(getSlant(getFont(engine))) * getExtendFactor(engine) + + getSlantFactor(engine)); + + /* get cap and x height from OS/2 table */ + getCapAndXHeight(engine, &a, &d); + *capheight = D2Fix(a); + *xheight = D2Fix(d); + + /* fallback in case the font does not have OS/2 table */ + if (*xheight == 0) { + int glyphID = mapCharToGlyph(engine, 'x'); + if (glyphID != 0) { + getGlyphHeightDepth(engine, glyphID, &a, &d); + *xheight = D2Fix(a); + } else { + *xheight = *ascent / 2; /* arbitrary figure if there's no 'x' in the font */ + } + } + + if (*capheight == 0) { + int glyphID = mapCharToGlyph(engine, 'X'); + if (glyphID != 0) { + getGlyphHeightDepth(engine, glyphID, &a, &d); + *capheight = D2Fix(a); + } else { + *capheight = *ascent; /* arbitrary figure if there's no 'X' in the font */ + } + } } integer otfontget(integer what, void* pEngine) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; - XeTeXFont fontInst = getFont(engine); - switch (what) { - case XeTeX_count_glyphs: - return countGlyphs(fontInst); - break; - - case XeTeX_count_features: /* ie Graphite features */ - return countGraphiteFeatures(engine); - break; + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; + XeTeXFont fontInst = getFont(engine); + switch (what) { + case XeTeX_count_glyphs: + return countGlyphs(fontInst); + break; - case XeTeX_OT_count_scripts: - return countScripts(fontInst); - break; - } - return 0; + case XeTeX_count_features: /* ie Graphite features */ + return countGraphiteFeatures(engine); + break; + + case XeTeX_OT_count_scripts: + return countScripts(fontInst); + break; + } + return 0; } integer otfontget1(integer what, void* pEngine, integer param) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; - XeTeXFont fontInst = getFont(engine); - switch (what) { - case XeTeX_OT_count_languages: - return countLanguages(fontInst, param); - break; - - 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; + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; + XeTeXFont fontInst = getFont(engine); + switch (what) { + case XeTeX_OT_count_languages: + return countLanguages(fontInst, param); + break; + + 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; } integer otfontget2(integer what, void* pEngine, integer param1, integer param2) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; - XeTeXFont fontInst = getFont(engine); - switch (what) { - case XeTeX_OT_language_code: - return getIndLanguage(fontInst, param1, param2); - break; - - case XeTeX_OT_count_features: - return countFeatures(fontInst, param1, param2); - break; + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; + XeTeXFont fontInst = getFont(engine); + switch (what) { + case XeTeX_OT_language_code: + return getIndLanguage(fontInst, param1, param2); + break; + + 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; + } - /* 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; + return 0; } integer otfontget3(integer what, void* pEngine, integer param1, integer param2, integer param3) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; - XeTeXFont fontInst = getFont(engine); - switch (what) { - case XeTeX_OT_feature_code: - return getIndFeature(fontInst, param1, param2, param3); - break; - } - - return 0; + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; + XeTeXFont fontInst = getFont(engine); + switch (what) { + case XeTeX_OT_feature_code: + return getIndFeature(fontInst, param1, param2, param3); + break; + } + + return 0; } void grprintfontname(integer what, void* pEngine, integer param1, integer param2) { - char* name = NULL; - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; - switch (what) { - case XeTeX_feature_name: - name = getGraphiteFeatureLabel(engine, param1); - break; - case XeTeX_selector_name: - name = getGraphiteFeatureSettingLabel(engine, param1, param2); - break; - } + char* name = NULL; + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine; + switch (what) { + case XeTeX_feature_name: + name = getGraphiteFeatureLabel(engine, param1); + break; + case XeTeX_selector_name: + name = getGraphiteFeatureSettingLabel(engine, param1, param2); + break; + } - if (name != NULL) { - printcstring(name); - gr_label_destroy(name); - } + if (name != NULL) { + printcstring(name); + gr_label_destroy(name); + } } 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; + 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; + 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_AAT 0x0001 -#define XDV_FLAG_FONTTYPE_OT 0x0002 +#define XDV_FLAG_FONTTYPE_AAT 0x0001 +#define XDV_FLAG_FONTTYPE_OT 0x0002 -#define XDV_FLAG_VERTICAL 0x0100 -#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 -#define XDV_FLAG_EMBOLDEN 0x4000 +#define XDV_FLAG_VERTICAL 0x0100 +#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 +#define XDV_FLAG_EMBOLDEN 0x4000 #ifdef XETEX_MAC static UInt32 cgColorToRGBA32(CGColorRef color) { - const CGFloat *components = CGColorGetComponents(color); + const CGFloat *components = CGColorGetComponents(color); - UInt32 rval = (UInt8)(components[0] * 255.0 + 0.5); - rval <<= 8; - rval += (UInt8)(components[1] * 255.0 + 0.5); - rval <<= 8; - rval += (UInt8)(components[2] * 255.0 + 0.5); - rval <<= 8; - rval += (UInt8)(components[3] * 255.0 + 0.5); - return rval; + UInt32 rval = (UInt8)(components[0] * 255.0 + 0.5); + rval <<= 8; + rval += (UInt8)(components[1] * 255.0 + 0.5); + rval <<= 8; + rval += (UInt8)(components[2] * 255.0 + 0.5); + rval <<= 8; + rval += (UInt8)(components[3] * 255.0 + 0.5); + return rval; } #endif -static int xdvBufSize = 0; +static int xdvBufSize = 0; int makeXDVGlyphArrayData(void* pNode) { - unsigned char* cp; - uint16_t* glyphIDs; - memoryword* p = pNode; - void* glyph_info; - FixedPoint* locations; - int opcode; - Fixed width; - uint16_t glyphCount = native_glyph_count(p); - - int i = glyphCount * native_glyph_info_size + 8; /* to guarantee enough space in the buffer */ - if (i > xdvBufSize) { - if (xdvbuffer != NULL) - free(xdvbuffer); - xdvBufSize = ((i / 1024) + 1) * 1024; - xdvbuffer = (char*)xmalloc(xdvBufSize); - } - - glyph_info = native_glyph_info_ptr(p); - locations = (FixedPoint*)glyph_info; - glyphIDs = (uint16_t*)(locations + glyphCount); - - opcode = XDV_GLYPH_STRING; - for (i = 0; i < glyphCount; ++i) - if (locations[i].y != 0) { - opcode = XDV_GLYPH_ARRAY; - break; - } - - cp = (unsigned char*)xdvbuffer; - *cp++ = opcode; - - width = node_width(p); - *cp++ = (width >> 24) & 0xff; - *cp++ = (width >> 16) & 0xff; - *cp++ = (width >> 8) & 0xff; - *cp++ = width & 0xff; - - *cp++ = (glyphCount >> 8) & 0xff; - *cp++ = glyphCount & 0xff; - - for (i = 0; i < glyphCount; ++i) { - Fixed x = locations[i].x; - *cp++ = (x >> 24) & 0xff; - *cp++ = (x >> 16) & 0xff; - *cp++ = (x >> 8) & 0xff; - *cp++ = x & 0xff; - if (opcode == XDV_GLYPH_ARRAY) { - Fixed y = locations[i].y; - *cp++ = (y >> 24) & 0xff; - *cp++ = (y >> 16) & 0xff; - *cp++ = (y >> 8) & 0xff; - *cp++ = y & 0xff; - } - } - - for (i = 0; i < glyphCount; ++i) { - uint16_t g = glyphIDs[i]; - *cp++ = (g >> 8) & 0xff; - *cp++ = g & 0xff; - } - - return ((char*)cp - xdvbuffer); + unsigned char* cp; + uint16_t* glyphIDs; + memoryword* p = (memoryword*) pNode; + void* glyph_info; + FixedPoint* locations; + int opcode; + Fixed width; + uint16_t glyphCount = native_glyph_count(p); + + int i = glyphCount * native_glyph_info_size + 8; /* to guarantee enough space in the buffer */ + if (i > xdvBufSize) { + if (xdvbuffer != NULL) + free(xdvbuffer); + xdvBufSize = ((i / 1024) + 1) * 1024; + xdvbuffer = (char*) xmalloc(xdvBufSize); + } + + glyph_info = native_glyph_info_ptr(p); + locations = (FixedPoint*)glyph_info; + glyphIDs = (uint16_t*)(locations + glyphCount); + + opcode = XDV_GLYPH_STRING; + for (i = 0; i < glyphCount; ++i) + if (locations[i].y != 0) { + opcode = XDV_GLYPH_ARRAY; + break; + } + + cp = (unsigned char*)xdvbuffer; + *cp++ = opcode; + + width = node_width(p); + *cp++ = (width >> 24) & 0xff; + *cp++ = (width >> 16) & 0xff; + *cp++ = (width >> 8) & 0xff; + *cp++ = width & 0xff; + + *cp++ = (glyphCount >> 8) & 0xff; + *cp++ = glyphCount & 0xff; + + for (i = 0; i < glyphCount; ++i) { + Fixed x = locations[i].x; + *cp++ = (x >> 24) & 0xff; + *cp++ = (x >> 16) & 0xff; + *cp++ = (x >> 8) & 0xff; + *cp++ = x & 0xff; + if (opcode == XDV_GLYPH_ARRAY) { + Fixed y = locations[i].y; + *cp++ = (y >> 24) & 0xff; + *cp++ = (y >> 16) & 0xff; + *cp++ = (y >> 8) & 0xff; + *cp++ = y & 0xff; + } + } + + for (i = 0; i < glyphCount; ++i) { + uint16_t g = glyphIDs[i]; + *cp++ = (g >> 8) & 0xff; + *cp++ = g & 0xff; + } + + return ((char*)cp - xdvbuffer); } int makefontdef(integer f) { - uint16_t flags = 0; - uint32_t variationCount = 0; - uint32_t rgba; - Fixed size; - const char* psName; - const char* famName; - const char* styName; - uint8_t psLen; - uint8_t famLen; - uint8_t styLen; - int fontDefLength; - char* cp; - PlatformFontRef fontRef = 0; - float extend = 1.0; - float slant = 0.0; - float embolden = 0.0; + uint16_t flags = 0; + uint32_t variationCount = 0; + uint32_t rgba; + Fixed size; + const char* psName; + const char* famName; + const char* styName; + uint8_t psLen; + uint8_t famLen; + uint8_t styLen; + int fontDefLength; + char* cp; + PlatformFontRef fontRef = 0; + float extend = 1.0; + float slant = 0.0; + float embolden = 0.0; #ifdef XETEX_MAC - CFDictionaryRef attributes = NULL; - CFDictionaryRef variation = NULL; - - if (fontarea[f] == AAT_FONT_FLAG) { - CTFontRef font; - CGColorRef color; - CGAffineTransform t; - CFNumberRef emboldenNumber; - CGFloat fSize; - char *pathname; - int index; - - flags = XDV_FLAG_FONTTYPE_AAT; - attributes = (CFDictionaryRef) fontlayoutengine[f]; - font = CFDictionaryGetValue(attributes, kCTFontAttributeName); - variation = CTFontCopyVariation(font); - if (variation) { - variationCount = CFDictionaryGetCount(variation); - CFRelease(variation); - } - - pathname = getFileNameFromCTFont(font, &index); - if (pathname) { - char buf[20]; - - if (index > 0) - sprintf(buf, ":%d", index); - else - buf[0] = '\0'; - - psName = xmalloc(strlen((char*) pathname) + 2 + strlen(buf) + 1); - sprintf((char*) psName, "[%s%s]", pathname, buf); - famName = ""; - styName = ""; - } else { - psName = getNameFromCTFont(font, kCTFontPostScriptNameKey); - famName = getNameFromCTFont(font, kCTFontFamilyNameKey); - styName = getNameFromCTFont(font, kCTFontStyleNameKey); - } - - if (CFDictionaryGetValue(attributes, kCTVerticalFormsAttributeName)) - flags |= XDV_FLAG_VERTICAL; - - color = (CGColorRef) CFDictionaryGetValue(attributes, kCTForegroundColorAttributeName); - if (color) - rgba = cgColorToRGBA32(color); - - t = CTFontGetMatrix(font); - extend = t.a; - slant = t.b; - - emboldenNumber = CFDictionaryGetValue(attributes, kXeTeXEmboldenAttributeName); - if (emboldenNumber) - CFNumberGetValue(emboldenNumber, kCFNumberFloatType, &embolden); - - fSize = CTFontGetSize(font); - size = D2Fix(fSize); - } else + CFDictionaryRef attributes = NULL; + CFDictionaryRef variation = NULL; + + if (fontarea[f] == AAT_FONT_FLAG) { + CTFontRef font; + CGColorRef color; + CGAffineTransform t; + CFNumberRef emboldenNumber; + CGFloat fSize; + char *pathname; + int index; + + flags = XDV_FLAG_FONTTYPE_AAT; + attributes = (CFDictionaryRef) fontlayoutengine[f]; + font = CFDictionaryGetValue(attributes, kCTFontAttributeName); + variation = CTFontCopyVariation(font); + if (variation) { + variationCount = CFDictionaryGetCount(variation); + CFRelease(variation); + } + + pathname = getFileNameFromCTFont(font, &index); + if (pathname) { + char buf[20]; + + if (index > 0) + sprintf(buf, ":%d", index); + else + buf[0] = '\0'; + + psName = xmalloc(strlen((char*) pathname) + 2 + strlen(buf) + 1); + sprintf((char*) psName, "[%s%s]", pathname, buf); + famName = xstrdup(""); + styName = xstrdup(""); + } else { + psName = getNameFromCTFont(font, kCTFontPostScriptNameKey); + famName = getNameFromCTFont(font, kCTFontFamilyNameKey); + styName = getNameFromCTFont(font, kCTFontStyleNameKey); + } + + if (CFDictionaryGetValue(attributes, kCTVerticalFormsAttributeName)) + flags |= XDV_FLAG_VERTICAL; + + color = (CGColorRef) CFDictionaryGetValue(attributes, kCTForegroundColorAttributeName); + if (color) + rgba = cgColorToRGBA32(color); + + t = CTFontGetMatrix(font); + extend = t.a; + slant = t.b; + + emboldenNumber = CFDictionaryGetValue(attributes, kXeTeXEmboldenAttributeName); + if (emboldenNumber) + CFNumberGetValue(emboldenNumber, kCFNumberFloatType, &embolden); + + fSize = CTFontGetSize(font); + size = D2Fix(fSize); + } else #endif - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine; - flags = XDV_FLAG_FONTTYPE_OT; - - engine = (XeTeXLayoutEngine)fontlayoutengine[f]; - fontRef = getFontRef(engine); - psName = getFontFilename(engine); - if (psName) { - famName = ""; - styName = ""; - } else { - getNames(getFontRef(engine), &psName, &famName, &styName); - } - - rgba = getRgbValue(engine); - if ((fontflags[f] & FONT_FLAGS_VERTICAL) != 0) - flags |= XDV_FLAG_VERTICAL; - - extend = getExtendFactor(engine); - slant = getSlantFactor(engine); - embolden = getEmboldenFactor(engine); - - size = D2Fix(getPointSize(engine)); - } else { - fprintf(stderr, "\n! Internal error: bad native font flag in `make_font_def'\n"); - exit(3); - } - - psLen = strlen(psName); - famLen = strlen(famName); - styLen = strlen(styName); - - /* parameters after internal font ID: - // size[4] - // flags[2] - // lp[1] lf[1] ls[1] ps[lp] fam[lf] sty[ls] - // if flags & COLORED: - // c[4] - // if flags & VARIATIONS: - // nv[2] - // a[4nv] - // v[4nv] - */ - - fontDefLength - = 4 /* size */ - + 2 /* flags */ - + 3 /* name length */ - + psLen + famLen + styLen; - - if ((fontflags[f] & FONT_FLAGS_COLORED) != 0) { - fontDefLength += 4; /* 32-bit RGBA value */ - flags |= XDV_FLAG_COLORED; - } - - if (extend != 1.0) { - fontDefLength += 4; - flags |= XDV_FLAG_EXTEND; - } - if (slant != 0.0) { - fontDefLength += 4; - flags |= XDV_FLAG_SLANT; - } - if (embolden != 0.0) { - fontDefLength += 4; - flags |= XDV_FLAG_EMBOLDEN; - } - - if (fontDefLength > xdvBufSize) { - if (xdvbuffer != NULL) - free(xdvbuffer); - xdvBufSize = ((fontDefLength / 1024) + 1) * 1024; - xdvbuffer = (char*)xmalloc(xdvBufSize); - } - cp = xdvbuffer; - - *(Fixed*)cp = SWAP32(size); - cp += 4; - - *(uint16_t*)cp = SWAP16(flags); - cp += 2; - - *(uint8_t*)cp = psLen; - cp += 1; - *(uint8_t*)cp = famLen; - cp += 1; - *(uint8_t*)cp = styLen; - cp += 1; - memcpy(cp, psName, psLen); - cp += psLen; - memcpy(cp, famName, famLen); - cp += famLen; - memcpy(cp, styName, styLen); - cp += styLen; - - if ((fontflags[f] & FONT_FLAGS_COLORED) != 0) { - *(uint32_t*)cp = SWAP32(rgba); - cp += 4; - } - - if (flags & XDV_FLAG_EXTEND) { - Fixed f = D2Fix(extend); - *(uint32_t*)(cp) = SWAP32(f); - cp += 4; - } - if (flags & XDV_FLAG_SLANT) { - Fixed f = D2Fix(slant); - *(uint32_t*)(cp) = SWAP32(f); - cp += 4; - } - if (flags & XDV_FLAG_EMBOLDEN) { - Fixed f = D2Fix(embolden); - *(uint32_t*)(cp) = SWAP32(f); - cp += 4; - } - - return fontDefLength; + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine; + flags = XDV_FLAG_FONTTYPE_OT; + + engine = (XeTeXLayoutEngine)fontlayoutengine[f]; + fontRef = getFontRef(engine); + psName = xstrdup(getFontFilename(engine)); + if (psName) { + famName = xstrdup(""); + styName = xstrdup(""); + } else { + getNames(getFontRef(engine), &psName, &famName, &styName); + } + + rgba = getRgbValue(engine); + if ((fontflags[f] & FONT_FLAGS_VERTICAL) != 0) + flags |= XDV_FLAG_VERTICAL; + + extend = getExtendFactor(engine); + slant = getSlantFactor(engine); + embolden = getEmboldenFactor(engine); + + size = D2Fix(getPointSize(engine)); + } else { + fprintf(stderr, "\n! Internal error: bad native font flag in `make_font_def'\n"); + exit(3); + } + + psLen = strlen(psName); + famLen = strlen(famName); + styLen = strlen(styName); + + /* parameters after internal font ID: + // size[4] + // flags[2] + // lp[1] lf[1] ls[1] ps[lp] fam[lf] sty[ls] + // if flags & COLORED: + // c[4] + // if flags & VARIATIONS: + // nv[2] + // a[4nv] + // v[4nv] + */ + + fontDefLength + = 4 /* size */ + + 2 /* flags */ + + 3 /* name length */ + + psLen + famLen + styLen; + + if ((fontflags[f] & FONT_FLAGS_COLORED) != 0) { + fontDefLength += 4; /* 32-bit RGBA value */ + flags |= XDV_FLAG_COLORED; + } + + if (extend != 1.0) { + fontDefLength += 4; + flags |= XDV_FLAG_EXTEND; + } + if (slant != 0.0) { + fontDefLength += 4; + flags |= XDV_FLAG_SLANT; + } + if (embolden != 0.0) { + fontDefLength += 4; + flags |= XDV_FLAG_EMBOLDEN; + } + + if (fontDefLength > xdvBufSize) { + if (xdvbuffer != NULL) + free(xdvbuffer); + xdvBufSize = ((fontDefLength / 1024) + 1) * 1024; + xdvbuffer = (char*) xmalloc(xdvBufSize); + } + cp = xdvbuffer; + + *(Fixed*)cp = SWAP32(size); + cp += 4; + + *(uint16_t*)cp = SWAP16(flags); + cp += 2; + + *(uint8_t*)cp = psLen; + cp += 1; + *(uint8_t*)cp = famLen; + cp += 1; + *(uint8_t*)cp = styLen; + cp += 1; + memcpy(cp, psName, psLen); + cp += psLen; + memcpy(cp, famName, famLen); + cp += famLen; + memcpy(cp, styName, styLen); + cp += styLen; + + if ((fontflags[f] & FONT_FLAGS_COLORED) != 0) { + *(uint32_t*)cp = SWAP32(rgba); + cp += 4; + } + + if (flags & XDV_FLAG_EXTEND) { + Fixed f = D2Fix(extend); + *(uint32_t*)(cp) = SWAP32(f); + cp += 4; + } + if (flags & XDV_FLAG_SLANT) { + Fixed f = D2Fix(slant); + *(uint32_t*)(cp) = SWAP32(f); + cp += 4; + } + if (flags & XDV_FLAG_EMBOLDEN) { + Fixed f = D2Fix(embolden); + *(uint32_t*)(cp) = SWAP32(f); + cp += 4; + } + + free((char*) psName); + free((char*) famName); + free((char*) styName); + + return fontDefLength; } int applymapping(void* pCnv, const uint16_t* txtPtr, int txtLen) { - TECkit_Converter cnv = (TECkit_Converter)pCnv; - UInt32 inUsed, outUsed; - TECkit_Status status; - static UInt32 outLength = 0; - - /* allocate outBuffer if not big enough */ - if (outLength < txtLen * sizeof(UniChar) + 32) { - if (mappedtext != 0) - free(mappedtext); - outLength = txtLen * sizeof(UniChar) + 32; - mappedtext = xmalloc(outLength); - } - - /* try the mapping */ + TECkit_Converter cnv = (TECkit_Converter)pCnv; + UInt32 inUsed, outUsed; + TECkit_Status status; + static UInt32 outLength = 0; + + /* allocate outBuffer if not big enough */ + if (outLength < txtLen * sizeof(UniChar) + 32) { + if (mappedtext != 0) + free(mappedtext); + outLength = txtLen * sizeof(UniChar) + 32; + mappedtext = xmalloc(outLength); + } + + /* try the mapping */ retry: - status = TECkit_ConvertBuffer(cnv, - (Byte*)txtPtr, txtLen * sizeof(UniChar), &inUsed, - (Byte*)mappedtext, outLength, &outUsed, true); - - switch (status) { - case kStatus_NoError: - txtPtr = (const UniChar*)mappedtext; - return outUsed / sizeof(UniChar); - - case kStatus_OutputBufferFull: - outLength += (txtLen * sizeof(UniChar)) + 32; - free(mappedtext); - mappedtext = xmalloc(outLength); - goto retry; - - default: - return 0; - } + status = TECkit_ConvertBuffer(cnv, + (Byte*)txtPtr, txtLen * sizeof(UniChar), &inUsed, + (Byte*)mappedtext, outLength, &outUsed, true); + + switch (status) { + case kStatus_NoError: + txtPtr = (const UniChar*)mappedtext; + return outUsed / sizeof(UniChar); + + case kStatus_OutputBufferFull: + outLength += (txtLen * sizeof(UniChar)) + 32; + free(mappedtext); + mappedtext = xmalloc(outLength); + goto retry; + + default: + return 0; + } } static void snap_zone(scaled* value, scaled snap_value, scaled fuzz) { - scaled difference = *value - snap_value; - if (difference <= fuzz && difference >= -fuzz) - *value = snap_value; + scaled difference = *value - snap_value; + if (difference <= fuzz && difference >= -fuzz) + *value = snap_value; } void getnativecharheightdepth(integer font, integer ch, scaled* height, scaled* depth) { -#define QUAD(f) fontinfo[6+parambase[f]].cint -#define X_HEIGHT(f) fontinfo[5+parambase[f]].cint -#define CAP_HEIGHT(f) fontinfo[8+parambase[f]].cint +#define QUAD(f) fontinfo[6+parambase[f]].cint +#define X_HEIGHT(f) fontinfo[5+parambase[f]].cint +#define CAP_HEIGHT(f) fontinfo[8+parambase[f]].cint - float ht = 0.0; - float dp = 0.0; - Fixed fuzz; + float ht = 0.0; + float dp = 0.0; + Fixed fuzz; #ifdef XETEX_MAC - if (fontarea[font] == AAT_FONT_FLAG) { - CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]); - int gid = MapCharToGlyph_AAT(attributes, ch); - GetGlyphHeightDepth_AAT(attributes, gid, &ht, &dp); - } else + if (fontarea[font] == AAT_FONT_FLAG) { + CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]); + int gid = MapCharToGlyph_AAT(attributes, ch); + GetGlyphHeightDepth_AAT(attributes, gid, &ht, &dp); + } else #endif - if (fontarea[font] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; - int gid = mapCharToGlyph(engine, ch); - getGlyphHeightDepth(engine, gid, &ht, &dp); - } else { - fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_height_depth`\n"); - exit(3); - } - - *height = D2Fix(ht); - *depth = D2Fix(dp); - - /* snap to "known" zones for baseline, x-height, cap-height if within 4% of em-size */ - fuzz = QUAD(font) / 25; - snap_zone(depth, 0, fuzz); - snap_zone(height, 0, fuzz); - snap_zone(height, X_HEIGHT(font), fuzz); - snap_zone(height, CAP_HEIGHT(font), fuzz); + if (fontarea[font] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; + int gid = mapCharToGlyph(engine, ch); + getGlyphHeightDepth(engine, gid, &ht, &dp); + } else { + fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_height_depth`\n"); + exit(3); + } + + *height = D2Fix(ht); + *depth = D2Fix(dp); + + /* snap to "known" zones for baseline, x-height, cap-height if within 4% of em-size */ + fuzz = QUAD(font) / 25; + snap_zone(depth, 0, fuzz); + snap_zone(height, 0, fuzz); + snap_zone(height, X_HEIGHT(font), fuzz); + snap_zone(height, CAP_HEIGHT(font), fuzz); } scaled getnativecharht(integer f, integer c) { - scaled h, d; - getnativecharheightdepth(f, c, &h, &d); - return h; + scaled h, d; + getnativecharheightdepth(f, c, &h, &d); + return h; } scaled getnativechardp(integer f, integer c) { - scaled h, d; - getnativecharheightdepth(f, c, &h, &d); - return d; + scaled h, d; + getnativecharheightdepth(f, c, &h, &d); + return d; } void getnativecharsidebearings(integer font, integer ch, scaled* lsb, scaled* rsb) { - float l, r; + float l, r; #ifdef XETEX_MAC - if (fontarea[font] == AAT_FONT_FLAG) { - CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]); - int gid = MapCharToGlyph_AAT(attributes, ch); - GetGlyphSidebearings_AAT(attributes, gid, &l, &r); - } else + if (fontarea[font] == AAT_FONT_FLAG) { + CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]); + int gid = MapCharToGlyph_AAT(attributes, ch); + GetGlyphSidebearings_AAT(attributes, gid, &l, &r); + } else #endif - if (fontarea[font] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; - int gid = mapCharToGlyph(engine, ch); - getGlyphSidebearings(engine, gid, &l, &r); - } else { - fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_side_bearings'\n"); - exit(3); - } + if (fontarea[font] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; + int gid = mapCharToGlyph(engine, ch); + getGlyphSidebearings(engine, gid, &l, &r); + } else { + fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_side_bearings'\n"); + exit(3); + } - *lsb = D2Fix(l); - *rsb = D2Fix(r); + *lsb = D2Fix(l); + *rsb = D2Fix(r); } scaled getglyphbounds(integer font, integer edge, integer gid) { /* edge codes 1,2,3,4 => L T R B */ - float a, b; - + float a, b; + #ifdef XETEX_MAC - if (fontarea[font] == AAT_FONT_FLAG) { - CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]); - if (edge & 1) - GetGlyphSidebearings_AAT(attributes, gid, &a, &b); - else - GetGlyphHeightDepth_AAT(attributes, gid, &a, &b); - } else + if (fontarea[font] == AAT_FONT_FLAG) { + CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]); + if (edge & 1) + GetGlyphSidebearings_AAT(attributes, gid, &a, &b); + else + GetGlyphHeightDepth_AAT(attributes, gid, &a, &b); + } else #endif - if (fontarea[font] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; - if (edge & 1) - getGlyphSidebearings(engine, gid, &a, &b); - else - getGlyphHeightDepth(engine, gid, &a, &b); - } else { - fprintf(stderr, "\n! Internal error: bad native font flag in `get_glyph_bounds'\n"); - exit(3); - } - return D2Fix((edge <= 2) ? a : b); + if (fontarea[font] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; + if (edge & 1) + getGlyphSidebearings(engine, gid, &a, &b); + else + getGlyphHeightDepth(engine, gid, &a, &b); + } else { + fprintf(stderr, "\n! Internal error: bad native font flag in `get_glyph_bounds'\n"); + exit(3); + } + return D2Fix((edge <= 2) ? a : b); } scaled getnativecharic(integer f, integer c) { - scaled lsb, rsb; - getnativecharsidebearings(f, c, &lsb, &rsb); - if (rsb < 0) - return fontletterspace[f] - rsb; - else - return fontletterspace[f]; + scaled lsb, rsb; + getnativecharsidebearings(f, c, &lsb, &rsb); + if (rsb < 0) + return fontletterspace[f] - rsb; + else + return fontletterspace[f]; } scaled getnativecharwd(integer f, integer c) { - scaled wd = 0; + scaled wd = 0; #ifdef XETEX_MAC - if (fontarea[f] == AAT_FONT_FLAG) { - CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[f]); - int gid = MapCharToGlyph_AAT(attributes, c); - wd = D2Fix(GetGlyphWidth_AAT(attributes, gid)); - } else + if (fontarea[f] == AAT_FONT_FLAG) { + CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[f]); + int gid = MapCharToGlyph_AAT(attributes, c); + wd = D2Fix(GetGlyphWidth_AAT(attributes, gid)); + } else #endif - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f]; - int gid = mapCharToGlyph(engine, c); - wd = D2Fix(getGlyphWidthFromEngine(engine, gid)); - } else { - fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_wd'\n"); - exit(3); - } - return wd; + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f]; + int gid = mapCharToGlyph(engine, c); + wd = D2Fix(getGlyphWidthFromEngine(engine, gid)); + } else { + fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_wd'\n"); + exit(3); + } + return wd; } uint16_t get_native_glyph(void* pNode, unsigned index) { - memoryword* node = (memoryword*)pNode; - FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); - uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node)); - if (index >= native_glyph_count(node)) - return 0; - else - return glyphIDs[index]; + memoryword* node = (memoryword*)pNode; + FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); + uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node)); + if (index >= native_glyph_count(node)) + return 0; + else + return glyphIDs[index]; } void store_justified_native_glyphs(void* node) { #ifdef XETEX_MAC /* this is only called for AAT fonts */ - (void)DoAATLayout(node, 1); + (void)DoAATLayout(node, 1); #endif } void measure_native_node(void* pNode, int use_glyph_metrics) { - memoryword* node = (memoryword*)pNode; - int txtLen = native_length(node); - uint16_t* txtPtr = (uint16_t*)(node + native_node_size); + memoryword* node = (memoryword*)pNode; + int txtLen = native_length(node); + uint16_t* txtPtr = (uint16_t*)(node + native_node_size); - unsigned f = native_font(node); + unsigned f = native_font(node); #ifdef XETEX_MAC - if (fontarea[f] == AAT_FONT_FLAG) { - /* we're using this font in AAT mode, so fontlayoutengine[f] is actually a CFDictionaryRef */ - DoAATLayout(node, 0); - } else + if (fontarea[f] == AAT_FONT_FLAG) { + /* we're using this font in AAT mode, so fontlayoutengine[f] is actually a CFDictionaryRef */ + DoAATLayout(node, 0); + } else #endif - if (fontarea[f] == OTGR_FONT_FLAG) { - /* using this font in OT Layout mode, so fontlayoutengine[f] is actually a XeTeXLayoutEngine */ - - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)(fontlayoutengine[f]); - - FixedPoint* locations; - uint16_t* glyphIDs; - Fixed* glyphAdvances; - int totalGlyphCount = 0; - - /* need to find direction runs within the text, and call layoutChars separately for each */ - - UBiDiDirection dir; - void* glyph_info = 0; - static float* positions = 0; - static float* advances = 0; - static uint32_t* glyphs = 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 width = 0; - int i, runIndex; - int32_t logicalStart, length; - for (runIndex = 0; runIndex < nRuns; ++runIndex) { - dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length); - totalGlyphCount += layoutChars(engine, txtPtr, logicalStart, length, txtLen, (dir == UBIDI_RTL)); - } - - if (totalGlyphCount > 0) { - double x, y; - glyph_info = xmalloc(totalGlyphCount * native_glyph_info_size); - locations = (FixedPoint*)glyph_info; - glyphIDs = (uint16_t*)(locations + totalGlyphCount); - glyphAdvances = xmalloc(totalGlyphCount * sizeof(Fixed)); - totalGlyphCount = 0; - - x = y = 0.0; - for (runIndex = 0; runIndex < nRuns; ++runIndex) { - int nGlyphs; - dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length); - nGlyphs = layoutChars(engine, txtPtr, logicalStart, length, txtLen, - (dir == UBIDI_RTL)); - - glyphs = xmalloc(nGlyphs * sizeof(uint32_t)); - positions = xmalloc((nGlyphs * 2 + 2) * sizeof(float)); - advances = xmalloc(nGlyphs * sizeof(float)); - - getGlyphs(engine, glyphs); - getGlyphAdvances(engine, advances); - getGlyphPositions(engine, positions); - - for (i = 0; i < nGlyphs; ++i) { - glyphIDs[totalGlyphCount] = glyphs[i]; - locations[totalGlyphCount].x = D2Fix(positions[2*i] + x); - locations[totalGlyphCount].y = D2Fix(positions[2*i+1] + y); - glyphAdvances[totalGlyphCount] = D2Fix(advances[i]); - ++totalGlyphCount; - } - x += positions[2*i]; - y += positions[2*i+1]; - - free(glyphs); - free(positions); - } - width = x; - } - - node_width(node) = D2Fix(width); - native_glyph_count(node) = totalGlyphCount; - native_glyph_info_ptr(node) = glyph_info; - } else { - double width = 0; - totalGlyphCount = layoutChars(engine, txtPtr, 0, txtLen, txtLen, (dir == UBIDI_RTL)); - - glyphs = xmalloc(totalGlyphCount * sizeof(uint32_t)); - positions = xmalloc((totalGlyphCount * 2 + 2) * sizeof(float)); - advances = xmalloc(totalGlyphCount * sizeof(float)); - - getGlyphs(engine, glyphs); - getGlyphAdvances(engine, advances); - getGlyphPositions(engine, positions); - - if (totalGlyphCount > 0) { - int i; - glyph_info = xmalloc(totalGlyphCount * native_glyph_info_size); - locations = (FixedPoint*)glyph_info; - glyphIDs = (uint16_t*)(locations + totalGlyphCount); - glyphAdvances = xmalloc(totalGlyphCount * sizeof(Fixed)); - for (i = 0; i < totalGlyphCount; ++i) { - glyphIDs[i] = glyphs[i]; - glyphAdvances[i] = D2Fix(advances[i]); - locations[i].x = D2Fix(positions[2*i]); - locations[i].y = D2Fix(positions[2*i+1]); - } - width = D2Fix(positions[2*i]); - } - - node_width(node) = width; - native_glyph_count(node) = totalGlyphCount; - native_glyph_info_ptr(node) = glyph_info; - - free(glyphs); - free(positions); - } - - ubidi_close(pBiDi); - - - if (fontletterspace[f] != 0) { - Fixed lsDelta = 0; - Fixed lsUnit = fontletterspace[f]; - int i; - for (i = 0; i < totalGlyphCount; ++i) { - if (glyphAdvances[i] == 0 && lsDelta != 0) - lsDelta -= lsUnit; - locations[i].x += lsDelta; - lsDelta += lsUnit; - } - if (lsDelta != 0) { - lsDelta -= lsUnit; - node_width(node) += lsDelta; - } - } - } else { - fprintf(stderr, "\n! Internal error: bad native font flag in `measure_native_node'\n"); - exit(3); - } - - if (use_glyph_metrics == 0 || native_glyph_count(node) == 0) { - /* for efficiency, height and depth are the font's ascent/descent, - not true values based on the actual content of the word, - unless use_glyph_metrics is non-zero */ - node_height(node) = heightbase[f]; - node_depth(node) = depthbase[f]; - } else { - /* this iterates over the glyph data whether it comes from AAT or OT layout */ - FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); - uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node)); - float yMin = 65536.0; - float yMax = -65536.0; - int i; - for (i = 0; i < native_glyph_count(node); ++i) { - float ht, dp; - float y = Fix2D(-locations[i].y); /* NB negative is upwards in locations[].y! */ - - GlyphBBox bbox; - if (getCachedGlyphBBox(f, glyphIDs[i], &bbox) == 0) { + if (fontarea[f] == OTGR_FONT_FLAG) { + /* using this font in OT Layout mode, so fontlayoutengine[f] is actually a XeTeXLayoutEngine */ + + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)(fontlayoutengine[f]); + + FixedPoint* locations; + uint16_t* glyphIDs; + Fixed* glyphAdvances; + int totalGlyphCount = 0; + + /* need to find direction runs within the text, and call layoutChars separately for each */ + + UBiDiDirection dir; + void* glyph_info = 0; + static float* positions = 0; + static float* advances = 0; + static uint32_t* glyphs = 0; + + UBiDi* pBiDi = ubidi_open(); + + UErrorCode errorCode = U_ZERO_ERROR; + ubidi_setPara(pBiDi, (const UChar*) 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 width = 0; + int i, runIndex; + int32_t logicalStart, length; + for (runIndex = 0; runIndex < nRuns; ++runIndex) { + dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length); + totalGlyphCount += layoutChars(engine, txtPtr, logicalStart, length, txtLen, (dir == UBIDI_RTL)); + } + + if (totalGlyphCount > 0) { + double x, y; + glyph_info = xcalloc(totalGlyphCount, native_glyph_info_size); + locations = (FixedPoint*)glyph_info; + glyphIDs = (uint16_t*)(locations + totalGlyphCount); + glyphAdvances = (Fixed*) xcalloc(totalGlyphCount, sizeof(Fixed)); + totalGlyphCount = 0; + + x = y = 0.0; + for (runIndex = 0; runIndex < nRuns; ++runIndex) { + int nGlyphs; + dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length); + nGlyphs = layoutChars(engine, txtPtr, logicalStart, length, txtLen, + (dir == UBIDI_RTL)); + + glyphs = (uint32_t*) xcalloc(nGlyphs, sizeof(uint32_t)); + positions = (float*) xcalloc(nGlyphs * 2 + 2, sizeof(float)); + advances = (float*) xcalloc(nGlyphs, sizeof(float)); + + getGlyphs(engine, glyphs); + getGlyphAdvances(engine, advances); + getGlyphPositions(engine, positions); + + for (i = 0; i < nGlyphs; ++i) { + glyphIDs[totalGlyphCount] = glyphs[i]; + locations[totalGlyphCount].x = D2Fix(positions[2*i] + x); + locations[totalGlyphCount].y = D2Fix(positions[2*i+1] + y); + glyphAdvances[totalGlyphCount] = D2Fix(advances[i]); + ++totalGlyphCount; + } + x += positions[2*i]; + y += positions[2*i+1]; + + free(glyphs); + free(positions); + free(advances); + } + width = x; + } + + node_width(node) = D2Fix(width); + native_glyph_count(node) = totalGlyphCount; + native_glyph_info_ptr(node) = glyph_info; + } else { + double width = 0; + totalGlyphCount = layoutChars(engine, txtPtr, 0, txtLen, txtLen, (dir == UBIDI_RTL)); + + glyphs = (uint32_t*) xcalloc(totalGlyphCount, sizeof(uint32_t)); + positions = (float*) xcalloc(totalGlyphCount * 2 + 2, sizeof(float)); + advances = (float*) xcalloc(totalGlyphCount, sizeof(float)); + + getGlyphs(engine, glyphs); + getGlyphAdvances(engine, advances); + getGlyphPositions(engine, positions); + + if (totalGlyphCount > 0) { + int i; + glyph_info = xcalloc(totalGlyphCount, native_glyph_info_size); + locations = (FixedPoint*)glyph_info; + glyphIDs = (uint16_t*)(locations + totalGlyphCount); + glyphAdvances = (Fixed*) xcalloc(totalGlyphCount, sizeof(Fixed)); + for (i = 0; i < totalGlyphCount; ++i) { + glyphIDs[i] = glyphs[i]; + glyphAdvances[i] = D2Fix(advances[i]); + locations[i].x = D2Fix(positions[2*i]); + locations[i].y = D2Fix(positions[2*i+1]); + } + width = D2Fix(positions[2*i]); + } + + node_width(node) = width; + native_glyph_count(node) = totalGlyphCount; + native_glyph_info_ptr(node) = glyph_info; + + free(glyphs); + free(positions); + free(advances); + } + + ubidi_close(pBiDi); + + + if (fontletterspace[f] != 0) { + Fixed lsDelta = 0; + Fixed lsUnit = fontletterspace[f]; + int i; + for (i = 0; i < totalGlyphCount; ++i) { + if (glyphAdvances[i] == 0 && lsDelta != 0) + lsDelta -= lsUnit; + locations[i].x += lsDelta; + lsDelta += lsUnit; + } + if (lsDelta != 0) { + lsDelta -= lsUnit; + node_width(node) += lsDelta; + } + } + free(glyphAdvances); + } else { + fprintf(stderr, "\n! Internal error: bad native font flag in `measure_native_node'\n"); + exit(3); + } + + if (use_glyph_metrics == 0 || native_glyph_count(node) == 0) { + /* for efficiency, height and depth are the font's ascent/descent, + not true values based on the actual content of the word, + unless use_glyph_metrics is non-zero */ + node_height(node) = heightbase[f]; + node_depth(node) = depthbase[f]; + } else { + /* this iterates over the glyph data whether it comes from AAT or OT layout */ + FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); + uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node)); + float yMin = 65536.0; + float yMax = -65536.0; + int i; + for (i = 0; i < native_glyph_count(node); ++i) { + float ht, dp; + float y = Fix2D(-locations[i].y); /* NB negative is upwards in locations[].y! */ + + GlyphBBox bbox; + if (getCachedGlyphBBox(f, glyphIDs[i], &bbox) == 0) { #ifdef XETEX_MAC - if (fontarea[f] == AAT_FONT_FLAG) - GetGlyphBBox_AAT((CFDictionaryRef)(fontlayoutengine[f]), glyphIDs[i], &bbox); - else + if (fontarea[f] == AAT_FONT_FLAG) + GetGlyphBBox_AAT((CFDictionaryRef)(fontlayoutengine[f]), glyphIDs[i], &bbox); + else #endif - if (fontarea[f] == OTGR_FONT_FLAG) - getGlyphBounds((XeTeXLayoutEngine)(fontlayoutengine[f]), glyphIDs[i], &bbox); - - cacheGlyphBBox(f, glyphIDs[i], &bbox); - } - - ht = bbox.yMax; - dp = -bbox.yMin; - - if (y + ht > yMax) - yMax = y + ht; - if (y - dp < yMin) - yMin = y - dp; - } - node_height(node) = D2Fix(yMax); - node_depth(node) = -D2Fix(yMin); - } + if (fontarea[f] == OTGR_FONT_FLAG) + getGlyphBounds((XeTeXLayoutEngine)(fontlayoutengine[f]), glyphIDs[i], &bbox); + + cacheGlyphBBox(f, glyphIDs[i], &bbox); + } + + ht = bbox.yMax; + dp = -bbox.yMin; + + if (y + ht > yMax) + yMax = y + ht; + if (y - dp < yMin) + yMin = y - dp; + } + node_height(node) = D2Fix(yMax); + node_depth(node) = -D2Fix(yMin); + } } Fixed get_native_italic_correction(void* pNode) { - memoryword* node = pNode; - unsigned f = native_font(node); - unsigned n = native_glyph_count(node); - if (n > 0) { - FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); - uint16_t* glyphIDs = (uint16_t*)(locations + n); + memoryword* node = (memoryword*) pNode; + unsigned f = native_font(node); + unsigned n = native_glyph_count(node); + if (n > 0) { + FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); + uint16_t* glyphIDs = (uint16_t*)(locations + n); #ifdef XETEX_MAC - if (fontarea[f] == AAT_FONT_FLAG) - return D2Fix(GetGlyphItalCorr_AAT((CFDictionaryRef)(fontlayoutengine[f]), glyphIDs[n-1])) - + fontletterspace[f]; + if (fontarea[f] == AAT_FONT_FLAG) + return D2Fix(GetGlyphItalCorr_AAT((CFDictionaryRef)(fontlayoutengine[f]), glyphIDs[n-1])) + + fontletterspace[f]; #endif - if (fontarea[f] == OTGR_FONT_FLAG) - return D2Fix(getGlyphItalCorr((XeTeXLayoutEngine)(fontlayoutengine[f]), glyphIDs[n-1])) - + fontletterspace[f]; - } + if (fontarea[f] == OTGR_FONT_FLAG) + return D2Fix(getGlyphItalCorr((XeTeXLayoutEngine)(fontlayoutengine[f]), glyphIDs[n-1])) + + fontletterspace[f]; + } - return 0; + return 0; } Fixed get_native_glyph_italic_correction(void* pNode) { - memoryword* node = pNode; - uint16_t gid = native_glyph(node); - unsigned f = native_font(node); + memoryword* node = (memoryword*) pNode; + uint16_t gid = native_glyph(node); + unsigned f = native_font(node); #ifdef XETEX_MAC - if (fontarea[f] == AAT_FONT_FLAG) - return D2Fix(GetGlyphItalCorr_AAT((CFDictionaryRef)(fontlayoutengine[f]), gid)); + if (fontarea[f] == AAT_FONT_FLAG) + return D2Fix(GetGlyphItalCorr_AAT((CFDictionaryRef)(fontlayoutengine[f]), gid)); #endif - if (fontarea[f] == OTGR_FONT_FLAG) - return D2Fix(getGlyphItalCorr((XeTeXLayoutEngine)(fontlayoutengine[f]), gid)); + if (fontarea[f] == OTGR_FONT_FLAG) + return D2Fix(getGlyphItalCorr((XeTeXLayoutEngine)(fontlayoutengine[f]), gid)); - return 0; /* can't actually happen */ + return 0; /* can't actually happen */ } void measure_native_glyph(void* pNode, int use_glyph_metrics) { - memoryword* node = pNode; - uint16_t gid = native_glyph(node); - unsigned f = native_font(node); + memoryword* node = (memoryword*) pNode; + uint16_t gid = native_glyph(node); + unsigned f = native_font(node); - float ht = 0.0; - float dp = 0.0; + float ht = 0.0; + float dp = 0.0; #ifdef XETEX_MAC - if (fontarea[f] == AAT_FONT_FLAG) { - CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[f]); - node_width(node) = D2Fix(GetGlyphWidth_AAT(attributes, gid)); - if (use_glyph_metrics) - GetGlyphHeightDepth_AAT(attributes, gid, &ht, &dp); - } else + if (fontarea[f] == AAT_FONT_FLAG) { + CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[f]); + node_width(node) = D2Fix(GetGlyphWidth_AAT(attributes, gid)); + if (use_glyph_metrics) + GetGlyphHeightDepth_AAT(attributes, gid, &ht, &dp); + } else #endif - if (fontarea[f] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f]; - XeTeXFont fontInst = getFont(engine); - node_width(node) = D2Fix(getGlyphWidth(fontInst, gid)); - if (use_glyph_metrics) - getGlyphHeightDepth(engine, gid, &ht, &dp); - } else { - fprintf(stderr, "\n! Internal error: bad native font flag in `measure_native_glyph'\n"); - exit(3); - } - - if (use_glyph_metrics) { - node_height(node) = D2Fix(ht); - node_depth(node) = D2Fix(dp); - } else { - node_height(node) = heightbase[f]; - node_depth(node) = depthbase[f]; - } + if (fontarea[f] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f]; + XeTeXFont fontInst = getFont(engine); + node_width(node) = D2Fix(getGlyphWidth(fontInst, gid)); + if (use_glyph_metrics) + getGlyphHeightDepth(engine, gid, &ht, &dp); + } else { + fprintf(stderr, "\n! Internal error: bad native font flag in `measure_native_glyph'\n"); + exit(3); + } + + if (use_glyph_metrics) { + node_height(node) = D2Fix(ht); + node_depth(node) = D2Fix(dp); + } else { + node_height(node) = heightbase[f]; + node_depth(node) = depthbase[f]; + } } integer mapchartoglyph(integer font, integer ch) { - if (ch > 0x10ffff || ((ch >= 0xd800) && (ch <= 0xdfff))) - return 0; + if (ch > 0x10ffff || ((ch >= 0xd800) && (ch <= 0xdfff))) + return 0; #ifdef XETEX_MAC - if (fontarea[font] == AAT_FONT_FLAG) - return MapCharToGlyph_AAT((CFDictionaryRef)(fontlayoutengine[font]), ch); - else + if (fontarea[font] == AAT_FONT_FLAG) + return MapCharToGlyph_AAT((CFDictionaryRef)(fontlayoutengine[font]), ch); + else #endif - if (fontarea[font] == OTGR_FONT_FLAG) - return mapCharToGlyph((XeTeXLayoutEngine)(fontlayoutengine[font]), ch); - else { - fprintf(stderr, "\n! Internal error: bad native font flag in `map_char_to_glyph'\n"); - exit(3); - } + if (fontarea[font] == OTGR_FONT_FLAG) + return mapCharToGlyph((XeTeXLayoutEngine)(fontlayoutengine[font]), ch); + else { + fprintf(stderr, "\n! Internal error: bad native font flag in `map_char_to_glyph'\n"); + exit(3); + } } integer mapglyphtoindex(integer font) - /* glyph name is at nameoffile+1 */ + /* glyph name is at nameoffile+1 */ { #ifdef XETEX_MAC - if (fontarea[font] == AAT_FONT_FLAG) - return MapGlyphToIndex_AAT((CFDictionaryRef)(fontlayoutengine[font]), (const char*)nameoffile + 1); - else + if (fontarea[font] == AAT_FONT_FLAG) + return MapGlyphToIndex_AAT((CFDictionaryRef)(fontlayoutengine[font]), (const char*)nameoffile + 1); + else #endif - 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 in `map_glyph_to_index'\n"); - exit(3); - } + 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 in `map_glyph_to_index'\n"); + exit(3); + } } integer getfontcharrange(integer font, int first) { #ifdef XETEX_MAC - if (fontarea[font] == AAT_FONT_FLAG) - return GetFontCharRange_AAT((CFDictionaryRef)(fontlayoutengine[font]), first); - else + if (fontarea[font] == AAT_FONT_FLAG) + return GetFontCharRange_AAT((CFDictionaryRef)(fontlayoutengine[font]), first); + else #endif - if (fontarea[font] == OTGR_FONT_FLAG) - return getFontCharRange((XeTeXLayoutEngine)(fontlayoutengine[font]), first); - else { - fprintf(stderr, "\n! Internal error: bad native font flag in `get_font_char_range'\n"); - exit(3); - } + if (fontarea[font] == OTGR_FONT_FLAG) + return getFontCharRange((XeTeXLayoutEngine)(fontlayoutengine[font]), first); + else { + fprintf(stderr, "\n! Internal error: bad native font flag in `get_font_char_range'\n"); + exit(3); + } } Fixed D2Fix(double d) { - Fixed rval = (int)(d * 65536.0 + 0.5); - return rval; + Fixed rval = (int)(d * 65536.0 + 0.5); + return rval; } double Fix2D(Fixed f) { - double rval = f / 65536.0; - return rval; + double rval = f / 65536.0; + return rval; } /* these are here, not XeTeX_mac.c, because we need stubs on other platforms */ @@ -2324,633 +2329,633 @@ void aatgetfontmetrics(CFDictionaryRef attributes, integer* ascent, integer* descent, integer* xheight, integer* capheight, integer* slant) { #ifdef XETEX_MAC - CTFontRef font = fontFromAttributes(attributes); + CTFontRef font = fontFromAttributes(attributes); - *ascent = D2Fix(CTFontGetAscent(font)); - *descent = D2Fix(CTFontGetDescent(font)); - *xheight = D2Fix(CTFontGetXHeight(font)); - *capheight = D2Fix(CTFontGetCapHeight(font)); - *slant = D2Fix(tan(-CTFontGetSlantAngle(font) * M_PI / 180.0)); + *ascent = D2Fix(CTFontGetAscent(font)); + *descent = D2Fix(CTFontGetDescent(font)); + *xheight = D2Fix(CTFontGetXHeight(font)); + *capheight = D2Fix(CTFontGetCapHeight(font)); + *slant = D2Fix(tan(-CTFontGetSlantAngle(font) * M_PI / 180.0)); #endif } int aatfontget(int what, CFDictionaryRef attributes) { - int rval = -1; + int rval = -1; #ifdef XETEX_MAC - CTFontRef font = fontFromAttributes(attributes); - CFArrayRef list; - - switch (what) { - case XeTeX_count_glyphs: - rval = CTFontGetGlyphCount(font); - break; - - case XeTeX_count_variations: - case XeTeX_count_features: - list = (what == XeTeX_count_variations ? CTFontCopyVariationAxes(font) - : CTFontCopyFeatures(font)); - if (list) { - rval = CFArrayGetCount(list); - CFRelease(list); - } - break; - } + CTFontRef font = fontFromAttributes(attributes); + CFArrayRef list; + + switch (what) { + case XeTeX_count_glyphs: + rval = CTFontGetGlyphCount(font); + break; + + case XeTeX_count_variations: + case XeTeX_count_features: + list = (what == XeTeX_count_variations ? CTFontCopyVariationAxes(font) + : CTFontCopyFeatures(font)); + if (list) { + rval = CFArrayGetCount(list); + CFRelease(list); + } + break; + } #endif - return rval; + return rval; } int aatfontget1(int what, CFDictionaryRef attributes, int param) { - int rval = -1; + int rval = -1; #ifdef XETEX_MAC - CTFontRef font = fontFromAttributes(attributes); - - switch (what) { - case XeTeX_variation: - { - CFArrayRef axes = CTFontCopyVariationAxes(font); - if (axes) { - if (CFArrayGetCount(axes) > param) { - CFDictionaryRef variation = CFArrayGetValueAtIndex(axes, param); - CFNumberRef identifier = CFDictionaryGetValue(variation, kCTFontVariationAxisIdentifierKey); - if (identifier) - CFNumberGetValue(identifier, kCFNumberIntType, &rval); - } - CFRelease(axes); - } - break; - } - - case XeTeX_variation_min: - case XeTeX_variation_max: - case XeTeX_variation_default: - { - CFArrayRef axes = CTFontCopyVariationAxes(font); - if (axes) { - CFDictionaryRef variation = findDictionaryInArrayWithIdentifier(axes, kCTFontVariationAxisIdentifierKey, param); - CFStringRef key = (what == XeTeX_variation_min ? kCTFontVariationAxisMinimumValueKey : - (what == XeTeX_variation_max ? kCTFontVariationAxisMaximumValueKey : - kCTFontVariationAxisDefaultValueKey)); - CFNumberRef value = CFDictionaryGetValue(variation, key); - if (value) - CFNumberGetValue(value, kCFNumberIntType, &rval); - CFRelease(axes); - } - break; - } - - case XeTeX_feature_code: - { - CFArrayRef features = CTFontCopyFeatures(font); - if (features) { - if (CFArrayGetCount(features) > param) { - CFDictionaryRef feature = CFArrayGetValueAtIndex(features, param); - CFNumberRef identifier = CFDictionaryGetValue(feature, kCTFontFeatureTypeIdentifierKey); - if (identifier) - CFNumberGetValue(identifier, kCFNumberIntType, &rval); - } - CFRelease(features); - } - break; - } - - case XeTeX_is_exclusive_feature: - { - CFArrayRef features = CTFontCopyFeatures(font); - if (features) { - CFBooleanRef value; - CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param); - Boolean found = CFDictionaryGetValueIfPresent(feature, kCTFontFeatureTypeExclusiveKey, (const void **)&value); - if (found) - rval = CFBooleanGetValue(value); - CFRelease(features); - } - break; - } - - case XeTeX_count_selectors: - { - CFArrayRef features = CTFontCopyFeatures(font); - if (features) { - CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param); - if (feature) { - CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); - if (selectors) - rval = CFArrayGetCount(selectors); - } - CFRelease(features); - } - break; - } - } + CTFontRef font = fontFromAttributes(attributes); + + switch (what) { + case XeTeX_variation: + { + CFArrayRef axes = CTFontCopyVariationAxes(font); + if (axes) { + if (CFArrayGetCount(axes) > param) { + CFDictionaryRef variation = CFArrayGetValueAtIndex(axes, param); + CFNumberRef identifier = CFDictionaryGetValue(variation, kCTFontVariationAxisIdentifierKey); + if (identifier) + CFNumberGetValue(identifier, kCFNumberIntType, &rval); + } + CFRelease(axes); + } + break; + } + + case XeTeX_variation_min: + case XeTeX_variation_max: + case XeTeX_variation_default: + { + CFArrayRef axes = CTFontCopyVariationAxes(font); + if (axes) { + CFDictionaryRef variation = findDictionaryInArrayWithIdentifier(axes, kCTFontVariationAxisIdentifierKey, param); + CFStringRef key = (what == XeTeX_variation_min ? kCTFontVariationAxisMinimumValueKey : + (what == XeTeX_variation_max ? kCTFontVariationAxisMaximumValueKey : + kCTFontVariationAxisDefaultValueKey)); + CFNumberRef value = CFDictionaryGetValue(variation, key); + if (value) + CFNumberGetValue(value, kCFNumberIntType, &rval); + CFRelease(axes); + } + break; + } + + case XeTeX_feature_code: + { + CFArrayRef features = CTFontCopyFeatures(font); + if (features) { + if (CFArrayGetCount(features) > param) { + CFDictionaryRef feature = CFArrayGetValueAtIndex(features, param); + CFNumberRef identifier = CFDictionaryGetValue(feature, kCTFontFeatureTypeIdentifierKey); + if (identifier) + CFNumberGetValue(identifier, kCFNumberIntType, &rval); + } + CFRelease(features); + } + break; + } + + case XeTeX_is_exclusive_feature: + { + CFArrayRef features = CTFontCopyFeatures(font); + if (features) { + CFBooleanRef value; + CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param); + Boolean found = CFDictionaryGetValueIfPresent(feature, kCTFontFeatureTypeExclusiveKey, (const void **)&value); + if (found) + rval = CFBooleanGetValue(value); + CFRelease(features); + } + break; + } + + case XeTeX_count_selectors: + { + CFArrayRef features = CTFontCopyFeatures(font); + if (features) { + CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param); + if (feature) { + CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); + if (selectors) + rval = CFArrayGetCount(selectors); + } + CFRelease(features); + } + break; + } + } #endif - - return rval; + + return rval; } int aatfontget2(int what, CFDictionaryRef attributes, int param1, int param2) { - int rval = -1; + int rval = -1; #ifdef XETEX_MAC - CTFontRef font = fontFromAttributes(attributes); - CFArrayRef features = CTFontCopyFeatures(font); - if (features) { - CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param1); - if (feature) { - CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); - if (selectors) { - CFDictionaryRef selector; - switch (what) { - case XeTeX_selector_code: - if (CFArrayGetCount(selectors) > param2) { - CFNumberRef identifier; - selector = CFArrayGetValueAtIndex(selectors, param2); - identifier = CFDictionaryGetValue(selector, kCTFontFeatureSelectorIdentifierKey); - if (identifier) - CFNumberGetValue(identifier, kCFNumberIntType, &rval); - } - break; - case XeTeX_is_default_selector: - selector = findDictionaryInArrayWithIdentifier(selectors, kCTFontFeatureSelectorIdentifierKey, param2); - if (selector) { - CFBooleanRef isDefault; - Boolean found = CFDictionaryGetValueIfPresent(selector, kCTFontFeatureSelectorDefaultKey, (const void **)&isDefault); - if (found) - rval = CFBooleanGetValue(isDefault); - } - break; - } - } - } - CFRelease(features); - } + CTFontRef font = fontFromAttributes(attributes); + CFArrayRef features = CTFontCopyFeatures(font); + if (features) { + CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param1); + if (feature) { + CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); + if (selectors) { + CFDictionaryRef selector; + switch (what) { + case XeTeX_selector_code: + if (CFArrayGetCount(selectors) > param2) { + CFNumberRef identifier; + selector = CFArrayGetValueAtIndex(selectors, param2); + identifier = CFDictionaryGetValue(selector, kCTFontFeatureSelectorIdentifierKey); + if (identifier) + CFNumberGetValue(identifier, kCFNumberIntType, &rval); + } + break; + case XeTeX_is_default_selector: + selector = findDictionaryInArrayWithIdentifier(selectors, kCTFontFeatureSelectorIdentifierKey, param2); + if (selector) { + CFBooleanRef isDefault; + Boolean found = CFDictionaryGetValueIfPresent(selector, kCTFontFeatureSelectorDefaultKey, (const void **)&isDefault); + if (found) + rval = CFBooleanGetValue(isDefault); + } + break; + } + } + } + CFRelease(features); + } #endif - - return rval; + + return rval; } int aatfontgetnamed(int what, CFDictionaryRef attributes) { - int rval = -1; + int rval = -1; #ifdef XETEX_MAC - CTFontRef font = fontFromAttributes(attributes); - - switch (what) { - case XeTeX_find_variation_by_name: - { - CFArrayRef axes = CTFontCopyVariationAxes(font); - if (axes) { - CFDictionaryRef variation = findDictionaryInArray(axes, kCTFontVariationAxisNameKey, - (const char*)nameoffile + 1, namelength); - if (variation) { - CFNumberRef identifier = CFDictionaryGetValue(variation, kCTFontVariationAxisIdentifierKey); - if (identifier) - CFNumberGetValue(identifier, kCFNumberIntType, &rval); - } - CFRelease(axes); - } - break; - } - - case XeTeX_find_feature_by_name: - { - CFArrayRef features = CTFontCopyFeatures(font); - if (features) { - CFDictionaryRef feature = findDictionaryInArray(features, kCTFontFeatureTypeNameKey, - (const char*)nameoffile + 1, namelength); - if (feature) { - CFNumberRef identifier = CFDictionaryGetValue(feature, kCTFontFeatureTypeIdentifierKey); - CFNumberGetValue(identifier, kCFNumberIntType, &rval); - } - CFRelease(features); - } - break; - } - } + CTFontRef font = fontFromAttributes(attributes); + + switch (what) { + case XeTeX_find_variation_by_name: + { + CFArrayRef axes = CTFontCopyVariationAxes(font); + if (axes) { + CFDictionaryRef variation = findDictionaryInArray(axes, kCTFontVariationAxisNameKey, + (const char*)nameoffile + 1, namelength); + if (variation) { + CFNumberRef identifier = CFDictionaryGetValue(variation, kCTFontVariationAxisIdentifierKey); + if (identifier) + CFNumberGetValue(identifier, kCFNumberIntType, &rval); + } + CFRelease(axes); + } + break; + } + + case XeTeX_find_feature_by_name: + { + CFArrayRef features = CTFontCopyFeatures(font); + if (features) { + CFDictionaryRef feature = findDictionaryInArray(features, kCTFontFeatureTypeNameKey, + (const char*)nameoffile + 1, namelength); + if (feature) { + CFNumberRef identifier = CFDictionaryGetValue(feature, kCTFontFeatureTypeIdentifierKey); + CFNumberGetValue(identifier, kCFNumberIntType, &rval); + } + CFRelease(features); + } + break; + } + } #endif - - return rval; + + return rval; } int aatfontgetnamed1(int what, CFDictionaryRef attributes, int param) { - int rval = -1; + int rval = -1; #ifdef XETEX_MAC - CTFontRef font = fontFromAttributes(attributes); - - if (what == XeTeX_find_selector_by_name) { - CFArrayRef features = CTFontCopyFeatures(font); - if (features) { - CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param); - if (feature) { - CFNumberRef selector = findSelectorByName(feature, (const char*)nameoffile + 1, namelength); - if (selector) - CFNumberGetValue(selector, kCFNumberIntType, &rval); - } - CFRelease(features); - } - } + CTFontRef font = fontFromAttributes(attributes); + + if (what == XeTeX_find_selector_by_name) { + CFArrayRef features = CTFontCopyFeatures(font); + if (features) { + CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param); + if (feature) { + CFNumberRef selector = findSelectorByName(feature, (const char*)nameoffile + 1, namelength); + if (selector) + CFNumberGetValue(selector, kCFNumberIntType, &rval); + } + CFRelease(features); + } + } #endif - - return rval; + + return rval; } void aatprintfontname(int what, CFDictionaryRef attributes, int param1, int param2) { #ifdef XETEX_MAC - CTFontRef font = fontFromAttributes(attributes); - CFStringRef name = NULL; - if (what == XeTeX_variation_name) { - CFArrayRef axes = CTFontCopyVariationAxes(font); - if (axes) { - CFDictionaryRef variation = findDictionaryInArrayWithIdentifier(axes, - kCTFontVariationAxisIdentifierKey, - param1); - if (variation) - name = CFDictionaryGetValue(variation, kCTFontVariationAxisNameKey); - CFRelease(axes); - } - } else if (what == XeTeX_feature_name || what == XeTeX_selector_name) { - CFArrayRef features = CTFontCopyFeatures(font); - if (features) { - CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, - kCTFontFeatureTypeIdentifierKey, - param1); - if (feature) { - if (what == XeTeX_feature_name) - name = CFDictionaryGetValue(feature, kCTFontFeatureTypeNameKey); - else { - CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); - CFDictionaryRef selector = findDictionaryInArrayWithIdentifier(selectors, - kCTFontFeatureSelectorIdentifierKey, - param2); - if (selector) - name = CFDictionaryGetValue(selector, kCTFontFeatureSelectorNameKey); - } - } - CFRelease(features); - } - } - - if (name) { - CFIndex len = CFStringGetLength(name); - UniChar* buf = xmalloc(len * sizeof(UniChar)); - CFStringGetCharacters(name, CFRangeMake(0, len), buf); - printchars(buf, len); - free(buf); - } + CTFontRef font = fontFromAttributes(attributes); + CFStringRef name = NULL; + if (what == XeTeX_variation_name) { + CFArrayRef axes = CTFontCopyVariationAxes(font); + if (axes) { + CFDictionaryRef variation = findDictionaryInArrayWithIdentifier(axes, + kCTFontVariationAxisIdentifierKey, + param1); + if (variation) + name = CFDictionaryGetValue(variation, kCTFontVariationAxisNameKey); + CFRelease(axes); + } + } else if (what == XeTeX_feature_name || what == XeTeX_selector_name) { + CFArrayRef features = CTFontCopyFeatures(font); + if (features) { + CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, + kCTFontFeatureTypeIdentifierKey, + param1); + if (feature) { + if (what == XeTeX_feature_name) + name = CFDictionaryGetValue(feature, kCTFontFeatureTypeNameKey); + else { + CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); + CFDictionaryRef selector = findDictionaryInArrayWithIdentifier(selectors, + kCTFontFeatureSelectorIdentifierKey, + param2); + if (selector) + name = CFDictionaryGetValue(selector, kCTFontFeatureSelectorNameKey); + } + } + CFRelease(features); + } + } + + if (name) { + CFIndex len = CFStringGetLength(name); + UniChar* buf = xcalloc(len, sizeof(UniChar)); + CFStringGetCharacters(name, CFRangeMake(0, len), buf); + printchars(buf, len); + free(buf); + } #endif } void printglyphname(integer font, integer gid) { - char* s; - int len = 0; + char* s; + int len = 0; #ifdef XETEX_MAC - if (fontarea[font] == AAT_FONT_FLAG) { - s = GetGlyphNameFromCTFont(fontFromInteger(font), gid, &len); - } else + if (fontarea[font] == AAT_FONT_FLAG) { + s = GetGlyphNameFromCTFont(fontFromInteger(font), gid, &len); + } else #endif - if (fontarea[font] == OTGR_FONT_FLAG) { - XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; - s = (char*)getGlyphName(getFont(engine), gid, &len); - } else { - fprintf(stderr, "\n! Internal error: bad native font flag in `print_glyph_name'\n"); - exit(3); - } - while (len-- > 0) - printchar(*s++); + if (fontarea[font] == OTGR_FONT_FLAG) { + XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font]; + s = (char*)getGlyphName(getFont(engine), gid, &len); + } else { + fprintf(stderr, "\n! Internal error: bad native font flag in `print_glyph_name'\n"); + exit(3); + } + while (len-- > 0) + printchar(*s++); } int u_open_in(unicodefile* f, integer filefmt, const_string fopen_mode, integer mode, integer encodingData) { - boolean rval; - *f = xmalloc(sizeof(UFILE)); - (*f)->encodingMode = 0; - (*f)->conversionData = 0; - (*f)->savedChar = -1; - (*f)->skipNextLF = 0; - rval = open_input (&((*f)->f), filefmt, fopen_mode); - if (rval) { - int B1, B2; - if (mode == AUTO) { - /* sniff encoding form */ - B1 = getc((*f)->f); - B2 = getc((*f)->f); - if (B1 == 0xfe && B2 == 0xff) - mode = UTF16BE; - else if (B2 == 0xfe && B1 == 0xff) - mode = UTF16LE; - else if (B1 == 0 && B2 != 0) { - mode = UTF16BE; - rewind((*f)->f); - } else if (B2 == 0 && B1 != 0) { - mode = UTF16LE; - rewind((*f)->f); - } else if (B1 == 0xef && B2 == 0xbb) { - int B3 = getc((*f)->f); - if (B3 == 0xbf) - mode = UTF8; - } - if (mode == AUTO) { - rewind((*f)->f); - mode = UTF8; - } - } - - setinputfileencoding(*f, mode, encodingData); - } - return rval; + boolean rval; + *f = (unicodefile) xmalloc(sizeof(UFILE)); + (*f)->encodingMode = 0; + (*f)->conversionData = 0; + (*f)->savedChar = -1; + (*f)->skipNextLF = 0; + rval = open_input (&((*f)->f), filefmt, fopen_mode); + if (rval) { + int B1, B2; + if (mode == AUTO) { + /* sniff encoding form */ + B1 = getc((*f)->f); + B2 = getc((*f)->f); + if (B1 == 0xfe && B2 == 0xff) + mode = UTF16BE; + else if (B2 == 0xfe && B1 == 0xff) + mode = UTF16LE; + else if (B1 == 0 && B2 != 0) { + mode = UTF16BE; + rewind((*f)->f); + } else if (B2 == 0 && B1 != 0) { + mode = UTF16LE; + rewind((*f)->f); + } else if (B1 == 0xef && B2 == 0xbb) { + int B3 = getc((*f)->f); + if (B3 == 0xbf) + mode = UTF8; + } + if (mode == AUTO) { + rewind((*f)->f); + mode = UTF8; + } + } + + setinputfileencoding(*f, mode, encodingData); + } + return rval; } #if defined(WIN32) static int Isspace(char c) { - return (c == ' ' || c == '\t'); + return (c == ' ' || c == '\t'); } #endif int open_dvi_output(FILE** fptr) { - if (nopdfoutput) { - return open_output(fptr, FOPEN_WBIN_MODE); - } else { - const char *p = (const char*)nameoffile+1; - char *cmd, *q; - int len = strlen(p); - while (*p) - if (*p++ == '\"') - ++len; - len += strlen(outputdriver); - if (output_directory) - len += strlen(output_directory); - len += 10; /* space for -o flag, quotes, NUL */ - for (p = (const char*)nameoffile+1; *p; p++) - if (*p == '\"') - ++len; /* allow extra space to escape quotes in filename */ - cmd = xmalloc(len); - strcpy(cmd, outputdriver); - strcat(cmd, " -o \""); - if (output_directory) { - len = strlen(output_directory); - if (IS_DIR_SEP(output_directory[len-1])) - output_directory[len-1] = '\0'; - strcat(cmd, output_directory); - strcat(cmd, "/"); - } - q = cmd + strlen(cmd); - for (p = (const char*)nameoffile+1; *p; p++) { - if (*p == '\"') - *q++ = '\\'; - *q++ = *p; - } - *q++ = '\"'; - *q = '\0'; - if (papersize != 0) { - char* cmd2 = concat3(cmd, " -p ", papersize); - free(cmd); - cmd = cmd2; - } - if (output_directory) { - char *fullname = concat3(output_directory, "/", (const char*)nameoffile+1); - free(nameoffile); - namelength = strlen(fullname); - nameoffile = (unsigned char*)xmalloc(namelength+2); - strcpy((char*)nameoffile+1, fullname); - free(fullname); - } + if (nopdfoutput) { + return open_output(fptr, FOPEN_WBIN_MODE); + } else { + const char *p = (const char*)nameoffile+1; + char *cmd, *q; + int len = strlen(p); + while (*p) + if (*p++ == '\"') + ++len; + len += strlen(outputdriver); + if (output_directory) + len += strlen(output_directory); + len += 10; /* space for -o flag, quotes, NUL */ + for (p = (const char*)nameoffile+1; *p; p++) + if (*p == '\"') + ++len; /* allow extra space to escape quotes in filename */ + cmd = xmalloc(len); + strcpy(cmd, outputdriver); + strcat(cmd, " -o \""); + if (output_directory) { + len = strlen(output_directory); + if (IS_DIR_SEP(output_directory[len-1])) + output_directory[len-1] = '\0'; + strcat(cmd, output_directory); + strcat(cmd, "/"); + } + q = cmd + strlen(cmd); + for (p = (const char*)nameoffile+1; *p; p++) { + if (*p == '\"') + *q++ = '\\'; + *q++ = *p; + } + *q++ = '\"'; + *q = '\0'; + if (papersize != 0) { + char* cmd2 = concat3(cmd, " -p ", papersize); + free(cmd); + cmd = cmd2; + } + if (output_directory) { + char *fullname = concat3(output_directory, "/", (const char*)nameoffile+1); + free(nameoffile); + namelength = strlen(fullname); + nameoffile = (unsigned char*) xmalloc(namelength + 2); + strcpy((char*)nameoffile+1, fullname); + free(fullname); + } #if defined(WIN32) - { - wchar_t *tmp1w; - char *p, *pp, *bindir, *fullcmd, *prgnam; - bindir = kpse_var_value("SELFAUTOLOC"); - for(pp = bindir; *pp; pp++) { - if(*pp == '/') *pp = '\\'; - } - pp = cmd; - while(Isspace(*pp)) - pp++; - prgnam = xmalloc(strlen(cmd)); - p = prgnam; - while(!Isspace(*pp)) { - *p++ = *pp++; - } - *p = '\0'; - fullcmd = concatn("\"\"", bindir, "\\", prgnam, "\"", pp, "\"", NULL); - tmp1w = get_wstring_from_mbstring(CP_UTF8, (const char *)fullcmd, tmp1w=NULL); - *fptr = _wpopen(tmp1w, L"wb"); - free(bindir); - free(prgnam); - free(fullcmd); - free(tmp1w); - } + { + wchar_t *tmp1w; + char *p, *pp, *bindir, *fullcmd, *prgnam; + bindir = kpse_var_value("SELFAUTOLOC"); + for(pp = bindir; *pp; pp++) { + if(*pp == '/') *pp = '\\'; + } + pp = cmd; + while(Isspace(*pp)) + pp++; + prgnam = xmalloc(strlen(cmd)); + p = prgnam; + while(!Isspace(*pp)) { + *p++ = *pp++; + } + *p = '\0'; + fullcmd = concatn("\"\"", bindir, "\\", prgnam, "\"", pp, "\"", NULL); + tmp1w = get_wstring_from_mbstring(CP_UTF8, (const char *)fullcmd, tmp1w=NULL); + *fptr = _wpopen(tmp1w, L"wb"); + free(bindir); + free(prgnam); + free(fullcmd); + free(tmp1w); + } #else - *fptr = popen(cmd, "w"); + *fptr = popen(cmd, "w"); #endif - free(cmd); - return (*fptr != 0); - } + free(cmd); + return (*fptr != 0); + } } int dviclose(FILE* fptr) { - if (nopdfoutput) { - if (fclose(fptr) != 0) - return errno; - } else { - return pclose(fptr); - } - return 0; + if (nopdfoutput) { + if (fclose(fptr) != 0) + return errno; + } else { + return pclose(fptr); + } + return 0; } int get_uni_c(UFILE* f) { - int rval; - int c; + int rval; + int c; #ifdef WIN32 - HANDLE hStdin; - DWORD ret; - wint_t wc[1]; + HANDLE hStdin; + DWORD ret; + wint_t wc[1]; #endif - if (f->savedChar != -1) { - rval = f->savedChar; - f->savedChar = -1; - return rval; - } - - switch (f->encodingMode) { - case UTF8: - c = rval = getc(f->f); - if (rval != EOF) { - uint16_t extraBytes = bytesFromUTF8[rval]; - switch (extraBytes) { /* note: code falls through cases! */ - case 3: c = getc(f->f); - if (c < 0x80 || c >= 0xc0) goto bad_utf8; - rval <<= 6; rval += c; - case 2: c = getc(f->f); - if (c < 0x80 || c >= 0xc0) goto bad_utf8; - rval <<= 6; rval += c; - case 1: c = getc(f->f); - if (c < 0x80 || c >= 0xc0) goto bad_utf8; - rval <<= 6; rval += c; - case 0: - break; - - bad_utf8: - if (c != EOF) - ungetc(c, f->f); - case 5: - case 4: - badutf8warning(); - return 0xfffd; /* return without adjusting by offsetsFromUTF8 */ - }; - rval -= offsetsFromUTF8[extraBytes]; - } - break; - - case UTF16BE: - rval = getc(f->f); - if (rval != EOF) { - 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); - if (rval != EOF) { - 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; + if (f->savedChar != -1) { + rval = f->savedChar; + f->savedChar = -1; + return rval; + } + + switch (f->encodingMode) { + case UTF8: + c = rval = getc(f->f); + if (rval != EOF) { + uint16_t extraBytes = bytesFromUTF8[rval]; + switch (extraBytes) { /* note: code falls through cases! */ + case 3: c = getc(f->f); + if (c < 0x80 || c >= 0xc0) goto bad_utf8; + rval <<= 6; rval += c; + case 2: c = getc(f->f); + if (c < 0x80 || c >= 0xc0) goto bad_utf8; + rval <<= 6; rval += c; + case 1: c = getc(f->f); + if (c < 0x80 || c >= 0xc0) goto bad_utf8; + rval <<= 6; rval += c; + case 0: + break; + + bad_utf8: + if (c != EOF) + ungetc(c, f->f); + case 5: + case 4: + badutf8warning(); + return 0xfffd; /* return without adjusting by offsetsFromUTF8 */ + }; + rval -= offsetsFromUTF8[extraBytes]; + } + break; + + case UTF16BE: + rval = getc(f->f); + if (rval != EOF) { + 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); + if (rval != EOF) { + 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; #ifdef WIN32 - case WIN32CONSOLE: - hStdin = GetStdHandle(STD_INPUT_HANDLE); - if (ReadConsoleW(hStdin, wc, 1, &ret, NULL) == 0) { - rval = EOF; - break; - } - rval = wc[0]; - if (rval >= 0xd800 && rval <= 0xdbff) { - int lo; - if (ReadConsoleW(hStdin, wc, 1, &ret, NULL) == 0) { - rval = EOF; - break; - } - lo = wc[0]; - 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 WIN32CONSOLE: + hStdin = GetStdHandle(STD_INPUT_HANDLE); + if (ReadConsoleW(hStdin, wc, 1, &ret, NULL) == 0) { + rval = EOF; + break; + } + rval = wc[0]; + if (rval >= 0xd800 && rval <= 0xdbff) { + int lo; + if (ReadConsoleW(hStdin, wc, 1, &ret, NULL) == 0) { + rval = EOF; + break; + } + lo = wc[0]; + 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; #endif - case RAW: - rval = getc(f->f); - break; + case RAW: + rval = getc(f->f); + break; - default: - /* this can't happen */ - fprintf(stderr, "! Internal error---file input mode=%d.\n", f->encodingMode); - uexit(3); - } + default: + /* this can't happen */ + fprintf(stderr, "! Internal error---file input mode=%d.\n", f->encodingMode); + uexit(3); + } - return rval; + return rval; } void makeutf16name() { - unsigned char* s = nameoffile + 1; - uint32_t rval; - uint16_t* t; - static int name16len = 0; - if (name16len <= namelength) { - if (nameoffile16 != 0) - free(nameoffile16); - name16len = namelength + 10; - nameoffile16 = xmalloc(name16len * sizeof(uint16_t)); - } - t = nameoffile16; - while (s <= nameoffile + namelength) { - uint16_t extraBytes; - rval = *(s++); - extraBytes = bytesFromUTF8[rval]; - switch (extraBytes) { /* note: code falls through cases! */ - case 5: rval <<= 6; if (*s) rval += *(s++); - case 4: rval <<= 6; if (*s) rval += *(s++); - case 3: rval <<= 6; if (*s) rval += *(s++); - case 2: rval <<= 6; if (*s) rval += *(s++); - case 1: rval <<= 6; if (*s) rval += *(s++); - case 0: ; - }; - rval -= offsetsFromUTF8[extraBytes]; - if (rval > 0xffff) { - rval -= 0x10000; - *(t++) = 0xd800 + rval / 0x0400; - *(t++) = 0xdc00 + rval % 0x0400; - } else { - *(t++) = rval; - } - } - namelength16 = t - nameoffile16; + unsigned char* s = nameoffile + 1; + uint32_t rval; + uint16_t* t; + static int name16len = 0; + if (name16len <= namelength) { + if (nameoffile16 != 0) + free(nameoffile16); + name16len = namelength + 10; + nameoffile16 = (uint16_t*) xcalloc(name16len, sizeof(uint16_t)); + } + t = nameoffile16; + while (s <= nameoffile + namelength) { + uint16_t extraBytes; + rval = *(s++); + extraBytes = bytesFromUTF8[rval]; + switch (extraBytes) { /* note: code falls through cases! */ + case 5: rval <<= 6; if (*s) rval += *(s++); + case 4: rval <<= 6; if (*s) rval += *(s++); + case 3: rval <<= 6; if (*s) rval += *(s++); + case 2: rval <<= 6; if (*s) rval += *(s++); + case 1: rval <<= 6; if (*s) rval += *(s++); + case 0: ; + }; + rval -= offsetsFromUTF8[extraBytes]; + if (rval > 0xffff) { + rval -= 0x10000; + *(t++) = 0xd800 + rval / 0x0400; + *(t++) = 0xdc00 + rval % 0x0400; + } else { + *(t++) = rval; + } + } + namelength16 = t - nameoffile16; } integer get_native_word_cp(void* pNode, int side) { - memoryword* node = (memoryword*)pNode; - FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); - uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node)); - uint16_t glyphCount = native_glyph_count(node); - integer f = native_font(node); - uint16_t actual_glyph; + memoryword* node = (memoryword*)pNode; + FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node); + uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node)); + uint16_t glyphCount = native_glyph_count(node); + integer f = native_font(node); + uint16_t actual_glyph; if (glyphCount == 0) return 0; diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h index e81b8781373..b0c42fe3060 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h +++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h @@ -41,11 +41,11 @@ authorization from the copyright holders. typedef struct UFILE* unicodefile; #endif -#define AAT_FONT_FLAG 0xFFFFU -#define OTGR_FONT_FLAG 0xFFFEU +#define AAT_FONT_FLAG 0xFFFFU +#define OTGR_FONT_FLAG 0xFFFEU -#define FONT_FLAGS_COLORED 0x01 -#define FONT_FLAGS_VERTICAL 0x02 +#define FONT_FLAGS_COLORED 0x01 +#define FONT_FLAGS_VERTICAL 0x02 /* some typedefs that XeTeX uses - on Mac OS, we get these from Apple headers, but otherwise we'll need these substitute definitions */ @@ -54,10 +54,10 @@ typedef struct UFILE* unicodefile; #include <CoreFoundation/CoreFoundation.h> #include <ApplicationServices/ApplicationServices.h> #else -typedef int32_t Fixed; +typedef int32_t Fixed; typedef struct { - Fixed x; - Fixed y; + Fixed x; + Fixed y; } FixedPoint; #endif @@ -67,76 +67,76 @@ typedef uint16_t GlyphID; /* these are also in xetex.web and must correspond! */ -#define pdfbox_crop 1 -#define pdfbox_media 2 -#define pdfbox_bleed 3 -#define pdfbox_trim 4 -#define pdfbox_art 5 +#define pdfbox_crop 1 +#define pdfbox_media 2 +#define pdfbox_bleed 3 +#define pdfbox_trim 4 +#define pdfbox_art 5 -#define XeTeX_count_glyphs 1 +#define XeTeX_count_glyphs 1 -#define XeTeX_count_variations 2 -#define XeTeX_variation 3 -#define XeTeX_find_variation_by_name 4 -#define XeTeX_variation_min 5 -#define XeTeX_variation_max 6 -#define XeTeX_variation_default 7 +#define XeTeX_count_variations 2 +#define XeTeX_variation 3 +#define XeTeX_find_variation_by_name 4 +#define XeTeX_variation_min 5 +#define XeTeX_variation_max 6 +#define XeTeX_variation_default 7 -#define XeTeX_count_features 8 -#define XeTeX_feature_code 9 -#define XeTeX_find_feature_by_name 10 -#define XeTeX_is_exclusive_feature 11 -#define XeTeX_count_selectors 12 -#define XeTeX_selector_code 13 -#define XeTeX_find_selector_by_name 14 -#define XeTeX_is_default_selector 15 +#define XeTeX_count_features 8 +#define XeTeX_feature_code 9 +#define XeTeX_find_feature_by_name 10 +#define XeTeX_is_exclusive_feature 11 +#define XeTeX_count_selectors 12 +#define XeTeX_selector_code 13 +#define XeTeX_find_selector_by_name 14 +#define XeTeX_is_default_selector 15 -#define XeTeX_OT_count_scripts 16 -#define XeTeX_OT_count_languages 17 -#define XeTeX_OT_count_features 18 -#define XeTeX_OT_script_code 19 -#define XeTeX_OT_language_code 20 -#define XeTeX_OT_feature_code 21 +#define XeTeX_OT_count_scripts 16 +#define XeTeX_OT_count_languages 17 +#define XeTeX_OT_count_features 18 +#define XeTeX_OT_script_code 19 +#define XeTeX_OT_language_code 20 +#define XeTeX_OT_feature_code 21 -#define XeTeX_map_char_to_glyph_code 22 +#define XeTeX_map_char_to_glyph_code 22 -#define XeTeX_variation_name 7 /* must match xetex.web */ -#define XeTeX_feature_name 8 -#define XeTeX_selector_name 9 +#define XeTeX_variation_name 7 /* must match xetex.web */ +#define XeTeX_feature_name 8 +#define XeTeX_selector_name 9 /* definitions used to access info in a native_word_node; must correspond with defines in xetex.web */ -#define width_offset 1 -#define depth_offset 2 -#define height_offset 3 -#define native_info_offset 4 -#define native_glyph_info_offset 5 - -#define node_width(node) node[width_offset].cint -#define node_depth(node) node[depth_offset].cint -#define node_height(node) node[height_offset].cint -#define native_length(node) node[native_info_offset].qqqq.b2 -#define native_font(node) node[native_info_offset].qqqq.b1 -#define native_glyph_count(node) node[native_info_offset].qqqq.b3 -#define native_glyph_info_ptr(node) node[native_glyph_info_offset].ptr -#define native_glyph_info_size 10 /* info for each glyph is location (FixedPoint) + glyph ID (uint16_t) */ - -#define native_glyph(p) native_length(p) /* glyph ID field in a glyph_node */ - -#define XDV_GLYPH_STRING 254 -#define XDV_GLYPH_ARRAY 253 +#define width_offset 1 +#define depth_offset 2 +#define height_offset 3 +#define native_info_offset 4 +#define native_glyph_info_offset 5 + +#define node_width(node) node[width_offset].cint +#define node_depth(node) node[depth_offset].cint +#define node_height(node) node[height_offset].cint +#define native_length(node) node[native_info_offset].qqqq.b2 +#define native_font(node) node[native_info_offset].qqqq.b1 +#define native_glyph_count(node) node[native_info_offset].qqqq.b3 +#define native_glyph_info_ptr(node) node[native_glyph_info_offset].ptr +#define native_glyph_info_size 10 /* info for each glyph is location (FixedPoint) + glyph ID (uint16_t) */ + +#define native_glyph(p) native_length(p) /* glyph ID field in a glyph_node */ + +#define XDV_GLYPH_STRING 254 +#define XDV_GLYPH_ARRAY 253 /* OT-related constants we need */ -#define kGSUB HB_TAG('G','S','U','B') -#define kGPOS HB_TAG('G','P','O','S') +#define kGSUB HB_TAG('G','S','U','B') +#define kGPOS HB_TAG('G','P','O','S') typedef struct { - float xMin; - float yMin; - float xMax; - float yMax; + float xMin; + float yMin; + float xMax; + float yMax; } GlyphBBox; @@ -200,110 +200,111 @@ extern const CFStringRef kXeTeXEmboldenAttributeName; #ifdef __cplusplus extern "C" { #endif - void initversionstring(char **versions); - - void setinputfileencoding(unicodefile f, integer mode, integer encodingData); - void uclose(unicodefile f); - void linebreakstart(int f, integer localeStrNum, const uint16_t* text, integer textLength); - int linebreaknext(); - int getencodingmodeandinfo(integer* info); - void printutf8str(const unsigned char* str, int len); - void printchars(const unsigned short* str, int len); - void* findnativefont(unsigned char* name, integer scaled_size); - void releasefontengine(void* engine, int type_flag); - int readCommonFeatures(const char* feat, const char* end, float* extend, float* slant, float* embolden, float* letterspace, uint32_t* rgbValue); - - /* the metrics params here are really TeX 'scaled' values, but that typedef isn't available every place this is included */ - void otgetfontmetrics(void* engine, integer* ascent, integer* descent, integer* xheight, integer* capheight, integer* slant); - void getnativecharheightdepth(integer font, integer ch, integer* height, integer* depth); - void getnativecharsidebearings(integer font, integer ch, integer* lsb, integer* rsb); - - /* single-purpose metrics accessors */ - integer getnativecharwd(integer font, integer ch); - integer getnativecharht(integer font, integer ch); - integer getnativechardp(integer font, integer ch); - integer getnativecharic(integer font, integer ch); - - integer getglyphbounds(integer font, integer edge, integer gid); - - integer otfontget(integer what, void* engine); - integer otfontget1(integer what, void* engine, integer param); - integer otfontget2(integer what, void* engine, integer param1, integer param2); - integer otfontget3(integer what, void* engine, integer param1, integer param2, integer param3); - int makeXDVGlyphArrayData(void* p); - int makefontdef(integer f); - int applymapping(void* cnv, const uint16_t* txtPtr, int txtLen); - void store_justified_native_glyphs(void* node); - void measure_native_node(void* node, int use_glyph_metrics); - Fixed get_native_italic_correction(void* node); - Fixed get_native_glyph_italic_correection(void* node); - void measure_native_glyph(void* node, int use_glyph_metrics); - integer mapchartoglyph(integer font, integer ch); - integer mapglyphtoindex(integer font); - integer getfontcharrange(integer font, int first); - void printglyphname(integer font, integer gid); - uint16_t get_native_glyph(void* pNode, unsigned index); - - void grprintfontname(integer what, void* pEngine, integer param1, integer param2); - integer grfontgetnamed(integer what, void* pEngine); - integer grfontgetnamed1(integer what, void* pEngine, integer param); - - double read_double(const char** s); - unsigned int read_rgb_a(const char** cp); - - int countpdffilepages(); - int find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page); - int u_open_in(unicodefile* f, integer filefmt, const char* fopen_mode, integer mode, integer encodingData); - int open_dvi_output(FILE** fptr); - int dviclose(FILE* fptr); - int get_uni_c(UFILE* f); - int input_line(UFILE* f); - void makeutf16name(); - - void terminatefontmanager(); - int maketexstring(const char* s); - - void checkfortfmfontmapping(); - void* loadtfmfontmapping(); - int applytfmfontmapping(void* mapping, int c); + void initversionstring(char **versions); + + void setinputfileencoding(unicodefile f, integer mode, integer encodingData); + void uclose(unicodefile f); + void linebreakstart(int f, integer localeStrNum, const uint16_t* text, integer textLength); + int linebreaknext(); + int getencodingmodeandinfo(integer* info); + void printutf8str(const unsigned char* str, int len); + void printchars(const unsigned short* str, int len); + void* findnativefont(unsigned char* name, integer scaled_size); + void releasefontengine(void* engine, int type_flag); + int readCommonFeatures(const char* feat, const char* end, float* extend, float* slant, float* embolden, float* letterspace, uint32_t* rgbValue); + + /* the metrics params here are really TeX 'scaled' values, but that typedef isn't available every place this is included */ + void otgetfontmetrics(void* engine, integer* ascent, integer* descent, integer* xheight, integer* capheight, integer* slant); + void getnativecharheightdepth(integer font, integer ch, integer* height, integer* depth); + void getnativecharsidebearings(integer font, integer ch, integer* lsb, integer* rsb); + + /* single-purpose metrics accessors */ + integer getnativecharwd(integer font, integer ch); + integer getnativecharht(integer font, integer ch); + integer getnativechardp(integer font, integer ch); + integer getnativecharic(integer font, integer ch); + + integer getglyphbounds(integer font, integer edge, integer gid); + + integer otfontget(integer what, void* engine); + integer otfontget1(integer what, void* engine, integer param); + integer otfontget2(integer what, void* engine, integer param1, integer param2); + integer otfontget3(integer what, void* engine, integer param1, integer param2, integer param3); + int makeXDVGlyphArrayData(void* p); + int makefontdef(integer f); + int applymapping(void* cnv, const uint16_t* txtPtr, int txtLen); + void store_justified_native_glyphs(void* node); + void measure_native_node(void* node, int use_glyph_metrics); + Fixed get_native_italic_correction(void* node); + Fixed get_native_glyph_italic_correction(void* node); + integer get_native_word_cp(void* node, int side); + void measure_native_glyph(void* node, int use_glyph_metrics); + integer mapchartoglyph(integer font, integer ch); + integer mapglyphtoindex(integer font); + integer getfontcharrange(integer font, int first); + void printglyphname(integer font, integer gid); + uint16_t get_native_glyph(void* pNode, unsigned index); + + void grprintfontname(integer what, void* pEngine, integer param1, integer param2); + integer grfontgetnamed(integer what, void* pEngine); + integer grfontgetnamed1(integer what, void* pEngine, integer param); + + double read_double(const char** s); + unsigned int read_rgb_a(const char** cp); + + int countpdffilepages(); + int find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page); + int u_open_in(unicodefile* f, integer filefmt, const char* fopen_mode, integer mode, integer encodingData); + int open_dvi_output(FILE** fptr); + int dviclose(FILE* fptr); + int get_uni_c(UFILE* f); + int input_line(UFILE* f); + void makeutf16name(); + + void terminatefontmanager(); + int maketexstring(const char* s); + + void checkfortfmfontmapping(); + void* loadtfmfontmapping(); + int applytfmfontmapping(void* mapping, int c); #ifndef XETEX_MAC typedef void* CFDictionaryRef; /* dummy declaration just so the stubs can compile */ #endif - int aatfontget(int what, CFDictionaryRef attrs); - int aatfontget1(int what, CFDictionaryRef attrs, int param); - int aatfontget2(int what, CFDictionaryRef attrs, int param1, int param2); - int aatfontgetnamed(int what, CFDictionaryRef attrs); - int aatfontgetnamed1(int what, CFDictionaryRef attrs, int param); - void aatprintfontname(int what, CFDictionaryRef attrs, int param1, int param2); - /* the metrics params here are really TeX 'scaled' (or MacOS 'Fixed') values, but that typedef isn't available every place this is included */ - void aatgetfontmetrics(CFDictionaryRef attrs, integer* ascent, integer* descent, integer* xheight, integer* capheight, integer* slant); + int aatfontget(int what, CFDictionaryRef attrs); + int aatfontget1(int what, CFDictionaryRef attrs, int param); + int aatfontget2(int what, CFDictionaryRef attrs, int param1, int param2); + int aatfontgetnamed(int what, CFDictionaryRef attrs); + int aatfontgetnamed1(int what, CFDictionaryRef attrs, int param); + void aatprintfontname(int what, CFDictionaryRef attrs, int param1, int param2); + /* the metrics params here are really TeX 'scaled' (or MacOS 'Fixed') values, but that typedef isn't available every place this is included */ + void aatgetfontmetrics(CFDictionaryRef attrs, integer* ascent, integer* descent, integer* xheight, integer* capheight, integer* slant); - void set_cp_code(int fontNum, unsigned int code, int side, int value); - int get_cp_code(int fontNum, unsigned int code, int side); + void set_cp_code(int fontNum, unsigned int code, int side, int value); + int get_cp_code(int fontNum, unsigned int code, int side); #ifdef XETEX_MAC /* functions in XeTeX_mac.c */ - void* loadAATfont(CTFontDescriptorRef descriptor, integer scaled_size, const char* cp1); - void DoAATLayout(void* node, int justify); - void GetGlyphBBox_AAT(CFDictionaryRef fontAttrs, uint16_t gid, GlyphBBox* bbox); - double GetGlyphWidth_AAT(CFDictionaryRef fontAttrs, uint16_t gid); - void GetGlyphHeightDepth_AAT(CFDictionaryRef fontAttrs, uint16_t gid, float* ht, float* dp); - void GetGlyphSidebearings_AAT(CFDictionaryRef fontAttrs, uint16_t gid, float* lsb, float* rsb); - double GetGlyphItalCorr_AAT(CFDictionaryRef fontAttrs, uint16_t gid); - int MapCharToGlyph_AAT(CFDictionaryRef fontAttrs, UInt32 ch); - int MapGlyphToIndex_AAT(CFDictionaryRef attributes, const char* glyphName); - char* GetGlyphNameFromCTFont(CTFontRef ctFontRef, uint16_t gid, int* len); - CFDictionaryRef findDictionaryInArray(CFArrayRef array, const void* nameKey, const char* name, int nameLength); - CFDictionaryRef findDictionaryInArrayWithIdentifier(CFArrayRef array, const void* identifierKey, int identifier); - CFNumberRef findSelectorByName(CFDictionaryRef feature, const char* name, int nameLength); - char* getNameFromCTFont(CTFontRef ctFontRef, CFStringRef nameKey); - char* getFileNameFromCTFont(CTFontRef ctFontRef, int* index); - int GetFontCharRange_AAT(CFDictionaryRef fontAttrs, int reqFirst); - CTFontRef fontFromAttributes(CFDictionaryRef fontAttrs); - CTFontRef fontFromInteger(integer font); + void* loadAATfont(CTFontDescriptorRef descriptor, integer scaled_size, const char* cp1); + void DoAATLayout(void* node, int justify); + void GetGlyphBBox_AAT(CFDictionaryRef fontAttrs, uint16_t gid, GlyphBBox* bbox); + double GetGlyphWidth_AAT(CFDictionaryRef fontAttrs, uint16_t gid); + void GetGlyphHeightDepth_AAT(CFDictionaryRef fontAttrs, uint16_t gid, float* ht, float* dp); + void GetGlyphSidebearings_AAT(CFDictionaryRef fontAttrs, uint16_t gid, float* lsb, float* rsb); + double GetGlyphItalCorr_AAT(CFDictionaryRef fontAttrs, uint16_t gid); + int MapCharToGlyph_AAT(CFDictionaryRef fontAttrs, UInt32 ch); + int MapGlyphToIndex_AAT(CFDictionaryRef attributes, const char* glyphName); + char* GetGlyphNameFromCTFont(CTFontRef ctFontRef, uint16_t gid, int* len); + CFDictionaryRef findDictionaryInArray(CFArrayRef array, const void* nameKey, const char* name, int nameLength); + CFDictionaryRef findDictionaryInArrayWithIdentifier(CFArrayRef array, const void* identifierKey, int identifier); + CFNumberRef findSelectorByName(CFDictionaryRef feature, const char* name, int nameLength); + char* getNameFromCTFont(CTFontRef ctFontRef, CFStringRef nameKey); + char* getFileNameFromCTFont(CTFontRef ctFontRef, int* index); + int GetFontCharRange_AAT(CFDictionaryRef fontAttrs, int reqFirst); + CTFontRef fontFromAttributes(CFDictionaryRef fontAttrs); + CTFontRef fontFromInteger(integer font); #endif #ifdef __cplusplus }; @@ -312,14 +313,14 @@ typedef void* CFDictionaryRef; /* dummy declaration just so the stubs can compil #ifdef __cplusplus extern "C" { #endif - double Fix2D(Fixed f); - Fixed D2Fix(double d); + double Fix2D(Fixed f); + Fixed D2Fix(double d); #ifdef __cplusplus }; #endif // copied from xetex.web -#define LEFT_SIDE 0 -#define RIGHT_SIDE 1 +#define LEFT_SIDE 0 +#define RIGHT_SIDE 1 #endif /* __XETEX_EXT_H */ diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c index 02fdc428c05..f3e78cb588b 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c @@ -48,496 +48,497 @@ authorization from the copyright holders. static inline double TeXtoPSPoints(double pts) { - return pts * 72.0 / 72.27; + return pts * 72.0 / 72.27; } static inline double PStoTeXPoints(double pts) { - return pts * 72.27 / 72.0; + return pts * 72.27 / 72.0; } static inline Fixed FixedPStoTeXPoints(double pts) { - return D2Fix(PStoTeXPoints(pts)); + return D2Fix(PStoTeXPoints(pts)); } CTFontRef fontFromAttributes(CFDictionaryRef attributes) { - return CFDictionaryGetValue(attributes, kCTFontAttributeName); + return CFDictionaryGetValue(attributes, kCTFontAttributeName); } CTFontRef fontFromInteger(integer font) { - CFDictionaryRef attributes = (CFDictionaryRef) fontlayoutengine[font]; - return fontFromAttributes(attributes); + CFDictionaryRef attributes = (CFDictionaryRef) fontlayoutengine[font]; + return fontFromAttributes(attributes); } void DoAATLayout(void* p, int justify) { - CFArrayRef glyphRuns; - CFIndex i, j, runCount; - CFIndex totalGlyphCount = 0; - UInt16* glyphIDs; - Fixed* glyphAdvances; - void* glyph_info; - FixedPoint* locations; - Fixed lsUnit, lsDelta; - CGFloat width; - - long txtLen; - const UniChar* txtPtr; - - CFDictionaryRef attributes; - CFStringRef string; - CFAttributedStringRef attrString; - CTTypesetterRef typesetter; - CTLineRef line; - - memoryword* node = (memoryword*)p; - - unsigned f = native_font(node); - if (fontarea[f] != AAT_FONT_FLAG) { - fprintf(stderr, "internal error: DoAATLayout called for non-AAT font\n"); - exit(1); - } - - txtLen = native_length(node); - txtPtr = (UniChar*)(node + native_node_size); - - attributes = fontlayoutengine[native_font(node)]; - string = CFStringCreateWithCharactersNoCopy(NULL, txtPtr, txtLen, kCFAllocatorNull); - attrString = CFAttributedStringCreate(NULL, string, attributes); - CFRelease(string); - - typesetter = CTTypesetterCreateWithAttributedString(attrString); - line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, txtLen)); - if (justify) { - CGFloat lineWidth = TeXtoPSPoints(Fix2D(node_width(node))); - CTLineRef justifiedLine = CTLineCreateJustifiedLine(line, TeXtoPSPoints(Fix2D(fract1)), lineWidth); - // TODO(jjgod): how to handle the case when justification failed? for - // now we just fallback to use the original line. - if (justifiedLine) { - CFRelease(line); - line = justifiedLine; - } - } - - glyphRuns = CTLineGetGlyphRuns(line); - runCount = CFArrayGetCount(glyphRuns); - totalGlyphCount = CTLineGetGlyphCount(line); - - if (totalGlyphCount > 0) { - glyph_info = xmalloc(totalGlyphCount * native_glyph_info_size); - locations = (FixedPoint*)glyph_info; - glyphIDs = (UInt16*)(locations + totalGlyphCount); - glyphAdvances = xmalloc(totalGlyphCount * sizeof(Fixed)); - totalGlyphCount = 0; - - width = 0; - for (i = 0; i < runCount; i++) { - CTRunRef run = CFArrayGetValueAtIndex(glyphRuns, i); - CFIndex count = CTRunGetGlyphCount(run); - CFDictionaryRef runAttributes = CTRunGetAttributes(run); - CFBooleanRef vertical = CFDictionaryGetValue(runAttributes, kCTVerticalFormsAttributeName); - // TODO(jjgod): Avoid unnecessary allocation with CTRunGetFoosPtr(). - CGGlyph* glyphs = (CGGlyph*) xmalloc(count * sizeof(CGGlyph)); - CGPoint* positions = (CGPoint*) xmalloc(count * sizeof(CGPoint)); - CGSize* advances = (CGSize*) xmalloc(count * sizeof(CGSize)); - CGFloat runWidth = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), NULL, NULL, NULL); - CTRunGetGlyphs(run, CFRangeMake(0, 0), glyphs); - CTRunGetPositions(run, CFRangeMake(0, 0), positions); - CTRunGetAdvances(run, CFRangeMake(0, 0), advances); - for (j = 0; j < count; j++) { - // XXX Core Text has that font cascading thing that will do - // font substitution for missing glyphs, which we do not want - // but I can not find a way to disable it yet, so if the font - // of the resulting run is not the same font we asked for, use - // the glyph at index 0 (usually .notdef) instead or we will be - // showing garbage or even invalid glyphs - char *ps_name1 = getNameFromCTFont(fontFromAttributes(attributes), kCTFontPostScriptNameKey); - char *ps_name2 = getNameFromCTFont(fontFromAttributes(runAttributes), kCTFontPostScriptNameKey); - if (strcmp(ps_name1, ps_name2) != 0) - glyphIDs[totalGlyphCount] = 0; - else - glyphIDs[totalGlyphCount] = glyphs[j]; - - // Swap X and Y when doing vertical layout - if (vertical == kCFBooleanTrue) { - locations[totalGlyphCount].x = FixedPStoTeXPoints(-positions[j].y); - // XXX trasformation matrix changes y positions! - //locations[totalGlyphCount].y = FixedPStoTeXPoints(-positions[j].x); - locations[totalGlyphCount].y = 0; - } else { - locations[totalGlyphCount].x = FixedPStoTeXPoints(positions[j].x); - // XXX trasformation matrix changes y positions! - //locations[totalGlyphCount].y = FixedPStoTeXPoints(positions[j].y); - locations[totalGlyphCount].y = 0; - } - glyphAdvances[totalGlyphCount] = advances[j].width; - totalGlyphCount++; - } - width += FixedPStoTeXPoints(runWidth); - free(glyphs); - free(positions); - } - } - - native_glyph_count(node) = totalGlyphCount; - native_glyph_info_ptr(node) = glyph_info; - - if (!justify) { - node_width(node) = width; - - if (totalGlyphCount > 0) { - /* this is essentially a copy from similar code in XeTeX_ext.c, easier - * to be done here */ - if (fontletterspace[f] != 0) { - Fixed lsDelta = 0; - Fixed lsUnit = fontletterspace[f]; - int i; - for (i = 0; i < totalGlyphCount; ++i) { - if (glyphAdvances[i] == 0 && lsDelta != 0) - lsDelta -= lsUnit; - locations[i].x += lsDelta; - lsDelta += lsUnit; - } - if (lsDelta != 0) { - lsDelta -= lsUnit; - node_width(node) += lsDelta; - } - } - } - } - - CFRelease(line); - CFRelease(typesetter); + CFArrayRef glyphRuns; + CFIndex i, j, runCount; + CFIndex totalGlyphCount = 0; + UInt16* glyphIDs; + Fixed* glyphAdvances; + void* glyph_info; + FixedPoint* locations; + Fixed lsUnit, lsDelta; + CGFloat width; + + long txtLen; + const UniChar* txtPtr; + + CFDictionaryRef attributes; + CFStringRef string; + CFAttributedStringRef attrString; + CTTypesetterRef typesetter; + CTLineRef line; + + memoryword* node = (memoryword*)p; + + unsigned f = native_font(node); + if (fontarea[f] != AAT_FONT_FLAG) { + fprintf(stderr, "internal error: DoAATLayout called for non-AAT font\n"); + exit(1); + } + + txtLen = native_length(node); + txtPtr = (UniChar*)(node + native_node_size); + + attributes = fontlayoutengine[native_font(node)]; + string = CFStringCreateWithCharactersNoCopy(NULL, txtPtr, txtLen, kCFAllocatorNull); + attrString = CFAttributedStringCreate(NULL, string, attributes); + CFRelease(string); + + typesetter = CTTypesetterCreateWithAttributedString(attrString); + CFRelease(attrString); + line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, txtLen)); + if (justify) { + CGFloat lineWidth = TeXtoPSPoints(Fix2D(node_width(node))); + CTLineRef justifiedLine = CTLineCreateJustifiedLine(line, TeXtoPSPoints(Fix2D(fract1)), lineWidth); + // TODO(jjgod): how to handle the case when justification failed? for + // now we just fallback to use the original line. + if (justifiedLine) { + CFRelease(line); + line = justifiedLine; + } + } + + glyphRuns = CTLineGetGlyphRuns(line); + runCount = CFArrayGetCount(glyphRuns); + totalGlyphCount = CTLineGetGlyphCount(line); + + if (totalGlyphCount > 0) { + glyph_info = xmalloc(totalGlyphCount * native_glyph_info_size); + locations = (FixedPoint*)glyph_info; + glyphIDs = (UInt16*)(locations + totalGlyphCount); + glyphAdvances = xmalloc(totalGlyphCount * sizeof(Fixed)); + totalGlyphCount = 0; + + width = 0; + for (i = 0; i < runCount; i++) { + CTRunRef run = CFArrayGetValueAtIndex(glyphRuns, i); + CFIndex count = CTRunGetGlyphCount(run); + CFDictionaryRef runAttributes = CTRunGetAttributes(run); + CFBooleanRef vertical = CFDictionaryGetValue(runAttributes, kCTVerticalFormsAttributeName); + // TODO(jjgod): Avoid unnecessary allocation with CTRunGetFoosPtr(). + CGGlyph* glyphs = (CGGlyph*) xmalloc(count * sizeof(CGGlyph)); + CGPoint* positions = (CGPoint*) xmalloc(count * sizeof(CGPoint)); + CGSize* advances = (CGSize*) xmalloc(count * sizeof(CGSize)); + CGFloat runWidth = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), NULL, NULL, NULL); + CTRunGetGlyphs(run, CFRangeMake(0, 0), glyphs); + CTRunGetPositions(run, CFRangeMake(0, 0), positions); + CTRunGetAdvances(run, CFRangeMake(0, 0), advances); + for (j = 0; j < count; j++) { + // XXX Core Text has that font cascading thing that will do + // font substitution for missing glyphs, which we do not want + // but I can not find a way to disable it yet, so if the font + // of the resulting run is not the same font we asked for, use + // the glyph at index 0 (usually .notdef) instead or we will be + // showing garbage or even invalid glyphs + if (!CFEqual(fontFromAttributes(attributes), fontFromAttributes(runAttributes))) + glyphIDs[totalGlyphCount] = 0; + else + glyphIDs[totalGlyphCount] = glyphs[j]; + + // Swap X and Y when doing vertical layout + if (vertical == kCFBooleanTrue) { + locations[totalGlyphCount].x = FixedPStoTeXPoints(-positions[j].y); + // XXX trasformation matrix changes y positions! + //locations[totalGlyphCount].y = FixedPStoTeXPoints(-positions[j].x); + locations[totalGlyphCount].y = 0; + } else { + locations[totalGlyphCount].x = FixedPStoTeXPoints(positions[j].x); + // XXX trasformation matrix changes y positions! + //locations[totalGlyphCount].y = FixedPStoTeXPoints(positions[j].y); + locations[totalGlyphCount].y = 0; + } + glyphAdvances[totalGlyphCount] = advances[j].width; + totalGlyphCount++; + } + width += FixedPStoTeXPoints(runWidth); + free(glyphs); + free(positions); + free(advances); + } + } + + native_glyph_count(node) = totalGlyphCount; + native_glyph_info_ptr(node) = glyph_info; + + if (!justify) { + node_width(node) = width; + + if (totalGlyphCount > 0) { + /* this is essentially a copy from similar code in XeTeX_ext.c, easier + * to be done here */ + if (fontletterspace[f] != 0) { + Fixed lsDelta = 0; + Fixed lsUnit = fontletterspace[f]; + int i; + for (i = 0; i < totalGlyphCount; ++i) { + if (glyphAdvances[i] == 0 && lsDelta != 0) + lsDelta -= lsUnit; + locations[i].x += lsDelta; + lsDelta += lsUnit; + } + if (lsDelta != 0) { + lsDelta -= lsUnit; + node_width(node) += lsDelta; + } + } + } + } + + free(glyphAdvances); + CFRelease(line); + CFRelease(typesetter); } static void getGlyphBBoxFromCTFont(CTFontRef font, UInt16 gid, GlyphBBox* bbox) { - CGRect rect; - - bbox->xMin = 65536.0; - bbox->yMin = 65536.0; - bbox->xMax = -65536.0; - bbox->yMax = -65536.0; - - rect = CTFontGetBoundingRectsForGlyphs(font, - 0, /* Use default orientation for now, handle vertical later */ - (const CGGlyph *) &gid, NULL, 1); - - if (CGRectIsNull(rect)) - bbox->xMin = bbox->yMin = bbox->xMax = bbox->yMax = 0; - else { - bbox->yMin = PStoTeXPoints(rect.origin.y); - bbox->yMax = PStoTeXPoints(rect.origin.y + rect.size.height); - bbox->xMin = PStoTeXPoints(rect.origin.x); - bbox->xMax = PStoTeXPoints(rect.origin.x + rect.size.width); - } + CGRect rect; + + bbox->xMin = 65536.0; + bbox->yMin = 65536.0; + bbox->xMax = -65536.0; + bbox->yMax = -65536.0; + + rect = CTFontGetBoundingRectsForGlyphs(font, + 0, /* Use default orientation for now, handle vertical later */ + (const CGGlyph *) &gid, NULL, 1); + + if (CGRectIsNull(rect)) + bbox->xMin = bbox->yMin = bbox->xMax = bbox->yMax = 0; + else { + bbox->yMin = PStoTeXPoints(rect.origin.y); + bbox->yMax = PStoTeXPoints(rect.origin.y + rect.size.height); + bbox->xMin = PStoTeXPoints(rect.origin.x); + bbox->xMax = PStoTeXPoints(rect.origin.x + rect.size.width); + } } void GetGlyphBBox_AAT(CFDictionaryRef attributes, UInt16 gid, GlyphBBox* bbox) - /* returns glyph bounding box in TeX points */ + /* returns glyph bounding box in TeX points */ { - CTFontRef font = fontFromAttributes(attributes); - return getGlyphBBoxFromCTFont(font, gid, bbox); + CTFontRef font = fontFromAttributes(attributes); + return getGlyphBBoxFromCTFont(font, gid, bbox); } static double getGlyphWidthFromCTFont(CTFontRef font, UInt16 gid) { - CGSize advances[1] = { CGSizeMake(0, 0) }; - return PStoTeXPoints(CTFontGetAdvancesForGlyphs(font, 0, &gid, advances, 1)); + return PStoTeXPoints(CTFontGetAdvancesForGlyphs(font, kCTFontHorizontalOrientation, &gid, NULL, 1)); } double GetGlyphWidth_AAT(CFDictionaryRef attributes, UInt16 gid) - /* returns TeX points */ + /* returns TeX points */ { - CTFontRef font = fontFromAttributes(attributes); - return getGlyphWidthFromCTFont(font, gid); + CTFontRef font = fontFromAttributes(attributes); + return getGlyphWidthFromCTFont(font, gid); } void GetGlyphHeightDepth_AAT(CFDictionaryRef attributes, UInt16 gid, float* ht, float* dp) - /* returns TeX points */ + /* returns TeX points */ { - GlyphBBox bbox; - - GetGlyphBBox_AAT(attributes, gid, &bbox); + GlyphBBox bbox; - *ht = bbox.yMax; - *dp = -bbox.yMin; + GetGlyphBBox_AAT(attributes, gid, &bbox); + + *ht = bbox.yMax; + *dp = -bbox.yMin; } void GetGlyphSidebearings_AAT(CFDictionaryRef attributes, UInt16 gid, float* lsb, float* rsb) - /* returns TeX points */ + /* returns TeX points */ { - CTFontRef font = fontFromAttributes(attributes); - CGSize advances[1] = { CGSizeMake(0, 0) }; - double advance = CTFontGetAdvancesForGlyphs(font, 0, &gid, advances, 1); - GlyphBBox bbox; - getGlyphBBoxFromCTFont(font, gid, &bbox); - *lsb = bbox.xMin; - *rsb = PStoTeXPoints(advance) - bbox.xMax; + CTFontRef font = fontFromAttributes(attributes); + CGSize advances[1] = { CGSizeMake(0, 0) }; + double advance = CTFontGetAdvancesForGlyphs(font, 0, &gid, advances, 1); + GlyphBBox bbox; + getGlyphBBoxFromCTFont(font, gid, &bbox); + *lsb = bbox.xMin; + *rsb = PStoTeXPoints(advance) - bbox.xMax; } double GetGlyphItalCorr_AAT(CFDictionaryRef attributes, UInt16 gid) { - CTFontRef font = fontFromAttributes(attributes); - CGSize advances[1] = { CGSizeMake(0, 0) }; - double advance = CTFontGetAdvancesForGlyphs(font, 0, &gid, advances, 1); + CTFontRef font = fontFromAttributes(attributes); + CGSize advances[1] = { CGSizeMake(0, 0) }; + double advance = CTFontGetAdvancesForGlyphs(font, 0, &gid, advances, 1); - GlyphBBox bbox; - getGlyphBBoxFromCTFont(font, gid, &bbox); + GlyphBBox bbox; + getGlyphBBoxFromCTFont(font, gid, &bbox); - if (bbox.xMax > PStoTeXPoints(advance)) - return bbox.xMax - PStoTeXPoints(advance); - return 0; + if (bbox.xMax > PStoTeXPoints(advance)) + return bbox.xMax - PStoTeXPoints(advance); + return 0; } static int mapCharToGlyphFromCTFont(CTFontRef font, UInt32 ch) { - CGGlyph glyphs[2] = { 0 }; - UniChar txt[2]; - int len = 1; - - if (ch > 0xffff) { - ch -= 0x10000; - txt[0] = 0xd800 + ch / 1024; - txt[1] = 0xdc00 + ch % 1024; - len = 2; - } else { - txt[0] = ch; - } - - if (CTFontGetGlyphsForCharacters(font, txt, glyphs, len)) - return glyphs[0]; - - return 0; + CGGlyph glyphs[2] = { 0 }; + UniChar txt[2]; + int len = 1; + + if (ch > 0xffff) { + ch -= 0x10000; + txt[0] = 0xd800 + ch / 1024; + txt[1] = 0xdc00 + ch % 1024; + len = 2; + } else { + txt[0] = ch; + } + + if (CTFontGetGlyphsForCharacters(font, txt, glyphs, len)) + return glyphs[0]; + + return 0; } int MapCharToGlyph_AAT(CFDictionaryRef attributes, UInt32 ch) { - CTFontRef font = fontFromAttributes(attributes); - return mapCharToGlyphFromCTFont(font, ch); + CTFontRef font = fontFromAttributes(attributes); + return mapCharToGlyphFromCTFont(font, ch); } static int GetGlyphIDFromCTFont(CTFontRef ctFontRef, const char* glyphName) { - CFStringRef glyphname = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, - glyphName, - kCFStringEncodingUTF8, - kCFAllocatorNull); - int rval = CTFontGetGlyphWithName(ctFontRef, glyphname); - CFRelease(glyphname); - return rval; + CFStringRef glyphname = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + glyphName, + kCFStringEncodingUTF8, + kCFAllocatorNull); + int rval = CTFontGetGlyphWithName(ctFontRef, glyphname); + CFRelease(glyphname); + return rval; } int MapGlyphToIndex_AAT(CFDictionaryRef attributes, const char* glyphName) { - CTFontRef font = fontFromAttributes(attributes); - return GetGlyphIDFromCTFont(font, glyphName); + CTFontRef font = fontFromAttributes(attributes); + return GetGlyphIDFromCTFont(font, glyphName); } char* GetGlyphNameFromCTFont(CTFontRef ctFontRef, UInt16 gid, int* len) { - CGFontRef cgfont; - static char buffer[256]; - buffer[0] = 0; - *len = 0; - - cgfont = CTFontCopyGraphicsFont(ctFontRef, 0); - if (cgfont && gid < CGFontGetNumberOfGlyphs(cgfont)) { - CFStringRef glyphname = CGFontCopyGlyphNameForGlyph(cgfont, gid); - if (glyphname) { - if (CFStringGetCString(glyphname, buffer, 256, kCFStringEncodingUTF8)) { - *len = strlen(buffer); - } - CFRelease(glyphname); - } - CGFontRelease(cgfont); - } - - return &buffer[0]; + CGFontRef cgfont; + static char buffer[256]; + buffer[0] = 0; + *len = 0; + + cgfont = CTFontCopyGraphicsFont(ctFontRef, 0); + if (cgfont && gid < CGFontGetNumberOfGlyphs(cgfont)) { + CFStringRef glyphname = CGFontCopyGlyphNameForGlyph(cgfont, gid); + if (glyphname) { + if (CFStringGetCString(glyphname, buffer, 256, kCFStringEncodingUTF8)) { + *len = strlen(buffer); + } + CFRelease(glyphname); + } + CGFontRelease(cgfont); + } + + return &buffer[0]; } int GetFontCharRange_AAT(CFDictionaryRef attributes, int reqFirst) { - if (reqFirst) { - int ch = 0; - while (MapCharToGlyph_AAT(attributes, ch) == 0 && ch < 0x10ffff) - ++ch; - return ch; - } else { - int ch = 0x10ffff; - while (MapCharToGlyph_AAT(attributes, ch) == 0 && ch > 0) - --ch; - return ch; - } + if (reqFirst) { + int ch = 0; + while (MapCharToGlyph_AAT(attributes, ch) == 0 && ch < 0x10ffff) + ++ch; + return ch; + } else { + int ch = 0x10ffff; + while (MapCharToGlyph_AAT(attributes, ch) == 0 && ch > 0) + --ch; + return ch; + } } char* getNameFromCTFont(CTFontRef ctFontRef, CFStringRef nameKey) { - char *buf; - CFStringRef name = CTFontCopyName(ctFontRef, nameKey); - CFIndex len = CFStringGetLength(name); - len = len * 6 + 1; - buf = xmalloc(len); - if (CFStringGetCString(name, buf, len, kCFStringEncodingUTF8)) - return buf; - free(buf); - return 0; + char *buf; + CFStringRef name = CTFontCopyName(ctFontRef, nameKey); + CFIndex len = CFStringGetLength(name); + len = len * 6 + 1; + buf = xmalloc(len); + if (CFStringGetCString(name, buf, len, kCFStringEncodingUTF8)) + return buf; + free(buf); + return NULL; } char* getFileNameFromCTFont(CTFontRef ctFontRef, int *index) { - char *ret = NULL; - CFURLRef url = NULL; + char *ret = NULL; + CFURLRef url = NULL; #if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 - /* kCTFontURLAttribute was not avialable before 10.6 */ - ATSFontRef atsFont; - FSRef fsref; - OSStatus status; - atsFont = CTFontGetPlatformFont(ctFontRef, NULL); - status = ATSFontGetFileReference(atsFont, &fsref); - if (status == noErr) - url = CFURLCreateFromFSRef(NULL, &fsref); + /* kCTFontURLAttribute was not avialable before 10.6 */ + ATSFontRef atsFont; + FSRef fsref; + OSStatus status; + atsFont = CTFontGetPlatformFont(ctFontRef, NULL); + status = ATSFontGetFileReference(atsFont, &fsref); + if (status == noErr) + url = CFURLCreateFromFSRef(NULL, &fsref); #else - url = (CFURLRef) CTFontCopyAttribute(ctFontRef, kCTFontURLAttribute); + url = (CFURLRef) CTFontCopyAttribute(ctFontRef, kCTFontURLAttribute); #endif - if (url) { - UInt8 pathname[PATH_MAX]; - if (CFURLGetFileSystemRepresentation(url, true, pathname, PATH_MAX)) { - FT_Error error; - FT_Face face; - - *index = 0; - - if (!gFreeTypeLibrary) { - error = FT_Init_FreeType(&gFreeTypeLibrary); - if (error) { - fprintf(stderr, "FreeType initialization failed! (%d)\n", error); - exit(1); - } - } - - error = FT_New_Face(gFreeTypeLibrary, (char *) pathname, 0, &face); - if (!error) { - if (face->num_faces > 1) { - int num_faces = face->num_faces; - char *ps_name1 = getNameFromCTFont(ctFontRef, kCTFontPostScriptNameKey); - int i; - *index = -1; - FT_Done_Face (face); - for (i = 0; i < num_faces; i++) { - error = FT_New_Face (gFreeTypeLibrary, (char *) pathname, i, &face); - if (!error) { - const char *ps_name2 = FT_Get_Postscript_Name(face); - if (strcmp(ps_name1, ps_name2) == 0) { - *index = i; - break; - } - FT_Done_Face (face); - } - } - } - } - - if (*index != -1) - ret = strdup((char *) pathname); - } - CFRelease(url); - } - - return ret; + if (url) { + UInt8 pathname[PATH_MAX]; + if (CFURLGetFileSystemRepresentation(url, true, pathname, PATH_MAX)) { + FT_Error error; + FT_Face face; + + *index = 0; + + if (!gFreeTypeLibrary) { + error = FT_Init_FreeType(&gFreeTypeLibrary); + if (error) { + fprintf(stderr, "FreeType initialization failed! (%d)\n", error); + exit(1); + } + } + + error = FT_New_Face(gFreeTypeLibrary, (char *) pathname, 0, &face); + if (!error) { + if (face->num_faces > 1) { + int num_faces = face->num_faces; + char *ps_name1 = getNameFromCTFont(ctFontRef, kCTFontPostScriptNameKey); + int i; + *index = -1; + FT_Done_Face (face); + for (i = 0; i < num_faces; i++) { + error = FT_New_Face (gFreeTypeLibrary, (char *) pathname, i, &face); + if (!error) { + const char *ps_name2 = FT_Get_Postscript_Name(face); + if (strcmp(ps_name1, ps_name2) == 0) { + *index = i; + break; + } + FT_Done_Face (face); + } + } + free(ps_name1); + } + } + + if (*index != -1) + ret = strdup((char *) pathname); + } + CFRelease(url); + } + + return ret; } CFDictionaryRef findDictionaryInArrayWithIdentifier(CFArrayRef array, const void* identifierKey, int identifier) { - CFDictionaryRef dict = NULL; - - if (array) { - int value = -1; - CFIndex i; - for (i = 0; i < CFArrayGetCount(array); i++) { - CFDictionaryRef item = CFArrayGetValueAtIndex(array, i); - CFNumberRef itemId = CFDictionaryGetValue(item, identifierKey); - if (itemId) { - CFNumberGetValue(itemId, kCFNumberIntType, &value); - if (value == identifier) { - dict = item; - break; - } - } - } - } - return dict; + CFDictionaryRef dict = NULL; + + if (array) { + int value = -1; + CFIndex i; + for (i = 0; i < CFArrayGetCount(array); i++) { + CFDictionaryRef item = CFArrayGetValueAtIndex(array, i); + CFNumberRef itemId = CFDictionaryGetValue(item, identifierKey); + if (itemId) { + CFNumberGetValue(itemId, kCFNumberIntType, &value); + if (value == identifier) { + dict = item; + break; + } + } + } + } + return dict; } CFDictionaryRef findDictionaryInArray(CFArrayRef array, const void* nameKey, const char* name, int nameLength) { - CFDictionaryRef dict = NULL; - - if (array) { - CFStringRef itemName; - CFIndex i; - itemName = CFStringCreateWithBytes(NULL, (UInt8 *) name, nameLength, - kCFStringEncodingUTF8, false); - for (i = 0; i < CFArrayGetCount(array); i++) { - CFDictionaryRef item = CFArrayGetValueAtIndex(array, i); - CFStringRef iName = CFDictionaryGetValue(item, nameKey); - if (iName && !CFStringCompare(itemName, iName, kCFCompareCaseInsensitive)) { - dict = item; - break; - } - } - CFRelease(itemName); - } - return dict; + CFDictionaryRef dict = NULL; + + if (array) { + CFStringRef itemName; + CFIndex i; + itemName = CFStringCreateWithBytes(NULL, (UInt8 *) name, nameLength, + kCFStringEncodingUTF8, false); + for (i = 0; i < CFArrayGetCount(array); i++) { + CFDictionaryRef item = CFArrayGetValueAtIndex(array, i); + CFStringRef iName = CFDictionaryGetValue(item, nameKey); + if (iName && !CFStringCompare(itemName, iName, kCFCompareCaseInsensitive)) { + dict = item; + break; + } + } + CFRelease(itemName); + } + return dict; } CFNumberRef findSelectorByName(CFDictionaryRef feature, const char* name, int nameLength) { - CFNumberRef selector = NULL; - CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); - if (selectors) { - CFDictionaryRef s = findDictionaryInArray(selectors, kCTFontFeatureSelectorNameKey, name, nameLength); - if (s) - selector = CFDictionaryGetValue(s, kCTFontFeatureSelectorIdentifierKey); - } - return selector; + CFNumberRef selector = NULL; + CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); + if (selectors) { + CFDictionaryRef s = findDictionaryInArray(selectors, kCTFontFeatureSelectorNameKey, name, nameLength); + if (s) + selector = CFDictionaryGetValue(s, kCTFontFeatureSelectorIdentifierKey); + } + return selector; } static CFDictionaryRef createFeatureSettingDictionary(CFNumberRef featureTypeIdentifier, CFNumberRef featureSelectorIdentifier) { - const void* settingKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey }; - const void* settingValues[] = { featureTypeIdentifier, featureSelectorIdentifier }; + const void* settingKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey }; + const void* settingValues[] = { featureTypeIdentifier, featureSelectorIdentifier }; - return CFDictionaryCreate(kCFAllocatorDefault, settingKeys, settingValues, 2, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + return CFDictionaryCreate(kCFAllocatorDefault, settingKeys, settingValues, 2, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } const CFStringRef kXeTeXEmboldenAttributeName = CFSTR("XeTeXEmbolden"); @@ -545,385 +546,260 @@ const CFStringRef kXeTeXEmboldenAttributeName = CFSTR("XeTeXEmbolden"); void* loadAATfont(CTFontDescriptorRef descriptor, integer scaled_size, const char* cp1) { - CTFontRef font, actualFont; - CGFloat ctSize; - CFMutableDictionaryRef stringAttributes, attributes; - CGAffineTransform matrix; - CFMutableArrayRef cascadeList; - CTFontDescriptorRef lastResort; - double tracking = 0.0; - float extend = 1.0; - float slant = 0.0; - float embolden = 0.0; - float letterspace = 0.0; - uint32_t rgbValue; - - // create a base font instance for applying further attributes - ctSize = TeXtoPSPoints(Fix2D(scaled_size)); - font = CTFontCreateWithFontDescriptor(descriptor, ctSize, NULL); - if (!font) - return NULL; - - stringAttributes = CFDictionaryCreateMutable(NULL, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - attributes = CFDictionaryCreateMutable(NULL, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - if (cp1) { - CFArrayRef features = CTFontCopyFeatures(font); - CFArrayRef axes = CTFontCopyVariationAxes(font); - CFMutableArrayRef featureSettings = - CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFMutableDictionaryRef variation = - CFDictionaryCreateMutable(NULL, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - // interpret features & variations following ":" - while (*cp1) { - CFDictionaryRef feature, axis; - int ret; - const char* cp2; - const char* cp3; - // locate beginning of name=value pair - if (*cp1 == ':' || *cp1 == ';') // skip over separator - ++cp1; - while (*cp1 == ' ' || *cp1 == '\t') // skip leading whitespace - ++cp1; - if (*cp1 == 0) // break if end of string - break; - - // scan to end of pair - cp2 = cp1; - while (*cp2 && (*cp2 != ';') && (*cp2 != ':')) - ++cp2; - - // look for the '=' separator - cp3 = cp1; - while ((cp3 < cp2) && (*cp3 != '=')) - ++cp3; - if (cp3 == cp2) - goto bad_option; - - // now cp1 points to option name, cp3 to '=', cp2 to ';' or null - - // first try for a feature by this name - feature = findDictionaryInArray(features, kCTFontFeatureTypeNameKey, cp1, cp3 - cp1); - if (feature) { - // look past the '=' separator for setting names - int featLen = cp3 - cp1; - int zeroInteger = 0; - CFNumberRef zero = CFNumberCreate(NULL, kCFNumberIntType, &zeroInteger); - ++cp3; - while (cp3 < cp2) { - CFNumberRef selector; - int disable = 0; - const char* cp4; - // skip leading whitespace - while (*cp3 == ' ' || *cp3 == '\t') - ++cp3; - - // possibly multiple settings... - if (*cp3 == '!') { // check for negation - disable = 1; - ++cp3; - } - - // scan for end of setting name - cp4 = cp3; - while (cp4 < cp2 && *cp4 != ',') - ++cp4; - - // now cp3 points to name, cp4 to ',' or ';' or null - selector = findSelectorByName(feature, cp3, cp4 - cp3); - if (selector && CFNumberCompare(selector, zero, NULL) >= 0) { - CFNumberRef featureType = CFDictionaryGetValue(feature, kCTFontFeatureTypeIdentifierKey); - CFDictionaryRef featureSetting = createFeatureSettingDictionary(featureType, selector); - CFArrayAppendValue(featureSettings, featureSetting); - CFRelease(featureSetting); - } else { - fontfeaturewarning(cp1, featLen, cp3, cp4 - cp3); - } - - // point beyond setting name terminator - cp3 = cp4 + 1; - } - CFRelease(zero); - - goto next_option; - } - - // try to find a variation by this name - axis = findDictionaryInArray(axes, kCTFontVariationAxisNameKey, cp1, cp3 - cp1); - if (axis) { - CFNumberRef axisIdentifier, axisValue; - double value = 0.0, decimal = 1.0; - bool negate = false; - // look past the '=' separator for the value - ++cp3; - if (*cp3 == '-') { - ++cp3; - negate = true; - } - while (cp3 < cp2) { - int v = *cp3 - '0'; - if (v >= 0 && v <= 9) { - if (decimal != 1.0) { - value += v / decimal; - decimal *= 10.0; - } else { - value = value * 10.0 + v; - } - } else if (*cp3 == '.') { - if (decimal != 1.0) - break; - decimal = 10.0; - } else { - break; - } - ++cp3; - } - if (negate) - value = -value; - - axisIdentifier = CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey); - axisValue = CFNumberCreate(NULL, kCFNumberDoubleType, &value); - CFDictionaryAddValue(variation, axisIdentifier, axisValue); - CFRelease(axisValue); - - goto next_option; - } - - // didn't find feature or variation, try other options... - ret = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden, &letterspace, &rgbValue); - if (ret == 1) - goto next_option; - else if (ret == -1) - goto bad_option; - - if (strncmp(cp1, "tracking", 8) == 0) { - CFNumberRef trackingNumber; - cp3 = cp1 + 8; - if (*cp3 != '=') - goto bad_option; - ++cp3; - tracking = read_double(&cp3); - trackingNumber = CFNumberCreate(NULL, kCFNumberDoubleType, &tracking); - CFDictionaryAddValue(stringAttributes, kCTKernAttributeName, trackingNumber); - CFRelease(trackingNumber); - goto next_option; - } - - bad_option: - // not a name=value pair, or not recognized.... - // check for plain "vertical" before complaining - 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) { - int orientation = kCTFontVerticalOrientation; - CFNumberRef orientationNumber = CFNumberCreate(NULL, kCFNumberIntType, &orientation); - CFDictionaryAddValue(attributes, kCTFontOrientationAttribute, orientationNumber); - CFRelease(orientationNumber); - CFDictionaryAddValue(stringAttributes, kCTVerticalFormsAttributeName, kCFBooleanTrue); - goto next_option; - } - } - - fontfeaturewarning(cp1, cp2 - cp1, 0, 0); - - next_option: - // go to next name=value pair - cp1 = cp2; - } - - if (features) - CFRelease(features); - if (axes) - CFRelease(axes); - - if (CFArrayGetCount(featureSettings)) - CFDictionaryAddValue(attributes, kCTFontFeatureSettingsAttribute, featureSettings); - CFRelease(featureSettings); - - if (CFDictionaryGetCount(variation)) - CFDictionaryAddValue(attributes, kCTFontVariationAttribute, variation); - CFRelease(variation); - } - - if ((loadedfontflags & FONT_FLAGS_COLORED) != 0) { - CGFloat red = ((rgbValue & 0xFF000000) >> 24) / 255.0; - CGFloat green = ((rgbValue & 0x00FF0000) >> 16) / 255.0; - CGFloat blue = ((rgbValue & 0x0000FF00) >> 8 ) / 255.0; - CGFloat alpha = ((rgbValue & 0x000000FF) ) / 255.0; - CGColorRef color = CGColorCreateGenericRGB(red, green, blue, alpha); - CFDictionaryAddValue(stringAttributes, kCTForegroundColorAttributeName, color); - CGColorRelease(color); - } - - matrix = CGAffineTransformIdentity; - // XXX this breaks y glyph positioning - if (extend != 1.0 || slant != 0.0) - matrix = CGAffineTransformMake(extend, slant, 0, 1.0, 0, 0); - - if (embolden != 0.0) { - CFNumberRef emboldenNumber; - embolden = embolden * Fix2D(scaled_size) / 100.0; - emboldenNumber = CFNumberCreate(NULL, kCFNumberFloatType, &embolden); - CFDictionaryAddValue(stringAttributes, kXeTeXEmboldenAttributeName, emboldenNumber); - CFRelease(emboldenNumber); - } - - if (letterspace != 0.0) - loadedfontletterspace = (letterspace / 100.0) * scaled_size; - - // Disable Core Text font fallback (cascading) with only the last resort font - // in the cascade list. - cascadeList = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); - lastResort = CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0); - CFArrayAppendValue(cascadeList, lastResort); - CFRelease(lastResort); - CFDictionaryAddValue(attributes, kCTFontCascadeListAttribute, cascadeList); - CFRelease(cascadeList); - - descriptor = CTFontDescriptorCreateWithAttributes(attributes); - CFRelease(attributes); - actualFont = CTFontCreateCopyWithAttributes(font, ctSize, &matrix, descriptor); - CFRelease(font); - CFDictionaryAddValue(stringAttributes, kCTFontAttributeName, actualFont); - CFRelease(actualFont); - - nativefonttypeflag = AAT_FONT_FLAG; - return (void *) stringAttributes; -} - -int -countpdffilepages() -{ - int rval = 0; - - char* pic_path = kpse_find_file((char*)nameoffile + 1, kpse_pict_format, 1); - CFURLRef picFileURL = NULL; - if (pic_path) { - picFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*)pic_path, strlen(pic_path), false); - if (picFileURL != NULL) { - FSRef picFileRef; - CGPDFDocumentRef document; - CFURLGetFSRef(picFileURL, &picFileRef); - document = CGPDFDocumentCreateWithURL(picFileURL); - if (document != NULL) { - rval = CGPDFDocumentGetNumberOfPages(document); - CGPDFDocumentRelease(document); - } - CFRelease(picFileURL); - } - free(pic_path); - } - - return rval; -} - -int -find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page) - /* returns bounds in TeX points */ -{ - OSStatus result = fnfErr; - char* pic_path = kpse_find_file((char*)nameoffile + 1, kpse_pict_format, 1); - CFURLRef picFileURL = NULL; - - *path = NULL; - - if (pic_path) { - picFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*)pic_path, strlen(pic_path), false); - - if (picFileURL != NULL) { - if (pdfBoxType > 0) { - CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(picFileURL); - if (document != NULL) { - CGPDFPageRef pageRef; - CGRect r; - CGPDFBox boxType; - int nPages = CGPDFDocumentGetNumberOfPages(document); - if (page < 0) - page = nPages + 1 + page; - if (page < 1) - page = 1; - if (page > nPages) - page = nPages; - - pageRef = CGPDFDocumentGetPage(document, page); - switch (pdfBoxType) { - case pdfbox_crop: - default: - boxType = kCGPDFCropBox; - break; - case pdfbox_media: - boxType = kCGPDFMediaBox; - break; - case pdfbox_bleed: - boxType = kCGPDFBleedBox; - break; - case pdfbox_trim: - boxType = kCGPDFTrimBox; - break; - case pdfbox_art: - boxType = kCGPDFArtBox; - break; - } - r = CGPDFPageGetBoxRect(pageRef, boxType); - - bounds->x = r.origin.x * 72.27 / 72.0; - bounds->y = r.origin.y * 72.27 / 72.0; - bounds->wd = r.size.width * 72.27 / 72.0; - bounds->ht = r.size.height * 72.27 / 72.0; - CGPDFDocumentRelease(document); - result = noErr; - } - } else { - CGImageSourceRef picFileSource = CGImageSourceCreateWithURL(picFileURL, NULL); - if (picFileSource) { - CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(picFileSource, 0, NULL); - - CFNumberRef imageWidth = CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth); - CFNumberRef imageHeight = CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight); - CFNumberRef DPIWidth = CFDictionaryGetValue(properties, kCGImagePropertyDPIWidth); - CFNumberRef DPIHeight = CFDictionaryGetValue(properties, kCGImagePropertyDPIHeight); - - if (imageWidth && imageHeight) { - int w = 0, h = 0, hRes = 72, vRes = 72; - CFNumberGetValue(imageWidth, kCFNumberIntType, &w); - CFNumberGetValue(imageHeight, kCFNumberIntType, &h); - if (DPIWidth) - CFNumberGetValue(DPIWidth, kCFNumberIntType, &hRes); - if (DPIHeight) - CFNumberGetValue(DPIHeight, kCFNumberIntType, &vRes); - - bounds->x = 0; - bounds->y = 0; - bounds->wd = w * 72.27 / hRes; - bounds->ht = h * 72.27 / vRes; - CFRelease(properties); - CFRelease(picFileSource); - result = noErr; - } - } - } - - CFRelease(picFileURL); - } - - /* if we couldn't import it, toss the pathname as we'll be returning an error */ - if (result != noErr) - free(pic_path); - else - *path = (char*)pic_path; - } - - return result; + CTFontRef font, actualFont; + CGFloat ctSize; + CFMutableDictionaryRef stringAttributes, attributes; + CGAffineTransform matrix; + CFMutableArrayRef cascadeList; + CTFontDescriptorRef lastResort; + double tracking = 0.0; + float extend = 1.0; + float slant = 0.0; + float embolden = 0.0; + float letterspace = 0.0; + uint32_t rgbValue; + + // create a base font instance for applying further attributes + ctSize = TeXtoPSPoints(Fix2D(scaled_size)); + font = CTFontCreateWithFontDescriptor(descriptor, ctSize, NULL); + if (!font) + return NULL; + + stringAttributes = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + attributes = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (cp1) { + CFArrayRef features = CTFontCopyFeatures(font); + CFArrayRef axes = CTFontCopyVariationAxes(font); + CFMutableArrayRef featureSettings = + CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFMutableDictionaryRef variation = + CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + // interpret features & variations following ":" + while (*cp1) { + CFDictionaryRef feature, axis; + int ret; + const char* cp2; + const char* cp3; + // locate beginning of name=value pair + if (*cp1 == ':' || *cp1 == ';') // skip over separator + ++cp1; + while (*cp1 == ' ' || *cp1 == '\t') // skip leading whitespace + ++cp1; + if (*cp1 == 0) // break if end of string + break; + + // scan to end of pair + cp2 = cp1; + while (*cp2 && (*cp2 != ';') && (*cp2 != ':')) + ++cp2; + + // look for the '=' separator + cp3 = cp1; + while ((cp3 < cp2) && (*cp3 != '=')) + ++cp3; + if (cp3 == cp2) + goto bad_option; + + // now cp1 points to option name, cp3 to '=', cp2 to ';' or null + + // first try for a feature by this name + feature = findDictionaryInArray(features, kCTFontFeatureTypeNameKey, cp1, cp3 - cp1); + if (feature) { + // look past the '=' separator for setting names + int featLen = cp3 - cp1; + int zeroInteger = 0; + CFNumberRef zero = CFNumberCreate(NULL, kCFNumberIntType, &zeroInteger); + ++cp3; + while (cp3 < cp2) { + CFNumberRef selector; + int disable = 0; + const char* cp4; + // skip leading whitespace + while (*cp3 == ' ' || *cp3 == '\t') + ++cp3; + + // possibly multiple settings... + if (*cp3 == '!') { // check for negation + disable = 1; + ++cp3; + } + + // scan for end of setting name + cp4 = cp3; + while (cp4 < cp2 && *cp4 != ',') + ++cp4; + + // now cp3 points to name, cp4 to ',' or ';' or null + selector = findSelectorByName(feature, cp3, cp4 - cp3); + if (selector && CFNumberCompare(selector, zero, NULL) >= 0) { + CFNumberRef featureType = CFDictionaryGetValue(feature, kCTFontFeatureTypeIdentifierKey); + CFDictionaryRef featureSetting = createFeatureSettingDictionary(featureType, selector); + CFArrayAppendValue(featureSettings, featureSetting); + CFRelease(featureSetting); + } else { + fontfeaturewarning(cp1, featLen, cp3, cp4 - cp3); + } + + // point beyond setting name terminator + cp3 = cp4 + 1; + } + CFRelease(zero); + + goto next_option; + } + + // try to find a variation by this name + axis = findDictionaryInArray(axes, kCTFontVariationAxisNameKey, cp1, cp3 - cp1); + if (axis) { + CFNumberRef axisIdentifier, axisValue; + double value = 0.0, decimal = 1.0; + bool negate = false; + // look past the '=' separator for the value + ++cp3; + if (*cp3 == '-') { + ++cp3; + negate = true; + } + while (cp3 < cp2) { + int v = *cp3 - '0'; + if (v >= 0 && v <= 9) { + if (decimal != 1.0) { + value += v / decimal; + decimal *= 10.0; + } else { + value = value * 10.0 + v; + } + } else if (*cp3 == '.') { + if (decimal != 1.0) + break; + decimal = 10.0; + } else { + break; + } + ++cp3; + } + if (negate) + value = -value; + + axisIdentifier = CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey); + axisValue = CFNumberCreate(NULL, kCFNumberDoubleType, &value); + CFDictionaryAddValue(variation, axisIdentifier, axisValue); + CFRelease(axisValue); + + goto next_option; + } + + // didn't find feature or variation, try other options... + ret = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden, &letterspace, &rgbValue); + if (ret == 1) + goto next_option; + else if (ret == -1) + goto bad_option; + + if (strncmp(cp1, "tracking", 8) == 0) { + CFNumberRef trackingNumber; + cp3 = cp1 + 8; + if (*cp3 != '=') + goto bad_option; + ++cp3; + tracking = read_double(&cp3); + trackingNumber = CFNumberCreate(NULL, kCFNumberDoubleType, &tracking); + CFDictionaryAddValue(stringAttributes, kCTKernAttributeName, trackingNumber); + CFRelease(trackingNumber); + goto next_option; + } + + bad_option: + // not a name=value pair, or not recognized.... + // check for plain "vertical" before complaining + 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) { + int orientation = kCTFontVerticalOrientation; + CFNumberRef orientationNumber = CFNumberCreate(NULL, kCFNumberIntType, &orientation); + CFDictionaryAddValue(attributes, kCTFontOrientationAttribute, orientationNumber); + CFRelease(orientationNumber); + CFDictionaryAddValue(stringAttributes, kCTVerticalFormsAttributeName, kCFBooleanTrue); + goto next_option; + } + } + + fontfeaturewarning(cp1, cp2 - cp1, 0, 0); + + next_option: + // go to next name=value pair + cp1 = cp2; + } + + if (features) + CFRelease(features); + if (axes) + CFRelease(axes); + + if (CFArrayGetCount(featureSettings)) + CFDictionaryAddValue(attributes, kCTFontFeatureSettingsAttribute, featureSettings); + CFRelease(featureSettings); + + if (CFDictionaryGetCount(variation)) + CFDictionaryAddValue(attributes, kCTFontVariationAttribute, variation); + CFRelease(variation); + } + + if ((loadedfontflags & FONT_FLAGS_COLORED) != 0) { + CGFloat red = ((rgbValue & 0xFF000000) >> 24) / 255.0; + CGFloat green = ((rgbValue & 0x00FF0000) >> 16) / 255.0; + CGFloat blue = ((rgbValue & 0x0000FF00) >> 8 ) / 255.0; + CGFloat alpha = ((rgbValue & 0x000000FF) ) / 255.0; + CGColorRef color = CGColorCreateGenericRGB(red, green, blue, alpha); + CFDictionaryAddValue(stringAttributes, kCTForegroundColorAttributeName, color); + CGColorRelease(color); + } + + matrix = CGAffineTransformIdentity; + // XXX this breaks y glyph positioning + if (extend != 1.0 || slant != 0.0) + matrix = CGAffineTransformMake(extend, slant, 0, 1.0, 0, 0); + + if (embolden != 0.0) { + CFNumberRef emboldenNumber; + embolden = embolden * Fix2D(scaled_size) / 100.0; + emboldenNumber = CFNumberCreate(NULL, kCFNumberFloatType, &embolden); + CFDictionaryAddValue(stringAttributes, kXeTeXEmboldenAttributeName, emboldenNumber); + CFRelease(emboldenNumber); + } + + if (letterspace != 0.0) + loadedfontletterspace = (letterspace / 100.0) * scaled_size; + + // Disable Core Text font fallback (cascading) with only the last resort font + // in the cascade list. + cascadeList = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); + lastResort = CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0); + CFArrayAppendValue(cascadeList, lastResort); + CFRelease(lastResort); + CFDictionaryAddValue(attributes, kCTFontCascadeListAttribute, cascadeList); + CFRelease(cascadeList); + + descriptor = CTFontDescriptorCreateWithAttributes(attributes); + CFRelease(attributes); + actualFont = CTFontCreateCopyWithAttributes(font, ctSize, &matrix, descriptor); + CFRelease(font); + CFDictionaryAddValue(stringAttributes, kCTFontAttributeName, actualFont); + CFRelease(actualFont); + + nativefonttypeflag = AAT_FONT_FLAG; + return (void *) stringAttributes; } diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_pic.c b/Build/source/texk/web2c/xetexdir/XeTeX_pic.c index ff4266be280..92233654232 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_pic.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_pic.c @@ -33,7 +33,6 @@ authorization from the copyright holders. /* XeTeX_pic.c interface between xetex and graphics files - (not used on OS X -- we use ImageIO graphics importers instead) only needs to get image dimensions, not actually load/process the file */ @@ -110,7 +109,7 @@ find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page) } goto done; } - + if (check_for_bmp(fp)) { struct bmp_info info; err = bmp_scan_file(&info, fp); @@ -120,7 +119,7 @@ find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page) } goto done; } - + if (check_for_png(fp)) { struct png_info info; err = png_scan_file(&info, fp); @@ -129,10 +128,10 @@ find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page) bounds->ht = (info.height * 72.27) / info.ydpi; } goto done; - } + } /* could support other file types here (TIFF, WMF, etc?) */ - + done: if (fp != NULL) fclose(fp); @@ -143,6 +142,6 @@ done: if (pic_path != NULL) free(pic_path); } - + return err; } diff --git a/Build/source/texk/web2c/xetexdir/am/xetex.am b/Build/source/texk/web2c/xetexdir/am/xetex.am index ef7683209c7..4bdc8b63e5c 100644 --- a/Build/source/texk/web2c/xetexdir/am/xetex.am +++ b/Build/source/texk/web2c/xetexdir/am/xetex.am @@ -26,9 +26,28 @@ xetex_cppflags += $(FREETYPE2_INCLUDES) xetex_cppflags += $(TECKIT_INCLUDES) xetex_cppflags += $(HARFBUZZ_INCLUDES) xetex_cppflags += $(GRAPHITE2_INCLUDES) -xetex_ldadd = $(libxetex) $(HARFBUZZ_LIBS) $(GRAPHITE2_LIBS) $(ICU_LIBS) $(TECKIT_LIBS) -xetex_dependencies = $(proglib) $(KPATHSEA_DEPEND) -xetex_dependencies += $(ICU_DEPEND) $(TECKIT_DEPEND) $(HARFBUZZ_DEPEND) $(GRAPHITE2_DEPEND) +xetex_cppflags += $(POPPLER_INCLUDES) +xetex_cppflags += $(LIBPNG_INCLUDES) +xetex_cppflags += $(ZLIB_INCLUDES) +xetex_ldadd = $(libxetex) +xetex_ldadd += $(HARFBUZZ_LIBS) +xetex_ldadd += $(GRAPHITE2_LIBS) +xetex_ldadd += $(ICU_LIBS) +xetex_ldadd += $(TECKIT_LIBS) +xetex_ldadd += $(POPPLER_LIBS) +xetex_ldadd += $(LIBPNG_LIBS) +xetex_ldadd += $(FREETYPE2_LIBS) +xetex_ldadd += $(ZLIB_LIBS) +xetex_dependencies = $(proglib) +xetex_dependencies += $(KPATHSEA_DEPEND) +xetex_dependencies += $(ICU_DEPEND) +xetex_dependencies += $(TECKIT_DEPEND) +xetex_dependencies += $(HARFBUZZ_DEPEND) +xetex_dependencies += $(GRAPHITE2_DEPEND) +xetex_dependencies += $(POPPLER_DEPEND) +xetex_dependencies += $(LIBPNG_DEPEND) +xetex_dependencies += $(FREETYPE2_DEPEND) +xetex_dependencies += $(ZLIB_DEPEND) if XETEX_MACOSX @@ -37,16 +56,11 @@ xetex_LDFLAGS = -framework ApplicationServices -framework Cocoa else !XETEX_MACOSX -xetex_cppflags += -DXETEX_OTHER -xetex_cppflags += $(POPPLER_INCLUDES) $(LIBPNG_INCLUDES) $(FONTCONFIG_INCLUDES) -xetex_ldadd += $(POPPLER_LIBS) $(LIBPNG_LIBS) $(FONTCONFIG_LIBS) -xetex_dependencies += $(POPPLER_DEPEND) $(LIBPNG_DEPEND) +xetex_cppflags += $(FONTCONFIG_INCLUDES) +xetex_ldadd += $(FONTCONFIG_LIBS) endif !XETEX_MACOSX -xetex_cppflags += $(ZLIB_INCLUDES) -xetex_ldadd += $(FREETYPE2_LIBS) $(ZLIB_LIBS) -xetex_dependencies += $(FREETYPE2_DEPEND) $(ZLIB_DEPEND) xetex_CPPFLAGS = $(xetex_cppflags) xetex_CFLAGS = # $(WARNING_CFLAGS) @@ -107,8 +121,6 @@ EXTRA_DIST += $(xetex_web_srcs) $(xetex_ch_srcs) xetexdir/xetex.defines DISTCLEANFILES += $(nodist_xetex_SOURCES) xetex.web xetex.ch xetex-web2c \ xetex.p xetex.pool xetex-tangle -EXTRA_DIST += \ - xetexdir/unicode-char-prep.pl ## libxetex ## @@ -131,11 +143,24 @@ libxetex_a_SOURCES = \ xetexdir/XeTeXOTMath.h \ xetexdir/XeTeX_ext.c \ xetexdir/XeTeX_ext.h \ + xetexdir/XeTeX_pic.c \ xetexdir/XeTeXswap.h \ xetexdir/trans.c \ xetexdir/trans.h \ xetexdir/hz.cpp \ - xetexdir/xetex.h + xetexdir/xetex.h \ + xetexdir/pdfimage.cpp \ + xetexdir/pdfimage.h \ + xetexdir/image/bmpimage.c \ + xetexdir/image/bmpimage.h \ + xetexdir/image/jpegimage.c \ + xetexdir/image/jpegimage.h \ + xetexdir/image/mfileio.c \ + xetexdir/image/mfileio.h \ + xetexdir/image/numbers.c \ + xetexdir/image/numbers.h \ + xetexdir/image/pngimage.c \ + xetexdir/image/pngimage.h if XETEX_MACOSX @@ -150,20 +175,7 @@ else !XETEX_MACOSX libxetex_a_SOURCES += \ xetexdir/XeTeXFontMgr_FC.cpp \ - xetexdir/XeTeXFontMgr_FC.h \ - xetexdir/XeTeX_pic.c \ - xetexdir/pdfimage.cpp \ - xetexdir/pdfimage.h \ - xetexdir/image/bmpimage.c \ - xetexdir/image/bmpimage.h \ - xetexdir/image/jpegimage.c \ - xetexdir/image/jpegimage.h \ - xetexdir/image/mfileio.c \ - xetexdir/image/mfileio.h \ - xetexdir/image/numbers.c \ - xetexdir/image/numbers.h \ - xetexdir/image/pngimage.c \ - xetexdir/image/pngimage.h + xetexdir/XeTeXFontMgr_FC.h endif !XETEX_MACOSX @@ -171,7 +183,6 @@ endif !XETEX_MACOSX libxetex_prereq = xetexd.h $(xetex_dependencies) $(libxetex_a_OBJECTS): $(libxetex_prereq) -EXTRA_DIST += xetexdir/ChangeLog # XeTeX Tests # @@ -183,9 +194,9 @@ if XETEX TESTS += $(xetex_tests) endif XETEX -## Not used -## EXTRA_DIST += \ + xetexdir/unicode-char-prep.pl \ + xetexdir/ChangeLog \ xetexdir/COPYING \ xetexdir/NEWS \ xetexdir/image/README \ diff --git a/Build/source/texk/web2c/xetexdir/pdfimage.cpp b/Build/source/texk/web2c/xetexdir/pdfimage.cpp index fac84953c5f..a9ccbd02e77 100644 --- a/Build/source/texk/web2c/xetexdir/pdfimage.cpp +++ b/Build/source/texk/web2c/xetexdir/pdfimage.cpp @@ -61,19 +61,19 @@ pdf_get_rect(char* filename, int page_num, int pdf_box, realrect* box) { GooString* name = new GooString(filename); PDFDoc* doc = new PDFDoc(name); - + if (!doc) { delete name; return -1; } - + /* if the doc got created, it now owns name, so we mustn't delete it! */ - + if (!doc->isOk()) { delete doc; return -1; } - + int pages = doc->getNumPages(); if (page_num > pages) page_num = pages; @@ -120,14 +120,14 @@ pdf_count_pages(char* filename) int pages = 0; GooString* name = new GooString(filename); PDFDoc* doc = new PDFDoc(name); - + if (!doc) { delete name; return 0; } - + /* if the doc got created, it now owns name, so we mustn't delete it! */ - + if (doc->isOk()) pages = doc->getNumPages(); diff --git a/Build/source/texk/web2c/xetexdir/xetex.ch b/Build/source/texk/web2c/xetexdir/xetex.ch index 304a3831307..1c389489fc9 100644 --- a/Build/source/texk/web2c/xetexdir/xetex.ch +++ b/Build/source/texk/web2c/xetexdir/xetex.ch @@ -277,7 +277,7 @@ if #<>0 then begin if #<>0 then begin j:=str_start_macro(#); while ((not must_quote) or (quote_char=0)) and (j<str_start_macro(#+1)) do begin - if (str_pool[j]=" ") then must_quote:=true + if str_pool[j]=" " then must_quote:=true else if (str_pool[j]="""") or (str_pool[j]="'") then begin must_quote:=true; quote_char:="""" + "'" - str_pool[j]; @@ -773,7 +773,7 @@ var i,@!j,@!k:integer; {all-purpose integers} @x [53a.1379] l.??? -etex command line switch incr(loc); eTeX_mode:=1; {enter extended mode} @y - if (buffer[loc]="*") then incr(loc); + if buffer[loc]="*" then incr(loc); eTeX_mode:=1; {enter extended mode} @z diff --git a/Build/source/texk/web2c/xetexdir/xetex.h b/Build/source/texk/web2c/xetexdir/xetex.h index 73d8f95502d..bcd5d0cfed8 100644 --- a/Build/source/texk/web2c/xetexdir/xetex.h +++ b/Build/source/texk/web2c/xetexdir/xetex.h @@ -32,11 +32,11 @@ authorization from the copyright holders. /* additional declarations we want to slip in for xetex */ -#define native_node_size 6 -#define native_node_text(p) ((unsigned short*)(&(mem[(p) + native_node_size]))) +#define native_node_size 6 +#define native_node_text(p) ((unsigned short*)(&(mem[(p) + native_node_size]))) -#define getnativechar(p,i) native_node_text(p)[i] -#define setnativechar(p,i,v) native_node_text(p)[i] = v +#define getnativechar(p,i) native_node_text(p)[i] +#define setnativechar(p,i,v) native_node_text(p)[i] = v #define getnativeusv(p,i) \ ((native_node_text(p)[i] >= 0xd800 && native_node_text(p)[i] < 0xdc00) ? \ @@ -44,84 +44,84 @@ authorization from the copyright holders. native_node_text(p)[i]) /* p is native_word node; g is XeTeX_use_glyph_metrics flag */ -#define setnativemetrics(p,g) measure_native_node(&(mem[p]), g) +#define setnativemetrics(p,g) measure_native_node(&(mem[p]), g) -#define setnativeglyphmetrics(p,g) measure_native_glyph(&(mem[p]), g) +#define setnativeglyphmetrics(p,g) measure_native_glyph(&(mem[p]), g) -#define setjustifiednativeglyphs(p) store_justified_native_glyphs(&(mem[p])) +#define setjustifiednativeglyphs(p) store_justified_native_glyphs(&(mem[p])) -#define getnativeitaliccorrection(p) get_native_italic_correction(&(mem[p])) -#define getnativeglyphitaliccorrection(p) get_native_glyph_italic_correction(&(mem[p])) +#define getnativeitaliccorrection(p) get_native_italic_correction(&(mem[p])) +#define getnativeglyphitaliccorrection(p) get_native_glyph_italic_correction(&(mem[p])) -#define getnativeglyph(p,i) get_native_glyph(&(mem[p]), i) +#define getnativeglyph(p,i) get_native_glyph(&(mem[p]), i) -#define makexdvglypharraydata(p) makeXDVGlyphArrayData(&(mem[p])) -#define xdvbufferbyte(i) xdvbuffer[i] +#define makexdvglypharraydata(p) makeXDVGlyphArrayData(&(mem[p])) +#define xdvbufferbyte(i) xdvbuffer[i] -#define getcpcode get_cp_code -#define setcpcode set_cp_code -#define getnativewordcp(p,s) get_native_word_cp(&(mem[p]), s) +#define getcpcode get_cp_code +#define setcpcode set_cp_code +#define getnativewordcp(p,s) get_native_word_cp(&(mem[p]), s) -#define pic_node_size 8 +#define pic_node_size 8 -#define deref(p) (*(p)) +#define deref(p) (*(p)) -#define findpicfile(a,b,c,d) find_pic_file(a, b, c, d) +#define findpicfile(a,b,c,d) find_pic_file(a, b, c, d) -#define picpathbyte(p,i) ((unsigned char*)&(mem[p+pic_node_size]))[i] +#define picpathbyte(p,i) ((unsigned char*)&(mem[p+pic_node_size]))[i] -#define dviopenout(f) open_dvi_output(&(f)) +#define dviopenout(f) open_dvi_output(&(f)) -#define nullptr (NULL) -#define glyphinfobyte(p,k) ((unsigned char*)p)[k] -#define casttoushort(x) (unsigned short)(x) +#define nullptr (NULL) +#define glyphinfobyte(p,k) ((unsigned char*)p)[k] +#define casttoushort(x) (unsigned short)(x) /* easier to do the bit-twiddling here than in Pascal */ /* read fields from a 32-bit math code */ -#define mathfamfield(x) (((unsigned)(x) >> 24) & 0xFF) -#define mathclassfield(x) (((unsigned)(x) >> 21) & 0x07) -#define mathcharfield(x) ((unsigned)(x) & 0x1FFFFF) +#define mathfamfield(x) (((unsigned)(x) >> 24) & 0xFF) +#define mathclassfield(x) (((unsigned)(x) >> 21) & 0x07) +#define mathcharfield(x) ((unsigned)(x) & 0x1FFFFF) /* calculate pieces to assign to a math code */ -#define setfamilyfield(x) (((unsigned)(x) & 0xFF) << 24) -#define setclassfield(x) (((unsigned)(x) & 0x07) << 21) +#define setfamilyfield(x) (((unsigned)(x) & 0xFF) << 24) +#define setclassfield(x) (((unsigned)(x) & 0x07) << 21) /* aliases */ -#define getnativemathsyparam get_native_mathsy_param -#define getnativemathexparam get_native_mathex_param -#define getotmathconstant get_ot_math_constant -#define getotmathvariant get_ot_math_variant -#define getotassemblyptr get_ot_assembly_ptr -#define getotmathitalcorr get_ot_math_ital_corr -#define getotmathaccentpos get_ot_math_accent_pos -#define getotmathkern get_ot_math_kern -#define otpartcount ot_part_count -#define otpartglyph ot_part_glyph -#define otpartisextender ot_part_is_extender -#define otpartstartconnector ot_part_start_connector -#define otpartendconnector ot_part_end_connector -#define otpartfulladvance ot_part_full_advance -#define otminconnectoroverlap ot_min_connector_overlap +#define getnativemathsyparam get_native_mathsy_param +#define getnativemathexparam get_native_mathex_param +#define getotmathconstant get_ot_math_constant +#define getotmathvariant get_ot_math_variant +#define getotassemblyptr get_ot_assembly_ptr +#define getotmathitalcorr get_ot_math_ital_corr +#define getotmathaccentpos get_ot_math_accent_pos +#define getotmathkern get_ot_math_kern +#define otpartcount ot_part_count +#define otpartglyph ot_part_glyph +#define otpartisextender ot_part_is_extender +#define otpartstartconnector ot_part_start_connector +#define otpartendconnector ot_part_end_connector +#define otpartfulladvance ot_part_full_advance +#define otminconnectoroverlap ot_min_connector_overlap /* prototypes used in xetex.web */ #include "XeTeXOTMath.h" /* Unicode file reading modes */ -#define AUTO 0 /* default: will become one of 1..3 at file open time, after sniffing */ -#define UTF8 1 -#define UTF16BE 2 -#define UTF16LE 3 -#define RAW 4 -#define ICUMAPPING 5 +#define AUTO 0 /* default: will become one of 1..3 at file open time, after sniffing */ +#define UTF8 1 +#define UTF16BE 2 +#define UTF16LE 3 +#define RAW 4 +#define ICUMAPPING 5 #ifdef WIN32 -#define WIN32CONSOLE 6 +#define WIN32CONSOLE 6 #endif /* we don't use xchr, so change the cpascal.h definition of this... */ #undef Xchr -#define Xchr(x) (x) +#define Xchr(x) (x) -#include "trans.h" /* functions for affine transform operations */ -#include <teckit/TECkit_Common.h> /* include this before XeTeX_ext.h */ -#include "XeTeX_ext.h" /* other extension functions */ +#include "trans.h" /* functions for affine transform operations */ +#include <teckit/TECkit_Common.h> /* include this before XeTeX_ext.h */ +#include "XeTeX_ext.h" /* other extension functions */ #include <math.h> /* apparently M_PI isn't defined by <math.h> under VC++ */ diff --git a/Build/source/texk/web2c/xetexdir/xetex.web b/Build/source/texk/web2c/xetexdir/xetex.web index 63dec34b229..9ad16b235a9 100644 --- a/Build/source/texk/web2c/xetexdir/xetex.web +++ b/Build/source/texk/web2c/xetexdir/xetex.web @@ -324,8 +324,8 @@ known as `\eTeX'. @d eTeX_version_string=='-2.6' {current \eTeX\ version} @# @d XeTeX_version=0 { \.{\\XeTeXversion} } -@d XeTeX_revision==".9999" { \.{\\XeTeXrevision} } -@d XeTeX_version_string=='-0.9999.3' {current \XeTeX\ version} +@d XeTeX_revision==".99991" { \.{\\XeTeXrevision} } +@d XeTeX_version_string=='-0.99991' {current \XeTeX\ version} @# @d XeTeX_banner=='This is XeTeX, Version 3.14159265',eTeX_version_string,XeTeX_version_string {printed when \XeTeX\ starts} @@ -1676,49 +1676,49 @@ label exit; var l: small_number; begin if (selector>pseudo) and (not doing_special) then {``printing'' to a new string, encode as UTF-16 rather than UTF-8} - begin if s>=@"10000 then begin - print_visible_char(@"D800 + (s - @"10000) div @"400); - print_visible_char(@"DC00 + (s - @"10000) mod @"400); - end else print_visible_char(s); - return; + begin if s>=@"10000 then + begin print_visible_char(@"D800 + (s - @"10000) div @"400); + print_visible_char(@"DC00 + (s - @"10000) mod @"400); + end else print_visible_char(s); + return; end; if @<Character |s| is the current new-line character@> then if selector<pseudo then begin print_ln; return; end; -if (s < 32) and (eight_bit_p = 0) and (not doing_special) then {control char: \.{\^\^X}} - begin - print_visible_char("^"); print_visible_char("^"); print_visible_char(s+64); -end else if s < 127 then - { printable ASCII } - print_visible_char(s) -else if (s = 127) then begin - { DEL } - if (eight_bit_p = 0) and (not doing_special) then begin - print_visible_char("^"); print_visible_char("^"); print_visible_char("?") - end else - print_visible_char(s) -end else if (s < @"A0) and (eight_bit_p = 0) and (not doing_special) then {C1 controls: \.{\^\^xx}} - begin - print_visible_char("^"); print_visible_char("^"); - print_lc_hex((s mod @"100) div @"10); print_lc_hex(s mod @"10); -end else begin - { |char >= 128|: encode as UTF8 } - if s<@"800 then begin - print_raw_char(@"C0 + s div @"40, false); - print_raw_char(@"80 + s mod @"40, true); - end - else if s<@"10000 then begin - print_raw_char(@"E0 + (s div @"1000), false); - print_raw_char(@"80 + (s mod @"1000) div @"40, false); - print_raw_char(@"80 + (s mod @"40), true); - end else begin - print_raw_char(@"F0 + (s div @"40000), false); - print_raw_char(@"80 + (s mod @"40000) div @"1000, false); - print_raw_char(@"80 + (s mod @"1000) div @"40, false); - print_raw_char(@"80 + (s mod @"40), true); - end -end; + if (s < 32) and (eight_bit_p = 0) and (not doing_special) then {control char: \.{\^\^X}} + begin print_visible_char("^"); print_visible_char("^"); print_visible_char(s+64); + end + else if s<127 then { printable ASCII } + print_visible_char(s) + else if s=127 then { DEL } + begin if (eight_bit_p = 0) and (not doing_special) then + begin print_visible_char("^"); print_visible_char("^"); print_visible_char("?") + end else + print_visible_char(s) + end + else if (s < @"A0) and (eight_bit_p = 0) and (not doing_special) then {C1 controls: \.{\^\^xx}} + begin print_visible_char("^"); print_visible_char("^"); + print_lc_hex((s mod @"100) div @"10); print_lc_hex(s mod @"10); + end + else begin + { |char >= 128|: encode as UTF8 } + if s<@"800 then begin + print_raw_char(@"C0 + s div @"40, false); + print_raw_char(@"80 + s mod @"40, true); + end + else if s<@"10000 then begin + print_raw_char(@"E0 + (s div @"1000), false); + print_raw_char(@"80 + (s mod @"1000) div @"40, false); + print_raw_char(@"80 + (s mod @"40), true); + end + else begin + print_raw_char(@"F0 + (s div @"40000), false); + print_raw_char(@"80 + (s mod @"40000) div @"1000, false); + print_raw_char(@"80 + (s mod @"1000) div @"40, false); + print_raw_char(@"80 + (s mod @"40), true); + end + end; exit:end; @ @d native_room(#)==while native_text_size <= native_len+# do begin @@ -1759,7 +1759,7 @@ else if s<biggest_char then else begin if selector>pseudo then begin print_char(s); return; {internal strings are not expanded} end; - if (@<Character |s| is the current new-line character@>) then + if @<Character |s| is the current new-line character@> then if selector<pseudo then begin print_ln; return; end; @@ -2904,7 +2904,7 @@ of its other fields and its other words. when |max_halfword| appears in the |link| field of a nonempty node.) @d empty_flag == max_halfword {the |link| of an empty variable-size node} -@d is_empty(#) == (link(#)=empty_flag) {tests for empty node} +@d is_empty(#) == link(#)=empty_flag {tests for empty node} @d node_size == info {the size field in empty variable-size nodes} @d llink(#) == info(#+1) {left link in doubly-linked list of empty nodes} @d rlink(#) == link(#+1) {right link in doubly-linked list of empty nodes} @@ -3171,7 +3171,7 @@ an hlist; the |height| and |depth| are never running in a~vlist. @d rule_node=2 {|type| of rule nodes} @d rule_node_size=4 {number of words to allocate for a rule node} @d null_flag==-@'10000000000 {$-2^{30}$, signifies a missing item} -@d is_running(#) == (#=null_flag) {tests for a running dimension} +@d is_running(#) == #=null_flag {tests for a running dimension} @ A new rule node is delivered by the |new_rule| function. It makes all the dimensions ``running,'' so you have to change the @@ -3973,13 +3973,13 @@ whatsit_node: case subtype(p) of native_word_node: begin if native_font(p)<>font_in_short_display then begin - print_esc(font_id_text(native_font(p))); - print_char(" "); - font_in_short_display:=native_font(p); - end; - print_native_word(p); - end; - othercases print("[]") + print_esc(font_id_text(native_font(p))); + print_char(" "); + font_in_short_display:=native_font(p); + end; + print_native_word(p); + end; + othercases print("[]") endcases; rule_node: print_char("|"); glue_node: if glue_ptr(p)<>zero_glue then print_char(" "); @@ -6064,7 +6064,7 @@ A global boolean variable called |no_new_control_sequence| is set to @d next(#) == hash[#].lh {link for coalesced lists} @d text(#) == hash[#].rh {string number for control sequence name} -@d hash_is_full == (hash_used=hash_base) {test if all positions are occupied} +@d hash_is_full == hash_used=hash_base {test if all positions are occupied} @d font_id_text(#) == text(font_id_base+#) {a frozen font identifier's name} @<Glob...@>= @@ -6081,7 +6081,7 @@ A global boolean variable called |no_new_control_sequence| is set to @d prim_base=1 @d prim_next(#) == prim[#].lh {link for coalesced lists} @d prim_text(#) == prim[#].rh {string number for control sequence name} -@d prim_is_full == (prim_used=prim_base) {test if all positions are occupied} +@d prim_is_full == prim_used=prim_base {test if all positions are occupied} @d prim_eq_level_field(#)==#.hh.b1 @d prim_eq_type_field(#)==#.hh.b0 @d prim_equiv_field(#)==#.hh.rh @@ -6710,7 +6710,7 @@ the call, since |eq_save| makes the necessary test. @p procedure eq_define(@!p:pointer;@!t:quarterword;@!e:halfword); {new data for |eqtb|} label exit; -begin if eTeX_ex and(eq_type(p)=t)and(equiv(p)=e) then +begin if (eTeX_ex)and(eq_type(p)=t)and(equiv(p)=e) then begin assign_trace(p,"reassigning")@;@/ eq_destroy(eqtb[p]); return; end; @@ -6727,7 +6727,7 @@ exit:end; @p procedure eq_word_define(@!p:pointer;@!w:integer); label exit; -begin if eTeX_ex and(eqtb[p].int=w) then +begin if (eTeX_ex)and(eqtb[p].int=w) then begin assign_trace(p,"reassigning")@;@/ return; end; @@ -7330,7 +7330,7 @@ put into a variable |@!page|, maintained for enclosing levels in by analogy with |line_stack|. @^system dependencies@> -@d terminal_input==(name=0) {are we reading from the terminal?} +@d terminal_input==name=0 {are we reading from the terminal?} @d cur_file==input_file[index] {the current |alpha_file| variable} @<Glob...@>= @@ -7558,7 +7558,7 @@ begin base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input; {store current state} nn:=-1; bottom_line:=false; loop@+begin cur_input:=input_stack[base_ptr]; {enter into the context} - if (state<>token_list) then + if state<>token_list then if (name>19) or (base_ptr=0) then bottom_line:=true; if (base_ptr=input_ptr)or bottom_line or(nn<error_context_lines) then @<Display the current context@> @@ -7882,7 +7882,7 @@ inserted `\.{\\show}' commands, the following routine removes completed error-inserted lines from memory. @p procedure clear_for_error_prompt; -begin while (state<>token_list)and terminal_input and@| +begin while (state<>token_list)and(terminal_input)and@| (input_ptr>0)and(loc>limit) do end_file_reading; print_ln; clear_terminal; end; @@ -8381,7 +8381,7 @@ There is one more branch. @<Move to next line of file, or |goto restart|...@>= if name>17 then @<Read next line of file into |buffer|, or |goto restart| if the file has ended@> -else begin if not terminal_input then {\.{\\read} line has ended} +else begin if not (terminal_input) then {\.{\\read} line has ended} begin cur_cmd:=0; cur_chr:=0; return; end; if input_ptr>0 then {text was inserted during error recovery} @@ -12062,14 +12062,14 @@ the font. @d otgr_font_flag=@"FFFE @d aat_font_flag=@"FFFF -@d is_aat_font(#)==(font_area[#]=aat_font_flag) -@d is_ot_font(#)==((font_area[#]=otgr_font_flag) and (usingOpenType(font_layout_engine[#]))) -@d is_gr_font(#)==((font_area[#]=otgr_font_flag) and (usingGraphite(font_layout_engine[#]))) -@d is_otgr_font(#)==(font_area[#]=otgr_font_flag) -@d is_native_font(#)==(is_aat_font(#) or is_otgr_font(#)) - {native fonts have |font_area| = 65534 or 65535, - which would be a string containing an invalid Unicode character} -@d is_new_mathfont(#)==((font_area[#]=otgr_font_flag) and (isOpenTypeMathFont(font_layout_engine[#]))) +@d is_aat_font(#)==font_area[#]=aat_font_flag +@d is_otgr_font(#)==font_area[#]=otgr_font_flag +@d is_ot_font(#)==usingOpenType(#) +@d is_gr_font(#)==usingGraphite(#) +@d is_native_font(#)==(is_aat_font(#)) or (is_otgr_font(#)) + {native fonts have |font_area| = 65534 or 65535, + which would be a string containing an invalid Unicode character} +@d is_new_mathfont(#)==isOpenTypeMathFont(#) @d non_char==qi(too_big_char) {a |halfword| code that can't match a real character} @d non_address=0 {a spurious |bchar_label|} @@ -12712,7 +12712,7 @@ procedure char_warning(@!f:internal_font_number;@!c:integer); var old_setting: integer; {saved value of |tracing_online|} begin if tracing_lost_chars>0 then begin old_setting:=tracing_online; - if eTeX_ex and(tracing_lost_chars>1) then tracing_online:=1; + if (eTeX_ex) and(tracing_lost_chars>1) then tracing_online:=1; begin begin_diagnostic; print_nl("Missing character: There is no "); @.Missing character@> @@ -13059,11 +13059,11 @@ file. Parameters |i|, |num|, |den|, |mag|, |k|, and |x| are explained below. \yskip\hang|post_post| 249. Ending of the postamble, see below. \yskip\hang|pic_file| 251 |flags[1]| |t[4][6]| |p[2]| |len[2]| |path[l]|. - |flags=0| for raster image, and |1| for \.{PDF}. - |t| is transform matrix. - |p| is page number from the graphic file (0-based). - |len| is length of pathname. - |path| is pathname of graphic file. + |flags=0| for raster image, and |1| for \.{PDF}. + |t| is transform matrix. + |p| is page number from the graphic file (0-based). + |len| is length of pathname. + |path| is pathname of graphic file. \yskip\hang\vbox{\halign{#&#\hfil\cr |define_native_font| 252 & |k[4]| |s[4]| |flags[2]| |lenps[1]| |lenfam[1]| |lensty[1]| |ps[lenps]| |fam[lenfam]| |sty[lensty]|\cr @@ -13116,11 +13116,11 @@ produced by \XeTeX. p\TeX\ uses 255. @ The preamble contains basic information about the file as a whole. As stated above, there are six parameters: $$\hbox{|@!i[1]| |@!num[4]| |@!den[4]| |@!mag[4]| |@!k[1]| |@!x[k]|.}$$ -The |i| byte identifies \.{DVI} format; currently this byte is always set -to~2. (The value |i=3| is currently used for an extended format that -allows a mixture of right-to-left and left-to-right typesetting. -Some day we will set |i=4|, when \.{DVI} format makes another -incompatible change---perhaps in the year 2048.) +The |i| byte identifies \.{DVI} format; in \XeTeX\ this byte is set to~5, as we +have new \.{DVI} opcodes, while in \TeX82 it is always set to~2. (The value +|i=3| is used for an extended format that allows a mixture of right-to-left and +left-to-right typesetting. Prre-1.0 \XeTeX\ releases using Mac~OS~X-specific +data types used |i=4|.) The next two parameters, |num| and |den|, are positive integers that define the units of measurement; they are the numerator and denominator of a @@ -13143,11 +13143,6 @@ users to override the |mag|~setting when a \.{DVI} file is being printed.) Finally, |k| and |x| allow the \.{DVI} writer to include a comment, which is not interpreted further. The length of comment |x| is |k|, where |0<=k<256|. -XeTeX changes the DVI version to 5, -as we have new DVI opcodes like |set_glyph_array| for native font text; -I used version 3 in an earlier extension of TeX, -and 4 in pre-1.0 XeTeX releases using Mac OS-specific data types. - @d id_byte=5 {identifies the kind of \.{DVI} files described here} @ Font definitions for a given font number |k| contain further parameters @@ -13418,8 +13413,8 @@ end; procedure dvi_two(s: UTF16_code); begin - dvi_out(s div @'400); - dvi_out(s mod @'400); + dvi_out(s div @'400); + dvi_out(s mod @'400); end; @ A mild optimization of the output is performed by the |dvi_pop| @@ -13437,12 +13432,12 @@ most 256 different fonts per job, |fnt_def1| is always used as the command code. @p procedure dvi_native_font_def(@!f:internal_font_number); var - font_def_length, i: integer; + font_def_length, i: integer; begin - dvi_out(define_native_font); - dvi_four(f-font_base-1); - font_def_length := make_font_def(f); - for i := 0 to font_def_length - 1 do dvi_out(xdv_buffer[i]); + dvi_out(define_native_font); + dvi_four(f-font_base-1); + font_def_length := make_font_def(f); + for i := 0 to font_def_length - 1 do dvi_out(xdv_buffer[i]); end; procedure dvi_font_def(@!f:internal_font_number); @@ -15588,65 +15583,65 @@ macro capabilities. This seems a bit ugly, but it works. @d total_mathsy_params=22 {the following are OpenType MATH constant indices for use with OT math fonts} -@d scriptPercentScaleDown = 0 -@d scriptScriptPercentScaleDown = 1 -@d delimitedSubFormulaMinHeight = 2 -@d displayOperatorMinHeight = 3 -@d mathLeading = 4 -@d firstMathValueRecord = mathLeading -@d axisHeight = 5 -@d accentBaseHeight = 6 -@d flattenedAccentBaseHeight = 7 -@d subscriptShiftDown = 8 -@d subscriptTopMax = 9 -@d subscriptBaselineDropMin = 10 -@d superscriptShiftUp = 11 -@d superscriptShiftUpCramped = 12 -@d superscriptBottomMin = 13 -@d superscriptBaselineDropMax = 14 -@d subSuperscriptGapMin = 15 -@d superscriptBottomMaxWithSubscript = 16 -@d spaceAfterScript = 17 -@d upperLimitGapMin = 18 -@d upperLimitBaselineRiseMin = 19 -@d lowerLimitGapMin = 20 -@d lowerLimitBaselineDropMin = 21 -@d stackTopShiftUp = 22 -@d stackTopDisplayStyleShiftUp = 23 -@d stackBottomShiftDown = 24 -@d stackBottomDisplayStyleShiftDown = 25 -@d stackGapMin = 26 -@d stackDisplayStyleGapMin = 27 -@d stretchStackTopShiftUp = 28 -@d stretchStackBottomShiftDown = 29 -@d stretchStackGapAboveMin = 30 -@d stretchStackGapBelowMin = 31 -@d fractionNumeratorShiftUp = 32 -@d fractionNumeratorDisplayStyleShiftUp = 33 -@d fractionDenominatorShiftDown = 34 -@d fractionDenominatorDisplayStyleShiftDown = 35 -@d fractionNumeratorGapMin = 36 -@d fractionNumDisplayStyleGapMin = 37 -@d fractionRuleThickness = 38 -@d fractionDenominatorGapMin = 39 -@d fractionDenomDisplayStyleGapMin = 40 -@d skewedFractionHorizontalGap = 41 -@d skewedFractionVerticalGap = 42 -@d overbarVerticalGap = 43 -@d overbarRuleThickness = 44 -@d overbarExtraAscender = 45 -@d underbarVerticalGap = 46 -@d underbarRuleThickness = 47 -@d underbarExtraDescender = 48 -@d radicalVerticalGap = 49 -@d radicalDisplayStyleVerticalGap = 50 -@d radicalRuleThickness = 51 -@d radicalExtraAscender = 52 -@d radicalKernBeforeDegree = 53 -@d radicalKernAfterDegree = 54 -@d lastMathValueRecord = radicalKernAfterDegree -@d radicalDegreeBottomRaisePercent = 55 -@d lastMathConstant = radicalDegreeBottomRaisePercent +@d scriptPercentScaleDown = 0 +@d scriptScriptPercentScaleDown = 1 +@d delimitedSubFormulaMinHeight = 2 +@d displayOperatorMinHeight = 3 +@d mathLeading = 4 +@d firstMathValueRecord = mathLeading +@d axisHeight = 5 +@d accentBaseHeight = 6 +@d flattenedAccentBaseHeight = 7 +@d subscriptShiftDown = 8 +@d subscriptTopMax = 9 +@d subscriptBaselineDropMin = 10 +@d superscriptShiftUp = 11 +@d superscriptShiftUpCramped = 12 +@d superscriptBottomMin = 13 +@d superscriptBaselineDropMax = 14 +@d subSuperscriptGapMin = 15 +@d superscriptBottomMaxWithSubscript = 16 +@d spaceAfterScript = 17 +@d upperLimitGapMin = 18 +@d upperLimitBaselineRiseMin = 19 +@d lowerLimitGapMin = 20 +@d lowerLimitBaselineDropMin = 21 +@d stackTopShiftUp = 22 +@d stackTopDisplayStyleShiftUp = 23 +@d stackBottomShiftDown = 24 +@d stackBottomDisplayStyleShiftDown = 25 +@d stackGapMin = 26 +@d stackDisplayStyleGapMin = 27 +@d stretchStackTopShiftUp = 28 +@d stretchStackBottomShiftDown = 29 +@d stretchStackGapAboveMin = 30 +@d stretchStackGapBelowMin = 31 +@d fractionNumeratorShiftUp = 32 +@d fractionNumeratorDisplayStyleShiftUp = 33 +@d fractionDenominatorShiftDown = 34 +@d fractionDenominatorDisplayStyleShiftDown = 35 +@d fractionNumeratorGapMin = 36 +@d fractionNumDisplayStyleGapMin = 37 +@d fractionRuleThickness = 38 +@d fractionDenominatorGapMin = 39 +@d fractionDenomDisplayStyleGapMin = 40 +@d skewedFractionHorizontalGap = 41 +@d skewedFractionVerticalGap = 42 +@d overbarVerticalGap = 43 +@d overbarRuleThickness = 44 +@d overbarExtraAscender = 45 +@d underbarVerticalGap = 46 +@d underbarRuleThickness = 47 +@d underbarExtraDescender = 48 +@d radicalVerticalGap = 49 +@d radicalDisplayStyleVerticalGap = 50 +@d radicalRuleThickness = 51 +@d radicalExtraAscender = 52 +@d radicalKernBeforeDegree = 53 +@d radicalKernAfterDegree = 54 +@d lastMathValueRecord = radicalKernAfterDegree +@d radicalDegreeBottomRaisePercent = 55 +@d lastMathConstant = radicalDegreeBottomRaisePercent @d mathsy(#)==font_info[#+param_base[f]].sc @@ -15725,348 +15720,348 @@ call |set_native_metrics(node)| if that is required. @<Declare subroutines for |new_character|@>= function new_native_word_node(@!f:internal_font_number;@!n:integer):pointer; var - l: integer; - q: pointer; + l: integer; + q: pointer; begin - l := native_node_size + (n * sizeof(UTF16_code) + sizeof(memory_word) - 1) div sizeof(memory_word); + l := native_node_size + (n * sizeof(UTF16_code) + sizeof(memory_word) - 1) div sizeof(memory_word); - q := get_node(l); - type(q) := whatsit_node; - subtype(q) := native_word_node; + q := get_node(l); + type(q) := whatsit_node; + subtype(q) := native_word_node; - native_size(q) := l; - native_font(q) := f; - native_length(q) := n; + native_size(q) := l; + native_font(q) := f; + native_length(q) := n; - native_glyph_count(q) := 0; - native_glyph_info_ptr(q) := null_ptr; + native_glyph_count(q) := 0; + native_glyph_info_ptr(q) := null_ptr; - new_native_word_node := q; + new_native_word_node := q; end; function new_native_character(@!f:internal_font_number;@!c:UnicodeScalar):pointer; var - p: pointer; - i, len: integer; + p: pointer; + i, len: integer; begin - if font_mapping[f] <> 0 then begin - if c > @"FFFF then begin - str_room(2); - append_char((c - @"10000) div 1024 + @"D800); - append_char((c - @"10000) mod 1024 + @"DC00); - end - else begin - str_room(1); - append_char(c); - end; - len := apply_mapping(font_mapping[f], addressof(str_pool[str_start_macro(str_ptr)]), cur_length); - pool_ptr := str_start_macro(str_ptr); { flush the string, as we'll be using the mapped text instead } - - i := 0; - while i < len do begin - if (mapped_text[i] >= @"D800) and (mapped_text[i] < @"DC00) then begin - c := (mapped_text[i] - @"D800) * 1024 + mapped_text[i+1] - @"DC00 + @"10000; - if map_char_to_glyph(f, c) = 0 then begin - char_warning(f, c); - end; - i := i + 2; - end - else begin - if map_char_to_glyph(f, mapped_text[i]) = 0 then begin - char_warning(f, mapped_text[i]); - end; - i := i + 1; - end; - end; - - p := new_native_word_node(f, len); - for i := 0 to len-1 do begin - set_native_char(p, i, mapped_text[i]); - end - end - else begin - if tracing_lost_chars > 0 then - if map_char_to_glyph(f, c) = 0 then begin - char_warning(f, c); - end; - - p := get_node(native_node_size + 1); - type(p) := whatsit_node; - subtype(p) := native_word_node; - - native_size(p) := native_node_size + 1; - native_glyph_count(p) := 0; - native_glyph_info_ptr(p) := null_ptr; - native_font(p) := f; - - if c > @"FFFF then begin - native_length(p) := 2; - set_native_char(p, 0, (c - @"10000) div 1024 + @"D800); - set_native_char(p, 1, (c - @"10000) mod 1024 + @"DC00); - end - else begin - native_length(p) := 1; - set_native_char(p, 0, c); - end; - end; - - set_native_metrics(p, XeTeX_use_glyph_metrics); - - new_native_character := p; + if font_mapping[f] <> 0 then begin + if c > @"FFFF then begin + str_room(2); + append_char((c - @"10000) div 1024 + @"D800); + append_char((c - @"10000) mod 1024 + @"DC00); + end + else begin + str_room(1); + append_char(c); + end; + len := apply_mapping(font_mapping[f], addressof(str_pool[str_start_macro(str_ptr)]), cur_length); + pool_ptr := str_start_macro(str_ptr); { flush the string, as we'll be using the mapped text instead } + + i := 0; + while i < len do begin + if (mapped_text[i] >= @"D800) and (mapped_text[i] < @"DC00) then begin + c := (mapped_text[i] - @"D800) * 1024 + mapped_text[i+1] - @"DC00 + @"10000; + if map_char_to_glyph(f, c) = 0 then begin + char_warning(f, c); + end; + i := i + 2; + end + else begin + if map_char_to_glyph(f, mapped_text[i]) = 0 then begin + char_warning(f, mapped_text[i]); + end; + i := i + 1; + end; + end; + + p := new_native_word_node(f, len); + for i := 0 to len-1 do begin + set_native_char(p, i, mapped_text[i]); + end + end + else begin + if tracing_lost_chars > 0 then + if map_char_to_glyph(f, c) = 0 then begin + char_warning(f, c); + end; + + p := get_node(native_node_size + 1); + type(p) := whatsit_node; + subtype(p) := native_word_node; + + native_size(p) := native_node_size + 1; + native_glyph_count(p) := 0; + native_glyph_info_ptr(p) := null_ptr; + native_font(p) := f; + + if c > @"FFFF then begin + native_length(p) := 2; + set_native_char(p, 0, (c - @"10000) div 1024 + @"D800); + set_native_char(p, 1, (c - @"10000) mod 1024 + @"DC00); + end + else begin + native_length(p) := 1; + set_native_char(p, 0, c); + end; + end; + + set_native_metrics(p, XeTeX_use_glyph_metrics); + + new_native_character := p; end; procedure font_feature_warning(featureNameP:void_pointer; featLen:integer; - settingNameP:void_pointer; setLen:integer); + settingNameP:void_pointer; setLen:integer); var - i: integer; + i: integer; begin - begin_diagnostic; - print_nl("Unknown "); - if setLen > 0 then begin - print("selector `"); - print_utf8_str(settingNameP, setLen); - print("' for "); - end; - print("feature `"); - print_utf8_str(featureNameP, featLen); - print("' in font `"); - i := 1; - while ord(name_of_file[i]) <> 0 do begin - print_visible_char(name_of_file[i]); { this is already UTF-8 } - incr(i); - end; - print("'."); - end_diagnostic(false); + begin_diagnostic; + print_nl("Unknown "); + if setLen > 0 then begin + print("selector `"); + print_utf8_str(settingNameP, setLen); + print("' for "); + end; + print("feature `"); + print_utf8_str(featureNameP, featLen); + print("' in font `"); + i := 1; + while ord(name_of_file[i]) <> 0 do begin + print_visible_char(name_of_file[i]); { this is already UTF-8 } + incr(i); + end; + print("'."); + end_diagnostic(false); end; procedure font_mapping_warning(mappingNameP:void_pointer; - mappingNameLen:integer; - warningType:integer); { 0: just logging; 1: file not found; 2: can't load } + mappingNameLen:integer; + warningType:integer); { 0: just logging; 1: file not found; 2: can't load } var - i: integer; + i: integer; begin - begin_diagnostic; - if warningType=0 then print_nl("Loaded mapping `") - else print_nl("Font mapping `"); - print_utf8_str(mappingNameP, mappingNameLen); - print("' for font `"); - i := 1; - while ord(name_of_file[i]) <> 0 do begin - print_visible_char(name_of_file[i]); { this is already UTF-8 } - incr(i); - end; - case warningType of - 1: print("' not found."); - 2: begin print("' not usable;"); - print_nl("bad mapping file or incorrect mapping type."); - end; - othercases print("'.") - endcases; - end_diagnostic(false); + begin_diagnostic; + if warningType=0 then print_nl("Loaded mapping `") + else print_nl("Font mapping `"); + print_utf8_str(mappingNameP, mappingNameLen); + print("' for font `"); + i := 1; + while ord(name_of_file[i]) <> 0 do begin + print_visible_char(name_of_file[i]); { this is already UTF-8 } + incr(i); + end; + case warningType of + 1: print("' not found."); + 2: begin print("' not usable;"); + print_nl("bad mapping file or incorrect mapping type."); + end; + othercases print("'.") + endcases; + end_diagnostic(false); end; procedure graphite_warning; var - i: integer; + i: integer; begin - begin_diagnostic; - print_nl("Font `"); - i := 1; - while ord(name_of_file[i]) <> 0 do begin - print_visible_char(name_of_file[i]); { this is already UTF-8 } - incr(i); - end; - print("' does not support Graphite. Trying OpenType layout instead."); - end_diagnostic(false); + begin_diagnostic; + print_nl("Font `"); + i := 1; + while ord(name_of_file[i]) <> 0 do begin + print_visible_char(name_of_file[i]); { this is already UTF-8 } + incr(i); + end; + print("' does not support Graphite. Trying OpenType layout instead."); + end_diagnostic(false); end; function load_native_font(u: pointer; nom, aire:str_number; s: scaled): internal_font_number; label - done; + done; const - first_math_fontdimen = 10; + first_math_fontdimen = 10; var - k, num_font_dimens: integer; - font_engine: void_pointer; {really an CFDictionaryRef or XeTeXLayoutEngine} - actual_size: scaled; {|s| converted to real size, if it was negative} - p: pointer; {for temporary |native_char| node we'll create} - ascent, descent, font_slant, x_ht, cap_ht: scaled; - f: internal_font_number; - full_name: str_number; + k, num_font_dimens: integer; + font_engine: void_pointer; {really an CFDictionaryRef or XeTeXLayoutEngine} + actual_size: scaled; {|s| converted to real size, if it was negative} + p: pointer; {for temporary |native_char| node we'll create} + ascent, descent, font_slant, x_ht, cap_ht: scaled; + f: internal_font_number; + full_name: str_number; begin - { on entry here, the full name is packed into |name_of_file| in UTF8 form } - - load_native_font := null_font; - - font_engine := find_native_font(name_of_file + 1, s); - if font_engine = 0 then goto done; - - if s>=0 then - actual_size := s - else begin - if (s <> -1000) then - actual_size := xn_over_d(loaded_font_design_size,-s,1000) - else - actual_size := loaded_font_design_size; - end; - - { look again to see if the font is already loaded, now that we know its canonical name } - str_room(name_length); - for k := 1 to name_length do - append_char(name_of_file[k]); + { on entry here, the full name is packed into |name_of_file| in UTF8 form } + + load_native_font := null_font; + + font_engine := find_native_font(name_of_file + 1, s); + if font_engine = 0 then goto done; + + if s>=0 then + actual_size := s + else begin + if (s <> -1000) then + actual_size := xn_over_d(loaded_font_design_size,-s,1000) + else + actual_size := loaded_font_design_size; + end; + + { look again to see if the font is already loaded, now that we know its canonical name } + str_room(name_length); + for k := 1 to name_length do + append_char(name_of_file[k]); full_name := make_string; { not |slow_make_string| because we'll flush it if the font was already loaded } - for f:=font_base+1 to font_ptr do - if (font_area[f] = native_font_type_flag) and str_eq_str(font_name[f], full_name) and (font_size[f] = actual_size) then begin - release_font_engine(font_engine, native_font_type_flag); - flush_string; - load_native_font := f; - goto done; + for f:=font_base+1 to font_ptr do + if (font_area[f] = native_font_type_flag) and str_eq_str(font_name[f], full_name) and (font_size[f] = actual_size) then begin + release_font_engine(font_engine, native_font_type_flag); + flush_string; + load_native_font := f; + goto done; end; - if (native_font_type_flag = otgr_font_flag) and isOpenTypeMathFont(font_engine) then - num_font_dimens := first_math_fontdimen + lastMathConstant - else - num_font_dimens := 8; - - if (font_ptr = font_max) or (fmem_ptr + num_font_dimens > font_mem_size) then begin - @<Apologize for not loading the font, |goto done|@>; - end; - - { we've found a valid installed font, and have room } - incr(font_ptr); - font_area[font_ptr] := native_font_type_flag; { set by |find_native_font| to either |aat_font_flag| or |ot_font_flag| } - - { store the canonical name } - font_name[font_ptr] := full_name; - - font_check[font_ptr].b0 := 0; - font_check[font_ptr].b1 := 0; - font_check[font_ptr].b2 := 0; - font_check[font_ptr].b3 := 0; - font_glue[font_ptr] := null; - font_dsize[font_ptr] := loaded_font_design_size; - font_size[font_ptr] := actual_size; - - if (native_font_type_flag = aat_font_flag) then begin - aat_get_font_metrics(font_engine, addressof(ascent), addressof(descent), - addressof(x_ht), addressof(cap_ht), addressof(font_slant)) - end else begin - ot_get_font_metrics(font_engine, addressof(ascent), addressof(descent), - addressof(x_ht), addressof(cap_ht), addressof(font_slant)); - end; - - height_base[font_ptr] := ascent; - depth_base[font_ptr] := -descent; - - font_params[font_ptr] := num_font_dimens; {we add an extra \.{\\fontdimen8} |:= cap_height|; then OT math fonts have a bunch more} - font_bc[font_ptr] := 0; - font_ec[font_ptr] := 65535; - font_used[font_ptr] := false; - hyphen_char[font_ptr] := default_hyphen_char; - skew_char[font_ptr] := default_skew_char; - param_base[font_ptr] := fmem_ptr-1; - - font_layout_engine[font_ptr] := font_engine; - font_mapping[font_ptr] := 0; {don't use the mapping, if any, when measuring space here} - font_letter_space[font_ptr] := loaded_font_letter_space; + if (font_ptr = font_max) or (fmem_ptr + num_font_dimens > font_mem_size) then begin + @<Apologize for not loading the font, |goto done|@>; + end; + + { we've found a valid installed font, and have room } + incr(font_ptr); + font_area[font_ptr] := native_font_type_flag; { set by |find_native_font| to either |aat_font_flag| or |ot_font_flag| } + + { store the canonical name } + font_name[font_ptr] := full_name; + + font_check[font_ptr].b0 := 0; + font_check[font_ptr].b1 := 0; + font_check[font_ptr].b2 := 0; + font_check[font_ptr].b3 := 0; + font_glue[font_ptr] := null; + font_dsize[font_ptr] := loaded_font_design_size; + font_size[font_ptr] := actual_size; + + if native_font_type_flag = aat_font_flag then begin + aat_get_font_metrics(font_engine, addressof(ascent), addressof(descent), + addressof(x_ht), addressof(cap_ht), addressof(font_slant)) + end else begin + ot_get_font_metrics(font_engine, addressof(ascent), addressof(descent), + addressof(x_ht), addressof(cap_ht), addressof(font_slant)); + end; + + height_base[font_ptr] := ascent; + depth_base[font_ptr] := -descent; + + font_layout_engine[font_ptr] := font_engine; + if isOpenTypeMathFont(font_ptr) then + num_font_dimens := first_math_fontdimen + lastMathConstant + else + num_font_dimens := 8; + + font_params[font_ptr] := num_font_dimens; {we add an extra \.{\\fontdimen8} |:= cap_height|; then OT math fonts have a bunch more} + font_bc[font_ptr] := 0; + font_ec[font_ptr] := 65535; + font_used[font_ptr] := false; + hyphen_char[font_ptr] := default_hyphen_char; + skew_char[font_ptr] := default_skew_char; + param_base[font_ptr] := fmem_ptr-1; + + font_mapping[font_ptr] := 0; {don't use the mapping, if any, when measuring space here} + font_letter_space[font_ptr] := loaded_font_letter_space; @# {measure the width of the space character and set up font parameters} - p := new_native_character(font_ptr, " "); - s := width(p) + loaded_font_letter_space; - free_node(p, native_size(p)); - - font_info[fmem_ptr].sc := font_slant; {|slant|} - incr(fmem_ptr); - font_info[fmem_ptr].sc := s; {|space| = width of space character} - incr(fmem_ptr); - font_info[fmem_ptr].sc := s div 2; {|space_stretch| = 1/2 * space} - incr(fmem_ptr); - font_info[fmem_ptr].sc := s div 3; {|space_shrink| = 1/3 * space} - incr(fmem_ptr); - font_info[fmem_ptr].sc := x_ht; {|x_height|} - incr(fmem_ptr); - font_info[fmem_ptr].sc := font_size[font_ptr]; {|quad| = font size} - incr(fmem_ptr); - font_info[fmem_ptr].sc := s div 3; {|extra_space| = 1/3 * space} - incr(fmem_ptr); - font_info[fmem_ptr].sc := cap_ht; {|cap_height|} - incr(fmem_ptr); - - if num_font_dimens = first_math_fontdimen + lastMathConstant then begin - font_info[fmem_ptr].int := num_font_dimens; { \.{\\fontdimen9} |:=| number of assigned fontdimens } - incr(fmem_ptr); - for k := 0 to lastMathConstant do begin - font_info[fmem_ptr].sc := get_ot_math_constant(font_ptr, k); - incr(fmem_ptr); - end; - end; - - font_mapping[font_ptr] := loaded_font_mapping; - font_flags[font_ptr] := loaded_font_flags; - - load_native_font := font_ptr; + p := new_native_character(font_ptr, " "); + s := width(p) + loaded_font_letter_space; + free_node(p, native_size(p)); + + font_info[fmem_ptr].sc := font_slant; {|slant|} + incr(fmem_ptr); + font_info[fmem_ptr].sc := s; {|space| = width of space character} + incr(fmem_ptr); + font_info[fmem_ptr].sc := s div 2; {|space_stretch| = 1/2 * space} + incr(fmem_ptr); + font_info[fmem_ptr].sc := s div 3; {|space_shrink| = 1/3 * space} + incr(fmem_ptr); + font_info[fmem_ptr].sc := x_ht; {|x_height|} + incr(fmem_ptr); + font_info[fmem_ptr].sc := font_size[font_ptr]; {|quad| = font size} + incr(fmem_ptr); + font_info[fmem_ptr].sc := s div 3; {|extra_space| = 1/3 * space} + incr(fmem_ptr); + font_info[fmem_ptr].sc := cap_ht; {|cap_height|} + incr(fmem_ptr); + + if num_font_dimens = first_math_fontdimen + lastMathConstant then begin + font_info[fmem_ptr].int := num_font_dimens; { \.{\\fontdimen9} |:=| number of assigned fontdimens } + incr(fmem_ptr); + for k := 0 to lastMathConstant do begin + font_info[fmem_ptr].sc := get_ot_math_constant(font_ptr, k); + incr(fmem_ptr); + end; + end; + + font_mapping[font_ptr] := loaded_font_mapping; + font_flags[font_ptr] := loaded_font_flags; + + load_native_font := font_ptr; done: end; procedure do_locale_linebreaks(s: integer; len: integer); var - offs, prevOffs, i: integer; - use_penalty, use_skip: boolean; + offs, prevOffs, i: integer; + use_penalty, use_skip: boolean; begin - if (XeTeX_linebreak_locale = 0) or (len = 1) then begin - link(tail) := new_native_word_node(main_f, len); - tail := link(tail); - for i := 0 to len - 1 do - set_native_char(tail, i, native_text[s + i]); - set_native_metrics(tail, XeTeX_use_glyph_metrics); - end else begin - use_skip := XeTeX_linebreak_skip <> zero_glue; - use_penalty := XeTeX_linebreak_penalty <> 0 or not use_skip; - linebreak_start(main_f, XeTeX_linebreak_locale, native_text + s, len); - offs := 0; - repeat - prevOffs := offs; - offs := linebreak_next; - if offs > 0 then begin - if prevOffs <> 0 then begin - if use_penalty then - tail_append(new_penalty(XeTeX_linebreak_penalty)); - if use_skip then - tail_append(new_param_glue(XeTeX_linebreak_skip_code)); - end; - link(tail) := new_native_word_node(main_f, offs - prevOffs); - tail := link(tail); - for i := prevOffs to offs - 1 do - set_native_char(tail, i - prevOffs, native_text[s + i]); - set_native_metrics(tail, XeTeX_use_glyph_metrics); - end; - until offs < 0; - end + if (XeTeX_linebreak_locale = 0) or (len = 1) then begin + link(tail) := new_native_word_node(main_f, len); + tail := link(tail); + for i := 0 to len - 1 do + set_native_char(tail, i, native_text[s + i]); + set_native_metrics(tail, XeTeX_use_glyph_metrics); + end else begin + use_skip := XeTeX_linebreak_skip <> zero_glue; + use_penalty := XeTeX_linebreak_penalty <> 0 or not use_skip; + linebreak_start(main_f, XeTeX_linebreak_locale, native_text + s, len); + offs := 0; + repeat + prevOffs := offs; + offs := linebreak_next; + if offs > 0 then begin + if prevOffs <> 0 then begin + if use_penalty then + tail_append(new_penalty(XeTeX_linebreak_penalty)); + if use_skip then + tail_append(new_param_glue(XeTeX_linebreak_skip_code)); + end; + link(tail) := new_native_word_node(main_f, offs - prevOffs); + tail := link(tail); + for i := prevOffs to offs - 1 do + set_native_char(tail, i - prevOffs, native_text[s + i]); + set_native_metrics(tail, XeTeX_use_glyph_metrics); + end; + until offs < 0; + end end; procedure bad_utf8_warning; begin - begin_diagnostic; - print_nl("Invalid UTF-8 byte or sequence"); - if terminal_input then print(" in terminal input") - else begin - print(" at line "); - print_int(line); - end; - print(" replaced by U+FFFD."); - end_diagnostic(false); + begin_diagnostic; + print_nl("Invalid UTF-8 byte or sequence"); + if terminal_input then print(" in terminal input") + else begin + print(" at line "); + print_int(line); + end; + print(" replaced by U+FFFD."); + end_diagnostic(false); end; function get_input_normalization_state: integer; begin - if eqtb=nil then get_input_normalization_state:=0 { may be called before eqtb is initialized } - else get_input_normalization_state:=XeTeX_input_normalization_state; + if eqtb=nil then get_input_normalization_state:=0 { may be called before eqtb is initialized } + else get_input_normalization_state:=XeTeX_input_normalization_state; end; function get_tracing_fonts_state: integer; begin - get_tracing_fonts_state:=XeTeX_tracing_fonts_state; + get_tracing_fonts_state:=XeTeX_tracing_fonts_state; end; @ We also need to compute the change in style between mlists and their @@ -16939,13 +16934,13 @@ var @!q,@!r:pointer; @!s,@!g:scaled; begin - if (math_type(nucleus(p))=math_char) then begin + if math_type(nucleus(p))=math_char then begin fetch(nucleus(p)); q:=new_native_character(cur_f, qo(cur_c)); g:=get_native_glyph(q, 0); s:=get_ot_math_accent_pos(cur_f, g); end else begin - if (math_type(nucleus(p))=sub_mlist) then begin + if math_type(nucleus(p))=sub_mlist then begin r:=info(nucleus(p)); if (r<>null) and (type(r)=accent_noad) then s:=compute_ot_math_accent_pos(r) @@ -17461,7 +17456,7 @@ if is_native_font(cur_f) then begin set_native_glyph_metrics(p, 1); free_node(z, native_size(z)); delta:=get_ot_math_ital_corr(cur_f, native_glyph(p)); - if (math_type(nucleus(q))=math_text_char)and(not is_new_mathfont(cur_f)<>0) then + if (math_type(nucleus(q))=math_text_char)and(not (is_new_mathfont(cur_f))<>0) then delta:=0; {no italic correction in mid-word of text font} if (math_type(subscr(q))=empty)and(delta<>0) then begin link(p):=new_kern(delta); delta:=0; @@ -17500,12 +17495,13 @@ end; procedure make_scripts(@!q:pointer;@!delta:scaled); var p,@!x,@!y,@!z:pointer; {temporary registers for box construction} @!shift_up,@!shift_down,@!clr,@!sub_kern,@!sup_kern:scaled; {dimensions in the calculation} -@!g:quarterword; {temporary register for native glyph id} +@!script_c:pointer; {temprary native character for sub/superscript} +@!script_g:quarterword; {temporary register for sub/superscript native glyph id} +@!script_f:internal_font_number; {temporary register for sub/superscript font} @!t:integer; {subsidiary size code} @!save_f:internal_font_number; -@!s:pointer; {temprary native character for sub/superscript} begin p:=new_hlist(q); -s:=null; sup_kern:=0; sub_kern:=0; g:=0; +script_c:=null; script_g:=0; script_f:=0; sup_kern:=0; sub_kern:=0; if is_char_node(p) or is_glyph_node(p) then begin shift_up:=0; shift_down:=0; end @@ -17615,33 +17611,43 @@ The following definitions should be kept in sync with \.{XeTeXOTMath.cpp}. @d sub_cmd=1 {subscript kern type for |get_ot_math_kern|} @<Attach subscript OpenType math kerning@>= -begin save_f:=cur_f;@/ -fetch(subscr(q)); -if is_new_mathfont(cur_f) then begin - s:=new_native_character(cur_f, qo(cur_c)); - g:=get_native_glyph(s, 0); +begin if math_type(subscr(q))=math_char then + begin save_f:=cur_f; + fetch(subscr(q)); + if is_new_mathfont(cur_f) then + begin script_c:=new_native_character(cur_f, qo(cur_c)); + script_g:=get_native_glyph(script_c, 0); + script_f:=cur_f; + end else + begin script_g:=0; script_f:=0 + end; + cur_f:=save_f; end; if is_glyph_node(p) then - sub_kern:=get_ot_math_kern(native_font(p), native_glyph(p), cur_f, g, sub_cmd, shift_down); + sub_kern:=get_ot_math_kern(native_font(p), native_glyph(p), script_f, script_g, sub_cmd, shift_down); if sub_kern<>0 then p:=attach_hkern_to_new_hlist(q, sub_kern); -cur_f:=save_f; end; @ @<Attach superscript OpenType math kerning@>= -begin save_f:=cur_f;@/ -fetch(supscr(q)); -if is_new_mathfont(cur_f) then begin - s:=new_native_character(cur_f, qo(cur_c)); - g:=get_native_glyph(s, 0); +begin if math_type(supscr(q))=math_char then + begin save_f:=cur_f; + fetch(supscr(q)); + if is_new_mathfont(cur_f) then + begin script_c:=new_native_character(cur_f, qo(cur_c)); + script_g:=get_native_glyph(script_c, 0); + script_f:=cur_f; + end else + begin script_g:=0; script_f:=0 + end; + cur_f:=save_f; end; if is_glyph_node(p) then - sup_kern:=get_ot_math_kern(native_font(p), native_glyph(p), cur_f, g, sup_cmd, shift_up); + sup_kern:=get_ot_math_kern(native_font(p), native_glyph(p), script_f, script_g, sup_cmd, shift_up); if (sup_kern<>0) and (math_type(subscr(q))=empty) then {if there is a superscript the kern will be added to |shift_amount(x)|} p:=attach_hkern_to_new_hlist(q, sup_kern); -cur_f:=save_f; end; @ We have now tied up all the loose ends of the first pass of |mlist_to_hlist|. @@ -19439,7 +19445,7 @@ else case type(v) of or (subtype(v)=pic_node) or (subtype(v)=pdf_node) then break_width[1]:=break_width[1]-width(v) - else confusion("disc1a"); + else confusion("disc1a"); othercases confusion("disc1") @:this can't happen disc1}{\quad disc1@> endcases @@ -19463,7 +19469,7 @@ else case type(s) of or (subtype(s)=pic_node) or (subtype(s)=pdf_node) then break_width[1]:=break_width[1]+width(s) - else confusion("disc2a"); + else confusion("disc2a"); othercases confusion("disc2") @:this can't happen disc2}{\quad disc2@> endcases @@ -20049,7 +20055,7 @@ else case type(s) of or (subtype(s)=pic_node) or (subtype(s)=pdf_node) then disc_width:=disc_width+width(s) - else confusion("disc3a"); + else confusion("disc3a"); othercases confusion("disc3") @:this can't happen disc3}{\quad disc3@> endcases @@ -20073,7 +20079,7 @@ else case type(s) of or (subtype(s)=pic_node) or (subtype(s)=pdf_node) then act_width:=act_width+width(s) - else confusion("disc4a"); + else confusion("disc4a"); othercases confusion("disc4") @:this can't happen disc4}{\quad disc4@> endcases @@ -20298,7 +20304,7 @@ if XeTeX_protrude_chars > 0 then begin k := new_margin_kern(-w, last_rightmost_char, right_side); link(k) := link(ptmp); link(ptmp) := k; - if (ptmp = q) then + if ptmp = q then q := link(q); end; end; @@ -20585,8 +20591,8 @@ restart: for l := 0 to native_length(ha)-1 do begin c := get_native_usv(ha, l); set_lc_code(c); - if (hc[0] = 0) then begin - if (hn > 0) then begin + if hc[0]=0 then begin + if hn>0 then begin { we've got some letters, and now found a non-letter, so break off the tail of the |native_word| and link it after this node, and goto done3 } @<Split the |native_word_node| at |l| and link the second part after |ha|@>; @@ -20597,7 +20603,7 @@ for l := 0 to native_length(ha)-1 do begin @<Split the |native_word_node| at |l| and link the second part after |ha|@>; ha := link(ha); goto restart; - end else if (hn = 63) then + end else if hn = 63 then { reached max hyphenatable length } goto done3 else begin @@ -20826,21 +20832,21 @@ for j := l_hyf to hn - r_hyf do begin { if this is a valid break.... } if odd(hyf[j]) then begin - { make a |native_word_node| for the fragment before the hyphen } - q := new_native_word_node(hf, j - hyphen_passed); - for i := 0 to j - hyphen_passed - 1 do - set_native_char(q, i, get_native_char(ha, i + hyphen_passed)); - set_native_metrics(q, XeTeX_use_glyph_metrics); - link(s) := q; { append the new node } - s := q; + { make a |native_word_node| for the fragment before the hyphen } + q := new_native_word_node(hf, j - hyphen_passed); + for i := 0 to j - hyphen_passed - 1 do + set_native_char(q, i, get_native_char(ha, i + hyphen_passed)); + set_native_metrics(q, XeTeX_use_glyph_metrics); + link(s) := q; { append the new node } + s := q; - { make the |disc_node| for the hyphenation point } + { make the |disc_node| for the hyphenation point } q := new_disc; - pre_break(q) := new_native_character(hf, hyf_char); - link(s) := q; - s := q; + pre_break(q) := new_native_character(hf, hyf_char); + link(s) := q; + s := q; - hyphen_passed := j; + hyphen_passed := j; end end; @@ -23339,49 +23345,49 @@ are inside the individual sections. @d check_for_inter_char_toks(#)=={check for a spacing token list, goto |#| if found, or |big_switch| in case of the initial letter of a run} - cur_ptr:=null; - space_class:=sf_code(cur_chr) div @"10000; - - if XeTeX_inter_char_tokens_en and space_class <> 256 then begin {class 256 = ignored (for combining marks etc)} - if prev_class = 255 then begin {boundary} - if (state<>token_list) or (token_type<>backed_up_char) then begin - find_sa_element(inter_char_val, 255*@"100 + space_class, false); - if cur_ptr<>null then begin - if cur_cmd<>letter then cur_cmd:=other_char; - cur_tok:=(cur_cmd*max_char_val)+cur_chr; - back_input; token_type:=backed_up_char; - begin_token_list(sa_ptr(cur_ptr), inter_char_text); - goto big_switch; - end - end - end else begin - find_sa_element(inter_char_val, prev_class*@"100 + space_class, false); - if cur_ptr<>null then begin - if cur_cmd<>letter then cur_cmd:=other_char; - cur_tok:=(cur_cmd*max_char_val)+cur_chr; - back_input; token_type:=backed_up_char; - begin_token_list(sa_ptr(cur_ptr), inter_char_text); - prev_class:=255; - goto #; - end; - end; - prev_class:=space_class; - end + cur_ptr:=null; + space_class:=sf_code(cur_chr) div @"10000; + + if XeTeX_inter_char_tokens_en and space_class <> 256 then begin {class 256 = ignored (for combining marks etc)} + if prev_class = 255 then begin {boundary} + if (state<>token_list) or (token_type<>backed_up_char) then begin + find_sa_element(inter_char_val, 255*@"100 + space_class, false); + if cur_ptr<>null then begin + if cur_cmd<>letter then cur_cmd:=other_char; + cur_tok:=(cur_cmd*max_char_val)+cur_chr; + back_input; token_type:=backed_up_char; + begin_token_list(sa_ptr(cur_ptr), inter_char_text); + goto big_switch; + end + end + end else begin + find_sa_element(inter_char_val, prev_class*@"100 + space_class, false); + if cur_ptr<>null then begin + if cur_cmd<>letter then cur_cmd:=other_char; + cur_tok:=(cur_cmd*max_char_val)+cur_chr; + back_input; token_type:=backed_up_char; + begin_token_list(sa_ptr(cur_ptr), inter_char_text); + prev_class:=255; + goto #; + end; + end; + prev_class:=space_class; + end @d check_for_post_char_toks(#)== - if XeTeX_inter_char_tokens_en and (space_class<>256) and (prev_class<>255) then begin - prev_class:=255; - find_sa_element(inter_char_val, space_class*@"100 + 255, false); {boundary} - if cur_ptr<>null then begin - if cur_cs=0 then begin - if cur_cmd=char_num then cur_cmd:=other_char; - cur_tok:=(cur_cmd*max_char_val)+cur_chr; - end else cur_tok:=cs_token_flag+cur_cs; - back_input; - begin_token_list(sa_ptr(cur_ptr), inter_char_text); - goto #; - end; - end + if XeTeX_inter_char_tokens_en and (space_class<>256) and (prev_class<>255) then begin + prev_class:=255; + find_sa_element(inter_char_val, space_class*@"100 + 255, false); {boundary} + if cur_ptr<>null then begin + if cur_cs=0 then begin + if cur_cmd=char_num then cur_cmd:=other_char; + cur_tok:=(cur_cmd*max_char_val)+cur_chr; + end else cur_tok:=cs_token_flag+cur_cs; + back_input; + begin_token_list(sa_ptr(cur_ptr), inter_char_text); + goto #; + end; + end @<Append character |cur_chr|...@>= @@ -23389,201 +23395,201 @@ prev_class := 255; {boundary} { added code for native font support } if is_native_font(cur_font) then begin - if mode>0 then if language<>clang then fix_language; + if mode>0 then if language<>clang then fix_language; - main_h := 0; - main_f := cur_font; - native_len := 0; + main_h := 0; + main_f := cur_font; + native_len := 0; collect_native: - adjust_space_factor; - - check_for_inter_char_toks(collected); - - if (cur_chr > @"FFFF) then begin - native_room(2); - append_native((cur_chr - @"10000) div 1024 + @"D800); - append_native((cur_chr - @"10000) mod 1024 + @"DC00); - end else begin - native_room(1); - append_native(cur_chr); - end; - is_hyph := (cur_chr = hyphen_char[main_f]) - or (XeTeX_dash_break_en and ((cur_chr = @"2014) or (cur_chr = @"2013))); - if (main_h = 0) and is_hyph then main_h := native_len; - - {try to collect as many chars as possible in the same font} - get_next; - if (cur_cmd=letter) or (cur_cmd=other_char) or (cur_cmd=char_given) then goto collect_native; - x_token; - if (cur_cmd=letter) or (cur_cmd=other_char) or (cur_cmd=char_given) then goto collect_native; - if cur_cmd=char_num then begin - scan_usv_num; - cur_chr:=cur_val; - goto collect_native; - end; - - check_for_post_char_toks(collected); + adjust_space_factor; + + check_for_inter_char_toks(collected); + + if (cur_chr > @"FFFF) then begin + native_room(2); + append_native((cur_chr - @"10000) div 1024 + @"D800); + append_native((cur_chr - @"10000) mod 1024 + @"DC00); + end else begin + native_room(1); + append_native(cur_chr); + end; + is_hyph := (cur_chr = hyphen_char[main_f]) + or (XeTeX_dash_break_en and ((cur_chr = @"2014) or (cur_chr = @"2013))); + if (main_h = 0) and is_hyph then main_h := native_len; + + {try to collect as many chars as possible in the same font} + get_next; + if (cur_cmd=letter) or (cur_cmd=other_char) or (cur_cmd=char_given) then goto collect_native; + x_token; + if (cur_cmd=letter) or (cur_cmd=other_char) or (cur_cmd=char_given) then goto collect_native; + if cur_cmd=char_num then begin + scan_usv_num; + cur_chr:=cur_val; + goto collect_native; + end; + + check_for_post_char_toks(collected); collected: - if (font_mapping[main_f] <> 0) then begin - main_k := apply_mapping(font_mapping[main_f], native_text, native_len); - native_len := 0; - native_room(main_k); - main_h := 0; - for main_p := 0 to main_k - 1 do begin - append_native(mapped_text[main_p]); - if (main_h = 0) and ((mapped_text[main_p] = hyphen_char[main_f]) - or (XeTeX_dash_break_en and ((mapped_text[main_p] = @"2014) or (mapped_text[main_p] = @"2013)) ) ) - then main_h := native_len; - end - end; - - if tracing_lost_chars > 0 then begin - temp_ptr := 0; - while (temp_ptr < native_len) do begin - main_k := native_text[temp_ptr]; - incr(temp_ptr); - if (main_k >= @"D800) and (main_k < @"DC00) then begin - main_k := @"10000 + (main_k - @"D800) * 1024; - main_k := main_k + native_text[temp_ptr] - @"DC00; - incr(temp_ptr); - end; - if map_char_to_glyph(main_f, main_k) = 0 then - char_warning(main_f, main_k); - end - end; - - main_k := native_len; - main_pp := tail; - - if mode=hmode then begin - - main_ppp := head; - if main_ppp<>main_pp then { find node preceding tail, skipping discretionaries } - while (link(main_ppp)<>main_pp) do begin - if (not is_char_node(main_ppp)) and (type(main_ppp=disc_node)) then begin - temp_ptr:=main_ppp; - for main_p:=1 to replace_count(temp_ptr) do main_ppp:=link(main_ppp); - end; - if main_ppp<>main_pp then main_ppp:=link(main_ppp); - end; - - temp_ptr := 0; - repeat - if main_h = 0 then main_h := main_k; - - if is_native_word_node(main_pp) - and (native_font(main_pp)=main_f) - and (main_ppp<>main_pp) - and (not is_char_node(main_ppp)) - and (type(main_ppp)<>disc_node) - then begin - - { make a new temp string that contains the concatenated text of |tail| + the current word/fragment } - main_k := main_h + native_length(main_pp); - native_room(main_k); - - save_native_len := native_len; - for main_p := 0 to native_length(main_pp) - 1 do - append_native(get_native_char(main_pp, main_p)); - for main_p := 0 to main_h - 1 do - append_native(native_text[temp_ptr + main_p]); - - do_locale_linebreaks(save_native_len, main_k); - - native_len := save_native_len; { discard the temp string } - main_k := native_len - main_h - temp_ptr; { and set |main_k| to remaining length of new word } - temp_ptr := main_h; { pointer to remaining fragment } - - main_h := 0; - while (main_h < main_k) and (native_text[temp_ptr + main_h] <> hyphen_char[main_f]) - and ( (not XeTeX_dash_break_en) - or ((native_text[temp_ptr + main_h] <> @"2014) and (native_text[temp_ptr + main_h] <> @"2013)) ) - do incr(main_h); { look for next hyphen or end of text } - if (main_h < main_k) then incr(main_h); - - { remove the preceding node from the list } - link(main_ppp) := link(main_pp); - link(main_pp) := null; - flush_node_list(main_pp); - main_pp := tail; - while (link(main_ppp)<>main_pp) do - main_ppp:=link(main_ppp); - - end else begin - - do_locale_linebreaks(temp_ptr, main_h); { append fragment of current word } - - temp_ptr := temp_ptr + main_h; { advance ptr to remaining fragment } - main_k := main_k - main_h; { decrement remaining length } - - main_h := 0; - while (main_h < main_k) and (native_text[temp_ptr + main_h] <> hyphen_char[main_f]) - and ( (not XeTeX_dash_break_en) - or ((native_text[temp_ptr + main_h] <> @"2014) and (native_text[temp_ptr + main_h] <> @"2013)) ) - do incr(main_h); { look for next hyphen or end of text } - if (main_h < main_k) then incr(main_h); - - end; - - if (main_k > 0) or is_hyph then begin - tail_append(new_disc); { add a break if we aren't at end of text (must be a hyphen), - or if last char in original text was a hyphen } - main_pp:=tail; - end; - until main_k = 0; - - end else begin - { must be restricted hmode, so no need for line-breaking or discretionaries } - { but there might already be explicit |disc_node|s in the list } - main_ppp := head; - if main_ppp<>main_pp then { find node preceding tail, skipping discretionaries } - while (link(main_ppp)<>main_pp) do begin - if (not is_char_node(main_ppp)) and (type(main_ppp=disc_node)) then begin - temp_ptr:=main_ppp; - for main_p:=1 to replace_count(temp_ptr) do main_ppp:=link(main_ppp); - end; - if main_ppp<>main_pp then main_ppp:=link(main_ppp); - end; - if is_native_word_node(main_pp) - and (native_font(main_pp)=main_f) - and (main_ppp<>main_pp) - and (not is_char_node(main_ppp)) - and (type(main_ppp)<>disc_node) - then begin - { total string length for the new merged whatsit } - link(main_pp) := new_native_word_node(main_f, main_k + native_length(main_pp)); - tail := link(main_pp); - - { copy text from the old one into the new } - for main_p := 0 to native_length(main_pp) - 1 do - set_native_char(tail, main_p, get_native_char(main_pp, main_p)); - { append the new text } - for main_p := 0 to main_k - 1 do - set_native_char(tail, main_p + native_length(main_pp), native_text[main_p]); - set_native_metrics(tail, XeTeX_use_glyph_metrics); - - { remove the preceding node from the list } - main_p := head; - if main_p<>main_pp then - while link(main_p)<>main_pp do - main_p := link(main_p); - link(main_p) := link(main_pp); - link(main_pp) := null; - flush_node_list(main_pp); - end else begin - { package the current string into a |native_word| whatsit } - link(main_pp) := new_native_word_node(main_f, main_k); - tail := link(main_pp); - for main_p := 0 to main_k - 1 do - set_native_char(tail, main_p, native_text[main_p]); - set_native_metrics(tail, XeTeX_use_glyph_metrics); - end - end; - - if cur_ptr<>null then goto big_switch - else goto reswitch; + if (font_mapping[main_f] <> 0) then begin + main_k := apply_mapping(font_mapping[main_f], native_text, native_len); + native_len := 0; + native_room(main_k); + main_h := 0; + for main_p := 0 to main_k - 1 do begin + append_native(mapped_text[main_p]); + if (main_h = 0) and ((mapped_text[main_p] = hyphen_char[main_f]) + or (XeTeX_dash_break_en and ((mapped_text[main_p] = @"2014) or (mapped_text[main_p] = @"2013)) ) ) + then main_h := native_len; + end + end; + + if tracing_lost_chars > 0 then begin + temp_ptr := 0; + while (temp_ptr < native_len) do begin + main_k := native_text[temp_ptr]; + incr(temp_ptr); + if (main_k >= @"D800) and (main_k < @"DC00) then begin + main_k := @"10000 + (main_k - @"D800) * 1024; + main_k := main_k + native_text[temp_ptr] - @"DC00; + incr(temp_ptr); + end; + if map_char_to_glyph(main_f, main_k) = 0 then + char_warning(main_f, main_k); + end + end; + + main_k := native_len; + main_pp := tail; + + if mode=hmode then begin + + main_ppp := head; + if main_ppp<>main_pp then { find node preceding tail, skipping discretionaries } + while (link(main_ppp)<>main_pp) do begin + if (not is_char_node(main_ppp)) and (type(main_ppp=disc_node)) then begin + temp_ptr:=main_ppp; + for main_p:=1 to replace_count(temp_ptr) do main_ppp:=link(main_ppp); + end; + if main_ppp<>main_pp then main_ppp:=link(main_ppp); + end; + + temp_ptr := 0; + repeat + if main_h = 0 then main_h := main_k; + + if is_native_word_node(main_pp) + and (native_font(main_pp)=main_f) + and (main_ppp<>main_pp) + and (not is_char_node(main_ppp)) + and (type(main_ppp)<>disc_node) + then begin + + { make a new temp string that contains the concatenated text of |tail| + the current word/fragment } + main_k := main_h + native_length(main_pp); + native_room(main_k); + + save_native_len := native_len; + for main_p := 0 to native_length(main_pp) - 1 do + append_native(get_native_char(main_pp, main_p)); + for main_p := 0 to main_h - 1 do + append_native(native_text[temp_ptr + main_p]); + + do_locale_linebreaks(save_native_len, main_k); + + native_len := save_native_len; { discard the temp string } + main_k := native_len - main_h - temp_ptr; { and set |main_k| to remaining length of new word } + temp_ptr := main_h; { pointer to remaining fragment } + + main_h := 0; + while (main_h < main_k) and (native_text[temp_ptr + main_h] <> hyphen_char[main_f]) + and ( (not XeTeX_dash_break_en) + or ((native_text[temp_ptr + main_h] <> @"2014) and (native_text[temp_ptr + main_h] <> @"2013)) ) + do incr(main_h); { look for next hyphen or end of text } + if (main_h < main_k) then incr(main_h); + + { remove the preceding node from the list } + link(main_ppp) := link(main_pp); + link(main_pp) := null; + flush_node_list(main_pp); + main_pp := tail; + while (link(main_ppp)<>main_pp) do + main_ppp:=link(main_ppp); + + end else begin + + do_locale_linebreaks(temp_ptr, main_h); { append fragment of current word } + + temp_ptr := temp_ptr + main_h; { advance ptr to remaining fragment } + main_k := main_k - main_h; { decrement remaining length } + + main_h := 0; + while (main_h < main_k) and (native_text[temp_ptr + main_h] <> hyphen_char[main_f]) + and ( (not XeTeX_dash_break_en) + or ((native_text[temp_ptr + main_h] <> @"2014) and (native_text[temp_ptr + main_h] <> @"2013)) ) + do incr(main_h); { look for next hyphen or end of text } + if (main_h < main_k) then incr(main_h); + + end; + + if (main_k > 0) or is_hyph then begin + tail_append(new_disc); { add a break if we aren't at end of text (must be a hyphen), + or if last char in original text was a hyphen } + main_pp:=tail; + end; + until main_k = 0; + + end else begin + { must be restricted hmode, so no need for line-breaking or discretionaries } + { but there might already be explicit |disc_node|s in the list } + main_ppp := head; + if main_ppp<>main_pp then { find node preceding tail, skipping discretionaries } + while (link(main_ppp)<>main_pp) do begin + if (not is_char_node(main_ppp)) and (type(main_ppp=disc_node)) then begin + temp_ptr:=main_ppp; + for main_p:=1 to replace_count(temp_ptr) do main_ppp:=link(main_ppp); + end; + if main_ppp<>main_pp then main_ppp:=link(main_ppp); + end; + if is_native_word_node(main_pp) + and (native_font(main_pp)=main_f) + and (main_ppp<>main_pp) + and (not is_char_node(main_ppp)) + and (type(main_ppp)<>disc_node) + then begin + { total string length for the new merged whatsit } + link(main_pp) := new_native_word_node(main_f, main_k + native_length(main_pp)); + tail := link(main_pp); + + { copy text from the old one into the new } + for main_p := 0 to native_length(main_pp) - 1 do + set_native_char(tail, main_p, get_native_char(main_pp, main_p)); + { append the new text } + for main_p := 0 to main_k - 1 do + set_native_char(tail, main_p + native_length(main_pp), native_text[main_p]); + set_native_metrics(tail, XeTeX_use_glyph_metrics); + + { remove the preceding node from the list } + main_p := head; + if main_p<>main_pp then + while link(main_p)<>main_pp do + main_p := link(main_p); + link(main_p) := link(main_pp); + link(main_pp) := null; + flush_node_list(main_pp); + end else begin + { package the current string into a |native_word| whatsit } + link(main_pp) := new_native_word_node(main_f, main_k); + tail := link(main_pp); + for main_p := 0 to main_k - 1 do + set_native_char(tail, main_p, native_text[main_p]); + set_native_metrics(tail, XeTeX_use_glyph_metrics); + end + end; + + if cur_ptr<>null then goto big_switch + else goto reswitch; end; { End of added code for native fonts } @@ -24904,11 +24910,11 @@ var p:pointer; {|char_node| at the tail of the current list} begin if tail<>head then begin if is_char_node(tail) then p:=tail else if type(tail)=ligature_node then p:=lig_char(tail) - else if (type(tail)=whatsit_node) then begin - if (subtype(tail)=native_word_node) then begin + else if type(tail)=whatsit_node then begin + if subtype(tail)=native_word_node then begin tail_append(new_kern(get_native_italic_correction(tail))); subtype(tail):=explicit; end - else if (subtype(tail)=glyph_node) then begin + else if subtype(tail)=glyph_node then begin tail_append(new_kern(get_native_glyph_italic_correction(tail))); subtype(tail):=explicit; end; return; @@ -25007,8 +25013,8 @@ q:=head; p:=link(q); n:=0; while p<>null do begin if not is_char_node(p) then if type(p)>rule_node then if type(p)<>kern_node then if type(p)<>ligature_node then - if (type(p)<>whatsit_node) or ((subtype(p)<>native_word_node) - and (subtype(p)<>glyph_node)) then + if (type(p)<>whatsit_node) or ((subtype(p)<>native_word_node) + and (subtype(p)<>glyph_node)) then begin print_err("Improper discretionary list"); @.Improper discretionary list@> help1("Discretionary lists must contain only boxes and kerns.");@/ @@ -25094,7 +25100,7 @@ end; if h<>x then {the accent must be shifted up or down} begin p:=hpack(p,natural); shift_amount(p):=x-h; end; -if is_native_font(f) and (a=0) then { special case for non-spacing marks } +if (is_native_font(f)) and (a=0) then { special case for non-spacing marks } delta:=round((w-lsb+rsb)/float_constant(2)+h*t-x*s) else delta:=round((w-a)/float_constant(2)+h*t-x*s); @^real multiplication@> @@ -26120,11 +26126,11 @@ end; @ @<Check that the necessary fonts...@>= if ((font_params[fam_fnt(2+text_size)]<total_mathsy_params) - and (not is_new_mathfont(fam_fnt(2+text_size)))) or@| + and (not (is_new_mathfont(fam_fnt(2+text_size))))) or@| ((font_params[fam_fnt(2+script_size)]<total_mathsy_params) - and (not is_new_mathfont(fam_fnt(2+script_size)))) or@| + and (not (is_new_mathfont(fam_fnt(2+script_size))))) or@| ((font_params[fam_fnt(2+script_script_size)]<total_mathsy_params) - and (not is_new_mathfont(fam_fnt(2+script_script_size)))) then + and (not (is_new_mathfont(fam_fnt(2+script_script_size))))) then begin print_err("Math formula deleted: Insufficient symbol fonts");@/ @.Math formula deleted...@> help3("Sorry, but I can't typeset math unless \textfont 2")@/ @@ -26133,11 +26139,11 @@ if ((font_params[fam_fnt(2+text_size)]<total_mathsy_params) error; flush_math; danger:=true; end else if ((font_params[fam_fnt(3+text_size)]<total_mathex_params) - and (not is_new_mathfont(fam_fnt(3+text_size)))) or@| + and (not (is_new_mathfont(fam_fnt(3+text_size))))) or@| ((font_params[fam_fnt(3+script_size)]<total_mathex_params) - and (not is_new_mathfont(fam_fnt(3+script_size)))) or@| + and (not (is_new_mathfont(fam_fnt(3+script_size))))) or@| ((font_params[fam_fnt(3+script_script_size)]<total_mathex_params) - and (not is_new_mathfont(fam_fnt(3+script_script_size)))) then + and (not (is_new_mathfont(fam_fnt(3+script_script_size))))) then begin print_err("Math formula deleted: Insufficient extension fonts");@/ help3("Sorry, but I can't typeset math unless \textfont 3")@/ ("and \scriptfont 3 and \scriptscriptfont 3 have all")@/ @@ -26849,7 +26855,7 @@ XeTeX_def_code: begin if cur_chr = sf_code_base then begin p:=cur_chr; scan_usv_num; p:=p+cur_val; - n:=sf_code(cur_val) mod @"10000; + n:=sf_code(cur_val) mod @"10000; scan_optional_equals; scan_char_class; define(p,data,cur_val*@"10000 + n); @@ -27307,7 +27313,7 @@ the new name becomes the font identifier of record. Font names `\.{xyz}' and flushable_string:=str_ptr-1; for f:=font_base+1 to font_ptr do begin if str_eq_str(font_name[f],cur_name) and - (((cur_area = "") and is_native_font(f)) or str_eq_str(font_area[f],cur_area)) then + (((cur_area = "") and (is_native_font(f))) or str_eq_str(font_area[f],cur_area)) then begin if cur_name=flushable_string then begin flush_string; cur_name:=font_name[f]; end; @@ -28712,11 +28718,10 @@ p:=scan_toks(false,true); write_tokens(tail):=def_ref; end @ @d call_func(#) == begin if # <> 0 then do_nothing end -@d flushable(#) == (# = str_ptr - 1) @p procedure flush_str(s: str_number); {flush a string if possible} begin - if flushable(s) then + if s = str_ptr-1 then flush_string; end; @@ -28787,22 +28792,22 @@ end; procedure print_native_word(@!p:pointer); var i,c,cc:integer; begin - for i:=0 to native_length(p) - 1 do begin - c:=get_native_char(p,i); - if (c >= @"D800) and (c <= @"DBFF) then begin - if i < native_length(p) - 1 then begin - cc:=get_native_char(p, i+1); - if (cc >= @"DC00) and (cc <= @"DFFF) then begin - c := @"10000 + (c - @"D800) * @"400 + (cc - @"DC00); - print_char(c); - incr(i); - end else - print("."); - end else - print("."); - end else - print_char(c); - end + for i:=0 to native_length(p) - 1 do begin + c:=get_native_char(p,i); + if (c >= @"D800) and (c <= @"DBFF) then begin + if i < native_length(p) - 1 then begin + cc:=get_native_char(p, i+1); + if (cc >= @"DC00) and (cc <= @"DFFF) then begin + c := @"10000 + (c - @"D800) * @"400 + (cc - @"DC00); + print_char(c); + incr(i); + end else + print("."); + end else + print("."); + end else + print_char(c); + end end; @ @<Display the whatsit...@>= @@ -28823,9 +28828,9 @@ language_node:begin print_esc("setlanguage"); print_int(what_rhm(p)); print_char(")"); end; native_word_node:begin - print_esc(font_id_text(native_font(p))); - print_char(" "); - print_native_word(p); + print_esc(font_id_text(native_font(p))); + print_char(" "); + print_native_word(p); end; glyph_node:begin print_esc(font_id_text(native_font(p))); @@ -28833,12 +28838,12 @@ glyph_node:begin print_int(native_glyph(p)); end; pic_node,pdf_node: begin - if subtype(p) = pic_node then print_esc("XeTeXpicfile") - else print_esc("XeTeXpdffile"); - print(" """); - for i:=0 to pic_path_length(p)-1 do - print_visible_char(pic_path_byte(p, i)); - print(""""); + if subtype(p) = pic_node then print_esc("XeTeXpicfile") + else print_esc("XeTeXpdffile"); + print(" """); + for i:=0 to pic_path_length(p)-1 do + print_visible_char(pic_path_byte(p, i)); + print(""""); end; pdf_save_pos_node: print_esc("pdfsavepos"); othercases print("whatsit?") @@ -28896,107 +28901,107 @@ end @ @<Incorporate a whatsit node into a vbox@>= begin - if (subtype(p)=pic_node) - or (subtype(p)=pdf_node) - then begin - x := x + d + height(p); - d := depth(p); - if width(p) > w then w := width(p); - end; + if (subtype(p)=pic_node) + or (subtype(p)=pdf_node) + then begin + x := x + d + height(p); + d := depth(p); + if width(p) > w then w := width(p); + end; end @ @<Incorporate a whatsit node into an hbox@>= begin - case subtype(p) of - - native_word_node: - begin - { merge with any following word fragments in same font, discarding discretionary breaks } - if type(q) = disc_node then k:=replace_count(q) else k:=0; - while (link(q) <> p) do begin - decr(k); - q := link(q); { bring q up in preparation for deletion of nodes starting at p } - if type(q) = disc_node then k:=replace_count(q); - end; - pp := link(p); - restart: - if (k <= 0) and (pp <> null) and (not is_char_node(pp)) then begin - if (type(pp) = whatsit_node) - and (subtype(pp) = native_word_node) - and (native_font(pp) = native_font(p)) then begin - pp := link(pp); - goto restart; - end - else if (type(pp) = disc_node) then begin - ppp := link(pp); - if is_native_word_node(ppp) - and (native_font(ppp) = native_font(p)) then begin - pp := link(ppp); - goto restart; - end - end - end; - - { now pp points to the non-|native_word| node that ended the chain, or null } - - { we can just check type(p)=|whatsit_node| below, as we know that the chain - contains only discretionaries and |native_word| nodes, no other whatsits or |char_node|s } - - if (pp <> link(p)) then begin - { found a chain of at least two pieces starting at p } - total_chars := 0; - p := link(q); { the first fragment } - while (p <> pp) do begin - if (type(p) = whatsit_node) then - total_chars := total_chars + native_length(p); { accumulate char count } - ppp := p; { remember last node seen } - p := link(p); { point to next fragment or discretionary or terminator } - end; - - p := link(q); { the first fragment again } - pp := new_native_word_node(native_font(p), total_chars); { make new node for merged word } - link(q) := pp; { link to preceding material } - link(pp) := link(ppp); { attach remainder of hlist to it } - link(ppp) := null; { and detach from the old fragments } - - { copy the chars into new node } - total_chars := 0; - ppp := p; - repeat - if (type(ppp) = whatsit_node) then - for k := 0 to native_length(ppp)-1 do begin - set_native_char(pp, total_chars, get_native_char(ppp, k)); - incr(total_chars); - end; - ppp := link(ppp); - until (ppp = null); - - flush_node_list(p); { delete the fragments } - p := link(q); { update p to point to the new node } - set_native_metrics(p, XeTeX_use_glyph_metrics); { and measure it (i.e., re-do the OT layout) } - end; - - { now incorporate the |native_word| node measurements into the box we're packing } - if height(p) > h then - h := height(p); - if depth(p) > d then - d := depth(p); - x := x + width(p); - end; - - glyph_node, pic_node, pdf_node: - begin - if height(p) > h then - h := height(p); - if depth(p) > d then - d := depth(p); - x := x + width(p); - end; - - othercases - do_nothing - - endcases + case subtype(p) of + + native_word_node: + begin + { merge with any following word fragments in same font, discarding discretionary breaks } + if type(q) = disc_node then k:=replace_count(q) else k:=0; + while (link(q) <> p) do begin + decr(k); + q := link(q); { bring q up in preparation for deletion of nodes starting at p } + if type(q) = disc_node then k:=replace_count(q); + end; + pp := link(p); + restart: + if (k <= 0) and (pp <> null) and (not is_char_node(pp)) then begin + if (type(pp) = whatsit_node) + and (subtype(pp) = native_word_node) + and (native_font(pp) = native_font(p)) then begin + pp := link(pp); + goto restart; + end + else if type(pp) = disc_node then begin + ppp := link(pp); + if is_native_word_node(ppp) + and (native_font(ppp) = native_font(p)) then begin + pp := link(ppp); + goto restart; + end + end + end; + + { now pp points to the non-|native_word| node that ended the chain, or null } + + { we can just check type(p)=|whatsit_node| below, as we know that the chain + contains only discretionaries and |native_word| nodes, no other whatsits or |char_node|s } + + if (pp <> link(p)) then begin + { found a chain of at least two pieces starting at p } + total_chars := 0; + p := link(q); { the first fragment } + while p <> pp do begin + if type(p) = whatsit_node then + total_chars := total_chars + native_length(p); { accumulate char count } + ppp := p; { remember last node seen } + p := link(p); { point to next fragment or discretionary or terminator } + end; + + p := link(q); { the first fragment again } + pp := new_native_word_node(native_font(p), total_chars); { make new node for merged word } + link(q) := pp; { link to preceding material } + link(pp) := link(ppp); { attach remainder of hlist to it } + link(ppp) := null; { and detach from the old fragments } + + { copy the chars into new node } + total_chars := 0; + ppp := p; + repeat + if type(ppp) = whatsit_node then + for k := 0 to native_length(ppp)-1 do begin + set_native_char(pp, total_chars, get_native_char(ppp, k)); + incr(total_chars); + end; + ppp := link(ppp); + until (ppp = null); + + flush_node_list(p); { delete the fragments } + p := link(q); { update p to point to the new node } + set_native_metrics(p, XeTeX_use_glyph_metrics); { and measure it (i.e., re-do the OT layout) } + end; + + { now incorporate the |native_word| node measurements into the box we're packing } + if height(p) > h then + h := height(p); + if depth(p) > d then + d := depth(p); + x := x + width(p); + end; + + glyph_node, pic_node, pdf_node: + begin + if height(p) > h then + h := height(p); + if depth(p) > d then + d := depth(p); + x := x + width(p); + end; + + othercases + do_nothing + + endcases end @ @<Let |d| be the width of the whatsit |p|, and |goto found| if ``visible''@>= @@ -29005,8 +29010,8 @@ or (subtype(p)=glyph_node) or (subtype(p)=pic_node) or (subtype(p)=pdf_node) then begin - d:=width(p); - goto found; + d:=width(p); + goto found; end else d := 0 @@ -29034,67 +29039,67 @@ adv_past_prehyph(s) @ @<Prepare to move whatsit |p| to the current page, then |goto contribute|@>= begin - if (subtype(p)=pic_node) - or (subtype(p)=pdf_node) - then begin - page_total := page_total + page_depth + height(p); - page_depth := depth(p); - end; - goto contribute; + if (subtype(p)=pic_node) + or (subtype(p)=pdf_node) + then begin + page_total := page_total + page_depth + height(p); + page_depth := depth(p); + end; + goto contribute; end @ @<Process whatsit |p| in |vert_break| loop, |goto not_found|@>= begin - if (subtype(p)=pic_node) - or (subtype(p)=pdf_node) - then begin - cur_height := cur_height + prev_dp + height(p); prev_dp := depth(p); - end; - goto not_found; + if (subtype(p)=pic_node) + or (subtype(p)=pdf_node) + then begin + cur_height := cur_height + prev_dp + height(p); prev_dp := depth(p); + end; + goto not_found; end @ @<Output the whatsit node |p| in a vlist@>= begin - case subtype(p) of - glyph_node: begin - cur_v:=cur_v+height(p); - cur_h:=left_edge; - - { synch DVI state to TeX state } - synch_h; synch_v; - f := native_font(p); - if f<>dvi_f then @<Change font |dvi_f| to |f|@>; - - dvi_out(set_glyph_string); - dvi_four(0); { width } - dvi_two(1); { glyph count } - dvi_four(0); { x-offset as fixed point } - dvi_two(native_glyph(p)); - - cur_v:=cur_v+depth(p); - cur_h:=left_edge; - end; - pic_node, pdf_node: begin - save_h:=dvi_h; save_v:=dvi_v; - cur_v:=cur_v+height(p); - pic_out(p, subtype(p) = pdf_node); - dvi_h:=save_h; dvi_v:=save_v; - cur_v:=save_v+depth(p); cur_h:=left_edge; - end; - - pdf_save_pos_node: - @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>; - - othercases - out_what(p) - - endcases + case subtype(p) of + glyph_node: begin + cur_v:=cur_v+height(p); + cur_h:=left_edge; + + { synch DVI state to TeX state } + synch_h; synch_v; + f := native_font(p); + if f<>dvi_f then @<Change font |dvi_f| to |f|@>; + + dvi_out(set_glyph_string); + dvi_four(0); { width } + dvi_two(1); { glyph count } + dvi_four(0); { x-offset as fixed point } + dvi_two(native_glyph(p)); + + cur_v:=cur_v+depth(p); + cur_h:=left_edge; + end; + pic_node, pdf_node: begin + save_h:=dvi_h; save_v:=dvi_v; + cur_v:=cur_v+height(p); + pic_out(p, subtype(p) = pdf_node); + dvi_h:=save_h; dvi_v:=save_v; + cur_v:=save_v+depth(p); cur_h:=left_edge; + end; + + pdf_save_pos_node: + @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>; + + othercases + out_what(p) + + endcases end @ @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>= begin pdf_last_x_pos := cur_h + cur_h_offset; - pdf_last_y_pos := cur_page_height - cur_v - cur_v_offset + pdf_last_y_pos := cur_page_height - cur_v - cur_v_offset end @ @<Calculate page dimensions and margins@>= @@ -29117,49 +29122,49 @@ else @ @<Output the whatsit node |p| in an hlist@>= begin - case subtype(p) of - native_word_node, glyph_node: begin - { synch DVI state to TeX state } - synch_h; synch_v; - f := native_font(p); - if f<>dvi_f then @<Change font |dvi_f| to |f|@>; - - if subtype(p) = glyph_node then begin - dvi_out(set_glyph_string); - dvi_four(width(p)); - dvi_two(1); { glyph count } - dvi_four(0); { x-offset as fixed point } - dvi_two(native_glyph(p)); - cur_h := cur_h + width(p); - end else begin - if native_glyph_info_ptr(p) <> null_ptr then begin - len := make_xdv_glyph_array_data(p); - for k := 0 to len-1 do - dvi_out(xdv_buffer_byte(k)); - end; - cur_h := cur_h + width(p); - end; - - dvi_h := cur_h; - end; - - pic_node, pdf_node: begin - save_h:=dvi_h; save_v:=dvi_v; - cur_v:=base_line; - edge:=cur_h+width(p); - if cur_dir=right_to_left then cur_h:=edge; - pic_out(p, subtype(p) = pdf_node); - dvi_h:=save_h; dvi_v:=save_v; - cur_h:=edge; cur_v:=base_line; - end; - - pdf_save_pos_node: - @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>; - - othercases - out_what(p) - - endcases + case subtype(p) of + native_word_node, glyph_node: begin + { synch DVI state to TeX state } + synch_h; synch_v; + f := native_font(p); + if f<>dvi_f then @<Change font |dvi_f| to |f|@>; + + if subtype(p) = glyph_node then begin + dvi_out(set_glyph_string); + dvi_four(width(p)); + dvi_two(1); { glyph count } + dvi_four(0); { x-offset as fixed point } + dvi_two(native_glyph(p)); + cur_h := cur_h + width(p); + end else begin + if native_glyph_info_ptr(p) <> null_ptr then begin + len := make_xdv_glyph_array_data(p); + for k := 0 to len-1 do + dvi_out(xdv_buffer_byte(k)); + end; + cur_h := cur_h + width(p); + end; + + dvi_h := cur_h; + end; + + pic_node, pdf_node: begin + save_h:=dvi_h; save_v:=dvi_v; + cur_v:=base_line; + edge:=cur_h+width(p); + if cur_dir=right_to_left then cur_h:=edge; + pic_out(p, subtype(p) = pdf_node); + dvi_h:=save_h; dvi_v:=save_v; + cur_h:=edge; cur_v:=base_line; + end; + + pdf_save_pos_node: + @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>; + + othercases + out_what(p) + + endcases end @ After all this preliminary shuffling, we come finally to the routines @@ -29263,9 +29268,9 @@ begin synch_h; synch_v; dvi_out(pic_file); if is_pdf then - dvi_out(pic_box_type(p)) + dvi_out(pic_box_type(p)) else - dvi_out(0); + dvi_out(0); dvi_four(pic_transform1(p)); dvi_four(pic_transform2(p)); dvi_four(pic_transform3(p)); @@ -29395,224 +29400,224 @@ end @ Load a picture file and handle following keywords. @d calc_min_and_max== - begin - xmin := 1000000.0; - xmax := -xmin; - ymin := xmin; - ymax := xmax; - for i := 0 to 3 do begin - if xCoord(corners[i]) < xmin then xmin := xCoord(corners[i]); - if xCoord(corners[i]) > xmax then xmax := xCoord(corners[i]); - if yCoord(corners[i]) < ymin then ymin := yCoord(corners[i]); - if yCoord(corners[i]) > ymax then ymax := yCoord(corners[i]); - end; - end + begin + xmin := 1000000.0; + xmax := -xmin; + ymin := xmin; + ymax := xmax; + for i := 0 to 3 do begin + if xCoord(corners[i]) < xmin then xmin := xCoord(corners[i]); + if xCoord(corners[i]) > xmax then xmax := xCoord(corners[i]); + if yCoord(corners[i]) < ymin then ymin := yCoord(corners[i]); + if yCoord(corners[i]) > ymax then ymax := yCoord(corners[i]); + end; + end @d update_corners== - for i := 0 to 3 do - transform_point(addressof(corners[i]), addressof(t2)) + for i := 0 to 3 do + transform_point(addressof(corners[i]), addressof(t2)) @d do_size_requests==begin - { calculate current width and height } - calc_min_and_max; - if x_size_req = 0.0 then begin - make_scale(addressof(t2), y_size_req / (ymax - ymin), y_size_req / (ymax - ymin)); - end else if y_size_req = 0.0 then begin - make_scale(addressof(t2), x_size_req / (xmax - xmin), x_size_req / (xmax - xmin)); - end else begin - make_scale(addressof(t2), x_size_req / (xmax - xmin), y_size_req / (ymax - ymin)); - end; - update_corners; - x_size_req := 0.0; - y_size_req := 0.0; - transform_concat(addressof(t), addressof(t2)); + { calculate current width and height } + calc_min_and_max; + if x_size_req = 0.0 then begin + make_scale(addressof(t2), y_size_req / (ymax - ymin), y_size_req / (ymax - ymin)); + end else if y_size_req = 0.0 then begin + make_scale(addressof(t2), x_size_req / (xmax - xmin), x_size_req / (xmax - xmin)); + end else begin + make_scale(addressof(t2), x_size_req / (xmax - xmin), y_size_req / (ymax - ymin)); + end; + update_corners; + x_size_req := 0.0; + y_size_req := 0.0; + transform_concat(addressof(t), addressof(t2)); end @<Declare procedures needed in |do_extension|@>= procedure load_picture(@!is_pdf:boolean); var - pic_path: ^char; - bounds: real_rect; - t, t2: transform; - corners: array[0..3] of real_point; - x_size_req,y_size_req: real; - check_keywords: boolean; - xmin,xmax,ymin,ymax: real; - i: small_number; - page: integer; - pdf_box_type: integer; - result: integer; + pic_path: ^char; + bounds: real_rect; + t, t2: transform; + corners: array[0..3] of real_point; + x_size_req,y_size_req: real; + check_keywords: boolean; + xmin,xmax,ymin,ymax: real; + i: small_number; + page: integer; + pdf_box_type: integer; + result: integer; begin - { scan the filename and pack into |name_of_file| } - scan_file_name; - pack_cur_name; + { scan the filename and pack into |name_of_file| } + scan_file_name; + pack_cur_name; pdf_box_type := 0; - page := 0; - if is_pdf then begin - if scan_keyword("page") then begin - scan_int; - page := cur_val; - end; - pdf_box_type := pdfbox_crop; - if scan_keyword("crop") then do_nothing - else if scan_keyword("media") then pdf_box_type := pdfbox_media - else if scan_keyword("bleed") then pdf_box_type := pdfbox_bleed - else if scan_keyword("trim") then pdf_box_type := pdfbox_trim - else if scan_keyword("art") then pdf_box_type := pdfbox_art; - end; - - { access the picture file and check its size } - result := find_pic_file(addressof(pic_path), addressof(bounds), pdf_box_type, page); - - setPoint(corners[0], xField(bounds), yField(bounds)); - setPoint(corners[1], xField(corners[0]), yField(bounds) + htField(bounds)); - setPoint(corners[2], xField(bounds) + wdField(bounds), yField(corners[1])); - setPoint(corners[3], xField(corners[2]), yField(corners[0])); - - x_size_req := 0.0; - y_size_req := 0.0; - - { look for any scaling requests for this picture } - make_identity(addressof(t)); - - check_keywords := true; - while check_keywords do begin - if scan_keyword("scaled") then begin - scan_int; - if (x_size_req = 0.0) and (y_size_req = 0.0) then begin - make_scale(addressof(t2), float(cur_val) / 1000.0, float(cur_val) / 1000.0); - update_corners; - transform_concat(addressof(t), addressof(t2)); - end - end else if scan_keyword("xscaled") then begin - scan_int; - if (x_size_req = 0.0) and (y_size_req = 0.0) then begin - make_scale(addressof(t2), float(cur_val) / 1000.0, 1.0); - update_corners; - transform_concat(addressof(t), addressof(t2)); - end - end else if scan_keyword("yscaled") then begin - scan_int; - if (x_size_req = 0.0) and (y_size_req = 0.0) then begin - make_scale(addressof(t2), 1.0, float(cur_val) / 1000.0); - update_corners; - transform_concat(addressof(t), addressof(t2)); - end - end else if scan_keyword("width") then begin - scan_normal_dimen; - if cur_val <= 0 then begin - print_err("Improper image "); - print("size ("); - print_scaled(cur_val); - print("pt) will be ignored"); - help2("I can't scale images to zero or negative sizes,")@/ - ("so I'm ignoring this."); - error; - end else - x_size_req := Fix2D(cur_val); - end else if scan_keyword("height") then begin - scan_normal_dimen; - if cur_val <= 0 then begin - print_err("Improper image "); - print("size ("); - print_scaled(cur_val); - print("pt) will be ignored"); - help2("I can't scale images to zero or negative sizes,")@/ - ("so I'm ignoring this."); - error; - end else - y_size_req := Fix2D(cur_val); - end else if scan_keyword("rotated") then begin - scan_decimal; - if (x_size_req <> 0.0) or (y_size_req <> 0.0) then do_size_requests; - make_rotation(addressof(t2), Fix2D(cur_val) * 3.141592653589793 / 180.0); - update_corners; - calc_min_and_max; - setPoint(corners[0], xmin, ymin); - setPoint(corners[1], xmin, ymax); - setPoint(corners[2], xmax, ymax); - setPoint(corners[3], xmax, ymin); - transform_concat(addressof(t), addressof(t2)); - end else - check_keywords := false; - end; - - if (x_size_req <> 0.0) or (y_size_req <> 0.0) then do_size_requests; - - calc_min_and_max; - make_translation(addressof(t2), -xmin * 72 / 72.27, -ymin * 72 / 72.27); - transform_concat(addressof(t), addressof(t2)); - - if result = 0 then begin - - new_whatsit(pic_node, pic_node_size + (strlen(pic_path) + sizeof(memory_word) - 1) div sizeof(memory_word)); - if is_pdf then begin - subtype(tail) := pdf_node; - pic_box_type(tail) := pdf_box_type; - end; - pic_path_length(tail) := strlen(pic_path); - pic_page(tail) := page; - - width(tail) := D2Fix(xmax - xmin); - height(tail) := D2Fix(ymax - ymin); - depth(tail) := 0; - - pic_transform1(tail) := D2Fix(aField(t)); - pic_transform2(tail) := D2Fix(bField(t)); - pic_transform3(tail) := D2Fix(cField(t)); - pic_transform4(tail) := D2Fix(dField(t)); - pic_transform5(tail) := D2Fix(xField(t)); - pic_transform6(tail) := D2Fix(yField(t)); - - memcpy(addressof(mem[tail + pic_node_size]), pic_path, strlen(pic_path)); - libc_free(pic_path); - - end else begin - - print_err("Unable to load picture or PDF file '"); - print_file_name(cur_name,cur_area,cur_ext); print("'"); - if result = -43 then begin { Mac OS file not found error } - help2("The requested image couldn't be read because")@/ - ("the file was not found."); - end - else begin { otherwise assume GraphicImport failed } - help2("The requested image couldn't be read because")@/ - ("it was not a recognized image format."); - end; - error; - - end; + page := 0; + if is_pdf then begin + if scan_keyword("page") then begin + scan_int; + page := cur_val; + end; + pdf_box_type := pdfbox_crop; + if scan_keyword("crop") then do_nothing + else if scan_keyword("media") then pdf_box_type := pdfbox_media + else if scan_keyword("bleed") then pdf_box_type := pdfbox_bleed + else if scan_keyword("trim") then pdf_box_type := pdfbox_trim + else if scan_keyword("art") then pdf_box_type := pdfbox_art; + end; + + { access the picture file and check its size } + result := find_pic_file(addressof(pic_path), addressof(bounds), pdf_box_type, page); + + setPoint(corners[0], xField(bounds), yField(bounds)); + setPoint(corners[1], xField(corners[0]), yField(bounds) + htField(bounds)); + setPoint(corners[2], xField(bounds) + wdField(bounds), yField(corners[1])); + setPoint(corners[3], xField(corners[2]), yField(corners[0])); + + x_size_req := 0.0; + y_size_req := 0.0; + + { look for any scaling requests for this picture } + make_identity(addressof(t)); + + check_keywords := true; + while check_keywords do begin + if scan_keyword("scaled") then begin + scan_int; + if (x_size_req = 0.0) and (y_size_req = 0.0) then begin + make_scale(addressof(t2), float(cur_val) / 1000.0, float(cur_val) / 1000.0); + update_corners; + transform_concat(addressof(t), addressof(t2)); + end + end else if scan_keyword("xscaled") then begin + scan_int; + if (x_size_req = 0.0) and (y_size_req = 0.0) then begin + make_scale(addressof(t2), float(cur_val) / 1000.0, 1.0); + update_corners; + transform_concat(addressof(t), addressof(t2)); + end + end else if scan_keyword("yscaled") then begin + scan_int; + if (x_size_req = 0.0) and (y_size_req = 0.0) then begin + make_scale(addressof(t2), 1.0, float(cur_val) / 1000.0); + update_corners; + transform_concat(addressof(t), addressof(t2)); + end + end else if scan_keyword("width") then begin + scan_normal_dimen; + if cur_val <= 0 then begin + print_err("Improper image "); + print("size ("); + print_scaled(cur_val); + print("pt) will be ignored"); + help2("I can't scale images to zero or negative sizes,")@/ + ("so I'm ignoring this."); + error; + end else + x_size_req := Fix2D(cur_val); + end else if scan_keyword("height") then begin + scan_normal_dimen; + if cur_val <= 0 then begin + print_err("Improper image "); + print("size ("); + print_scaled(cur_val); + print("pt) will be ignored"); + help2("I can't scale images to zero or negative sizes,")@/ + ("so I'm ignoring this."); + error; + end else + y_size_req := Fix2D(cur_val); + end else if scan_keyword("rotated") then begin + scan_decimal; + if (x_size_req <> 0.0) or (y_size_req <> 0.0) then do_size_requests; + make_rotation(addressof(t2), Fix2D(cur_val) * 3.141592653589793 / 180.0); + update_corners; + calc_min_and_max; + setPoint(corners[0], xmin, ymin); + setPoint(corners[1], xmin, ymax); + setPoint(corners[2], xmax, ymax); + setPoint(corners[3], xmax, ymin); + transform_concat(addressof(t), addressof(t2)); + end else + check_keywords := false; + end; + + if (x_size_req <> 0.0) or (y_size_req <> 0.0) then do_size_requests; + + calc_min_and_max; + make_translation(addressof(t2), -xmin * 72 / 72.27, -ymin * 72 / 72.27); + transform_concat(addressof(t), addressof(t2)); + + if result = 0 then begin + + new_whatsit(pic_node, pic_node_size + (strlen(pic_path) + sizeof(memory_word) - 1) div sizeof(memory_word)); + if is_pdf then begin + subtype(tail) := pdf_node; + pic_box_type(tail) := pdf_box_type; + end; + pic_path_length(tail) := strlen(pic_path); + pic_page(tail) := page; + + width(tail) := D2Fix(xmax - xmin); + height(tail) := D2Fix(ymax - ymin); + depth(tail) := 0; + + pic_transform1(tail) := D2Fix(aField(t)); + pic_transform2(tail) := D2Fix(bField(t)); + pic_transform3(tail) := D2Fix(cField(t)); + pic_transform4(tail) := D2Fix(dField(t)); + pic_transform5(tail) := D2Fix(xField(t)); + pic_transform6(tail) := D2Fix(yField(t)); + + memcpy(addressof(mem[tail + pic_node_size]), pic_path, strlen(pic_path)); + libc_free(pic_path); + + end else begin + + print_err("Unable to load picture or PDF file '"); + print_file_name(cur_name,cur_area,cur_ext); print("'"); + if result = -43 then begin { Mac OS file not found error } + help2("The requested image couldn't be read because")@/ + ("the file was not found."); + end + else begin { otherwise assume GraphicImport failed } + help2("The requested image couldn't be read because")@/ + ("it was not a recognized image format."); + end; + error; + + end; end; @ @<Implement \.{\\XeTeXinputencoding}@>= begin - scan_and_pack_name; {scan a filename-like arg for the input encoding} + scan_and_pack_name; {scan a filename-like arg for the input encoding} - i := get_encoding_mode_and_info(addressof(j)); {convert it to |mode| and |encoding| values} - if i = XeTeX_input_mode_auto then begin - print_err("Encoding mode `auto' is not valid for \XeTeXinputencoding"); + i := get_encoding_mode_and_info(addressof(j)); {convert it to |mode| and |encoding| values} + if i = XeTeX_input_mode_auto then begin + print_err("Encoding mode `auto' is not valid for \XeTeXinputencoding"); help2("You can't use `auto' encoding here, only for \XeTeXdefaultencoding.")@/ ("I'll ignore this and leave the current encoding unchanged.");@/ - error; - end else set_input_file_encoding(input_file[in_open], i, j); {apply them to the current input file} + error; + end else set_input_file_encoding(input_file[in_open], i, j); {apply them to the current input file} end @ @<Implement \.{\\XeTeXdefaultencoding}@>= begin - scan_and_pack_name; {scan a filename-like arg for the input encoding} + scan_and_pack_name; {scan a filename-like arg for the input encoding} - i := get_encoding_mode_and_info(addressof(j)); {convert it to |mode| and |encoding| values} - XeTeX_default_input_mode := i; {store them as defaults for new input files} - XeTeX_default_input_encoding := j; + i := get_encoding_mode_and_info(addressof(j)); {convert it to |mode| and |encoding| values} + XeTeX_default_input_mode := i; {store them as defaults for new input files} + XeTeX_default_input_encoding := j; end @ @<Implement \.{\\XeTeXlinebreaklocale}@>= begin - scan_file_name; {scan a filename-like arg for the locale name} - if length(cur_name) = 0 then XeTeX_linebreak_locale := 0 - else XeTeX_linebreak_locale := cur_name; {we ignore the area and extension!} + scan_file_name; {scan a filename-like arg for the locale name} + if length(cur_name) = 0 then XeTeX_linebreak_locale := 0 + else XeTeX_linebreak_locale := cur_name; {we ignore the area and extension!} end @ @<Glob...@>= @@ -30084,7 +30089,7 @@ XeTeX_variation_name_code: XeTeX_feature_name_code: begin scan_font_ident; fnt:=cur_val; - if is_aat_font(fnt) or is_gr_font(fnt) then begin + if (is_aat_font(fnt)) or (is_gr_font(fnt)) then begin scan_int; arg1:=cur_val; arg2:=0; end else not_aat_gr_font_error(convert, c, fnt); @@ -30093,7 +30098,7 @@ XeTeX_feature_name_code: XeTeX_selector_name_code: begin scan_font_ident; fnt:=cur_val; - if is_aat_font(fnt) or is_gr_font(fnt) then begin + if (is_aat_font(fnt)) or (is_gr_font(fnt)) then begin scan_int; arg1:=cur_val; scan_int; arg2:=cur_val; end else not_aat_gr_font_error(convert, c, fnt); @@ -30165,7 +30170,7 @@ right_margin_kern_code: begin print("pt"); end; -@ @d eTeX_ex==(eTeX_mode=1) {is this extended mode?} +@ @d eTeX_ex==eTeX_mode=1 {is this extended mode?} @<Glob...@>= @!eTeX_mode: 0..1; {identifies compatibility and extended mode} diff --git a/Build/source/texk/web2c/xetexdir/xetexextra.h b/Build/source/texk/web2c/xetexdir/xetexextra.h index 0751fbfe4d8..6fb91423fa0 100644 --- a/Build/source/texk/web2c/xetexdir/xetexextra.h +++ b/Build/source/texk/web2c/xetexdir/xetexextra.h @@ -57,7 +57,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <xetexdir/xetex_version.h> /* for XETEX_VERSION */ #define BANNER "This is XeTeX, Version 3.14159265-" ETEX_VERSION "-" XETEX_VERSION -#define COPYRIGHT_HOLDER "SIL International and Jonathan Kew" +#define COPYRIGHT_HOLDER "SIL International, Jonathan Kew and Khaled Hosny" #define AUTHOR "Jonathan Kew" #define PROGRAM_HELP XETEXHELP #define BUG_ADDRESS "xetex@tug.org" |