18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *           (C) 1999 Antti Koivisto (koivisto@kde.org)
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *           (C) 2000 Dirk Mueller (mueller@kde.org)
5dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc.
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "config.h"
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "Font.h"
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "GlyphBuffer.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "GraphicsContext.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "Logging.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "SimpleFontData.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebCoreSystemInterface.h"
318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#import <AppKit/AppKit.h>
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define SYNTHETIC_OBLIQUE_ANGLE 14
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef __LP64__
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define URefCon void*
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define URefCon UInt32
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool Font::canReturnFallbackFontsForComplexText()
465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return true;
485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
502fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool Font::canExpandAroundIdeographsInComplexText()
512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return true;
532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
552bde8e466a4451c7319e3a072d118917957d6554Steve Block// CTFontGetVerticalTranslationsForGlyphs is different on Snow Leopard.  It returns values for a font-size of 1
562bde8e466a4451c7319e3a072d118917957d6554Steve Block// without unitsPerEm applied.  We have to apply a transform that scales up to the point size and that also
572bde8e466a4451c7319e3a072d118917957d6554Steve Block// divides by unitsPerEm.
582bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic bool hasBrokenCTFontGetVerticalTranslationsForGlyphs()
59dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
602bde8e466a4451c7319e3a072d118917957d6554Steve Block// Chromium runs the same binary on both Leopard and Snow Leopard, so the check has to happen at runtime.
612bde8e466a4451c7319e3a072d118917957d6554Steve Block#if PLATFORM(CHROMIUM)
622bde8e466a4451c7319e3a072d118917957d6554Steve Block    static bool isCached = false;
632bde8e466a4451c7319e3a072d118917957d6554Steve Block    static bool result;
642bde8e466a4451c7319e3a072d118917957d6554Steve Block
652bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!isCached) {
662bde8e466a4451c7319e3a072d118917957d6554Steve Block        SInt32 majorVersion = 0;
672bde8e466a4451c7319e3a072d118917957d6554Steve Block        SInt32 minorVersion = 0;
682bde8e466a4451c7319e3a072d118917957d6554Steve Block        Gestalt(gestaltSystemVersionMajor, &majorVersion);
692bde8e466a4451c7319e3a072d118917957d6554Steve Block        Gestalt(gestaltSystemVersionMinor, &minorVersion);
702bde8e466a4451c7319e3a072d118917957d6554Steve Block        result = majorVersion == 10 && minorVersion == 6;
712bde8e466a4451c7319e3a072d118917957d6554Steve Block        isCached = true;
722bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
732bde8e466a4451c7319e3a072d118917957d6554Steve Block    return result;
742bde8e466a4451c7319e3a072d118917957d6554Steve Block#elif defined(BUILDING_ON_SNOW_LEOPARD)
752bde8e466a4451c7319e3a072d118917957d6554Steve Block    return true;
762bde8e466a4451c7319e3a072d118917957d6554Steve Block#else
772bde8e466a4451c7319e3a072d118917957d6554Steve Block    return false;
782bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif
792bde8e466a4451c7319e3a072d118917957d6554Steve Block}
802bde8e466a4451c7319e3a072d118917957d6554Steve Block
812bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic void showGlyphsWithAdvances(const FloatPoint& point, const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
822bde8e466a4451c7319e3a072d118917957d6554Steve Block{
832bde8e466a4451c7319e3a072d118917957d6554Steve Block    CGContextSetTextPosition(context, point.x(), point.y());
842bde8e466a4451c7319e3a072d118917957d6554Steve Block
85e14391e94c850b8bd03680c23b38978db68687a8John Reck    const FontPlatformData& platformData = font->platformData();
86e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!platformData.isColorBitmapFont()) {
87e14391e94c850b8bd03680c23b38978db68687a8John Reck        CGAffineTransform savedMatrix;
882bde8e466a4451c7319e3a072d118917957d6554Steve Block        bool isVertical = font->platformData().orientation() == Vertical;
89e14391e94c850b8bd03680c23b38978db68687a8John Reck        if (isVertical) {
90e14391e94c850b8bd03680c23b38978db68687a8John Reck            CGAffineTransform rotateLeftTransform = CGAffineTransformMake(0, -1, 1, 0, 0, 0);
91e14391e94c850b8bd03680c23b38978db68687a8John Reck            savedMatrix = CGContextGetTextMatrix(context);
92e14391e94c850b8bd03680c23b38978db68687a8John Reck            CGAffineTransform runMatrix = CGAffineTransformConcat(savedMatrix, rotateLeftTransform);
93e14391e94c850b8bd03680c23b38978db68687a8John Reck            CGContextSetTextMatrix(context, runMatrix);
942bde8e466a4451c7319e3a072d118917957d6554Steve Block
952bde8e466a4451c7319e3a072d118917957d6554Steve Block            CGAffineTransform translationsTransform;
962bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (hasBrokenCTFontGetVerticalTranslationsForGlyphs()) {
972bde8e466a4451c7319e3a072d118917957d6554Steve Block                translationsTransform = CGAffineTransformMake(platformData.m_size, 0, 0, platformData.m_size, 0, 0);
982bde8e466a4451c7319e3a072d118917957d6554Steve Block                translationsTransform = CGAffineTransformConcat(translationsTransform, rotateLeftTransform);
992bde8e466a4451c7319e3a072d118917957d6554Steve Block                CGFloat unitsPerEm = CGFontGetUnitsPerEm(platformData.cgFont());
1002bde8e466a4451c7319e3a072d118917957d6554Steve Block                translationsTransform = CGAffineTransformConcat(translationsTransform, CGAffineTransformMakeScale(1 / unitsPerEm, 1 / unitsPerEm));
1012bde8e466a4451c7319e3a072d118917957d6554Steve Block            } else {
1022bde8e466a4451c7319e3a072d118917957d6554Steve Block                translationsTransform = rotateLeftTransform;
1032bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
1042bde8e466a4451c7319e3a072d118917957d6554Steve Block            Vector<CGSize, 256> translations(count);
1052bde8e466a4451c7319e3a072d118917957d6554Steve Block            CTFontGetVerticalTranslationsForGlyphs(platformData.ctFont(), glyphs, translations.data(), count);
1062bde8e466a4451c7319e3a072d118917957d6554Steve Block
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block            CGAffineTransform transform = CGAffineTransformInvert(CGContextGetTextMatrix(context));
1082bde8e466a4451c7319e3a072d118917957d6554Steve Block
1092bde8e466a4451c7319e3a072d118917957d6554Steve Block            CGPoint position = FloatPoint(point.x(), point.y() + font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
1102bde8e466a4451c7319e3a072d118917957d6554Steve Block            Vector<CGPoint, 256> positions(count);
1112bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (size_t i = 0; i < count; ++i) {
1122bde8e466a4451c7319e3a072d118917957d6554Steve Block                CGSize translation = CGSizeApplyAffineTransform(translations[i], translationsTransform);
1132bde8e466a4451c7319e3a072d118917957d6554Steve Block                positions[i] = CGPointApplyAffineTransform(CGPointMake(position.x - translation.width, position.y + translation.height), transform);
1142bde8e466a4451c7319e3a072d118917957d6554Steve Block                position.x += advances[i].width;
1152bde8e466a4451c7319e3a072d118917957d6554Steve Block                position.y += advances[i].height;
1162bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
1172bde8e466a4451c7319e3a072d118917957d6554Steve Block            CGContextShowGlyphsAtPositions(context, glyphs, positions.data(), count);
118e14391e94c850b8bd03680c23b38978db68687a8John Reck            CGContextSetTextMatrix(context, savedMatrix);
1192bde8e466a4451c7319e3a072d118917957d6554Steve Block        } else
1202bde8e466a4451c7319e3a072d118917957d6554Steve Block            CGContextShowGlyphsWithAdvances(context, glyphs, advances, count);
121e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else {
124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!count)
125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        Vector<CGPoint, 256> positions(count);
128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        CGAffineTransform matrix = CGAffineTransformInvert(CGContextGetTextMatrix(context));
129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        positions[0] = CGPointZero;
130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        for (size_t i = 1; i < count; ++i) {
131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            CGSize advance = CGSizeApplyAffineTransform(advances[i - 1], matrix);
132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            positions[i].x = positions[i - 1].x + advance.width;
133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            positions[i].y = positions[i - 1].y + advance.height;
134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
135e14391e94c850b8bd03680c23b38978db68687a8John Reck        CTFontDrawGlyphs(platformData.ctFont(), glyphs, positions.data(), count, context);
136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif
138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextRef cgContext = context->platformContext();
143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
144f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool shouldSmoothFonts = true;
145f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool changeFontSmoothing = false;
146f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    switch(fontDescription().fontSmoothing()) {
148231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case Antialiased: {
149231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        context->setShouldAntialias(true);
150f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        shouldSmoothFonts = false;
151f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        changeFontSmoothing = true;
152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        break;
153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case SubpixelAntialiased: {
155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        context->setShouldAntialias(true);
156f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        shouldSmoothFonts = true;
157f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        changeFontSmoothing = true;
158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        break;
159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case NoSmoothing: {
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        context->setShouldAntialias(false);
162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        shouldSmoothFonts = false;
163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        changeFontSmoothing = true;
164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        break;
165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case AutoSmoothing: {
167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // For the AutoSmooth case, don't do anything! Keep the default settings.
168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        break;
169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    default:
171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT_NOT_REACHED();
172231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
174f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!shouldUseSmoothing()) {
175f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        shouldSmoothFonts = false;
176f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        changeFontSmoothing = true;
177f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
178f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
179f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool originalShouldUseFontSmoothing = false;
180f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (changeFontSmoothing) {
181f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
182f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        CGContextSetShouldSmoothFonts(cgContext, shouldSmoothFonts);
183f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
184f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const FontPlatformData& platformData = font->platformData();
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSFont* drawFont;
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!isPrinterFont()) {
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        drawFont = [platformData.font() screenFont];
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (drawFont != platformData.font())
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We are getting this in too many places (3406411); use ERROR so it only prints on debug versions for now. (We should debug this also, eventually).
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            LOG_ERROR("Attempting to set non-screen font (%@) when drawing to screen.  Using screen font anyway, may result in incorrect metrics.",
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                [[[platformData.font() fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]);
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        drawFont = [platformData.font() printerFont];
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (drawFont != platformData.font())
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            NSLog(@"Attempting to set non-printer font (%@) when printing.  Using printer font anyway, may result in incorrect metrics.",
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                [[[platformData.font() fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]);
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextSetFont(cgContext, platformData.cgFont());
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGAffineTransform matrix = CGAffineTransformIdentity;
203dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (drawFont && !platformData.isColorBitmapFont())
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        memcpy(&matrix, [drawFont matrix], sizeof(matrix));
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    matrix.b = -matrix.b;
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    matrix.d = -matrix.d;
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (platformData.m_syntheticOblique)
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextSetTextMatrix(cgContext, matrix);
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (drawFont) {
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        wkSetCGFontRenderingMode(cgContext, drawFont);
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextSetFontSize(cgContext, 1.0f);
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextSetFontSize(cgContext, platformData.m_size);
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    FloatSize shadowOffset;
219545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    float shadowBlur;
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Color shadowColor;
221f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ColorSpace shadowColorSpace;
222643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ColorSpace fillColorSpace = context->fillColorSpace();
223f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
225f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool hasSimpleShadow = context->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont() && (!context->shadowsIgnoreTransforms() || context->getCTM().isIdentityOrTranslationOrFlipped());
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hasSimpleShadow) {
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        context->clearShadow();
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color fillColor = context->fillColor();
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
231f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        context->setFillColor(shadowFillColor, shadowColorSpace);
232f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        float shadowTextX = point.x() + shadowOffset.width();
233f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.
234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        float shadowTextY = point.y() + shadowOffset.height() * (context->shadowsIgnoreTransforms() ? -1 : 1);
2352bde8e466a4451c7319e3a072d118917957d6554Steve Block        showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
2362bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (font->syntheticBoldOffset())
2372bde8e466a4451c7319e3a072d118917957d6554Steve Block            showGlyphsWithAdvances(FloatPoint(shadowTextX + font->syntheticBoldOffset(), shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
238643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        context->setFillColor(fillColor, fillColorSpace);
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2412bde8e466a4451c7319e3a072d118917957d6554Steve Block    showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
2422bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (font->syntheticBoldOffset())
2432bde8e466a4451c7319e3a072d118917957d6554Steve Block        showGlyphsWithAdvances(FloatPoint(point.x() + font->syntheticBoldOffset(), point.y()), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hasSimpleShadow)
246f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
248f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (changeFontSmoothing)
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing);
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
253