~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtGui module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qfontengine_coretext_p.h"
 
43
 
 
44
#include <QtCore/qendian.h>
 
45
#include <QtCore/qsettings.h>
 
46
 
 
47
#include <private/qimage_p.h>
 
48
 
 
49
#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
 
50
 
 
51
QT_BEGIN_NAMESPACE
 
52
 
 
53
static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90);
 
54
 
 
55
static void loadAdvancesForGlyphs(CTFontRef ctfont,
 
56
                                  QVarLengthArray<CGGlyph> &cgGlyphs,
 
57
                                  QGlyphLayout *glyphs, int len,
 
58
                                  QFontEngine::ShaperFlags flags,
 
59
                                  const QFontDef &fontDef)
 
60
{
 
61
    Q_UNUSED(flags);
 
62
    QVarLengthArray<CGSize> advances(len);
 
63
    CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len);
 
64
 
 
65
    for (int i = 0; i < len; ++i) {
 
66
        if (glyphs->glyphs[i] & 0xff000000)
 
67
            continue;
 
68
        glyphs->advances_x[i] = QFixed::fromReal(advances[i].width);
 
69
        glyphs->advances_y[i] = QFixed::fromReal(advances[i].height);
 
70
    }
 
71
 
 
72
    if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
 
73
        for (int i = 0; i < len; ++i) {
 
74
            glyphs->advances_x[i] = glyphs->advances_x[i].round();
 
75
            glyphs->advances_y[i] = glyphs->advances_y[i].round();
 
76
        }
 
77
    }
 
78
}
 
79
 
 
80
 
 
81
int QCoreTextFontEngine::antialiasingThreshold = 0;
 
82
QFontEngineGlyphCache::Type QCoreTextFontEngine::defaultGlyphFormat = QFontEngineGlyphCache::Raster_RGBMask;
 
83
 
 
84
CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef)
 
85
{
 
86
    CGAffineTransform transform = CGAffineTransformIdentity;
 
87
    if (fontDef.stretch != 100)
 
88
        transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
 
89
    return transform;
 
90
}
 
91
 
 
92
QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def)
 
93
{
 
94
    fontDef = def;
 
95
    transform = qt_transform_from_fontdef(fontDef);
 
96
    ctfont = font;
 
97
    CFRetain(ctfont);
 
98
    cgFont = CTFontCopyGraphicsFont(font, NULL);
 
99
    init();
 
100
}
 
101
 
 
102
QCoreTextFontEngine::QCoreTextFontEngine(CGFontRef font, const QFontDef &def)
 
103
{
 
104
    fontDef = def;
 
105
    transform = qt_transform_from_fontdef(fontDef);
 
106
    cgFont = font;
 
107
    // Keep reference count balanced
 
108
    CFRetain(cgFont);
 
109
    ctfont = CTFontCreateWithGraphicsFont(font, fontDef.pixelSize, &transform, NULL);
 
110
    init();
 
111
}
 
112
 
 
113
QCoreTextFontEngine::~QCoreTextFontEngine()
 
114
{
 
115
    CFRelease(cgFont);
 
116
    CFRelease(ctfont);
 
117
}
 
118
 
 
119
static QFont::Weight weightFromInteger(int weight)
 
120
{
 
121
    if (weight < 400)
 
122
        return QFont::Light;
 
123
    else if (weight < 600)
 
124
        return QFont::Normal;
 
125
    else if (weight < 700)
 
126
        return QFont::DemiBold;
 
127
    else if (weight < 800)
 
128
        return QFont::Bold;
 
129
    else
 
130
        return QFont::Black;
 
131
}
 
132
 
 
133
int getTraitValue(CFDictionaryRef allTraits, CFStringRef trait)
 
