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