18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Font.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "AffineTransform.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatConversion.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GlyphBuffer.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "IntRect.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SimpleFontData.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "UniscribeController.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebCoreTextRenderer.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <ApplicationServices/ApplicationServices.h>
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <WebKitSystemInterface/WebKitSystemInterface.h>
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/MathExtras.h>
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst int syntheticObliqueAngle = 14;
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline CGFloat toCGFloat(FIXED f)
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return f.value + f.fract / CGFloat(65536.0);
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic CGPathRef createPathForGlyph(HDC hdc, Glyph glyph)
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGMutablePathRef path = CGPathCreateMutable();
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    GLYPHMETRICS glyphMetrics;
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // GGO_NATIVE matches the outline perfectly when Windows font smoothing is off.
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // GGO_NATIVE | GGO_UNHINTED does not match perfectly either when Windows font smoothing is on or off.
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    DWORD outlineLength = GetGlyphOutline(hdc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE, &glyphMetrics, 0, 0, &identity);
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(outlineLength >= 0);
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (outlineLength < 0)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return path;
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<UInt8> outline(outlineLength);
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    GetGlyphOutline(hdc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE, &glyphMetrics, outlineLength, outline.data(), &identity);
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned offset = 0;
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (offset < outlineLength) {
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LPTTPOLYGONHEADER subpath = reinterpret_cast<LPTTPOLYGONHEADER>(outline.data() + offset);
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(subpath->dwType == TT_POLYGON_TYPE);
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (subpath->dwType != TT_POLYGON_TYPE)
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return path;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGPathMoveToPoint(path, 0, toCGFloat(subpath->pfxStart.x), toCGFloat(subpath->pfxStart.y));
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned subpathOffset = sizeof(*subpath);
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (subpathOffset < subpath->cb) {
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            LPTTPOLYCURVE segment = reinterpret_cast<LPTTPOLYCURVE>(reinterpret_cast<UInt8*>(subpath) + subpathOffset);
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            switch (segment->wType) {
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                case TT_PRIM_LINE:
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    for (unsigned i = 0; i < segment->cpfx; i++)
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGPathAddLineToPoint(path, 0, toCGFloat(segment->apfx[i].x), toCGFloat(segment->apfx[i].y));
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                case TT_PRIM_QSPLINE:
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    for (unsigned i = 0; i < segment->cpfx; i++) {
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat x = toCGFloat(segment->apfx[i].x);
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat y = toCGFloat(segment->apfx[i].y);
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat cpx;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat cpy;
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (i == segment->cpfx - 2) {
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            cpx = toCGFloat(segment->apfx[i + 1].x);
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            cpy = toCGFloat(segment->apfx[i + 1].y);
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            i++;
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        } else {
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            cpx = (toCGFloat(segment->apfx[i].x) + toCGFloat(segment->apfx[i + 1].x)) / 2;
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            cpy = (toCGFloat(segment->apfx[i].y) + toCGFloat(segment->apfx[i + 1].y)) / 2;
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGPathAddQuadCurveToPoint(path, 0, x, y, cpx, cpy);
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                case TT_PRIM_CSPLINE:
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    for (unsigned i = 0; i < segment->cpfx; i += 3) {
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat cp1x = toCGFloat(segment->apfx[i].x);
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat cp1y = toCGFloat(segment->apfx[i].y);
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat cp2x = toCGFloat(segment->apfx[i + 1].x);
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat cp2y = toCGFloat(segment->apfx[i + 1].y);
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat x = toCGFloat(segment->apfx[i + 2].x);
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGFloat y = toCGFloat(segment->apfx[i + 2].y);
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CGPathAddCurveToPoint(path, 0, cp1x, cp1y, cp2x, cp2y, x, y);
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                default:
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    ASSERT_NOT_REACHED();
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return path;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            subpathOffset += sizeof(*segment) + (segment->cpfx - 1) * sizeof(segment->apfx[0]);
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGPathCloseSubpath(path);
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        offset += subpath->cb;
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return path;
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                      int from, int numGlyphs, const FloatPoint& point)
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Color fillColor = graphicsContext->fillColor();
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool drawIntoBitmap = false;
136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    TextDrawingModeFlags drawingMode = graphicsContext->textDrawingMode();
137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (drawingMode == TextModeFill) {
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!fillColor.alpha())
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        drawIntoBitmap = fillColor.alpha() != 255 || graphicsContext->inTransparencyLayer();
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!drawIntoBitmap) {
1435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            FloatSize offset;
144545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            float blur;
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Color color;
146f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            ColorSpace shadowColorSpace;
147f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
148f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            graphicsContext->getShadow(offset, blur, color, shadowColorSpace);
1495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            drawIntoBitmap = offset.width() || offset.height() || blur;
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We have to convert CG's two-dimensional floating point advances to just horizontal integer advances.
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<int, 2048> gdiAdvances;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int totalWidth = 0;
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (int i = 0; i < numGlyphs; i++) {
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gdiAdvances.append(lroundf(glyphBuffer.advanceAt(from + i)));
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        totalWidth += gdiAdvances[i];
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HDC hdc = 0;
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    OwnPtr<GraphicsContext::WindowsBitmap> bitmap;
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntRect textRect;
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!drawIntoBitmap)
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        hdc = graphicsContext->getWindowsContext(textRect, true, false);
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!hdc) {
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        drawIntoBitmap = true;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We put slop into this rect, since glyphs can overflow the ascent/descent bounds and the left/right edges.
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // FIXME: Can get glyphs' optical bounds (even from CG) to get this right.
1702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        const FontMetrics& fontMetrics = font->fontMetrics();
1712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        int lineGap = fontMetrics.lineGap();
1722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        textRect = IntRect(point.x() - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
1732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                           point.y() - fontMetrics.ascent() - lineGap,
1742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                           totalWidth + fontMetrics.ascent() + fontMetrics.descent(),
1752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                           fontMetrics.lineSpacing());
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bitmap.set(graphicsContext->createWindowsBitmap(textRect.size()));
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        memset(bitmap->buffer(), 255, bitmap->bufferLength());
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        hdc = bitmap->hdc();
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        XFORM xform;
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM11 = 1.0f;
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM12 = 0.0f;
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM21 = 0.0f;
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM22 = 1.0f;
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eDx = -textRect.x();
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eDy = -textRect.y();
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SetWorldTransform(hdc, &xform);
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    SelectObject(hdc, font->platformData().hfont());
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Set the correct color.
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (drawIntoBitmap)
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SetTextColor(hdc, RGB(0, 0, 0));
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SetTextColor(hdc, RGB(fillColor.red(), fillColor.green(), fillColor.blue()));
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SetBkMode(hdc, TRANSPARENT);
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SetTextAlign(hdc, TA_LEFT | TA_BASELINE);
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Uniscribe gives us offsets to help refine the positioning of combining glyphs.
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatSize translation = glyphBuffer.offsetAt(from);
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (translation.width() || translation.height()) {
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        XFORM xform;
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM11 = 1.0;
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM12 = 0;
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM21 = 0;
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM22 = 1.0;
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eDx = translation.width();
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eDy = translation.height();
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
214f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (drawingMode == TextModeFill) {
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        XFORM xform;
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM11 = 1.0;
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM12 = 0;
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM21 = font->platformData().syntheticOblique() ? -tanf(syntheticObliqueAngle * piFloat / 180.0f) : 0;
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eM22 = 1.0;
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eDx = point.x();
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        xform.eDy = point.y();
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, reinterpret_cast<const WCHAR*>(glyphBuffer.glyphs(from)), numGlyphs, gdiAdvances.data());
2245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (font->syntheticBoldOffset()) {
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            xform.eM21 = 0;
2265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            xform.eDx = font->syntheticBoldOffset();
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            xform.eDy = 0;
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, reinterpret_cast<const WCHAR*>(glyphBuffer.glyphs(from)), numGlyphs, gdiAdvances.data());
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        XFORM xform;
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        GetWorldTransform(hdc, &xform);
2348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        AffineTransform hdcTransform(xform.eM11, xform.eM21, xform.eM12, xform.eM22, xform.eDx, xform.eDy);
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGAffineTransform initialGlyphTransform = hdcTransform.isInvertible() ? hdcTransform.inverse() : CGAffineTransformIdentity;
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (font->platformData().syntheticOblique())
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            initialGlyphTransform = CGAffineTransformConcat(initialGlyphTransform, CGAffineTransformMake(1, 0, tanf(syntheticObliqueAngle * piFloat / 180.0f), 1, 0, 0));
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        initialGlyphTransform.tx = 0;
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        initialGlyphTransform.ty = 0;
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextRef cgContext = graphicsContext->platformContext();
2418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextSaveGState(cgContext);
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        BOOL fontSmoothingEnabled = false;
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothingEnabled, 0);
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextSetShouldAntialias(cgContext, fontSmoothingEnabled);
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextScaleCTM(cgContext, 1.0, -1.0);
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextTranslateCTM(cgContext, point.x() + glyphBuffer.offsetAt(from).width(), -(point.y() + glyphBuffer.offsetAt(from).height()));
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        for (unsigned i = 0; i < numGlyphs; ++i) {
2528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            RetainPtr<CGPathRef> glyphPath(AdoptCF, createPathForGlyph(hdc, glyphBuffer.glyphAt(from + i)));
2538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            CGContextSaveGState(cgContext);
2548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            CGContextConcatCTM(cgContext, initialGlyphTransform);
2558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
256f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (drawingMode & TextModeFill) {
2578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                CGContextAddPath(cgContext, glyphPath.get());
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                CGContextFillPath(cgContext);
2595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                if (font->syntheticBoldOffset()) {
2605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                    CGContextTranslateCTM(cgContext, font->syntheticBoldOffset(), 0);
2618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    CGContextAddPath(cgContext, glyphPath.get());
2628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    CGContextFillPath(cgContext);
2635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                    CGContextTranslateCTM(cgContext, -font->syntheticBoldOffset(), 0);
2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                }
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (drawingMode & TextModeStroke) {
2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                CGContextAddPath(cgContext, glyphPath.get());
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                CGContextStrokePath(cgContext);
2695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                if (font->syntheticBoldOffset()) {
2705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                    CGContextTranslateCTM(cgContext, font->syntheticBoldOffset(), 0);
2718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    CGContextAddPath(cgContext, glyphPath.get());
2728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    CGContextStrokePath(cgContext);
2735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                    CGContextTranslateCTM(cgContext, -font->syntheticBoldOffset(), 0);
2748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                }
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            CGContextRestoreGState(cgContext);
2788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            CGContextTranslateCTM(cgContext, gdiAdvances[i], 0);
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextRestoreGState(cgContext);
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (drawIntoBitmap) {
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        UInt8* buffer = bitmap->buffer();
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned bufferLength = bitmap->bufferLength();
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (unsigned i = 0; i < bufferLength; i += 4) {
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Use green, which is always in the middle.
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            UInt8 alpha = (255 - buffer[i + 1]) * fillColor.alpha() / 255;
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            buffer[i] = fillColor.blue();
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            buffer[i + 1] = fillColor.green();
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            buffer[i + 2] = fillColor.red();
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            buffer[i + 3] = alpha;
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        graphicsContext->drawWindowsBitmap(bitmap.get(), textRect.location());
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        graphicsContext->releaseWindowsContext(hdc, textRect, true, false);
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                      int from, int numGlyphs, const FloatPoint& point) const
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextRef cgContext = graphicsContext->platformContext();
304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    bool shouldUseFontSmoothing = WebCoreShouldUseFontSmoothing();
305635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
306231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    switch(fontDescription().fontSmoothing()) {
307231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case Antialiased: {
308231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        graphicsContext->setShouldAntialias(true);
309231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        shouldUseFontSmoothing = false;
310231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        break;
311231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
312231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case SubpixelAntialiased: {
313231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        graphicsContext->setShouldAntialias(true);
314231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        shouldUseFontSmoothing = true;
315231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        break;
316231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
317231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case NoSmoothing: {
318231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        graphicsContext->setShouldAntialias(false);
319231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        shouldUseFontSmoothing = false;
320231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        break;
321231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
322231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case AutoSmoothing: {
323231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // For the AutoSmooth case, don't do anything! Keep the default settings.
324231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        break;
325231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
326231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    default:
327231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT_NOT_REACHED();
328231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
329231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
330dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (font->platformData().useGDI() && !shouldUseFontSmoothing) {
331dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
332dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
333635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
335635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext, shouldUseFontSmoothing);
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const FontPlatformData& platformData = font->platformData();
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextSetFont(cgContext, platformData.cgFont());
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGAffineTransform matrix = CGAffineTransformIdentity;
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    matrix.b = -matrix.b;
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    matrix.d = -matrix.d;
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (platformData.syntheticOblique()) {
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        static float skew = -tanf(syntheticObliqueAngle * piFloat / 180.0f);
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, skew, 1, 0, 0));
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextSetTextMatrix(cgContext, matrix);
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Uniscribe gives us offsets to help refine the positioning of combining glyphs.
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatSize translation = glyphBuffer.offsetAt(from);
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextSetFontSize(cgContext, platformData.size());
356635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    wkSetCGContextFontRenderingStyle(cgContext, font->isSystemFont(), false, font->platformData().useGDI());
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    FloatSize shadowOffset;
359545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    float shadowBlur;
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Color shadowColor;
361f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ColorSpace shadowColorSpace;
362f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
364f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool hasSimpleShadow = graphicsContext->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && (!graphicsContext->shadowsIgnoreTransforms() || graphicsContext->getCTM().isIdentityOrTranslationOrFlipped());
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hasSimpleShadow) {
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        graphicsContext->clearShadow();
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color fillColor = graphicsContext->fillColor();
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
370a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        graphicsContext->setFillColor(shadowFillColor, ColorSpaceDeviceRGB);
371f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        float shadowTextX = point.x() + translation.width() + shadowOffset.width();
372f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.
373f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        float shadowTextY = point.y() + translation.height() + shadowOffset.height() * (graphicsContext->shadowsIgnoreTransforms() ? -1 : 1);
374f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        CGContextSetTextPosition(cgContext, shadowTextX, shadowTextY);
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
3765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (font->syntheticBoldOffset()) {
3775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowOffset.height());
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
380a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        graphicsContext->setFillColor(fillColor, ColorSpaceDeviceRGB);
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height());
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
3855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (font->syntheticBoldOffset()) {
3865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        CGContextSetTextPosition(cgContext, point.x() + translation.width() + font->syntheticBoldOffset(), point.y() + translation.height());
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hasSimpleShadow)
391a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        graphicsContext->setShadow(shadowOffset, shadowBlur, shadowColor, ColorSpaceDeviceRGB);
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle);
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
397