134
{
 
135
    if (CFDictionaryContainsKey(allTraits, trait)) {
 
136
        CFNumberRef traitNum = (CFNumberRef) CFDictionaryGetValue(allTraits, trait);
 
137
        float v = 0;
 
138
        CFNumberGetValue(traitNum, kCFNumberFloatType, &v);
 
139
        // the value we get from CFNumberRef is from -1.0 to 1.0
 
140
        int value = v * 500 + 500;
 
141
        return value;
 
142
    }
 
143
 
 
144
    return 0;
 
145
}
 
146
 
 
147
void QCoreTextFontEngine::init()
 
148
{
 
149
    Q_ASSERT(ctfont != NULL);
 
150
    Q_ASSERT(cgFont != NULL);
 
151
 
 
152
    glyphFormat = defaultGlyphFormat;
 
153
 
 
154
    QCFString family = CTFontCopyFamilyName(ctfont);
 
155
    fontDef.family = family;
 
156
 
 
157
    QCFString styleName = (CFStringRef) CTFontCopyAttribute(ctfont, kCTFontStyleNameAttribute);
 
158
    fontDef.styleName = styleName;
 
159
 
 
160
    synthesisFlags = 0;
 
161
    CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont);
 
162
    if (traits & kCTFontItalicTrait)
 
163
        fontDef.style = QFont::StyleItalic;
 
164
 
 
165
    CFDictionaryRef allTraits = CTFontCopyTraits(ctfont);
 
166
    fontDef.weight = weightFromInteger(getTraitValue(allTraits, kCTFontWeightTrait));
 
167
    int slant = getTraitValue(allTraits, kCTFontSlantTrait);
 
168
    if (slant > 500 && !(traits & kCTFontItalicTrait))
 
169
        fontDef.style = QFont::StyleOblique;
 
170
    CFRelease(allTraits);
 
171
 
 
172
    if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait))
 
173
        synthesisFlags |= SynthesizedBold;
 
174
    // XXX: we probably don't need to synthesis italic for oblique font
 
175
    if (fontDef.style != QFont::StyleNormal && !(traits & kCTFontItalicTrait))
 
176
        synthesisFlags |= SynthesizedItalic;
 
177
 
 
178
    avgCharWidth = 0;
 
179
    QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
 
180
    unsigned emSize = CTFontGetUnitsPerEm(ctfont);
 
181
    if (os2Table.size() >= 10) {
 
182
        fsType = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 8));
 
183
        // qAbs is a workaround for weird fonts like Lucida Grande
 
184
        qint16 width = qAbs(qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 2)));
 
185
        avgCharWidth = QFixed::fromReal(width * fontDef.pixelSize / emSize);
 
186
    } else
 
187
        avgCharWidth = QFontEngine::averageCharWidth();
 
188
}
 
189
 
 
190
bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
 
191
                                       int *nglyphs, QFontEngine::ShaperFlags flags) const
 
192
{
 
193
    QCFType<CFStringRef> cfstring;
 
194
 
 
195
    QVarLengthArray<CGGlyph> cgGlyphs(len);
 
196
    CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len);
 
197
 
 
198
    int glyph_pos = 0;
 
199
    for (int i = 0; i < len; ++i) {
 
200
        if (cgGlyphs[i]) {
 
201
            glyphs->glyphs[glyph_pos] = cgGlyphs[i];
 
202
            if (glyph_pos < i)
 
203
                cgGlyphs[glyph_pos] = cgGlyphs[i];
 
204
        }
 
205
        glyph_pos++;
 
206
 
 
207
        // If it's a non-BMP char, skip the lower part of surrogate pair and go
 
208
        // directly to the next char without increasing glyph_pos
 
209
        if (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate())
 
210
            ++i;
 
211
    }
 
212
 
 
213
    *nglyphs = glyph_pos;
 
214
    glyphs->numGlyphs = glyph_pos;
 
215
 
 
216
    if (flags & GlyphIndicesOnly)
 
217
        return true;
 
218
 
 
219
    QVarLengthArray<CGSize> advances(glyph_pos);
 
220
    CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), glyph_pos);
 
