18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Eric Seidel <eric@webkit.org> 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define _USE_MATH_DEFINES 1 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 29a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "GraphicsContextCG.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 315e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block#include "AffineTransform.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatConversion.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContextPlatformPrivateCG.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ImageBuffer.h" 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "KURL.h" 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Path.h" 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Pattern.h" 382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "ShadowBlur.h" 39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 40cad810f21b803229eb11403f9209855525a25d57Steve Block#include <CoreGraphics/CoreGraphics.h> 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/MathExtras.h> 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/OwnArrayPtr.h> 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/RetainPtr.h> 44f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <wtf/UnusedParam.h> 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 46d0825bca7fe65beaee391d30da42e937db621564Steve Block#if PLATFORM(MAC) || PLATFORM(CHROMIUM) 47d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "WebCoreSystemInterface.h" 48d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 49d0825bca7fe65beaee391d30da42e937db621564Steve Block 50d0825bca7fe65beaee391d30da42e937db621564Steve Block#if PLATFORM(WIN) 51d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <WebKitSystemInterface/WebKitSystemInterface.h> 52d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 53d0825bca7fe65beaee391d30da42e937db621564Steve Block 54d0825bca7fe65beaee391d30da42e937db621564Steve Block#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) 55643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Building on 10.6 or later: kCGInterpolationMedium is defined in the CGInterpolationQuality enum. 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define HAVE_CG_INTERPOLATION_MEDIUM 1 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if !defined(TARGETING_TIGER) && !defined(TARGETING_LEOPARD) 62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Targeting 10.6 or later: use kCGInterpolationMedium. 63643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define WTF_USE_CG_INTERPOLATION_MEDIUM 1 64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif 65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif 67643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 6881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch// Undocumented CGContextSetCTM function, available at least since 10.4. 6981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochextern "C" { 7081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform); 7181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}; 7281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std; 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 77643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic void setCGFillColor(CGContextRef context, const Color& color, ColorSpace colorSpace) 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch CGContextSetFillColorWithColor(context, cachedCGColor(color, colorSpace)); 80643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 81643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 82643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic void setCGStrokeColor(CGContextRef context, const Color& color, ColorSpace colorSpace) 83643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch CGContextSetStrokeColorWithColor(context, cachedCGColor(color, colorSpace)); 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockCGColorSpaceRef deviceRGBColorSpaceRef() 888a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{ 898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB(); 908a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return deviceSpace; 918a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block} 928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 938a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockCGColorSpaceRef sRGBColorSpaceRef() 948a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{ 958a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block // FIXME: Windows should be able to use kCGColorSpaceSRGB, this is tracked by http://webkit.org/b/31363. 968a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#if PLATFORM(WIN) || defined(BUILDING_ON_TIGER) 978a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return deviceRGBColorSpaceRef(); 988a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else 998a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block static CGColorSpaceRef sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); 1008a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return sRGBSpace; 1018a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif 1028a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block} 1038a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 104a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochCGColorSpaceRef linearRGBColorSpaceRef() 105a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // FIXME: Windows should be able to use kCGColorSpaceGenericRGBLinear, this is tracked by http://webkit.org/b/31363. 107a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if PLATFORM(WIN) || defined(BUILDING_ON_TIGER) 108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return deviceRGBColorSpaceRef(); 109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#else 110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch static CGColorSpaceRef linearRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear); 111a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return linearRGBSpace; 112a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif 113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::platformInit(CGContextRef cgContext) 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_data = new GraphicsContextPlatformPrivate(cgContext); 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project setPaintingDisabled(!cgContext); 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (cgContext) { 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Make sure the context starts in sync with our state. 121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setPlatformFillColor(fillColor(), fillColorSpace()); 122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setPlatformStrokeColor(strokeColor(), strokeColorSpace()); 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 126f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::platformDestroy() 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delete m_data; 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectCGContextRef GraphicsContext::platformContext() const 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!paintingDisabled()); 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_data->m_cgContext); 135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return m_data->m_cgContext.get(); 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::savePlatformState() 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Note: Do not use this function within this class implementation, since we want to avoid the extra 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // save of the secondary context (in GraphicsContextPlatformPrivateCG.h). 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSaveGState(platformContext()); 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->save(); 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::restorePlatformState() 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Note: Do not use this function within this class implementation, since we want to avoid the extra 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // restore of the secondary context (in GraphicsContextPlatformPrivateCG.h). 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRestoreGState(platformContext()); 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->restore(); 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->m_userToDeviceTransformKnownToBeIdentity = false; 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Draws a filled rectangle with a stroked border. 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::drawRect(const IntRect& rect) 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: this function does not handle patterns and gradients 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // like drawPath does, it probably should. 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian CGContextFillRect(context, rect); 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (strokeStyle() != NoStroke) { 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We do a fill of four rects to simulate the stroke of a border. 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Color oldFillColor = fillColor(); 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (oldFillColor != strokeColor()) 171643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGFillColor(context, strokeColor(), strokeColorSpace()); 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGRect rects[4] = { 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project FloatRect(rect.x(), rect.y(), rect.width(), 1), 1742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block FloatRect(rect.x(), rect.maxY() - 1, rect.width(), 1), 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project FloatRect(rect.x(), rect.y() + 1, 1, rect.height() - 2), 1762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block FloatRect(rect.maxX() - 1, rect.y() + 1, 1, rect.height() - 2) 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project }; 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextFillRects(context, rects, 4); 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (oldFillColor != strokeColor()) 180643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGFillColor(context, oldFillColor, fillColorSpace()); 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This is only used to draw borders. 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (strokeStyle() == NoStroke) 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float width = strokeThickness(); 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project FloatPoint p1 = point1; 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project FloatPoint p2 = point2; 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool isVerticalLine = (p1.x() == p2.x()); 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // works out. For example, with a border width of 3, KHTML will pass us (y1+y2)/2, e.g., 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // us a perfect position, but an odd width gave us a position that is off by exactly 0.5. 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) { 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isVerticalLine) { 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p1.move(0, width); 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p2.move(0, -width); 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p1.move(width, 0); 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p2.move(-width, 0); 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (((int)width) % 2) { 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isVerticalLine) { 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We're a vertical line. Adjust our x. 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p1.move(0.5f, 0.0f); 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p2.move(0.5f, 0.0f); 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We're a horizontal line. Adjust our y. 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p1.move(0.0f, 0.5f); 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p2.move(0.0f, 0.5f); 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int patWidth = 0; 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (strokeStyle()) { 227231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case NoStroke: 228231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case SolidStroke: 229231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 230231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case DottedStroke: 231231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block patWidth = (int)width; 232231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 233231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case DashedStroke: 234231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block patWidth = 3 * (int)width; 235231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 239231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 240635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (shouldAntialias()) 241635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextSetShouldAntialias(context, false); 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (patWidth) { 244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextSaveGState(context); 245635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Do a rect fill of our endpoints. This ensures we always have the 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // appearance of being a border. We then draw the actual dotted/dashed line. 248643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGFillColor(context, strokeColor(), strokeColorSpace()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color. 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isVerticalLine) { 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextFillRect(context, FloatRect(p1.x() - width / 2, p1.y() - width, width, width)); 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextFillRect(context, FloatRect(p2.x() - width / 2, p2.y(), width, width)); 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextFillRect(context, FloatRect(p1.x() - width, p1.y() - width / 2, width, width)); 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextFillRect(context, FloatRect(p2.x(), p2.y() - width / 2, width, width)); 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Example: 80 pixels with a width of 30 pixels. 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remainder is 20. The maximum pixels of line we could paint 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // will be 50 pixels. 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*(int)width; 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int remainder = distance % patWidth; 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int coverage = distance - remainder; 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int numSegments = coverage / patWidth; 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float patternOffset = 0.0f; 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Special case 1px dotted borders for speed. 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (patWidth == 1) 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset = 1.0f; 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 270231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block bool evenNumberOfSegments = !(numSegments % 2); 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (remainder) 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project evenNumberOfSegments = !evenNumberOfSegments; 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (evenNumberOfSegments) { 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (remainder) { 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset += patWidth - remainder; 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset += remainder / 2; 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset = patWidth / 2; 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (remainder) 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset = (patWidth - remainder)/2; 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 284231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const CGFloat dottedLine[2] = { patWidth, patWidth }; 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetLineDash(context, patternOffset, dottedLine, 2); 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextBeginPath(context); 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextMoveToPoint(context, p1.x(), p1.y()); 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextAddLineToPoint(context, p2.x(), p2.y()); 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextStrokePath(context); 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (patWidth) 296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextRestoreGState(context); 297231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 298635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (shouldAntialias()) 299635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextSetShouldAntialias(context, true); 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This method is only used to draw the little circles used in lists. 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::drawEllipse(const IntRect& rect) 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 307231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 308f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Path path; 309f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch path.addEllipse(rect); 310f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawPath(path); 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan) 315231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 3165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f) 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 318231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSaveGState(context); 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextBeginPath(context); 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetShouldAntialias(context, false); 323231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int x = rect.x(); 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int y = rect.y(); 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float w = (float)rect.width(); 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float h = (float)rect.height(); 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float scaleFactor = h / w; 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float reverseScaleFactor = w / h; 330231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (w != h) 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project scale(FloatSize(1, scaleFactor)); 333231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float hRadius = w / 2; 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float vRadius = h / 2; 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float fa = startAngle; 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float falen = fa + angleSpan; 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float start = -fa * piFloat / 180.0f; 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float end = -falen * piFloat / 180.0f; 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextAddArc(context, x + hRadius, (y + vRadius) * reverseScaleFactor, hRadius, start, end, true); 3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (w != h) 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project scale(FloatSize(1, reverseScaleFactor)); 344231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float width = strokeThickness(); 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int patWidth = 0; 347231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (strokeStyle()) { 349231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case DottedStroke: 350231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block patWidth = (int)(width / 2); 351231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 352231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case DashedStroke: 353231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block patWidth = 3 * (int)(width / 2); 354231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 355231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block default: 356231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 358231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (patWidth) { 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Example: 80 pixels with a width of 30 pixels. 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remainder is 20. The maximum pixels of line we could paint 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // will be 50 pixels. 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int distance; 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hRadius == vRadius) 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project distance = static_cast<int>((piFloat * hRadius) / 2.0f); 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else // We are elliptical and will have to estimate the distance 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project distance = static_cast<int>((piFloat * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0f)) / 2.0f); 368231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int remainder = distance % patWidth; 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int coverage = distance - remainder; 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int numSegments = coverage / patWidth; 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float patternOffset = 0.0f; 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Special case 1px dotted borders for speed. 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (patWidth == 1) 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset = 1.0f; 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 378231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block bool evenNumberOfSegments = !(numSegments % 2); 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (remainder) 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project evenNumberOfSegments = !evenNumberOfSegments; 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (evenNumberOfSegments) { 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (remainder) { 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset += patWidth - remainder; 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset += remainder / 2.0f; 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset = patWidth / 2.0f; 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (remainder) 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project patternOffset = (patWidth - remainder) / 2.0f; 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 392231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const CGFloat dottedLine[2] = { patWidth, patWidth }; 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetLineDash(context, patternOffset, dottedLine, 2); 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextStrokePath(context); 398231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRestoreGState(context); 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 402f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic void addConvexPolygonToPath(Path& path, size_t numberOfPoints, const FloatPoint* points) 403ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{ 404f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(numberOfPoints > 0); 405f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 406f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch path.moveTo(points[0]); 407f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (size_t i = 1; i < numberOfPoints; ++i) 408f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch path.addLineTo(points[i]); 409f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch path.closeSubpath(); 410ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block} 411ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block 412f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::drawConvexPolygon(size_t numberOfPoints, const FloatPoint* points, bool antialiased) 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (paintingDisabled()) 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 417f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (numberOfPoints <= 1) 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 422635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (antialiased != shouldAntialias()) 423635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextSetShouldAntialias(context, antialiased); 424231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 425f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Path path; 426f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch addConvexPolygonToPath(path, numberOfPoints, points); 427f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawPath(path); 428231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 429635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (antialiased != shouldAntialias()) 430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextSetShouldAntialias(context, shouldAntialias()); 4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 433f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::clipConvexPolygon(size_t numberOfPoints, const FloatPoint* points, bool antialias) 434ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{ 435ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block if (paintingDisabled()) 436ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block return; 437ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block 438f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (numberOfPoints <= 1) 439ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block return; 4400617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 4410617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen CGContextRef context = platformContext(); 4420617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 4430617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (antialias != shouldAntialias()) 4440617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen CGContextSetShouldAntialias(context, antialias); 445f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 446f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Path path; 447f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch addConvexPolygonToPath(path, numberOfPoints, points); 448f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch clipPath(path, RULE_NONZERO); 4490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 4500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (antialias != shouldAntialias()) 4510617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen CGContextSetShouldAntialias(context, shouldAntialias()); 452ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block} 453ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block 454635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid GraphicsContext::applyStrokePattern() 4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 456635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextRef cgContext = platformContext(); 457231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 458f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_state.strokePattern->createPlatformPattern(getCTM())); 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!platformPattern) 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 462231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0)); 463231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetStrokeColorSpace(cgContext, patternSpace.get()); 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const CGFloat patternAlpha = 1; 466231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetStrokePattern(cgContext, platformPattern.get(), &patternAlpha); 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 469635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid GraphicsContext::applyFillPattern() 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 471635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextRef cgContext = platformContext(); 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 473f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_state.fillPattern->createPlatformPattern(getCTM())); 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!platformPattern) 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 477231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0)); 478231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetFillColorSpace(cgContext, patternSpace.get()); 4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const CGFloat patternAlpha = 1; 481231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetFillPattern(cgContext, platformPattern.get(), &patternAlpha); 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool calculateDrawingMode(const GraphicsContextState& state, CGPathDrawingMode& mode) 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 486643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool shouldFill = state.fillPattern || state.fillColor.alpha(); 487643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool shouldStroke = state.strokePattern || (state.strokeStyle != NoStroke && state.strokeColor.alpha()); 4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool useEOFill = state.fillRule == RULE_EVENODD; 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldFill) { 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldStroke) { 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (useEOFill) 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mode = kCGPathEOFillStroke; 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mode = kCGPathFillStroke; 4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { // fill, no stroke 4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (useEOFill) 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mode = kCGPathEOFill; 4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mode = kCGPathFill; 5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Setting mode to kCGPathStroke even if shouldStroke is false. In that case, we return false and mode will not be used, 504d0825bca7fe65beaee391d30da42e937db621564Steve Block // but the compiler will not complain about an uninitialized variable. 5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mode = kCGPathStroke; 5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return shouldFill || shouldStroke; 5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 511f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::drawPath(const Path& path) 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 517f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const GraphicsContextState& state = m_state; 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 519643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (state.fillGradient || state.strokeGradient) { 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We don't have any optimized way to fill & stroke a path using gradients 521f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // FIXME: Be smarter about this. 522f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch fillPath(path); 523f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch strokePath(path); 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 526231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 527f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextBeginPath(context); 528f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextAddPath(context, path.platformPath()); 529f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 530643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (state.fillPattern) 531635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project applyFillPattern(); 532643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (state.strokePattern) 533635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project applyStrokePattern(); 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGPathDrawingMode drawingMode; 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (calculateDrawingMode(state, drawingMode)) 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextDrawPath(context, drawingMode); 5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline void fillPathWithFillRule(CGContextRef context, WindRule fillRule) 5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (fillRule == RULE_EVENODD) 5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextEOFillPath(context); 5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextFillPath(context); 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 548f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::fillPath(const Path& path) 5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 554643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 555f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_state.fillGradient) { 55665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (hasShadow()) { 55765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch FloatRect rect = path.boundingRect(); 55865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0); 55965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextRef layerContext = CGLayerGetContext(layer); 56065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 56165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextTranslateCTM(layerContext, -rect.x(), -rect.y()); 56265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextBeginPath(layerContext); 56365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextAddPath(layerContext, path.platformPath()); 56465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextConcatCTM(layerContext, m_state.fillGradient->gradientSpaceTransform()); 56565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 56665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (fillRule() == RULE_EVENODD) 56765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextEOClip(layerContext); 56865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch else 56965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextClip(layerContext); 57065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 57165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch m_state.fillGradient->paint(layerContext); 5722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer); 57365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGLayerRelease(layer); 57465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } else { 57565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextBeginPath(context); 57665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextAddPath(context, path.platformPath()); 57765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextSaveGState(context); 57865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform()); 57965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 58065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (fillRule() == RULE_EVENODD) 58165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextEOClip(context); 58265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch else 58365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextClip(context); 58465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 58565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch m_state.fillGradient->paint(this); 58665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextRestoreGState(context); 58765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 58865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 589643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 591643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 59265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextBeginPath(context); 59365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch CGContextAddPath(context, path.platformPath()); 59465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 595f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_state.fillPattern) 596643ca7872b450ea4efacab6188849e5aac2ba161Steve Block applyFillPattern(); 597643ca7872b450ea4efacab6188849e5aac2ba161Steve Block fillPathWithFillRule(context, fillRule()); 5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 600f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::strokePath(const Path& path) 6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 606643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 607f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextBeginPath(context); 608f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextAddPath(context, path.platformPath()); 609f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 610f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_state.strokeGradient) { 61181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (hasShadow()) { 61281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch FloatRect rect = path.boundingRect(); 61381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float lineWidth = strokeThickness(); 61481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float doubleLineWidth = lineWidth * 2; 61581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float layerWidth = ceilf(rect.width() + doubleLineWidth); 61681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float layerHeight = ceilf(rect.height() + doubleLineWidth); 61781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 61881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(layerWidth, layerHeight), 0); 61981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextRef layerContext = CGLayerGetContext(layer); 62081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextSetLineWidth(layerContext, lineWidth); 62181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 62281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Compensate for the line width, otherwise the layer's top-left corner would be 62381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // aligned with the rect's top-left corner. This would result in leaving pixels out of 62481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // the layer on the left and top sides. 62581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float translationX = lineWidth - rect.x(); 62681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float translationY = lineWidth - rect.y(); 62781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextTranslateCTM(layerContext, translationX, translationY); 62881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 62981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextAddPath(layerContext, path.platformPath()); 63081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextReplacePathWithStrokedPath(layerContext); 63181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextClip(layerContext); 63281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextConcatCTM(layerContext, m_state.strokeGradient->gradientSpaceTransform()); 63381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_state.strokeGradient->paint(layerContext); 63481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 63581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float destinationX = roundf(rect.x() - lineWidth); 63681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float destinationY = roundf(rect.y() - lineWidth); 63781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextDrawLayerAtPoint(context, CGPointMake(destinationX, destinationY), layer); 63881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGLayerRelease(layer); 63981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } else { 64081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextSaveGState(context); 64181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextReplacePathWithStrokedPath(context); 64281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextClip(context); 64381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextConcatCTM(context, m_state.strokeGradient->gradientSpaceTransform()); 64481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_state.strokeGradient->paint(this); 64581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextRestoreGState(context); 64681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 647643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 649643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 650f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_state.strokePattern) 651643ca7872b450ea4efacab6188849e5aac2ba161Steve Block applyStrokePattern(); 652643ca7872b450ea4efacab6188849e5aac2ba161Steve Block CGContextStrokePath(context); 6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6552fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic float radiusToLegacyRadius(float radius) 6562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 6572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return radius > 8 ? 8 + 4 * sqrt((radius - 8) / 2) : radius; 6582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 6592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 6602fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic bool hasBlurredShadow(const GraphicsContextState& state) 6612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 6622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return state.shadowColor.isValid() && state.shadowColor.alpha() && state.shadowBlur; 6632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 6642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::fillRect(const FloatRect& rect) 6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 669643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 671643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 672f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_state.fillGradient) { 6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSaveGState(context); 674cad810f21b803229eb11403f9209855525a25d57Steve Block if (hasShadow()) { 675cad810f21b803229eb11403f9209855525a25d57Steve Block CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0); 676cad810f21b803229eb11403f9209855525a25d57Steve Block CGContextRef layerContext = CGLayerGetContext(layer); 6772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 6782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextTranslateCTM(layerContext, -rect.x(), -rect.y()); 6792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextAddRect(layerContext, rect); 6802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextClip(layerContext); 6812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 6822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextConcatCTM(layerContext, m_state.fillGradient->gradientSpaceTransform()); 683cad810f21b803229eb11403f9209855525a25d57Steve Block m_state.fillGradient->paint(layerContext); 6842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer); 685cad810f21b803229eb11403f9209855525a25d57Steve Block CGLayerRelease(layer); 686cad810f21b803229eb11403f9209855525a25d57Steve Block } else { 687cad810f21b803229eb11403f9209855525a25d57Steve Block CGContextClipToRect(context, rect); 688ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform()); 689cad810f21b803229eb11403f9209855525a25d57Steve Block m_state.fillGradient->paint(this); 690cad810f21b803229eb11403f9209855525a25d57Steve Block } 6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRestoreGState(context); 692643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 694643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 695f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_state.fillPattern) 696643ca7872b450ea4efacab6188849e5aac2ba161Steve Block applyFillPattern(); 6972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 6982bde8e466a4451c7319e3a072d118917957d6554Steve Block bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. 6992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (drawOwnShadow) { 7002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur; 7012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Turn off CG shadows. 7022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextSaveGState(context); 7032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0); 7042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace); 7062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii()); 7072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 7082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 709643ca7872b450ea4efacab6188849e5aac2ba161Steve Block CGContextFillRect(context, rect); 7102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (drawOwnShadow) 7122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextRestoreGState(context); 7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 715643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) 7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 719a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 7205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian CGContextRef context = platformContext(); 7215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Color oldFillColor = fillColor(); 722643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ColorSpace oldColorSpace = fillColorSpace(); 723643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 724643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (oldFillColor != color || oldColorSpace != colorSpace) 725a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch setCGFillColor(context, color, colorSpace); 726643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 7272bde8e466a4451c7319e3a072d118917957d6554Steve Block bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. 7282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (drawOwnShadow) { 7292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur; 7302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Turn off CG shadows. 7312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextSaveGState(context); 7322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0); 7332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace); 7352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii()); 7362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 7372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian CGContextFillRect(context, rect); 7392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (drawOwnShadow) 7412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextRestoreGState(context); 742643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 743643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (oldFillColor != color || oldColorSpace != colorSpace) 744a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch setCGFillColor(context, oldFillColor, oldColorSpace); 7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 747643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace) 7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (paintingDisabled()) 7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Color oldFillColor = fillColor(); 754643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ColorSpace oldColorSpace = fillColorSpace(); 755643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 756643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (oldFillColor != color || oldColorSpace != colorSpace) 757643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGFillColor(context, color, colorSpace); 7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7592bde8e466a4451c7319e3a072d118917957d6554Steve Block bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet. 7602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (drawOwnShadow) { 7612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur; 7622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Turn off CG shadows. 7642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextSaveGState(context); 7652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0); 7662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace); 7682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii(topLeft, topRight, bottomLeft, bottomRight)); 7692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 7702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bool equalWidths = (topLeft.width() == topRight.width() && topRight.width() == bottomLeft.width() && bottomLeft.width() == bottomRight.width()); 7722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bool equalHeights = (topLeft.height() == bottomLeft.height() && bottomLeft.height() == topRight.height() && topRight.height() == bottomRight.height()); 7732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (equalWidths && equalHeights && topLeft.width() * 2 == rect.width() && topLeft.height() * 2 == rect.height()) 7742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch CGContextFillEllipseInRect(context, rect); 7752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch else { 7762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch Path path; 7772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight); 7782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch fillPath(path); 7792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (drawOwnShadow) 7822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextRestoreGState(context); 7832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 784643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (oldFillColor != color || oldColorSpace != colorSpace) 785643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGFillColor(context, oldFillColor, oldColorSpace); 7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7882fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedIntRect& roundedHoleRect, const Color& color, ColorSpace colorSpace) 7892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 7902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (paintingDisabled()) 7912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return; 7922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextRef context = platformContext(); 7942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block Path path; 7962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block path.addRect(rect); 7972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!roundedHoleRect.radii().isZero()) 7992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch path.addRoundedRect(roundedHoleRect); 8002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else 8012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block path.addRect(roundedHoleRect.rect()); 8022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block WindRule oldFillRule = fillRule(); 8042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block Color oldFillColor = fillColor(); 8052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ColorSpace oldFillColorSpace = fillColorSpace(); 8062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block setFillRule(RULE_EVENODD); 8082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block setFillColor(color, colorSpace); 8092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // fillRectWithRoundedHole() assumes that the edges of rect are clipped out, so we only care about shadows cast around inside the hole. 8112bde8e466a4451c7319e3a072d118917957d6554Steve Block bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; 8122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (drawOwnShadow) { 8132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur; 8142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Turn off CG shadows. 8162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextSaveGState(context); 8172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0); 8182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace); 8202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block contextShadow.drawInsetShadow(this, rect, roundedHoleRect.rect(), roundedHoleRect.radii()); 8212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 8222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block fillPath(path); 8242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (drawOwnShadow) 8262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CGContextRestoreGState(context); 8272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block setFillRule(oldFillRule); 8292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block setFillColor(oldFillColor, oldFillColorSpace); 8302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 8312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::clip(const FloatRect& rect) 8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextClipToRect(platformContext(), rect); 8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->clip(rect); 8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::clipOut(const IntRect& rect) 8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 844231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGRect rects[2] = { CGContextGetClipBoundingBox(platformContext()), rect }; 8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextBeginPath(platformContext()); 8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextAddRects(platformContext(), rects, 2); 8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextEOClip(platformContext()); 8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 851f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::clipPath(const Path& path, WindRule clipRule) 852635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 853635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (paintingDisabled()) 854635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 855635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 856f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (path.isEmpty()) 857f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 858f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 859635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextRef context = platformContext(); 860635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 861f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextBeginPath(platformContext()); 862f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextAddPath(platformContext(), path.platformPath()); 863f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 864f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (clipRule == RULE_EVENODD) 865f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextEOClip(context); 866f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 867f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextClip(context); 868635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 869635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 8702fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockIntRect GraphicsContext::clipBounds() const 8712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 8722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return enclosingIntRect(CGContextGetClipBoundingBox(platformContext())); 8732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 8742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) 8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project clip(rect); 8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 882231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Add outer ellipse 8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextAddEllipseInRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height())); 8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Add inner ellipse. 8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextAddEllipseInRect(context, CGRectMake(rect.x() + thickness, rect.y() + thickness, 8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project rect.width() - (thickness * 2), rect.height() - (thickness * 2))); 888231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextEOClip(context); 8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::beginTransparencyLayer(float opacity) 8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSaveGState(context); 8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetAlpha(context, opacity); 8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextBeginTransparencyLayer(context, 0); 9008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->beginTransparencyLayer(); 9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->m_userToDeviceTransformKnownToBeIdentity = false; 9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::endTransparencyLayer() 9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextEndTransparencyLayer(context); 9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRestoreGState(context); 9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->endTransparencyLayer(); 9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->m_userToDeviceTransformKnownToBeIdentity = false; 9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 91506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenvoid GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace) 9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // FIXME: we could avoid the shadow setup cost when we know we'll render the shadow ourselves. 9212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 922d0825bca7fe65beaee391d30da42e937db621564Steve Block CGFloat xOffset = offset.width(); 923d0825bca7fe65beaee391d30da42e937db621564Steve Block CGFloat yOffset = offset.height(); 924635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGFloat blurRadius = blur; 9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 927f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!m_state.shadowsIgnoreTransforms) { 928d0825bca7fe65beaee391d30da42e937db621564Steve Block CGAffineTransform userToBaseCTM = wkGetUserToBaseCTM(context); 9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 930d0825bca7fe65beaee391d30da42e937db621564Steve Block CGFloat A = userToBaseCTM.a * userToBaseCTM.a + userToBaseCTM.b * userToBaseCTM.b; 931d0825bca7fe65beaee391d30da42e937db621564Steve Block CGFloat B = userToBaseCTM.a * userToBaseCTM.c + userToBaseCTM.b * userToBaseCTM.d; 932635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGFloat C = B; 933d0825bca7fe65beaee391d30da42e937db621564Steve Block CGFloat D = userToBaseCTM.c * userToBaseCTM.c + userToBaseCTM.d * userToBaseCTM.d; 9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 935635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGFloat smallEigenvalue = narrowPrecisionToCGFloat(sqrt(0.5 * ((A + D) - sqrt(4 * B * C + (A - D) * (A - D))))); 9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9372bde8e466a4451c7319e3a072d118917957d6554Steve Block blurRadius = blur * smallEigenvalue; 9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 939d0825bca7fe65beaee391d30da42e937db621564Steve Block CGSize offsetInBaseSpace = CGSizeApplyAffineTransform(offset, userToBaseCTM); 940635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 941d0825bca7fe65beaee391d30da42e937db621564Steve Block xOffset = offsetInBaseSpace.width; 942d0825bca7fe65beaee391d30da42e937db621564Steve Block yOffset = offsetInBaseSpace.height; 943635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9452bde8e466a4451c7319e3a072d118917957d6554Steve Block // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp 9462bde8e466a4451c7319e3a072d118917957d6554Steve Block blurRadius = min(blurRadius, narrowPrecisionToCGFloat(1000.0)); 9472bde8e466a4451c7319e3a072d118917957d6554Steve Block 9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated 9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // to the desired integer. 9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128); 951d0825bca7fe65beaee391d30da42e937db621564Steve Block if (xOffset > 0) 952d0825bca7fe65beaee391d30da42e937db621564Steve Block xOffset += extraShadowOffset; 953d0825bca7fe65beaee391d30da42e937db621564Steve Block else if (xOffset < 0) 954d0825bca7fe65beaee391d30da42e937db621564Steve Block xOffset -= extraShadowOffset; 9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 956d0825bca7fe65beaee391d30da42e937db621564Steve Block if (yOffset > 0) 957d0825bca7fe65beaee391d30da42e937db621564Steve Block yOffset += extraShadowOffset; 958d0825bca7fe65beaee391d30da42e937db621564Steve Block else if (yOffset < 0) 959d0825bca7fe65beaee391d30da42e937db621564Steve Block yOffset -= extraShadowOffset; 9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check for an invalid color, as this means that the color was not set for the shadow 9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // and we should therefore just use the default shadow color. 9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!color.isValid()) 964d0825bca7fe65beaee391d30da42e937db621564Steve Block CGContextSetShadow(context, CGSizeMake(xOffset, yOffset), blurRadius); 965a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch else 966a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch CGContextSetShadowWithColor(context, CGSizeMake(xOffset, yOffset), blurRadius, cachedCGColor(color, colorSpace)); 9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::clearPlatformShadow() 9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0); 9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::setMiterLimit(float limit) 9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetMiterLimit(platformContext(), limit); 9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::setAlpha(float alpha) 9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetAlpha(platformContext(), alpha); 9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::clearRect(const FloatRect& r) 9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 9938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextClearRect(platformContext(), r); 9958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 99781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) 9988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1001635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1002635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextRef context = platformContext(); 1003643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1004f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_state.strokeGradient) { 100581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (hasShadow()) { 100681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const float doubleLineWidth = lineWidth * 2; 100781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const float layerWidth = ceilf(rect.width() + doubleLineWidth); 100881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const float layerHeight = ceilf(rect.height() + doubleLineWidth); 100981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(layerWidth, layerHeight), 0); 101081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 101181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextRef layerContext = CGLayerGetContext(layer); 101281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_state.strokeThickness = lineWidth; 101381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextSetLineWidth(layerContext, lineWidth); 101481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 101581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Compensate for the line width, otherwise the layer's top-left corner would be 101681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // aligned with the rect's top-left corner. This would result in leaving pixels out of 101781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // the layer on the left and top sides. 101881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const float translationX = lineWidth - rect.x(); 101981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const float translationY = lineWidth - rect.y(); 102081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextTranslateCTM(layerContext, translationX, translationY); 102181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 102281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextAddRect(layerContext, rect); 102381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextReplacePathWithStrokedPath(layerContext); 102481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextClip(layerContext); 102581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextConcatCTM(layerContext, m_state.strokeGradient->gradientSpaceTransform()); 102681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_state.strokeGradient->paint(layerContext); 102781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 102881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const float destinationX = roundf(rect.x() - lineWidth); 102981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const float destinationY = roundf(rect.y() - lineWidth); 103081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextDrawLayerAtPoint(context, CGPointMake(destinationX, destinationY), layer); 103181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGLayerRelease(layer); 103281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } else { 103381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextSaveGState(context); 103481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch setStrokeThickness(lineWidth); 103581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextAddRect(context, rect); 103681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextReplacePathWithStrokedPath(context); 103781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextClip(context); 103881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextConcatCTM(context, m_state.strokeGradient->gradientSpaceTransform()); 103981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_state.strokeGradient->paint(this); 104081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextRestoreGState(context); 104181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 1042643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 1043635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 1044643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1045f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_state.strokePattern) 1046643ca7872b450ea4efacab6188849e5aac2ba161Steve Block applyStrokePattern(); 104781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextStrokeRectWithWidth(context, rect, lineWidth); 10488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::setLineCap(LineCap cap) 10518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 10538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 10548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (cap) { 1055231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case ButtCap: 1056231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetLineCap(platformContext(), kCGLineCapButt); 1057231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1058231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case RoundCap: 1059231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetLineCap(platformContext(), kCGLineCapRound); 1060231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1061231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case SquareCap: 1062231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetLineCap(platformContext(), kCGLineCapSquare); 1063231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 10648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) 10688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetLineDash(platformContext(), dashOffset, dashes.data(), dashes.size()); 10708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::setLineJoin(LineJoin join) 10738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 10758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 10768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (join) { 1077231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case MiterJoin: 1078231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetLineJoin(platformContext(), kCGLineJoinMiter); 1079231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1080231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case RoundJoin: 1081231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetLineJoin(platformContext(), kCGLineJoinRound); 1082231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1083231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case BevelJoin: 1084231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetLineJoin(platformContext(), kCGLineJoinBevel); 1085231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 10868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::clip(const Path& path) 10908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 10928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 10938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 1094f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 1095f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // CGContextClip does nothing if the path is empty, so in this case, we 1096f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // instead clip against a zero rect to reduce the clipping region to 1097f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // nothing - which is the intended behavior of clip() if the path is empty. 1098f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (path.isEmpty()) 1099f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick CGContextClipToRect(context, CGRectZero); 1100f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick else { 1101f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick CGContextBeginPath(context); 1102f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick CGContextAddPath(context, path.platformPath()); 1103f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick CGContextClip(context); 1104f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick } 11058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->clip(path); 11068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1108cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockvoid GraphicsContext::canvasClip(const Path& path) 1109cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 1110cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block clip(path); 1111cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 1112cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 11138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::clipOut(const Path& path) 11148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 11168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 11188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextBeginPath(platformContext()); 11198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext())); 11208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextAddPath(platformContext(), path.platformPath()); 11218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextEOClip(platformContext()); 11228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::scale(const FloatSize& size) 11258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextScaleCTM(platformContext(), size.width(), size.height()); 11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->scale(size); 11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->m_userToDeviceTransformKnownToBeIdentity = false; 11318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::rotate(float angle) 11348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRotateCTM(platformContext(), angle); 11388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->rotate(angle); 11398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->m_userToDeviceTransformKnownToBeIdentity = false; 11408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::translate(float x, float y) 11438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 11458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextTranslateCTM(platformContext(), x, y); 11478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->translate(x, y); 11488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->m_userToDeviceTransformKnownToBeIdentity = false; 11498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11515e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Blockvoid GraphicsContext::concatCTM(const AffineTransform& transform) 11525e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{ 11535e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block if (paintingDisabled()) 11545e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block return; 11555e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block CGContextConcatCTM(platformContext(), transform); 11565e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block m_data->concatCTM(transform); 11575e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block m_data->m_userToDeviceTransformKnownToBeIdentity = false; 11585e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block} 11595e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 116081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid GraphicsContext::setCTM(const AffineTransform& transform) 116181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 116281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (paintingDisabled()) 116381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return; 116481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGContextSetCTM(platformContext(), transform); 116581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_data->setCTM(transform); 116681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_data->m_userToDeviceTransformKnownToBeIdentity = false; 116781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 116881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 11698a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockAffineTransform GraphicsContext::getCTM() const 11705e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{ 11715e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block CGAffineTransform t = CGContextGetCTM(platformContext()); 11725e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block return AffineTransform(t.a, t.b, t.c, t.d, t.tx, t.ty); 11735e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block} 11745e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 11752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochFloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode roundingMode) 11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if PLATFORM(CHROMIUM) 11782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return rect; 11792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#else 1180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // It is not enough just to round to pixels in device space. The rotation part of the 11818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // affine transform matrix to device space can mess with this conversion if we have a 1182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // rotating image like the hands of the world clock widget. We just need the scale, so 11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // we get the affine transform matrix and extract the scale. 11848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_data->m_userToDeviceTransformKnownToBeIdentity) 11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return rect; 11878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGAffineTransform deviceMatrix = CGContextGetUserSpaceToDeviceSpaceTransform(platformContext()); 11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (CGAffineTransformIsIdentity(deviceMatrix)) { 11908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_data->m_userToDeviceTransformKnownToBeIdentity = true; 11918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return rect; 11928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float deviceScaleX = sqrtf(deviceMatrix.a * deviceMatrix.a + deviceMatrix.b * deviceMatrix.b); 11958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float deviceScaleY = sqrtf(deviceMatrix.c * deviceMatrix.c + deviceMatrix.d * deviceMatrix.d); 11968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGPoint deviceOrigin = CGPointMake(rect.x() * deviceScaleX, rect.y() * deviceScaleY); 11988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGPoint deviceLowerRight = CGPointMake((rect.x() + rect.width()) * deviceScaleX, 11998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project (rect.y() + rect.height()) * deviceScaleY); 12008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project deviceOrigin.x = roundf(deviceOrigin.x); 12028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project deviceOrigin.y = roundf(deviceOrigin.y); 12032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (roundingMode == RoundAllSides) { 12042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch deviceLowerRight.x = roundf(deviceLowerRight.x); 12052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch deviceLowerRight.y = roundf(deviceLowerRight.y); 12062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } else { 12072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch deviceLowerRight.x = deviceOrigin.x + roundf(rect.width() * deviceScaleX); 12082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch deviceLowerRight.y = deviceOrigin.y + roundf(rect.height() * deviceScaleY); 12092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 1210231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 12118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Don't let the height or width round to 0 unless either was originally 0 1212231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (deviceOrigin.y == deviceLowerRight.y && rect.height()) 12138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project deviceLowerRight.y += 1; 1214231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (deviceOrigin.x == deviceLowerRight.x && rect.width()) 12158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project deviceLowerRight.x += 1; 12168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project FloatPoint roundedOrigin = FloatPoint(deviceOrigin.x / deviceScaleX, deviceOrigin.y / deviceScaleY); 12188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project FloatPoint roundedLowerRight = FloatPoint(deviceLowerRight.x / deviceScaleX, deviceLowerRight.y / deviceScaleY); 12198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin); 12202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif 12218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 122381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid GraphicsContext::drawLineForText(const FloatPoint& point, float width, bool printing) 12248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 12268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (width <= 0) 12298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float x = point.x(); 12328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float y = point.y(); 12338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float lineLength = width; 12348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Use a minimum thickness of 0.5 in user space. 12368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // See http://bugs.webkit.org/show_bug.cgi?id=4255 for details of why 0.5 is the right minimum thickness to use. 12378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float thickness = max(strokeThickness(), 0.5f); 12388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool restoreAntialiasMode = false; 1240635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 12418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!printing) { 12428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // On screen, use a minimum thickness of 1.0 in user space (later rounded to an integral number in device space). 12438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float adjustedThickness = max(thickness, 1.0f); 12448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This should be done a better way. 12468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We try to round all parameters to integer boundaries in device space. If rounding pixels in device space 12478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // makes our thickness more than double, then there must be a shrinking-scale factor and rounding to pixels 12488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // in device space will make the underlines too thick. 12492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch CGRect lineRect = roundToDevicePixels(FloatRect(x, y, lineLength, adjustedThickness), RoundOriginAndDimensions); 12508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (lineRect.size.height < thickness * 2.0) { 12518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project x = lineRect.origin.x; 12528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project y = lineRect.origin.y; 12538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project lineLength = lineRect.size.width; 12548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project thickness = lineRect.size.height; 1255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (shouldAntialias()) { 1256635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextSetShouldAntialias(platformContext(), false); 1257635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project restoreAntialiasMode = true; 1258635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 12598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1261231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 12628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (fillColor() != strokeColor()) 1263643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGFillColor(platformContext(), strokeColor(), strokeColorSpace()); 12648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextFillRect(platformContext(), CGRectMake(x, y, lineLength, thickness)); 1265635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (fillColor() != strokeColor()) 1266643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGFillColor(platformContext(), fillColor(), fillColorSpace()); 1267231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1268635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (restoreAntialiasMode) 1269635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CGContextSetShouldAntialias(platformContext(), true); 12708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) 12738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 12758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1276231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1277231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block RetainPtr<CFURLRef> urlRef(AdoptCF, link.createCFURL()); 1278231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!urlRef) 1279231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 1280231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1281231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextRef context = platformContext(); 1282231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1283231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Get the bounding box to handle clipping. 1284231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGRect box = CGContextGetClipBoundingBox(context); 1285231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1286231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block IntRect intBox((int)box.origin.x, (int)box.origin.y, (int)box.size.width, (int)box.size.height); 1287231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block IntRect rect = destRect; 1288231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block rect.intersect(intBox); 1289231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1290231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGPDFContextSetURLForRect(context, urlRef.get(), 1291231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGRectApplyAffineTransform(rect, CGContextGetCTM(context))); 12928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode) 12958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 12978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1298231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 12998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGInterpolationQuality quality = kCGInterpolationDefault; 13008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (mode) { 1301231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case InterpolationDefault: 1302231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block quality = kCGInterpolationDefault; 1303231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1304231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case InterpolationNone: 1305231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block quality = kCGInterpolationNone; 1306231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1307231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case InterpolationLow: 1308231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block quality = kCGInterpolationLow; 1309231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1310231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1311643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Fall through to InterpolationHigh if kCGInterpolationMedium is not usable. 1312231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case InterpolationMedium: 1313643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if USE(CG_INTERPOLATION_MEDIUM) 1314231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block quality = kCGInterpolationMedium; 1315231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 13168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 1317231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case InterpolationHigh: 1318231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block quality = kCGInterpolationHigh; 1319231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 13208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetInterpolationQuality(platformContext(), quality); 13228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectInterpolationQuality GraphicsContext::imageInterpolationQuality() const 13258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 13278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return InterpolationDefault; 13288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGInterpolationQuality quality = CGContextGetInterpolationQuality(platformContext()); 13308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (quality) { 1331231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case kCGInterpolationDefault: 1332231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return InterpolationDefault; 1333231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case kCGInterpolationNone: 1334231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return InterpolationNone; 1335231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case kCGInterpolationLow: 1336231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return InterpolationLow; 13378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(CG_INTERPOLATION_MEDIUM) 1338643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // kCGInterpolationMedium is known to be present in the CGInterpolationQuality enum. 1339231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case kCGInterpolationMedium: 1340643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if USE(CG_INTERPOLATION_MEDIUM) 1341643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Only map to InterpolationMedium if targeting a system that understands it. 1342231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return InterpolationMedium; 1343643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#else 1344643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return InterpolationDefault; 1345643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif // USE(CG_INTERPOLATION_MEDIUM) 1346643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif // HAVE(CG_INTERPOLATION_MEDIUM) 1347231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case kCGInterpolationHigh: 1348231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return InterpolationHigh; 13498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return InterpolationDefault; 13518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1353f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::setAllowsFontSmoothing(bool allowsFontSmoothing) 1354f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 1355f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UNUSED_PARAM(allowsFontSmoothing); 1356f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 1357f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextRef context = platformContext(); 1358f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextSetAllowsFontSmoothing(context, allowsFontSmoothing); 1359f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif 1360f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1361f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 13622bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid GraphicsContext::setIsCALayerContext(bool isLayerContext) 136381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 13642bde8e466a4451c7319e3a072d118917957d6554Steve Block if (isLayerContext) 13652bde8e466a4451c7319e3a072d118917957d6554Steve Block m_data->m_contextFlags |= IsLayerCGContext; 13662bde8e466a4451c7319e3a072d118917957d6554Steve Block else 13672bde8e466a4451c7319e3a072d118917957d6554Steve Block m_data->m_contextFlags &= ~IsLayerCGContext; 136881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 136981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 137081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool GraphicsContext::isCALayerContext() const 137181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 13722bde8e466a4451c7319e3a072d118917957d6554Steve Block return m_data->m_contextFlags & IsLayerCGContext; 13732bde8e466a4451c7319e3a072d118917957d6554Steve Block} 13742bde8e466a4451c7319e3a072d118917957d6554Steve Block 13752bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid GraphicsContext::setIsAcceleratedContext(bool isAccelerated) 13762bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 13772bde8e466a4451c7319e3a072d118917957d6554Steve Block if (isAccelerated) 13782bde8e466a4451c7319e3a072d118917957d6554Steve Block m_data->m_contextFlags |= IsAcceleratedCGContext; 13792bde8e466a4451c7319e3a072d118917957d6554Steve Block else 13802bde8e466a4451c7319e3a072d118917957d6554Steve Block m_data->m_contextFlags &= ~IsAcceleratedCGContext; 13812bde8e466a4451c7319e3a072d118917957d6554Steve Block} 13822bde8e466a4451c7319e3a072d118917957d6554Steve Block 13832bde8e466a4451c7319e3a072d118917957d6554Steve Blockbool GraphicsContext::isAcceleratedContext() const 13842bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 13852bde8e466a4451c7319e3a072d118917957d6554Steve Block return m_data->m_contextFlags & IsAcceleratedCGContext; 138681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 138781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 1388f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode) 13898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 13918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 13928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Wow, wish CG had used bits here. 13948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextRef context = platformContext(); 13958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (mode) { 1396f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case TextModeInvisible: 1397231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetTextDrawingMode(context, kCGTextInvisible); 1398231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1399f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case TextModeFill: 1400231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetTextDrawingMode(context, kCGTextFill); 1401231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1402f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case TextModeStroke: 1403231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetTextDrawingMode(context, kCGTextStroke); 1404231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1405f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case TextModeFill | TextModeStroke: 1406231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetTextDrawingMode(context, kCGTextFillStroke); 1407231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1408f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case TextModeClip: 1409231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetTextDrawingMode(context, kCGTextClip); 1410231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1411f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case TextModeFill | TextModeClip: 1412231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetTextDrawingMode(context, kCGTextFillClip); 1413231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1414f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case TextModeStroke | TextModeClip: 1415231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetTextDrawingMode(context, kCGTextStrokeClip); 1416231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1417f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case TextModeFill | TextModeStroke | TextModeClip: 1418231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip); 1419231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1420231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block default: 1421231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 14228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1425643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace) 14268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 14288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1429643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGStrokeColor(platformContext(), color, colorSpace); 14308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::setPlatformStrokeThickness(float thickness) 14338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 14358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 14368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetLineWidth(platformContext(), thickness); 14378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1439643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace) 14408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 14428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1443643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setCGFillColor(platformContext(), color, colorSpace); 14448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1446635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid GraphicsContext::setPlatformShouldAntialias(bool enable) 14478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 14498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 14508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetShouldAntialias(platformContext(), enable); 14518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1453f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::setPlatformShouldSmoothFonts(bool enable) 1454f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 1455f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (paintingDisabled()) 1456f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 1457f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch CGContextSetShouldSmoothFonts(platformContext(), enable); 1458f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1459f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1460f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#ifndef BUILDING_ON_TIGER // Tiger's setPlatformCompositeOperation() is defined in GraphicsContextMac.mm. 1461f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::setPlatformCompositeOperation(CompositeOperator mode) 1462231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 14638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (paintingDisabled()) 14648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 14658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1466231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CGBlendMode target = kCGBlendModeNormal; 14678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (mode) { 1468231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeClear: 1469231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeClear; 1470231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1471231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeCopy: 1472231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeCopy; 1473231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1474231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeSourceOver: 1475231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block //kCGBlendModeNormal 1476231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1477231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeSourceIn: 1478231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeSourceIn; 1479231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1480231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeSourceOut: 1481231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeSourceOut; 1482231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1483231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeSourceAtop: 1484231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeSourceAtop; 1485231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1486231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeDestinationOver: 1487231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeDestinationOver; 1488231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1489231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeDestinationIn: 1490231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeDestinationIn; 1491231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1492231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeDestinationOut: 1493231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeDestinationOut; 1494231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1495231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeDestinationAtop: 1496231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeDestinationAtop; 1497231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1498231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeXOR: 1499231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModeXOR; 1500231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1501231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositePlusDarker: 1502231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModePlusDarker; 1503231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1504231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositeHighlight: 1505231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // currently unsupported 1506231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 1507231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block case CompositePlusLighter: 1508231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block target = kCGBlendModePlusLighter; 1509231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block break; 15108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGContextSetBlendMode(platformContext(), target); 15128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 15148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1516