summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/xetexdir/XeTeX_mac.c
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2013-02-19 00:32:39 +0000
committerKhaled Hosny <khaledhosny@eglug.org>2013-02-19 00:32:39 +0000
commitb9a5b9cad6d163192c3ab462fc86adc525a81e71 (patch)
tree11f84a8fdd80d31f9e49565a2e75a4e782146308 /Build/source/texk/web2c/xetexdir/XeTeX_mac.c
parente43ae240f33296136cb498e6d9d0e9a55eba7493 (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.c1238
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] = &vert;
- 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);
}
}