221
 
 
222
    for (int i = 0; i < glyph_pos; ++i) {
 
223
        if (glyphs->glyphs[i] & 0xff000000)
 
224
            continue;
 
225
        glyphs->advances_x[i] = QFixed::fromReal(advances[i].width);
 
226
        glyphs->advances_y[i] = QFixed::fromReal(advances[i].height);
 
227
    }
 
228
 
 
229
    if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
 
230
        for (int i = 0; i < glyph_pos; ++i) {
 
231
            glyphs->advances_x[i] = glyphs->advances_x[i].round();
 
232
            glyphs->advances_y[i] = glyphs->advances_y[i].round();
 
233
        }
 
234
    }
 
235
    return true;
 
236
}
 
237
 
 
238
glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
 
239
{
 
240
    QFixed w;
 
241
    bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics;
 
242
 
 
243
    for (int i = 0; i < glyphs.numGlyphs; ++i) {
 
244
        w += round ? glyphs.effectiveAdvance(i).round()
 
245
                   : glyphs.effectiveAdvance(i);
 
246
    }
 
247
    return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0);
 
248
}
 
249
 
 
250
glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
 
251
{
 
252
    glyph_metrics_t ret;
 
253
    CGGlyph g = glyph;
 
254
    CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1);
 
255
    if (synthesisFlags & QFontEngine::SynthesizedItalic) {
 
256
        rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW;
 
257
    }
 
258
    ret.width = QFixed::fromReal(rect.size.width);
 
259
    ret.height = QFixed::fromReal(rect.size.height);
 
260
    ret.x = QFixed::fromReal(rect.origin.x);
 
261
    ret.y = -QFixed::fromReal(rect.origin.y) - ret.height;
 
262
    CGSize advances[1];
 
263
    CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
 
264
    ret.xoff = QFixed::fromReal(advances[0].width);
 
265
    ret.yoff = QFixed::fromReal(advances[0].height);
 
266
 
 
267
    if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
 
268
        ret.xoff = ret.xoff.round();
 
269
        ret.yoff = ret.yoff.round();
 
270
    }
 
271
 
 
272
    return ret;
 
273
}
 
274
 
 
275
QFixed QCoreTextFontEngine::ascent() const
 
276
{
 
277
    return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
 
278
            ? QFixed::fromReal(CTFontGetAscent(ctfont)).round()
 
279
            : QFixed::fromReal(CTFontGetAscent(ctfont));
 
280
}
 
281
QFixed QCoreTextFontEngine::descent() const
 
282
{
 
283
    QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont));
 
284
    if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
 
285
        d = d.round();
 
286
 
 
287
    return d;
 
288
}
 
289
QFixed QCoreTextFontEngine::leading() const
 
290
{
 
291
    return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
 
292
            ? QFixed::fromReal(CTFontGetLeading(ctfont)).round()
 
293
            : QFixed::fromReal(CTFontGetLeading(ctfont));
 
294
}
 
295
QFixed QCoreTextFontEngine::xHeight() const
 
296
{
 
297
    return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
 
298
            ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round()
 
299
            : QFixed::fromReal(CTFontGetXHeight(ctfont));
 
300
}
 
301
 
 
302
QFixed QCoreTextFontEngine::averageCharWidth() const
 
303
{
 
304
    return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
 
305
            ? avgCharWidth.round() : avgCharWidth;
 
306
}
 
307
 
 
308
qreal QCoreTextFontEngine::maxCharWidth() const
 
309
{
 
310
    return 0;
 
311
}
 
312
 
 
313
qreal QCoreTextFontEngine::minLeftBearing() const
 
314
{
 
315
    return 0;
 
316
}
 
317
 
 
318
qreal QCoreTextFontEngine::minRightBearing() const
 
319
{
 
320
    return 0;
 
321
}
 
322
 
 
323
void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
 
