1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/*
2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2006, 2007 Apple Computer, Inc.
3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
4635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Redistribution and use in source and binary forms, with or without
6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modification, are permitted provided that the following conditions are
7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * met:
8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Redistributions of source code must retain the above copyright
10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * notice, this list of conditions and the following disclaimer.
11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Redistributions in binary form must reproduce the above
12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * copyright notice, this list of conditions and the following disclaimer
13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * in the documentation and/or other materials provided with the
14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * distribution.
15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Neither the name of Google Inc. nor the names of its
16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * contributors may be used to endorse or promote products derived from
17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * this software without specific prior written permission.
18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */
31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "config.h"
33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Font.h"
34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "FontFallbackList.h"
36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "GlyphBuffer.h"
37f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "NotImplemented.h"
38ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "PlatformBridge.h"
39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "PlatformContextSkia.h"
40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "SimpleFontData.h"
41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "SkiaFontWin.h"
42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "SkiaUtils.h"
438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "TransparencyWin.h"
44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "UniscribeHelperTextRun.h"
45635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "skia/ext/platform_canvas.h"
47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "skia/ext/skia_utils_win.h"  // FIXME: remove this dependency.
48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <windows.h>
50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WebCore {
52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiannamespace {
548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool canvasHasMultipleLayers(const SkCanvas* canvas)
568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    iter.next();  // There is always at least one layer.
598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return !iter.done();  // There is > 1 layer if the the iterator can stil advance.
608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianclass TransparencyAwareFontPainter {
638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianpublic:
648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransparencyAwareFontPainter(GraphicsContext*, const FloatPoint&);
658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ~TransparencyAwareFontPainter();
668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianprotected:
688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Called by our subclass' constructor to initialize GDI if necessary. This
698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // is a separate function so it can be called after the subclass finishes
708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // construction (it calls virtual functions).
718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void init();
728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual IntRect estimateTextBounds() = 0;
748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Use the context from the transparency helper when drawing with GDI. It
768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // may point to a temporary one.
778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    GraphicsContext* m_graphicsContext;
788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    PlatformGraphicsContext* m_platformContext;
798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FloatPoint m_point;
818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Set when Windows can handle the type of drawing we're doing.
838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool m_useGDI;
848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // These members are valid only when m_useGDI is set.
868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    HDC m_hdc;
878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransparencyWin m_transparency;
888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianprivate:
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Call when we're using GDI mode to initialize the TransparencyWin to help
918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // us draw GDI text.
928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void initializeForGDI();
938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool m_createdTransparencyLayer;  // We created a layer to give the font some alpha.
958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian};
968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransparencyAwareFontPainter::TransparencyAwareFontPainter(GraphicsContext* context,
988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                                           const FloatPoint& point)
998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    : m_graphicsContext(context)
1008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_platformContext(context->platformContext())
1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_point(point)
1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_useGDI(windowsCanHandleTextDrawing(context))
1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_hdc(0)
1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_createdTransparencyLayer(false)
1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransparencyAwareFontPainter::init()
109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_useGDI)
1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        initializeForGDI();
112635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransparencyAwareFontPainter::initializeForGDI()
115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
116643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_graphicsContext->save();
1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    SkColor color = m_platformContext->effectiveFillColor();
118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Used only when m_createdTransparencyLayer is true.
119643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    float layerAlpha = 0.0f;
1208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (SkColorGetA(color) != 0xFF) {
1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // When the font has some transparency, apply it by creating a new
122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // transparency layer with that opacity applied. We'll actually create
123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // a new transparency layer after we calculate the bounding box.
1248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_createdTransparencyLayer = true;
125643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        layerAlpha = SkColorGetA(color) / 255.0f;
1268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // The color should be opaque now.
1278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
128635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransparencyWin::LayerMode layerMode;
1318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    IntRect layerRect;
1328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_platformContext->isDrawingToImageBuffer()) {
1338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // Assume if we're drawing to an image buffer that the background
1348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // is not opaque and we have to undo ClearType. We may want to
1358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // enhance this to actually check, since it will often be opaque
1368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // and we could do ClearType in that case.
1378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        layerMode = TransparencyWin::TextComposite;
1388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        layerRect = estimateTextBounds();
139643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        m_graphicsContext->clip(layerRect);
140643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (m_createdTransparencyLayer)
141643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            m_graphicsContext->beginTransparencyLayer(layerAlpha);
1428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // The transparency helper requires that we draw text in black in
1448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // this mode and it will apply the color.
1458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_transparency.setTextCompositeColor(color);
1468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        color = SkColorSetRGB(0, 0, 0);
147643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    } else if (m_createdTransparencyLayer || canvasHasMultipleLayers(m_platformContext->canvas())) {
1488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // When we're drawing a web page, we know the background is opaque,
1498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // but if we're drawing to a layer, we still need extra work.
1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        layerMode = TransparencyWin::OpaqueCompositeLayer;
1518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        layerRect = estimateTextBounds();
152643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        m_graphicsContext->clip(layerRect);
153643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (m_createdTransparencyLayer)
154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            m_graphicsContext->beginTransparencyLayer(layerAlpha);
1558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
1568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // Common case of drawing onto the bottom layer of a web page: we
1578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // know everything is opaque so don't need to do anything special.
1588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        layerMode = TransparencyWin::NoLayer;
1598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Bug 26088 - init() might fail if layerRect is invalid. Given this, we
1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // need to be careful to check for null pointers everywhere after this call
1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_transparency.init(m_graphicsContext, layerMode,
1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                        TransparencyWin::KeepTransform, layerRect);
165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Set up the DC, using the one from the transparency helper.
1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_transparency.platformContext()) {
1682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_hdc = skia::BeginPlatformPaint(m_transparency.platformContext()->canvas());
1690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        SetTextColor(m_hdc, skia::SkColorToCOLORREF(color));
1700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        SetBkMode(m_hdc, TRANSPARENT);
1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
173635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransparencyAwareFontPainter::~TransparencyAwareFontPainter()
175635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_useGDI || !m_graphicsContext || !m_platformContext)
1778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;  // Nothing to do.
1788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_transparency.composite();
1798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_createdTransparencyLayer)
1808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_graphicsContext->endTransparencyLayer();
181643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_graphicsContext->restore();
1822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    skia::EndPlatformPaint(m_platformContext->canvas());
1838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Specialization for simple GlyphBuffer painting.
1868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianclass TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter {
1878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian public:
1888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransparencyAwareGlyphPainter(GraphicsContext*,
1898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                  const SimpleFontData*,
1908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                  const GlyphBuffer&,
1918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                  int from, int numGlyphs,
1928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                  const FloatPoint&);
1938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ~TransparencyAwareGlyphPainter();
1948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Draws the partial string of glyphs, starting at |startAdvance| to the
1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // left of m_point. We express it this way so that if we're using the Skia
1978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // drawing path we can use floating-point positioning, even though we have
1988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // to use integer positioning in the GDI path.
1992bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, float startAdvance) const;
2008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian private:
2028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual IntRect estimateTextBounds();
2038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const SimpleFontData* m_font;
2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const GlyphBuffer& m_glyphBuffer;
2068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int m_from;
2078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int m_numGlyphs;
2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // When m_useGdi is set, this stores the previous HFONT selected into the
2108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // m_hdc so we can restore it.
2118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    HGDIOBJ m_oldFont;  // For restoring the DC to its original state.
2128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian};
2138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransparencyAwareGlyphPainter::TransparencyAwareGlyphPainter(
2158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    GraphicsContext* context,
2168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const SimpleFontData* font,
2178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const GlyphBuffer& glyphBuffer,
2188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int from, int numGlyphs,
2198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const FloatPoint& point)
2208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    : TransparencyAwareFontPainter(context, point)
2218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_font(font)
2228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_glyphBuffer(glyphBuffer)
2238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_from(from)
2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_numGlyphs(numGlyphs)
2258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_oldFont(0)
2268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    init();
2288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_hdc)
2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_oldFont = ::SelectObject(m_hdc, m_font->platformData().hfont());
2318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
232635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransparencyAwareGlyphPainter::~TransparencyAwareGlyphPainter()
2348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_useGDI && m_hdc)
2368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ::SelectObject(m_hdc, m_oldFont);
2378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Estimates the bounding box of the given text. This is copied from
2418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// FontCGWin.cpp, it is possible, but a lot more work, to get the precide
2428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// bounds.
2438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianIntRect TransparencyAwareGlyphPainter::estimateTextBounds()
2448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int totalWidth = 0;
2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    for (int i = 0; i < m_numGlyphs; i++)
2478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        totalWidth += lroundf(m_glyphBuffer.advanceAt(m_from + i));
2488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const FontMetrics& fontMetrics = m_font->fontMetrics();
2502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return IntRect(m_point.x() - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
2512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                   m_point.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
2522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                   totalWidth + fontMetrics.ascent() + fontMetrics.descent(),
2532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                   fontMetrics.lineSpacing());
2548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
2578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                               const WORD* glyphs,
2588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                               const int* advances,
2592bde8e466a4451c7319e3a072d118917957d6554Steve Block                                               float startAdvance) const
2608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!m_useGDI) {
2628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        SkPoint origin = m_point;
2632bde8e466a4451c7319e3a072d118917957d6554Steve Block        origin.fX += SkFloatToScalar(startAdvance);
2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return paintSkiaText(m_graphicsContext, m_font->platformData().hfont(),
2658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                             numGlyphs, glyphs, advances, 0, &origin);
266635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_graphicsContext || !m_hdc)
2690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Windows' origin is the top-left of the bounding box, so we have
2728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // to subtract off the font ascent to get it.
2738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int x = lroundf(m_point.x() + startAdvance);
2742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int y = lroundf(m_point.y() - m_font->fontMetrics().ascent());
2755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If there is a non-blur shadow and both the fill color and shadow color
2775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // are opaque, handle without skia.
2785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    FloatSize shadowOffset;
279545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    float shadowBlur;
2805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Color shadowColor;
281f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ColorSpace shadowColorSpace;
282f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace)) {
2835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow()
2845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // will have already returned true during the ctor initiatization of m_useGDI
2855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(shadowColor.alpha() == 255);
2865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(m_graphicsContext->fillColor().alpha() == 255);
2875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(shadowBlur == 0);
2885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
2895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        COLORREF savedTextColor = GetTextColor(m_hdc);
2905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        SetTextColor(m_hdc, textColor);
2915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        ExtTextOut(m_hdc, x + shadowOffset.width(), y + shadowOffset.height(), ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
2920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        SetTextColor(m_hdc, savedTextColor);
2935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return !!ExtTextOut(m_hdc, x, y, ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
2968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianclass TransparencyAwareUniscribePainter : public TransparencyAwareFontPainter {
2998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian public:
3008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransparencyAwareUniscribePainter(GraphicsContext*,
3018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                      const Font*,
3028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                      const TextRun&,
3038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                      int from, int to,
3048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                      const FloatPoint&);
3058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ~TransparencyAwareUniscribePainter();
3068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Uniscibe will draw directly into our buffer, so we need to expose our DC.
3088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    HDC hdc() const { return m_hdc; }
3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian private:
3118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual IntRect estimateTextBounds();
3128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const Font* m_font;
3148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const TextRun& m_run;
3158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int m_from;
3168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int m_to;
3178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian};
3188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter(
3208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    GraphicsContext* context,
3218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const Font* font,
3228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const TextRun& run,
3238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int from, int to,
3248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const FloatPoint& point)
3258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    : TransparencyAwareFontPainter(context, point)
3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_font(font)
3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_run(run)
3288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_from(from)
3298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_to(to)
3308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
3318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    init();
332635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
333635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter()
3358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
3368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
3378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianIntRect TransparencyAwareUniscribePainter::estimateTextBounds()
3398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
3408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // This case really really sucks. There is no convenient way to estimate
3418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // the bounding box. So we run Uniscribe twice. If we find this happens a
3428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // lot, the way to fix it is to make the extra layer after the
3438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // UniscribeHelper has measured the text.
3448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    IntPoint intPoint(lroundf(m_point.x()),
3458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                      lroundf(m_point.y()));
3468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    UniscribeHelperTextRun state(m_run, *m_font);
3488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int left = lroundf(m_point.x()) + state.characterToX(m_from);
3498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int right = lroundf(m_point.x()) + state.characterToX(m_to);
3505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Adjust for RTL script since we just want to know the text bounds.
3525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (left > right)
3535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        std::swap(left, right);
3548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // This algorithm for estimating how much extra space we need (the text may
3568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // go outside the selection rect) is based roughly on
3578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // TransparencyAwareGlyphPainter::estimateTextBounds above.
3582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const FontMetrics& fontMetrics = m_font->fontMetrics();
3592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return IntRect(left - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
3602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                   m_point.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
3612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                   (right - left) + fontMetrics.ascent() + fontMetrics.descent(),
3622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                   fontMetrics.lineSpacing());
3638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
3648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}  // namespace
3668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool Font::canReturnFallbackFontsForComplexText()
3685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
3695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return false;
3705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
3715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3722fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool Font::canExpandAroundIdeographsInComplexText()
3732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return false;
3752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void drawGlyphsWin(GraphicsContext* graphicsContext,
3782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                          const SimpleFontData* font,
3792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                          const GlyphBuffer& glyphBuffer,
3802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                          int from,
3812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                          int numGlyphs,
3822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                          const FloatPoint& point) {
3835abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    graphicsContext->platformContext()->prepareForSoftwareDraw();
3845abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
3858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransparencyAwareGlyphPainter painter(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
386635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
387635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // We draw the glyphs in chunks to avoid having to do a heap allocation for
388635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // the arrays of characters and advances. Since ExtTextOut is the
389635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // lowest-level text output function on Windows, there should be little
390635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // penalty for splitting up the text. On the other hand, the buffer cannot
391635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // be bigger than 4094 or the function will fail.
3928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const int kMaxBufferLength = 256;
3938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Vector<WORD, kMaxBufferLength> glyphs;
3948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Vector<int, kMaxBufferLength> advances;
3958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int glyphIndex = 0;  // The starting glyph of the current chunk.
3962bde8e466a4451c7319e3a072d118917957d6554Steve Block
3972bde8e466a4451c7319e3a072d118917957d6554Steve Block    // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position
3982bde8e466a4451c7319e3a072d118917957d6554Steve Block    // of each glyph in floating point units and rounds to integer advances at the last possible moment.
3992bde8e466a4451c7319e3a072d118917957d6554Steve Block
4002bde8e466a4451c7319e3a072d118917957d6554Steve Block    float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.
4012bde8e466a4451c7319e3a072d118917957d6554Steve Block    int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered.
402635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    while (glyphIndex < numGlyphs) {
4038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // How many chars will be in this chunk?
404635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
405635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        glyphs.resize(curLen);
406635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        advances.resize(curLen);
407635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
4082bde8e466a4451c7319e3a072d118917957d6554Steve Block        float currentWidth = 0;
409635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        for (int i = 0; i < curLen; ++i, ++glyphIndex) {
410635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
4112bde8e466a4451c7319e3a072d118917957d6554Steve Block            horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex);
4122bde8e466a4451c7319e3a072d118917957d6554Steve Block            advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded;
4132bde8e466a4451c7319e3a072d118917957d6554Steve Block            lastHorizontalOffsetRounded += advances[i];
4142bde8e466a4451c7319e3a072d118917957d6554Steve Block            currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
4150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // Bug 26088 - very large positive or negative runs can fail to
4170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // render so we clamp the size here. In the specs, negative
4180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // letter-spacing is implementation-defined, so this should be
4190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // fine, and it matches Safari's implementation. The call actually
4200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // seems to crash if kMaxNegativeRun is set to somewhere around
4210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // -32830, so we give ourselves a little breathing room.
4220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            const int maxNegativeRun = -32768;
4230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            const int maxPositiveRun =  32768;
4242bde8e466a4451c7319e3a072d118917957d6554Steve Block            if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun))
4250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                advances[i] = 0;
426635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
427635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
4288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // Actually draw the glyphs (with retry on failure).
429635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool success = false;
430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        for (int executions = 0; executions < 2; ++executions) {
4312bde8e466a4451c7319e3a072d118917957d6554Steve Block            success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], horizontalOffset - point.x() - currentWidth);
432635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (!success && executions == 0) {
433635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                // Ask the browser to load the font for us and retry.
434ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                PlatformBridge::ensureFontLoaded(font->platformData().hfont());
435635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                continue;
436635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            }
437635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            break;
438635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
439635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
4400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!success)
4410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            LOG_ERROR("Unable to draw the glyphs after second attempt");
442635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
443635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
444635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
4452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid Font::drawGlyphs(GraphicsContext* graphicsContext,
4462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                      const SimpleFontData* font,
4472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                      const GlyphBuffer& glyphBuffer,
4482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                      int from,
4492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                      int numGlyphs,
4502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                      const FloatPoint& point) const
4512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    SkColor color = graphicsContext->platformContext()->effectiveFillColor();
4532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned char alpha = SkColorGetA(color);
4542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Skip 100% transparent text; no need to draw anything.
4552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke && !graphicsContext->hasShadow())
4562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
45754cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block
4582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
4592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
461635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectFloatRect Font::selectionRectForComplexText(const TextRun& run,
46206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                                            const FloatPoint& point,
463635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                            int h,
464635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                            int from,
465635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                            int to) const
466635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
467635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UniscribeHelperTextRun state(run, *this);
468635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    float left = static_cast<float>(point.x() + state.characterToX(from));
469635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    float right = static_cast<float>(point.x() + state.characterToX(to));
470635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
471635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // If the text is RTL, left will actually be after right.
472635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (left < right)
47306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return FloatRect(left, point.y(),
474635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                       right - left, static_cast<float>(h));
475635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
47606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    return FloatRect(right, point.y(),
477635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                     left - right, static_cast<float>(h));
478635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
479635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
480635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid Font::drawComplexText(GraphicsContext* graphicsContext,
481635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                           const TextRun& run,
482635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                           const FloatPoint& point,
483635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                           int from,
484635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                           int to) const
485635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
486635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    PlatformGraphicsContext* context = graphicsContext->platformContext();
487635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UniscribeHelperTextRun state(run, *this);
488635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
4898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    SkColor color = graphicsContext->platformContext()->effectiveFillColor();
490635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    unsigned char alpha = SkColorGetA(color);
491635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Skip 100% transparent text; no need to draw anything.
4928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke)
493635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
494635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
4958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransparencyAwareUniscribePainter painter(graphicsContext, this, run, from, to, point);
4968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    HDC hdc = painter.hdc();
498231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (windowsCanHandleTextDrawing(graphicsContext) && !hdc)
4990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
500635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
501635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
502635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Enforce non-transparent color.
503635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
504231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (hdc) {
505231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        SetTextColor(hdc, skia::SkColorToCOLORREF(color));
506231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        SetBkMode(hdc, TRANSPARENT);
507231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
508635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
5095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If there is a non-blur shadow and both the fill color and shadow color
5105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // are opaque, handle without skia.
5115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    FloatSize shadowOffset;
512545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    float shadowBlur;
5135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Color shadowColor;
514f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ColorSpace shadowColorSpace;
515f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace) && windowsCanHandleDrawTextShadow(graphicsContext)) {
5165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
5175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        COLORREF savedTextColor = GetTextColor(hdc);
5185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        SetTextColor(hdc, textColor);
5195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowOffset.width(),
5202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                   static_cast<int>(point.y() - fontMetrics().ascent()) + shadowOffset.height(), from, to);
5215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        SetTextColor(hdc, savedTextColor);
5225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
5235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
524635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Uniscribe counts the coordinates from the upper left, while WebKit uses
525635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // the baseline, so we have to subtract off the ascent.
5262bde8e466a4451c7319e3a072d118917957d6554Steve Block    state.draw(graphicsContext, hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), from, to);
5278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    skia::EndPlatformPaint(context->canvas());
529635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
530635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
531f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
532f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
533f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    notImplemented();
534f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
535f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
536dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfloat Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
537635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
538635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UniscribeHelperTextRun state(run, *this);
539635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return static_cast<float>(state.width());
540635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
541635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
54206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenint Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
543635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                          bool includePartialGlyphs) const
544635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
54506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
54606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
54706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    int x = static_cast<int>(xFloat);
54806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
549635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Mac code ignores includePartialGlyphs, and they don't know what it's
550635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // supposed to do, so we just ignore it as well.
551635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UniscribeHelperTextRun state(run, *this);
552635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    int charIndex = state.xToCharacter(x);
553635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
554635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // XToCharacter will return -1 if the position is before the first
555635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // character (we get called like this sometimes).
556635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (charIndex < 0)
557635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        charIndex = 0;
558635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return charIndex;
559635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
560635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
561635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} // namespace WebCore
562