• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2006,2007,2008, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 
33 #include "platform/graphics/skia/SkiaUtils.h"
34 
35 #include "SkColorPriv.h"
36 #include "SkRegion.h"
37 #include "platform/graphics/GraphicsContext.h"
38 #include "platform/graphics/ImageBuffer.h"
39 
40 namespace WebCore {
41 
42 static const struct CompositOpToXfermodeMode {
43     uint8_t mCompositOp;
44     uint8_t m_xfermodeMode;
45 } gMapCompositOpsToXfermodeModes[] = {
46     { CompositeClear,           SkXfermode::kClear_Mode },
47     { CompositeCopy,            SkXfermode::kSrc_Mode },
48     { CompositeSourceOver,      SkXfermode::kSrcOver_Mode },
49     { CompositeSourceIn,        SkXfermode::kSrcIn_Mode },
50     { CompositeSourceOut,       SkXfermode::kSrcOut_Mode },
51     { CompositeSourceAtop,      SkXfermode::kSrcATop_Mode },
52     { CompositeDestinationOver, SkXfermode::kDstOver_Mode },
53     { CompositeDestinationIn,   SkXfermode::kDstIn_Mode },
54     { CompositeDestinationOut,  SkXfermode::kDstOut_Mode },
55     { CompositeDestinationAtop, SkXfermode::kDstATop_Mode },
56     { CompositeXOR,             SkXfermode::kXor_Mode },
57     { CompositePlusDarker,      SkXfermode::kDarken_Mode },
58     { CompositePlusLighter,     SkXfermode::kPlus_Mode }
59 };
60 
61 // keep this array in sync with blink::WebBlendMode enum in public/platform/WebBlendMode.h
62 static const uint8_t gMapBlendOpsToXfermodeModes[] = {
63     SkXfermode::kClear_Mode, // blink::WebBlendModeNormal
64     SkXfermode::kMultiply_Mode, // blink::WebBlendModeMultiply
65     SkXfermode::kScreen_Mode, // blink::WebBlendModeScreen
66     SkXfermode::kOverlay_Mode, // blink::WebBlendModeOverlay
67     SkXfermode::kDarken_Mode, // blink::WebBlendModeDarken
68     SkXfermode::kLighten_Mode, // blink::WebBlendModeLighten
69     SkXfermode::kColorDodge_Mode, // blink::WebBlendModeColorDodge
70     SkXfermode::kColorBurn_Mode, // blink::WebBlendModeColorBurn
71     SkXfermode::kHardLight_Mode, // blink::WebBlendModeHardLight
72     SkXfermode::kSoftLight_Mode, // blink::WebBlendModeSoftLight
73     SkXfermode::kDifference_Mode, // blink::WebBlendModeDifference
74     SkXfermode::kExclusion_Mode, // blink::WebBlendModeExclusion
75     SkXfermode::kHue_Mode, // blink::WebBlendModeHue
76     SkXfermode::kSaturation_Mode, // blink::WebBlendModeSaturation
77     SkXfermode::kColor_Mode, // blink::WebBlendModeColor
78     SkXfermode::kLuminosity_Mode // blink::WebBlendModeLuminosity
79 };
80 
WebCoreCompositeToSkiaComposite(CompositeOperator op,blink::WebBlendMode blendMode)81 PassRefPtr<SkXfermode> WebCoreCompositeToSkiaComposite(CompositeOperator op, blink::WebBlendMode blendMode)
82 {
83     if (blendMode != blink::WebBlendModeNormal) {
84         if ((uint8_t)blendMode >= SK_ARRAY_COUNT(gMapBlendOpsToXfermodeModes)) {
85             SkDEBUGF(("GraphicsContext::setPlatformCompositeOperation unknown blink::WebBlendMode %d\n", blendMode));
86             return adoptRef(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
87         }
88         SkXfermode::Mode mode = (SkXfermode::Mode)gMapBlendOpsToXfermodeModes[(uint8_t)blendMode];
89         return adoptRef(SkXfermode::Create(mode));
90     }
91 
92     const CompositOpToXfermodeMode* table = gMapCompositOpsToXfermodeModes;
93 
94     for (unsigned i = 0; i < SK_ARRAY_COUNT(gMapCompositOpsToXfermodeModes); i++) {
95         if (table[i].mCompositOp == op)
96             return adoptRef(SkXfermode::Create((SkXfermode::Mode)table[i].m_xfermodeMode));
97     }
98 
99     SkDEBUGF(("GraphicsContext::setPlatformCompositeOperation unknown CompositeOperator %d\n", op));
100     return adoptRef(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); // fall-back
101 }
102 
InvScaleByte(U8CPU component,uint32_t scale)103 static U8CPU InvScaleByte(U8CPU component, uint32_t scale)
104 {
105     SkASSERT(component == (uint8_t)component);
106     return (component * scale + 0x8000) >> 16;
107 }
108 
SkPMColorToColor(SkPMColor pm)109 SkColor SkPMColorToColor(SkPMColor pm)
110 {
111     if (!pm)
112         return 0;
113     unsigned a = SkGetPackedA32(pm);
114     if (!a) {
115         // A zero alpha value when there are non-zero R, G, or B channels is an
116         // invalid premultiplied color (since all channels should have been
117         // multiplied by 0 if a=0).
118         SkASSERT(false);
119         // In production, return 0 to protect against division by zero.
120         return 0;
121     }
122 
123     uint32_t scale = (255 << 16) / a;
124 
125     return SkColorSetARGB(a,
126                           InvScaleByte(SkGetPackedR32(pm), scale),
127                           InvScaleByte(SkGetPackedG32(pm), scale),
128                           InvScaleByte(SkGetPackedB32(pm), scale));
129 }
130 
SkPathContainsPoint(const SkPath & originalPath,const FloatPoint & point,SkPath::FillType ft)131 bool SkPathContainsPoint(const SkPath& originalPath, const FloatPoint& point, SkPath::FillType ft)
132 {
133     SkRect bounds = originalPath.getBounds();
134 
135     // We can immediately return false if the point is outside the bounding
136     // rect.  We don't use bounds.contains() here, since it would exclude
137     // points on the right and bottom edges of the bounding rect, and we want
138     // to include them.
139     SkScalar fX = SkFloatToScalar(point.x());
140     SkScalar fY = SkFloatToScalar(point.y());
141     if (fX < bounds.fLeft || fX > bounds.fRight || fY < bounds.fTop || fY > bounds.fBottom)
142         return false;
143 
144     // Scale the path to a large size before hit testing for two reasons:
145     // 1) Skia has trouble with coordinates close to the max signed 16-bit values, so we scale larger paths down.
146     //    TODO: when Skia is patched to work properly with large values, this will not be necessary.
147     // 2) Skia does not support analytic hit testing, so we scale paths up to do raster hit testing with subpixel accuracy.
148     SkScalar biggestCoord = std::max(std::max(std::max(bounds.fRight, bounds.fBottom), -bounds.fLeft), -bounds.fTop);
149     if (SkScalarNearlyZero(biggestCoord))
150         return false;
151     biggestCoord = std::max(std::max(biggestCoord, fX + 1), fY + 1);
152 
153     const SkScalar kMaxCoordinate = SkIntToScalar(1 << 15);
154     SkScalar scale = SkScalarDiv(kMaxCoordinate, biggestCoord);
155 
156     SkRegion rgn;
157     SkRegion clip;
158     SkMatrix m;
159     SkPath scaledPath(originalPath);
160 
161     scaledPath.setFillType(ft);
162     m.setScale(scale, scale);
163     scaledPath.transform(m, 0);
164 
165     int x = static_cast<int>(floorf(0.5f + point.x() * scale));
166     int y = static_cast<int>(floorf(0.5f + point.y() * scale));
167     clip.setRect(x - 1, y - 1, x + 1, y + 1);
168 
169     return rgn.setPath(scaledPath, clip);
170 }
171 
affineTransformToSkMatrix(const AffineTransform & source)172 SkMatrix affineTransformToSkMatrix(const AffineTransform& source)
173 {
174     SkMatrix result;
175 
176     result.setScaleX(WebCoreDoubleToSkScalar(source.a()));
177     result.setSkewX(WebCoreDoubleToSkScalar(source.c()));
178     result.setTranslateX(WebCoreDoubleToSkScalar(source.e()));
179 
180     result.setScaleY(WebCoreDoubleToSkScalar(source.d()));
181     result.setSkewY(WebCoreDoubleToSkScalar(source.b()));
182     result.setTranslateY(WebCoreDoubleToSkScalar(source.f()));
183 
184     // FIXME: Set perspective properly.
185     result.setPerspX(0);
186     result.setPerspY(0);
187     result.set(SkMatrix::kMPersp2, SK_Scalar1);
188 
189     return result;
190 }
191 
192 }  // namespace WebCore
193