324
{
 
325
    QVarLengthArray<QFixedPoint> positions;
 
326
    QVarLengthArray<glyph_t> glyphs;
 
327
    QTransform matrix;
 
328
    matrix.translate(x, y);
 
329
    getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
 
330
    if (glyphs.size() == 0)
 
331
        return;
 
332
 
 
333
    CGContextSetFontSize(ctx, fontDef.pixelSize);
 
334
 
 
335
    CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
 
336
 
 
337
    CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
 
338
 
 
339
    CGAffineTransformConcat(cgMatrix, oldTextMatrix);
 
340
 
 
341
    if (synthesisFlags & QFontEngine::SynthesizedItalic)
 
342
        cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
 
343
 
 
344
    cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
 
345
 
 
346
    CGContextSetTextMatrix(ctx, cgMatrix);
 
347
 
 
348
    CGContextSetTextDrawingMode(ctx, kCGTextFill);
 
349
 
 
350
 
 
351
    QVarLengthArray<CGSize> advances(glyphs.size());
 
352
    QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size());
 
353
 
 
354
    for (int i = 0; i < glyphs.size() - 1; ++i) {
 
355
        advances[i].width = (positions[i + 1].x - positions[i].x).toReal();
 
356
        advances[i].height = (positions[i + 1].y - positions[i].y).toReal();
 
357
        cgGlyphs[i] = glyphs[i];
 
358
    }
 
359
    advances[glyphs.size() - 1].width = 0;
 
360
    advances[glyphs.size() - 1].height = 0;
 
361
    cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1];
 
362
 
 
363
    CGContextSetFont(ctx, cgFont);
 
364
    //NSLog(@"Font inDraw %@  ctfont %@", CGFontCopyFullName(cgFont), CTFontCopyFamilyName(ctfont));
 
365
 
 
366
    CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal());
 
367
 
 
368
    CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
 
369
 
 
370
    if (synthesisFlags & QFontEngine::SynthesizedBold) {
 
371
        CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(),
 
372
                                 positions[0].y.toReal());
 
373
 
 
374
        CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
 
375
    }
 
376
 
 
377
    CGContextSetTextMatrix(ctx, oldTextMatrix);
 
378
}
 
379
 
 
380
struct ConvertPathInfo
 
381
{
 
382
    ConvertPathInfo(QPainterPath *newPath, const QPointF &newPos) : path(newPath), pos(newPos) {}
 
383
    QPainterPath *path;
 
384
    QPointF pos;
 
385
};
 
386
 
 
387
static void convertCGPathToQPainterPath(void *info, const CGPathElement *element)
 
388
{
 
389
    ConvertPathInfo *myInfo = static_cast<ConvertPathInfo *>(info);
 
390
    switch(element->type) {
 
391
        case kCGPathElementMoveToPoint:
 
392
            myInfo->path->moveTo(element->points[0].x + myInfo->pos.x(),
 
393
                                 element->points[0].y + myInfo->pos.y());
 
394
            break;
 
395
        case kCGPathElementAddLineToPoint:
 
396
            myInfo->path->lineTo(element->points[0].x + myInfo->pos.x(),
 
397
                                 element->points[0].y + myInfo->pos.y());
 
398
            break;
 
399
        case kCGPathElementAddQuadCurveToPoint:
 
400
            myInfo->path->quadTo(element->points[0].x + myInfo->pos.x(),
 
401
                                 element->points[0].y + myInfo->pos.y(),
 
402
                                 element->points[1].x + myInfo->pos.x(),
 
403
                                 element->points[1].y + myInfo->pos.y());
 
404
            break;
 
405
        case kCGPathElementAddCurveToPoint:
 
406
            myInfo->path->cubicTo(element->points[0].x + myInfo->pos.x(),
 
407
                                  element->points[0].y + myInfo->pos.y(),
 
408
                                  element->points[1].x + myInfo->pos.x(),
 
409
                                  element->points[1].y + myInfo->pos.y(),
 
410
                                  element->points[2].x + myInfo->pos.x(),
 
411
                                  element->points[2].y + myInfo->pos.y());
 
412
            break;
 
413
        case kCGPathElementCloseSubpath:
 
414
            myInfo->path->closeSubpath();
 
415
            break;
 
416
        default:
 
417
            qDebug() << "Unhandled path transform type: " << element->type;
 
418
    }
 
419
 
 
420
}
 
