diff options
author | Khaled Hosny <khaledhosny@eglug.org> | 2013-02-19 00:32:39 +0000 |
---|---|---|
committer | Khaled Hosny <khaledhosny@eglug.org> | 2013-02-19 00:32:39 +0000 |
commit | b9a5b9cad6d163192c3ab462fc86adc525a81e71 (patch) | |
tree | 11f84a8fdd80d31f9e49565a2e75a4e782146308 /Build/source/texk/web2c/xetexdir/XeTeX_mac.c | |
parent | e43ae240f33296136cb498e6d9d0e9a55eba7493 (diff) |
Sync with XeTeX
git-svn-id: svn://tug.org/texlive/trunk@29157 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/xetexdir/XeTeX_mac.c')
-rw-r--r-- | Build/source/texk/web2c/xetexdir/XeTeX_mac.c | 1238 |
1 files changed, 491 insertions, 747 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c index bef5ef3c8ac..4f0f186bdf4 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c @@ -2,6 +2,8 @@ Part of the XeTeX typesetting system Copyright (c) 1994-2008 by SIL International Copyright (c) 2009 by Jonathan Kew + Copyright (c) 2012, 2013 by Jiang Jiang + Copyright (c) 2012, 2013 by Khaled Hosny SIL Author(s): Jonathan Kew @@ -43,9 +45,7 @@ authorization from the copyright holders. #define EXTERN extern #include "xetexd.h" -#undef input /* this is defined in texmfmp.h, but we don't need it and it confuses the carbon headers */ -#include <Carbon/Carbon.h> -#include <QuickTime/QuickTime.h> +#include <ApplicationServices/ApplicationServices.h> #include <teckit/TECkit_Engine.h> #include "XeTeX_ext.h" @@ -53,22 +53,6 @@ authorization from the copyright holders. #include "XeTeXswap.h" -static ATSUTextLayout sTextLayout = 0; - -static void -InitializeLayout() -{ - OSStatus status = ATSUCreateTextLayout(&sTextLayout); - ATSUFontFallbacks fallbacks; - status = ATSUCreateFontFallbacks(&fallbacks); - status = ATSUSetObjFontFallbacks(fallbacks, 0, 0, kATSULastResortOnlyFallback); - ATSUAttributeTag tag = kATSULineFontFallbacksTag; - ByteCount valueSize = sizeof(fallbacks); - ATSUAttributeValuePtr value = &fallbacks; - status = ATSUSetLayoutControls(sTextLayout, 1, &tag, &valueSize, &value); - status = ATSUSetTransientFontMatching(sTextLayout, true); -} - static inline double TeXtoPSPoints(double pts) { @@ -82,15 +66,20 @@ PStoTeXPoints(double pts) } static inline Fixed -FixedTeXtoPSPoints(Fixed pts) +FixedPStoTeXPoints(double pts) { - return D2Fix(TeXtoPSPoints(Fix2D(pts))); + return D2Fix(PStoTeXPoints(pts)); } -static inline Fixed -FixedPStoTeXPoints(Fixed pts) +CTFontRef fontFromAttributes(CFDictionaryRef attributes) +{ + return CFDictionaryGetValue(attributes, kCTFontAttributeName); +} + +CTFontRef fontFromInteger(integer font) { - return D2Fix(PStoTeXPoints(Fix2D(pts))); + CFDictionaryRef attributes = (CFDictionaryRef) fontlayoutengine[font]; + return fontFromAttributes(attributes); } void @@ -104,336 +93,168 @@ DoAtsuiLayout(void* p, int justify) exit(1); } - if (sTextLayout == 0) - InitializeLayout(); - - OSStatus status = noErr; - long txtLen = native_length(node); const UniChar* txtPtr = (UniChar*)(node + native_node_size); - status = ATSUSetTextPointerLocation(sTextLayout, txtPtr, 0, txtLen, txtLen); - - // we're using this font in AAT mode, so fontlayoutengine[f] is actually an ATSUStyle - ATSUStyle style = (ATSUStyle)(fontlayoutengine[native_font(node)]); - status = ATSUSetRunStyle(sTextLayout, style, 0, txtLen); + CFDictionaryRef attributes = fontlayoutengine[native_font(node)]; + CFStringRef string = CFStringCreateWithCharactersNoCopy(NULL, txtPtr, txtLen, kCFAllocatorNull); + CFAttributedStringRef attrString = CFAttributedStringCreate(NULL, string, attributes); + CFRelease(string); - ATSUAttributeTag tags[] = { kATSULineWidthTag, kATSULineJustificationFactorTag }; - ItemCount numTags = sizeof(tags) / sizeof(ATSUAttributeTag); + CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString(attrString); + CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, txtLen)); if (justify) { - ByteCount valSizes[] = { sizeof(Fixed), sizeof(Fract) }; - Fixed wid = FixedTeXtoPSPoints(node_width(node)); - Fract just = fract1; - ATSUAttributeValuePtr valPtrs[] = { &wid, &just }; - status = ATSUSetLayoutControls(sTextLayout, numTags, tags, valSizes, valPtrs); - } - - ItemCount count; - ATSLayoutRecord* layoutRec = NULL; - status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(sTextLayout, 0, - kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void*)&layoutRec, &count); - - int i; - int realGlyphCount = 0; - int lastRealGlyph = 0; - for (i = 0; i < count; ++i) - if (layoutRec[i].glyphID < 0xfffe) { - lastRealGlyph = i; - ++realGlyphCount; + 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; } + } - void* glyph_info = xmalloc(realGlyphCount * native_glyph_info_size); - FixedPoint* locations = (FixedPoint*)glyph_info; - UInt16* glyphIDs = (UInt16*)(locations + realGlyphCount); + CFArrayRef glyphRuns = CTLineGetGlyphRuns(line); + CFIndex i, runCount = CFArrayGetCount(glyphRuns); + CFIndex totalGlyphCount = CTLineGetGlyphCount(line); + UInt16* realGlyphIDs = xmalloc(totalGlyphCount * sizeof(UInt16)); + void* glyph_info = xmalloc(totalGlyphCount * native_glyph_info_size); + FixedPoint* locations = (FixedPoint*)glyph_info; + Fixed lsUnit = justify ? 0 : fontletterspace[f]; + Fixed lsDelta = 0; - Fixed lsUnit = justify ? 0 : fontletterspace[f]; - Fixed lsDelta = 0; - - realGlyphCount = 0; - for (i = 0; i < count; ++i) { - if (layoutRec[i].glyphID < 0xfffe) { - if ((layoutRec[i].flags & kATSGlyphInfoIsAttachment) && (lsDelta != 0)) - lsDelta -= lsUnit; - glyphIDs[realGlyphCount] = layoutRec[i].glyphID; - locations[realGlyphCount].y = 0; /* FIXME: won't handle baseline offsets */ - locations[realGlyphCount].x = FixedPStoTeXPoints(layoutRec[i].realPos) + lsDelta; - lsDelta += lsUnit; - ++realGlyphCount; + int realGlyphCount = 0; + CGFloat lastGlyphAdvance = 0; + for (i = 0; i < runCount; i++) { + CTRunRef run = CFArrayGetValueAtIndex(glyphRuns, i); + CFIndex count = CTRunGetGlyphCount(run); + // 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)); + CTRunGetGlyphs(run, CFRangeMake(0, 0), glyphs); + CTRunGetPositions(run, CFRangeMake(0, 0), positions); + CTRunGetAdvances(run, CFRangeMake(0, 0), advances); + CFIndex j; + for (j = 0; j < count; j++) { + if (glyphs[j] < 0xfffe) { + realGlyphIDs[realGlyphCount] = glyphs[j]; + locations[realGlyphCount].x = FixedPStoTeXPoints(positions[j].x) + lsDelta; + lastGlyphAdvance = advances[j].width; + locations[realGlyphCount].y = FixedPStoTeXPoints(positions[j].y); + lsDelta += lsUnit; + realGlyphCount++; + } } + free(advances); + free(glyphs); + free(positions); } if (lsDelta != 0) lsDelta -= lsUnit; + UInt16* glyphIDs = (UInt16*)(locations + realGlyphCount); + memcpy(glyphIDs, realGlyphIDs, realGlyphCount * sizeof(UInt16)); + free(realGlyphIDs); + native_glyph_count(node) = realGlyphCount; native_glyph_info_ptr(node) = glyph_info; - - if (!justify) - node_width(node) = FixedPStoTeXPoints(layoutRec[count-1].realPos) + lsDelta; - - ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void*)&layoutRec); - - if (justify) - ATSUClearLayoutControls(sTextLayout, numTags, tags); -} - -static OSStatus QuadraticClosePath(void *callBackDataPtr) -{ - return 0; -} - -static OSStatus QuadraticCurve(const Float32Point *pt1, const Float32Point *controlPt, const Float32Point *pt2, void *callBackDataPtr) -{ - GlyphBBox* data = (GlyphBBox*)callBackDataPtr; - - if (pt1->x < data->xMin) - data->xMin = pt1->x; - if (pt1->x > data->xMax) - data->xMax = pt1->x; - if (pt1->y < data->yMin) - data->yMin = pt1->y; - if (pt1->y > data->yMax) - data->yMax = pt1->y; - - if (pt2->x < data->xMin) - data->xMin = pt2->x; - if (pt2->x > data->xMax) - data->xMax = pt2->x; - if (pt2->y < data->yMin) - data->yMin = pt2->y; - if (pt2->y > data->yMax) - data->yMax = pt2->y; - - if (controlPt->x < data->xMin) - data->xMin = controlPt->x; - if (controlPt->x > data->xMax) - data->xMax = controlPt->x; - if (controlPt->y < data->yMin) - data->yMin = controlPt->y; - if (controlPt->y > data->yMax) - data->yMax = controlPt->y; - - return 0; -} - -static OSStatus QuadraticLine(const Float32Point *pt1, const Float32Point *pt2, void *callBackDataPtr) -{ - GlyphBBox* data = (GlyphBBox*)callBackDataPtr; - - if (pt1->x < data->xMin) - data->xMin = pt1->x; - if (pt1->x > data->xMax) - data->xMax = pt1->x; - if (pt1->y < data->yMin) - data->yMin = pt1->y; - if (pt1->y > data->yMax) - data->yMax = pt1->y; - - if (pt2->x < data->xMin) - data->xMin = pt2->x; - if (pt2->x > data->xMax) - data->xMax = pt2->x; - if (pt2->y < data->yMin) - data->yMin = pt2->y; - if (pt2->y > data->yMax) - data->yMax = pt2->y; - - return 0; -} - -static OSStatus QuadraticNewPath(void *callBackDataPtr) -{ - return 0; -} - -static OSStatus CubicMoveTo(const Float32Point *pt, void *callBackDataPtr) -{ - GlyphBBox* data = (GlyphBBox*)callBackDataPtr; - - if (pt->x < data->xMin) - data->xMin = pt->x; - if (pt->x > data->xMax) - data->xMax = pt->x; - if (pt->y < data->yMin) - data->yMin = pt->y; - if (pt->y > data->yMax) - data->yMax = pt->y; - - return 0; -} - -static OSStatus CubicLineTo(const Float32Point *pt, void *callBackDataPtr) -{ - GlyphBBox* data = (GlyphBBox*)callBackDataPtr; - - if (pt->x < data->xMin) - data->xMin = pt->x; - if (pt->x > data->xMax) - data->xMax = pt->x; - if (pt->y < data->yMin) - data->yMin = pt->y; - if (pt->y > data->yMax) - data->yMax = pt->y; - - return 0; -} - -static OSStatus CubicCurveTo(const Float32Point *pt1, const Float32Point *pt2, const Float32Point *pt3, void *callBackDataPtr) -{ - GlyphBBox* data = (GlyphBBox*)callBackDataPtr; - - if (pt1->x < data->xMin) - data->xMin = pt1->x; - if (pt1->x > data->xMax) - data->xMax = pt1->x; - if (pt1->y < data->yMin) - data->yMin = pt1->y; - if (pt1->y > data->yMax) - data->yMax = pt1->y; - - if (pt2->x < data->xMin) - data->xMin = pt2->x; - if (pt2->x > data->xMax) - data->xMax = pt2->x; - if (pt2->y < data->yMin) - data->yMin = pt2->y; - if (pt2->y > data->yMax) - data->yMax = pt2->y; - - if (pt3->x < data->xMin) - data->xMin = pt3->x; - if (pt3->x > data->xMax) - data->xMax = pt3->x; - if (pt3->y < data->yMin) - data->yMin = pt3->y; - if (pt3->y > data->yMax) - data->yMax = pt3->y; - return 0; -} + if (!justify) { + node_width(node) = + (realGlyphCount > 0 ? locations[realGlyphCount - 1].x : 0) + + FixedPStoTeXPoints(lastGlyphAdvance) + + lsDelta; + } -static OSStatus CubicClosePath(void *callBackDataPtr) -{ - return 0; + CFRelease(line); + CFRelease(typesetter); } -void GetGlyphBBox_AAT(ATSUStyle style, UInt16 gid, GlyphBBox* bbox) - /* returns glyph bounding box in TeX points */ +void getGlyphBBoxFromCTFont(CTFontRef font, UInt16 gid, GlyphBBox* bbox) { - ATSCurveType curveType; - OSStatus status; - bbox->xMin = 65536.0; bbox->yMin = 65536.0; bbox->xMax = -65536.0; bbox->yMax = -65536.0; - status = ATSUGetNativeCurveType(style, &curveType); - if (status == noErr) { - OSStatus cbStatus; - - if (curveType == kATSCubicCurveType) { - static ATSCubicMoveToUPP cubicMoveToProc; - static ATSCubicLineToUPP cubicLineToProc; - static ATSCubicCurveToUPP cubicCurveToProc; - static ATSCubicClosePathUPP cubicClosePathProc; - if (cubicMoveToProc == NULL) { - cubicMoveToProc = NewATSCubicMoveToUPP(&CubicMoveTo); - cubicLineToProc = NewATSCubicLineToUPP(&CubicLineTo); - cubicCurveToProc = NewATSCubicCurveToUPP(&CubicCurveTo); - cubicClosePathProc = NewATSCubicClosePathUPP(&CubicClosePath); - } - status = ATSUGlyphGetCubicPaths(style, gid, - cubicMoveToProc, cubicLineToProc, cubicCurveToProc, cubicClosePathProc, - bbox, &cbStatus); - } - else { - static ATSQuadraticNewPathUPP quadraticNewPathProc; - static ATSQuadraticLineUPP quadraticLineProc; - static ATSQuadraticCurveUPP quadraticCurveProc; - static ATSQuadraticClosePathUPP quadraticClosePathProc; - if (quadraticNewPathProc == NULL) { - quadraticNewPathProc = NewATSQuadraticNewPathUPP(&QuadraticNewPath); - quadraticLineProc = NewATSQuadraticLineUPP(&QuadraticLine); - quadraticCurveProc = NewATSQuadraticCurveUPP(&QuadraticCurve); - quadraticClosePathProc = NewATSQuadraticClosePathUPP(&QuadraticClosePath); - } - status = ATSUGlyphGetQuadraticPaths(style, gid, - quadraticNewPathProc, quadraticLineProc, quadraticCurveProc, quadraticClosePathProc, - bbox, &cbStatus); - } - } + CGRect rect = CTFontGetBoundingRectsForGlyphs(font, + 0, /* Use default orientation for now, handle vertical later */ + (const CGGlyph *) &gid, NULL, 1); - if (status != noErr || bbox->xMin == 65536.0) + if (CGRectIsNull(rect)) bbox->xMin = bbox->yMin = bbox->xMax = bbox->yMax = 0; else { // convert PS to TeX points and flip y-axis - float tmp = bbox->yMin; - bbox->yMin = -bbox->yMax * 72.27 / 72.0; - bbox->yMax = -tmp * 72.27 / 72.0; - bbox->xMin *= 72.27 / 72.0; - bbox->xMax *= 72.27 / 72.0; + // TODO: do we need to flip for bounding rect returned by Core Text? + bbox->yMin = -PStoTeXPoints(rect.origin.y + rect.size.height); + bbox->yMax = -PStoTeXPoints(rect.origin.y); + bbox->xMin = PStoTeXPoints(rect.origin.x); + bbox->xMax = PStoTeXPoints(rect.origin.x + rect.size.width); } } -float GetGlyphWidth_AAT(ATSUStyle style, UInt16 gid) +void GetGlyphBBox_AAT(CFDictionaryRef attributes, UInt16 gid, GlyphBBox* bbox) + /* returns glyph bounding box in TeX points */ +{ + CTFontRef font = fontFromAttributes(attributes); + return getGlyphBBoxFromCTFont(font, gid, bbox); +} + +double getGlyphWidthFromCTFont(CTFontRef font, UInt16 gid) +{ + CGSize advances[1] = { CGSizeMake(0, 0) }; + return PStoTeXPoints(CTFontGetAdvancesForGlyphs(font, 0, &gid, advances, 1)); +} + +double GetGlyphWidth_AAT(CFDictionaryRef attributes, UInt16 gid) /* returns TeX points */ { - ATSGlyphIdealMetrics metrics; - OSStatus status = ATSUGlyphGetIdealMetrics(style, 1, &gid, 0, &metrics); - if (status == noErr) - return PStoTeXPoints(metrics.advance.x); - else - return 0; + CTFontRef font = fontFromAttributes(attributes); + return getGlyphWidthFromCTFont(font, gid); } -void GetGlyphHeightDepth_AAT(ATSUStyle style, UInt16 gid, float* ht, float* dp) +void GetGlyphHeightDepth_AAT(CFDictionaryRef attributes, UInt16 gid, float* ht, float* dp) /* returns TeX points */ { GlyphBBox bbox; - GetGlyphBBox_AAT(style, gid, &bbox); + GetGlyphBBox_AAT(attributes, gid, &bbox); *ht = bbox.yMax; *dp = -bbox.yMin; } -void GetGlyphSidebearings_AAT(ATSUStyle style, UInt16 gid, float* lsb, float* rsb) +void GetGlyphSidebearings_AAT(CFDictionaryRef attributes, UInt16 gid, float* lsb, float* rsb) /* returns TeX points */ { - ATSGlyphIdealMetrics metrics; - OSStatus status = ATSUGlyphGetIdealMetrics(style, 1, &gid, 0, &metrics); - if (status == noErr) { - GlyphBBox bbox; - GetGlyphBBox_AAT(style, gid, &bbox); - *lsb = bbox.xMin; - *rsb = PStoTeXPoints(metrics.advance.x) - bbox.xMax; - } - else { - *lsb = *rsb = 0; - } + 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; } -float GetGlyphItalCorr_AAT(ATSUStyle style, UInt16 gid) +double GetGlyphItalCorr_AAT(CFDictionaryRef attributes, UInt16 gid) { - float rval = 0.0; - ATSGlyphIdealMetrics metrics; - OSStatus status = ATSUGlyphGetIdealMetrics(style, 1, &gid, 0, &metrics); - if (status == noErr) { - GlyphBBox bbox; - GetGlyphBBox_AAT(style, gid, &bbox); - if (bbox.xMax > PStoTeXPoints(metrics.advance.x)) - rval = bbox.xMax - PStoTeXPoints(metrics.advance.x); - } - return rval; + CTFontRef font = fontFromAttributes(attributes); + CGSize advances[1] = { CGSizeMake(0, 0) }; + double advance = CTFontGetAdvancesForGlyphs(font, 0, &gid, advances, 1); + + GlyphBBox bbox; + getGlyphBBoxFromCTFont(font, gid, &bbox); + + if (bbox.xMax > PStoTeXPoints(advance)) + return bbox.xMax - PStoTeXPoints(advance); + return 0; } -int MapCharToGlyph_AAT(ATSUStyle style, UInt32 ch) +int mapCharToGlyphFromCTFont(CTFontRef font, UInt32 ch, UInt32 vs) { - UniChar txt[2]; + UniChar txt[4]; int len = 1; - - if (sTextLayout == 0) - InitializeLayout(); if (ch > 0xffff) { ch -= 0x10000; @@ -444,448 +265,377 @@ int MapCharToGlyph_AAT(ATSUStyle style, UInt32 ch) else txt[0] = ch; - OSStatus status = ATSUSetTextPointerLocation(sTextLayout, &txt[0], 0, len, len); - if (status != noErr) - return 0; - status = ATSUSetRunStyle(sTextLayout, style, 0, len); - if (status != noErr) - return 0; - - ByteCount bufferSize = sizeof(ATSUGlyphInfoArray); - ATSUGlyphInfoArray info; - status = ATSUGetGlyphInfo(sTextLayout, 0, len, &bufferSize, &info); - if (status == noErr) { - if (bufferSize > 0 && info.numGlyphs > 0) - return info.glyphs[0].glyphID; + if (vs) { + if (vs > 0xffff) { + vs -= 0x10000; + txt[len] = 0xd800 + vs / 1024; + txt[len + 1] = 0xdc00 + vs % 1024; + len += 2; + } else { + txt[len] = vs; + len += 1; + } } + + CGGlyph glyphs[2] = { 0 }; + if (CTFontGetGlyphsForCharacters(font, txt, glyphs, len)) + return glyphs[0]; + return 0; } -int MapGlyphToIndex_AAT(ATSUStyle style, const char* glyphName) +int MapCharToGlyph_AAT(CFDictionaryRef attributes, UInt32 ch) { - ATSUFontID fontID; - ATSUGetAttribute(style, kATSUFontTag, sizeof(ATSUFontID), &fontID, 0); - - ATSFontRef fontRef = FMGetATSFontRefFromFont(fontID); - - ByteCount length; - OSStatus status = ATSFontGetTable(fontRef, kPOST, 0, 0, 0, &length); - if (status != noErr) - goto ats_failed; - - void* table = xmalloc(length); - status = ATSFontGetTable(fontRef, kPOST, 0, length, table, &length); - if (status != noErr) { - free(table); - goto ats_failed; - } - - int rval = findGlyphInPostTable(table, length, glyphName); - free(table); - - if (rval) - return rval; - -ats_failed: - return GetGlyphIDFromCGFont(fontRef, glyphName); + CTFontRef font = fontFromAttributes(attributes); + return mapCharToGlyphFromCTFont(font, ch, 0); } -int GetGlyphIDFromCGFont(ATSFontRef atsFontRef, const char* glyphName) +int MapGlyphToIndex_AAT(CFDictionaryRef attributes, const char* glyphName) { -#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - if (&CGFontGetGlyphWithGlyphName == NULL) - return 0; - - int rval = 0; - CFStringRef psname; - OSStatus status = ATSFontGetPostScriptName(atsFontRef, 0, &psname); - if ((status == noErr) && psname) { - CGFontRef cgfont = CGFontCreateWithFontName(psname); - CFRelease(psname); - if (cgfont) { - CFStringRef glyphname = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, - glyphName, - kCFStringEncodingUTF8, - kCFAllocatorNull); - rval = CGFontGetGlyphWithGlyphName(cgfont, glyphname); - CFRelease(glyphname); - CGFontRelease(cgfont); - } - } - return rval; -#else - return 0; -#endif + CTFontRef font = fontFromAttributes(attributes); + return GetGlyphIDFromCTFont(font, glyphName); } -char* -GetGlyphName_AAT(ATSUStyle style, UInt16 gid, int* len) +int GetGlyphIDFromCTFont(CTFontRef ctFontRef, const char* glyphName) { - static char buffer[256]; - const char* namePtr; - - ATSUFontID fontID; - ATSUGetAttribute(style, kATSUFontTag, sizeof(ATSUFontID), &fontID, 0); - - ATSFontRef fontRef = FMGetATSFontRefFromFont(fontID); - - ByteCount length; - OSStatus status = ATSFontGetTable(fontRef, kPOST, 0, 0, 0, &length); - if (status != noErr) - goto ats_failed; - - void* table = xmalloc(length); - status = ATSFontGetTable(fontRef, kPOST, 0, length, table, &length); - if (status != noErr) { - free(table); - goto ats_failed; - } - - buffer[0] = 0; - namePtr = getGlyphNamePtr(table, length, gid, len); - if (*len > 255) - *len = 255; - if (namePtr) { - memcpy(buffer, namePtr, *len); - buffer[*len] = 0; - } - - free(table); - - if (buffer[0]) - return &buffer[0]; - -ats_failed: - return GetGlyphNameFromCGFont(fontRef, gid, len); + CFStringRef glyphname = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + glyphName, + kCFStringEncodingUTF8, + kCFAllocatorNull); + int rval = CTFontGetGlyphWithName(ctFontRef, glyphname); + CFRelease(glyphname); + return rval; } char* -GetGlyphNameFromCGFont(ATSFontRef atsFontRef, UInt16 gid, int* len) +GetGlyphNameFromCTFont(CTFontRef ctFontRef, UInt16 gid, int* len) { *len = 0; static char buffer[256]; buffer[0] = 0; -#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (&CGFontCopyGlyphNameForGlyph == NULL) return &buffer[0]; - CFStringRef psname; - OSStatus status = ATSFontGetPostScriptName(atsFontRef, 0, &psname); - if ((status == noErr) && psname) { - CGFontRef cgfont = CGFontCreateWithFontName(psname); - CFRelease(psname); - if (cgfont && gid < CGFontGetNumberOfGlyphs(cgfont)) { - CFStringRef glyphname = CGFontCopyGlyphNameForGlyph(cgfont, gid); - if (glyphname) { - if (CFStringGetCString(glyphname, buffer, 256, kCFStringEncodingUTF8)) { - *len = strlen(buffer); - } - CFRelease(glyphname); + CGFontRef 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); } - CGFontRelease(cgfont); + CFRelease(glyphname); } + CGFontRelease(cgfont); } -#endif return &buffer[0]; } int -GetFontCharRange_AAT(ATSUStyle style, int reqFirst) +GetFontCharRange_AAT(CFDictionaryRef attributes, int reqFirst) { if (reqFirst) { int ch = 0; - while (MapCharToGlyph_AAT(style, ch) == 0 && ch < 0x10ffff) + while (MapCharToGlyph_AAT(attributes, ch) == 0 && ch < 0x10ffff) ++ch; return ch; } else { int ch = 0x10ffff; - while (MapCharToGlyph_AAT(style, ch) == 0 && ch > 0) + while (MapCharToGlyph_AAT(attributes, ch) == 0 && ch > 0) --ch; return ch; } } -ATSUFontVariationAxis -find_axis_by_name(ATSUFontID fontID, const char* name, int nameLength) +char* getNameFromCTFont(CTFontRef ctFontRef, CFStringRef nameKey) { - ATSUFontVariationAxis result = 0; - - Str255 inName; - inName[0] = nameLength; - int i; - for (i = 0; i < inName[0]; ++i) - inName[i + 1] = name[i]; - - ItemCount varCount; - ATSUCountFontVariations(fontID, &varCount); - if (varCount > 0) { - for (i = 0; i < varCount; ++i) { - ATSUFontVariationAxis axis; - ATSUGetIndFontVariation(fontID, i, &axis, 0, 0, 0); - FontNameCode nameCode; - ATSUGetFontVariationNameCode(fontID, axis, &nameCode); - Str255 name; - ByteCount nameLen; - ATSUFindFontName(fontID, nameCode, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, - 255, (Ptr)&name[1], &nameLen, 0); - name[0] = nameLen; - if (EqualString(inName, name, false, true)) { - result = axis; - break; + CFStringRef name = CTFontCopyName(ctFontRef, nameKey); + CFIndex len = CFStringGetLength(name); + len = len * 6 + 1; + char *buf = xmalloc(len); + if (CFStringGetCString(name, buf, len, kCFStringEncodingUTF8)) + return buf; + free(buf); + return 0; +} + +char* getFileNameFromCTFont(CTFontRef ctFontRef) +{ + char *ret = NULL; + + CFURLRef url = (CFURLRef) CTFontCopyAttribute(ctFontRef, kCTFontURLAttribute); + if (url) { + UInt8 pathname[PATH_MAX]; + if (CFURLGetFileSystemRepresentation(url, true, pathname, PATH_MAX)) { + int index = 0; + + /* finding face index by searching for preceding font ids with the same FSRef */ + /* logic copied from FreeType but without using ATS/FS APIs */ + ATSFontRef id1 = CTFontGetPlatformFont(ctFontRef, NULL); + ATSFontRef id2 = id1 - 1; + while (id2 > 0) { + FSRef dummy; + if (noErr != ATSFontGetFileReference(id2, &dummy)) /* check if id2 is valid, any better way? */ + break; + CTFontRef ctFontRef2 = CTFontCreateWithPlatformFont(id2, 0.0, NULL, NULL); + CFURLRef url2 = (CFURLRef) CTFontCopyAttribute(ctFontRef2, kCTFontURLAttribute); + if (!url2) + break; + if (!CFEqual(url, url2)) + break; + id2--; } + index = id1 - (id2 + 1); + + char buf[20]; + if (index > 0) + sprintf(buf, ":%d", index); + else + buf[0] = '\0'; + + ret = xmalloc(strlen((char*) pathname) + 2 + strlen(buf) + 1); + sprintf(ret, "[%s%s]", pathname, buf); } + CFRelease(url); } - - return result; + + return ret; } -ATSUFontFeatureType -find_feature_by_name(ATSUFontID fontID, const char* name, int nameLength) +CFDictionaryRef findDictionaryInArrayWithIdentifier(CFArrayRef array, + const void* identifierKey, + int identifier) { - ATSUFontFeatureType result = 0x0000FFFF; - - Str255 inName; - inName[0] = nameLength; - int i; - for (i = 0; i < inName[0]; ++i) - inName[i + 1] = name[i]; - - ItemCount typeCount; - ATSUCountFontFeatureTypes(fontID, &typeCount); - if (typeCount > 0) { - ATSUFontFeatureType* types = (ATSUFontFeatureType*)xmalloc(typeCount * sizeof(ATSUFontFeatureType)); - ATSUGetFontFeatureTypes(fontID, typeCount, types, 0); - for (i = 0; i < typeCount; ++i) { - FontNameCode nameCode; - ATSUGetFontFeatureNameCode(fontID, types[i], 0x0000FFFF, &nameCode); - Str255 name; - ByteCount nameLen; - ATSUFindFontName(fontID, nameCode, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, - 255, (Ptr)&name[1], &nameLen, 0); - name[0] = nameLen; - if (EqualString(inName, name, false, true)) { - result = types[i]; + if (!array) + return NULL; + + CFDictionaryRef dict = NULL; + 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; } } - free((char*)types); } - - return result; + return dict; } -ATSUFontFeatureSelector -find_selector_by_name(ATSUFontID fontID, ATSUFontFeatureType featureType, const char* name, int nameLength) +CFDictionaryRef findDictionaryInArray(CFArrayRef array, const void* nameKey, + const char* name, int nameLength) { - ATSUFontFeatureSelector result = 0x0000FFFF; - - Str255 inName; - inName[0] = nameLength; - int i; - for (i = 0; i < inName[0]; ++i) - inName[i + 1] = name[i]; - - ItemCount selectorCount; - ATSUCountFontFeatureSelectors(fontID, featureType, &selectorCount); - if (selectorCount > 0) { - ATSUFontFeatureSelector* selectors = (ATSUFontFeatureSelector*)xmalloc(selectorCount * sizeof(ATSUFontFeatureSelector)); - ATSUGetFontFeatureSelectors(fontID, featureType, selectorCount, selectors, 0, 0, 0); - for (i = 0; i < selectorCount; ++i) { - FontNameCode nameCode; - ATSUGetFontFeatureNameCode(fontID, featureType, selectors[i], &nameCode); - Str255 name; - ByteCount nameLen; - ATSUFindFontName(fontID, nameCode, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, - 255, (Ptr)&name[1], &nameLen, 0); - name[0] = nameLen; - if (EqualString(inName, name, false, true)) { - result = selectors[i]; - break; - } + if (!array) + return NULL; + + CFDictionaryRef dict = NULL; + CFStringRef itemName = CFStringCreateWithBytes(NULL, name, nameLength, + kCFStringEncodingUTF8, false); + CFIndex i; + 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; } - free((char*)selectors); } - - return result; + CFRelease(itemName); + return dict; +} + +CFNumberRef findSelectorByName(CFDictionaryRef feature, const char* name, int nameLength) +{ + CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey); + CFDictionaryRef s = findDictionaryInArray(selectors, kCTFontFeatureSelectorNameKey, name, nameLength); + CFNumberRef selector = NULL; + 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 }; + + return CFDictionaryCreate(kCFAllocatorDefault, settingKeys, settingValues, 2, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } +const CFStringRef kXeTeXEmboldenAttributeName = CFSTR("XeTeXEmbolden"); + void* -loadAATfont(ATSFontRef fontRef, long scaled_size, const char* cp1) +loadAATfont(CTFontDescriptorRef descriptor, integer scaled_size, const char* cp1) { - ATSUFontID fontID = FMGetFontFromATSFontRef(fontRef); - ATSUStyle style = 0; - OSStatus status = ATSUCreateStyle(&style); - float extend = 1.0; - float slant = 0.0; - float embolden = 0.0; - float letterspace = 0.0; - int i; - - if (status == noErr) { - UInt32 rgbValue; - Fixed tracking = 0x80000000; - Fixed atsuSize = FixedTeXtoPSPoints(scaled_size); - - ATSStyleRenderingOptions options = kATSStyleNoHinting; - Fract hangInhibit = fract1; - ATSUAttributeTag tags[] = { kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag, kATSUHangingInhibitFactorTag }; - ByteCount sizes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(ATSStyleRenderingOptions), sizeof(Fract) }; - ATSUAttributeValuePtr attrs[] = { &fontID, &atsuSize, &options, &hangInhibit }; - ATSUSetAttributes(style, sizeof(tags) / sizeof(ATSUAttributeTag), tags, sizes, attrs); - -#define FEAT_ALLOC_CHUNK 8 -#define VAR_ALLOC_CHUNK 4 - - if (cp1 != NULL) { - int allocFeats = FEAT_ALLOC_CHUNK; - UInt16* featureTypes = (UInt16*)xmalloc(allocFeats * sizeof(UInt16)); - UInt16* selectorValues = (UInt16*)xmalloc(allocFeats * sizeof(UInt16)); - int numFeatures = 0; - - int allocVars = VAR_ALLOC_CHUNK; - UInt32* axes = (UInt32*)xmalloc(allocVars * sizeof(UInt32)); - SInt32* values = (SInt32*)xmalloc(allocVars * sizeof(SInt32)); - int numVariations = 0; - - // interpret features & variations following ":" - while (*cp1) { - // 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 - const char* cp2 = cp1; - while (*cp2 && *cp2 != ';' && *cp2 != ':') - ++cp2; - - // look for the '=' separator - const char* 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 - ATSUFontFeatureType featureType; - featureType = find_feature_by_name(fontID, cp1, cp3 - cp1); - if (featureType != 0x0000FFFF) { - // look past the '=' separator for setting names - int featLen = cp3 - cp1; - ++cp3; - while (cp3 < cp2) { - // skip leading whitespace - while (*cp3 == ' ' || *cp3 == '\t') - ++cp3; - - // possibly multiple settings... - int disable = 0; - if (*cp3 == '!') { // check for negation - disable = 1; - ++cp3; - } - - // scan for end of setting name - const char* cp4 = cp3; - while (cp4 < cp2 && *cp4 != ',') - ++cp4; - - // now cp3 points to name, cp4 to ',' or ';' or null - ATSUFontFeatureSelector selectorValue = find_selector_by_name(fontID, featureType, cp3, cp4 - cp3); - if (selectorValue != 0x0000FFFF) { - if (numFeatures == allocFeats) { - allocFeats += FEAT_ALLOC_CHUNK; - featureTypes = xrealloc(featureTypes, allocFeats * sizeof(UInt16)); - selectorValues = xrealloc(selectorValues, allocFeats * sizeof(UInt16)); - } - featureTypes[numFeatures] = featureType; - selectorValues[numFeatures] = selectorValue + disable; - ++numFeatures; - } - else { - fontfeaturewarning(cp1, featLen, cp3, cp4 - cp3); - } - - // point beyond setting name terminator - cp3 = cp4 + 1; + CGFloat ctSize = TeXtoPSPoints(Fix2D(scaled_size)); + // create a base font instance for applying further attributes + CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, ctSize, NULL); + + if (!font) + return NULL; + + CFMutableDictionaryRef stringAttributes = + CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFMutableDictionaryRef attributes = + CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + double tracking = 0.0; + float extend = 1.0; + float slant = 0.0; + float embolden = 0.0; + float letterspace = 0.0; + UInt32 rgbValue; + 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) { + // 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 + const char* cp2 = cp1; + while (*cp2 && *cp2 != ';' && *cp2 != ':') + ++cp2; + + // look for the '=' separator + const char* 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 + CFDictionaryRef feature = findDictionaryInArray(features, kCTFontFeatureTypeNameKey, cp1, cp3 - cp1); + if (feature) { + // look past the '=' separator for setting names + int featLen = cp3 - cp1; + ++cp3; + int zeroInteger = 0; + CFNumberRef zero = CFNumberCreate(NULL, kCFNumberIntType, &zeroInteger); + while (cp3 < cp2) { + // skip leading whitespace + while (*cp3 == ' ' || *cp3 == '\t') + ++cp3; + + // possibly multiple settings... + int disable = 0; + if (*cp3 == '!') { // check for negation + disable = 1; + ++cp3; } - - goto next_option; + + // scan for end of setting name + const char* cp4 = cp3; + while (cp4 < cp2 && *cp4 != ',') + ++cp4; + + // now cp3 points to name, cp4 to ',' or ';' or null + CFNumberRef 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; } - - // try to find a variation by this name - ATSUFontVariationAxis axis; - axis = find_axis_by_name(fontID, cp1, cp3 - cp1); - if (axis != 0) { - // look past the '=' separator for the value + CFRelease(zero); + + goto next_option; + } + + // try to find a variation by this name + CFDictionaryRef axis = findDictionaryInArray(axes, kCTFontVariationAxisNameKey, cp1, cp3 - cp1); + if (axis) { + // look past the '=' separator for the value + ++cp3; + double value = 0.0, decimal = 1.0; + bool negate = false; + if (*cp3 == '-') { ++cp3; - double value = 0.0, decimal = 1.0; - bool negate = false; - 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; + 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 - break; - ++cp3; + value = value * 10.0 + v; } - if (negate) - value = -value; - if (numVariations == allocVars) { - allocVars += VAR_ALLOC_CHUNK; - axes = xrealloc(axes, allocVars * sizeof(UInt32)); - values = xrealloc(values, allocVars * sizeof(SInt32)); + else if (*cp3 == '.') { + if (decimal != 1.0) + break; + decimal = 10.0; } - axes[numVariations] = axis; - values[numVariations] = value * 65536.0; // D2Fix(value); - ++numVariations; - - goto next_option; - } - - // didn't find feature or variation, try other options.... - - i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden, &letterspace, &rgbValue); - if (i == 1) - goto next_option; - else if (i == -1) - goto bad_option; - - if (strncmp(cp1, "tracking", 8) == 0) { - cp3 = cp1 + 8; - if (*cp3 != '=') - goto bad_option; + else + break; ++cp3; - double val = read_double(&cp3); - tracking = D2Fix(val); - goto next_option; } - + if (negate) + value = -value; + + CFNumberRef axisIdentifier = CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey); + CFNumberRef axisValue = CFNumberCreate(NULL, kCFNumberDoubleType, &value); + CFDictionaryAddValue(variation, axisIdentifier, axisValue); + CFRelease(axisValue); + + goto next_option; + } + + // didn't find feature or variation, try other options... + int 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) { + cp3 = cp1 + 8; + if (*cp3 != '=') + goto bad_option; + ++cp3; + tracking = read_double(&cp3); + CFNumberRef trackingNumber = CFNumberCreate(NULL, kCFNumberDoubleType, &tracking); + CFDictionaryAddValue(stringAttributes, kCTKernAttributeName, trackingNumber); + CFRelease(trackingNumber); + goto next_option; + } + bad_option: - // not a name=value pair, or not recognized.... + // not a name=value pair, or not recognized.... // check for plain "vertical" before complaining if (strncmp(cp1, "vertical", 8) == 0) { cp3 = cp2; @@ -896,75 +646,69 @@ loadAATfont(ATSFontRef fontRef, long scaled_size, const char* cp1) if (*cp3) ++cp3; if (cp3 == cp1 + 8) { - ATSUVerticalCharacterType vert = kATSUStronglyVertical; - tags[0] = kATSUVerticalCharacterTag; - sizes[0] = sizeof(ATSUVerticalCharacterType); - attrs[0] = | - ATSUSetAttributes(style, 1, tags, sizes, attrs); + 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 (numFeatures > 0) - ATSUSetFontFeatures(style, numFeatures, featureTypes, selectorValues); - - if (numVariations > 0) - ATSUSetVariations(style, numVariations, axes, values); - - if ((loadedfontflags & FONT_FLAGS_COLORED) != 0) { - ATSURGBAlphaColor rgba; - rgba.red = ((rgbValue & 0xFF000000) >> 24) / 255.0; - rgba.green = ((rgbValue & 0x00FF0000) >> 16) / 255.0; - rgba.blue = ((rgbValue & 0x0000FF00) >> 8 ) / 255.0; - rgba.alpha = ((rgbValue & 0x000000FF) ) / 255.0; - tags[0] = kATSURGBAlphaColorTag; - sizes[0] = sizeof(ATSURGBAlphaColor); - attrs[0] = &rgba; - ATSUSetAttributes(style, 1, tags, sizes, attrs); - } - - if (tracking != 0x80000000) { - tags[0] = kATSUTrackingTag; - sizes[0] = sizeof(Fixed); - attrs[0] = &tracking; - ATSUSetAttributes(style, 1, tags, sizes, attrs); - } - - if (extend != 1.0 || slant != 0.0) { - CGAffineTransform t = { extend, slant, 0, 1.0, 0, 0 }; - tags[0] = kATSUFontMatrixTag; - sizes[0] = sizeof(CGAffineTransform); - attrs[0] = &t; - ATSUSetAttributes(style, 1, tags, sizes, attrs); - } - - if (embolden != 0.0) { - embolden = embolden * Fix2D(scaled_size) / 100.0; - tags[0] = kXeTeXEmboldenTag; - sizes[0] = sizeof(float); - attrs[0] = &embolden; - ATSUSetAttributes(style, 1, tags, sizes, attrs); - } - - if (letterspace != 0.0) - loadedfontletterspace = (letterspace / 100.0) * scaled_size; - - free((char*)featureTypes); - free((char*)selectorValues); - free((char*)axes); - free((char*)values); } + + 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); + } + + CGAffineTransform matrix = CGAffineTransformIdentity; + if (extend != 1.0 || slant != 0.0) + matrix = CGAffineTransformMake(extend, slant, 0, 1.0, 0, 0); + + if (embolden != 0.0) { + embolden = embolden * Fix2D(scaled_size) / 100.0; + CFNumberRef emboldenNumber = CFNumberCreate(NULL, kCFNumberFloatType, &embolden); + CFDictionaryAddValue(stringAttributes, kXeTeXEmboldenAttributeName, emboldenNumber); + CFRelease(emboldenNumber); } + if (letterspace != 0.0) + loadedfontletterspace = (letterspace / 100.0) * scaled_size; + + descriptor = CTFontDescriptorCreateWithAttributes(attributes); + CFRelease(attributes); + CTFontRef actualFont = CTFontCreateCopyWithAttributes(font, ctSize, &matrix, descriptor); + CFRelease(font); + CFDictionaryAddValue(stringAttributes, kCTFontAttributeName, actualFont); + CFRelease(actualFont); + nativefonttypeflag = AAT_FONT_FLAG; - return style; + return (void *) stringAttributes; } int @@ -1005,10 +749,6 @@ find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page) picFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*)pic_path, strlen(pic_path), false); if (picFileURL != NULL) { - /* get an FSRef for the URL we constructed */ - FSRef picFileRef; - CFURLGetFSRef(picFileURL, &picFileRef); - if (pdfBoxType > 0) { CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(picFileURL); if (document != NULL) { @@ -1077,22 +817,26 @@ find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page) } } else { - /* make an FSSpec for the file, and try to import it as a pic */ - FSSpec picFileSpec; - result = FSGetCatalogInfo(&picFileRef, kFSCatInfoNone, NULL, NULL, &picFileSpec, NULL); - if (result == noErr) { - ComponentInstance ci; - result = GetGraphicsImporterForFile(&picFileSpec, &ci); - if (result == noErr) { - ImageDescriptionHandle desc = NULL; - result = GraphicsImportGetImageDescription(ci, &desc); - bounds->x = 0; - bounds->y = 0; - bounds->wd = (*desc)->width * 72.27 / Fix2D((*desc)->hRes); - bounds->ht = (*desc)->height * 72.27 / Fix2D((*desc)->vRes); - DisposeHandle((Handle)desc); - (void)CloseComponent(ci); - } + 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); + int w = 0, h = 0, hRes = 72, vRes = 72; + CFNumberGetValue(imageWidth, kCFNumberIntType, &w); + CFNumberGetValue(imageHeight, kCFNumberIntType, &h); + CFNumberGetValue(DPIWidth, kCFNumberIntType, &hRes); + 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); } } |