421
 
 
422
void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs,
 
423
                                          QPainterPath *path, QTextItem::RenderFlags)
 
424
{
 
425
    CGAffineTransform cgMatrix = CGAffineTransformIdentity;
 
426
    cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1);
 
427
 
 
428
    if (synthesisFlags & QFontEngine::SynthesizedItalic)
 
429
        cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
 
430
 
 
431
    for (int i = 0; i < nGlyphs; ++i) {
 
432
        QCFType<CGPathRef> cgpath = CTFontCreatePathForGlyph(ctfont, glyphs[i], &cgMatrix);
 
433
        ConvertPathInfo info(path, positions[i].toPointF());
 
434
        CGPathApply(cgpath, &info, convertCGPathToQPainterPath);
 
435
    }
 
436
}
 
437
 
 
438
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &m)
 
439
{
 
440
    glyph_metrics_t br = boundingBox(glyph);
 
441
 
 
442
    if (m.isScaling()) {
 
443
        qreal hscale = m.m11();
 
444
        qreal vscale = m.m22();
 
445
        br.width  = QFixed::fromReal(br.width.toReal() * hscale);
 
446
        br.height = QFixed::fromReal(br.height.toReal() * vscale);
 
447
        br.x      = QFixed::fromReal(br.x.toReal() * hscale);
 
448
        br.y      = QFixed::fromReal(br.y.toReal() * vscale);
 
449
    }
 
450
 
 
451
    QImage im(qAbs(qRound(br.width))+2, qAbs(qRound(br.height))+2, QImage::Format_RGB32);
 
452
    im.fill(0);
 
453
 
 
454
#ifndef Q_OS_IOS
 
455
    CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
 
456
#else
 
457
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
 
458
#endif
 
459
    uint cgflags = kCGImageAlphaNoneSkipFirst;
 
460
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
 
461
    cgflags |= kCGBitmapByteOrder32Host;
 
462
#endif
 
463
    CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(),
 
464
                                             8, im.bytesPerLine(), colorspace,
 
465
                                             cgflags);
 
466
    CGContextSetFontSize(ctx, fontDef.pixelSize);
 
467
    CGContextSetShouldAntialias(ctx, (aa || fontDef.pointSize > antialiasingThreshold)
 
468
                                 && !(fontDef.styleStrategy & QFont::NoAntialias));
 
469
    CGContextSetShouldSmoothFonts(ctx, aa);
 
470
    CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
 
471
    CGAffineTransform cgMatrix = CGAffineTransformIdentity;
 
472
 
 
473
    CGAffineTransformConcat(cgMatrix, oldTextMatrix);
 
474
 
 
475
    if (synthesisFlags & QFontEngine::SynthesizedItalic)
 
476
        cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
 
477
 
 
478
    cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
 
479
    if (m.isScaling())
 
480
        cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMakeScale(m.m11(), m.m22()));
 
481
 
 
482
    CGContextSetTextMatrix(ctx, cgMatrix);
 
483
    CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
 
484
    CGContextSetTextDrawingMode(ctx, kCGTextFill);
 
485
 
 
486
    CGContextSetFont(ctx, cgFont);
 
487
 
 
488
    qreal pos_x = -br.x.truncate() + subPixelPosition.toReal();
 
489
    qreal pos_y = im.height() + br.y.toReal();
 
490
    CGContextSetTextPosition(ctx, pos_x, pos_y);
 
491
 
 
492
    CGSize advance;
 
493
    advance.width = 0;
 
494
    advance.height = 0;
 
495
    CGGlyph cgGlyph = glyph;
 
496
    CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
 
497
 
 
498
    if (synthesisFlags & QFontEngine::SynthesizedBold) {
 
499
        CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y);
 
500
        CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
 
501
    }
 
502
 
 
503
    CGContextRelease(ctx);
 
504
    CGColorSpaceRelease(colorspace);
 
505
 
 
506
    return im;
 
507
}
 
508
 
 
509
QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
 
510
{
 
511
    QImage im = imageForGlyph(glyph, subPixelPosition, false, QTransform());
 
512
 
 
513
    QImage indexed(im.width(), im.height(), QImage::Format_Indexed8);
 
514
    QVector<QRgb> colors(256);
 
515
    for (int i=0; i<256; ++i)
 
516
        colors[i] = qRgba(0, 0, 0, i);
 
517
    indexed.setColorTable(colors);
 
518
 
 
519
    for (int y=0; y<im.height(); ++y) {
 
520
        uint *src = (uint*) im.scanLine(y);
 
521
        uchar *dst = indexed.scanLine(y);
 
522
        for (int x=0; x<im.width(); ++x) {
 
523
            *dst = qGray(*src);
 
524
            ++dst;
 
525
            ++src;
 
526
        }
 
527
    }
 
528
 
 
529
    return indexed;
 
530
}
 
531
 
 
532
QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &x)
 
533
{
 
534
    if (x.type() > QTransform::TxScale)
 
535
        return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, x);
 
536
 
 
537
    QImage im = imageForGlyph(glyph, subPixelPosition, true, x);
 
538
    qGamma_correct_back_to_linear_cs(&im);
 
539
    return im;
 
540
}
 
541
 
 
542
void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const
 
543
{
 
544
    int i, numGlyphs = glyphs->numGlyphs;
 
545
    QVarLengthArray<CGGlyph> cgGlyphs(numGlyphs);
 
546
 
 
547
    for (i = 0; i < numGlyphs; ++i) {
 
548
        if (glyphs->glyphs[i] & 0xff000000)
 
549
            cgGlyphs[i] = 0;
 
550
        else
 
551
            cgGlyphs[i] = glyphs->glyphs[i];
 
552
    }
 
553
 
 
554
    loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, numGlyphs, flags, fontDef);
 
555
}
 
556
 
 
557
QFontEngine::FaceId QCoreTextFontEngine::faceId() const
 
558
{
 
559
    return QFontEngine::FaceId();
 
560
}
 
561
 
 
562
bool QCoreTextFontEngine::canRender(const QChar *string, int len)
 
563
{
 
564
    QVarLengthArray<CGGlyph> cgGlyphs(len);
 
565
    return CTFontGetGlyphsForCharacters(ctfont, (const UniChar *) string, cgGlyphs.data(), len);
 
566
}
 
567
 
 
568
bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const
 
569
{
 
570
    QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0);
 
571
    if (!table || !length)
 
572
        return false;
 
573
    CFIndex tableLength = CFDataGetLength(table);
 
574
    int availableLength = *length;
 
575
    *length = tableLength;
 
576
    if (buffer) {
 
577
        if (tableLength > availableLength)
 
578
            return false;
 
579
        CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer);
 
580
    }
 
581
    return true;
 
582
}
 
583
 
 
584
void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metrics_t *)
 
585
{
 
586
    // ###
 
587
}
 
588
 
 
589
QFixed QCoreTextFontEngine::emSquareSize() const
 
590
{
 
591
    return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
 
592
}
 
593
 
 
594
QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const
 
595
{
 
596
    QFontDef newFontDef = fontDef;
 
597
    newFontDef.pixelSize = pixelSize;
 
598
    newFontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi();
 
599
 
 
600
    return new QCoreTextFontEngine(cgFont, newFontDef);
 
601
}
 
602
 
 
603
bool QCoreTextFontEngine::supportsTransformations(const QTransform &transform) const
 
604
{
 
605
    return transform.type() > QTransform::TxTranslate;
 
606
}
 
607
 
 
608
QT_END_NAMESPACE
 
609
 
 
610
#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
 
611