• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "android_graphics.h"
28 #include "IntPoint.h"
29 #include "IntRect.h"
30 #include "FloatPoint.h"
31 #include "FloatRect.h"
32 #include "SkCanvas.h"
33 #include "SkColorPriv.h"
34 #include "SkCornerPathEffect.h"
35 #include "SkGradientShader.h"
36 #include "SkPath.h"
37 #include "SkRegion.h"
38 
android_setpt(SkPoint * dst,const WebCore::IntPoint & src)39 SkPoint* android_setpt(SkPoint* dst, const WebCore::IntPoint& src)
40 {
41     dst->set(SkIntToScalar(src.x()), SkIntToScalar(src.y()));
42     return dst;
43 }
44 
android_setpt(SkPoint * dst,const WebCore::FloatPoint & src)45 SkPoint* android_setpt(SkPoint* dst, const WebCore::FloatPoint& src)
46 {
47     dst->set(SkFloatToScalar(src.x()), SkFloatToScalar(src.y()));
48     return dst;
49 }
50 
android_setrect(SkRect * dst,const WebCore::IntRect & src)51 SkRect* android_setrect(SkRect* dst, const WebCore::IntRect& src)
52 {
53     dst->set(SkIntToScalar(src.x()),
54              SkIntToScalar(src.y()),
55              SkIntToScalar(src.x() + src.width()),
56              SkIntToScalar(src.y() + src.height()));
57     return dst;
58 }
59 
android_setrect(SkIRect * dst,const WebCore::IntRect & src)60 SkIRect* android_setrect(SkIRect* dst, const WebCore::IntRect& src)
61 {
62     dst->set(src.x(), src.y(),
63              src.x() + src.width(),
64              src.y() + src.height());
65     return dst;
66 }
67 
android_setrect(SkRect * dst,const WebCore::FloatRect & src)68 SkRect* android_setrect(SkRect* dst, const WebCore::FloatRect& src)
69 {
70     dst->set(SkFloatToScalar(src.x()),
71              SkFloatToScalar(src.y()),
72              SkFloatToScalar(src.x() + src.width()),
73              SkFloatToScalar(src.y() + src.height()));
74     return dst;
75 }
76 
android_setrect(SkIRect * dst,const WebCore::FloatRect & src)77 SkIRect* android_setrect(SkIRect* dst, const WebCore::FloatRect& src)
78 {
79     dst->set(SkScalarRound(SkFloatToScalar(src.x())),
80              SkScalarRound(SkFloatToScalar(src.y())),
81              SkScalarRound(SkFloatToScalar(src.x() + src.width())),
82              SkScalarRound(SkFloatToScalar(src.y() + src.height())));
83     return dst;
84 }
85 
android_setrect_scaled(SkIRect * dst,const WebCore::FloatRect & src,float sx,float sy)86 SkIRect* android_setrect_scaled(SkIRect* dst, const WebCore::FloatRect& src,
87                                 float sx, float sy)
88 {
89     dst->set(SkScalarRound(SkFloatToScalar(src.x() * sx)),
90              SkScalarRound(SkFloatToScalar(src.y() * sy)),
91              SkScalarRound(SkFloatToScalar((src.x() + src.width()) * sx)),
92              SkScalarRound(SkFloatToScalar((src.y() + src.height()) * sy)));
93     return dst;
94 }
95 
96 static const struct CompositOpToPorterDuffMode {
97     uint8_t mCompositOp;
98     uint8_t mPorterDuffMode;
99 } gMapCompositOpsToPorterDuffModes[] = {
100     { WebCore::CompositeClear,           SkPorterDuff::kClear_Mode },
101     { WebCore::CompositeCopy,            SkPorterDuff::kSrc_Mode },
102     { WebCore::CompositeSourceOver,      SkPorterDuff::kSrcOver_Mode },
103     { WebCore::CompositeSourceIn,        SkPorterDuff::kSrcIn_Mode },
104     { WebCore::CompositeSourceOut,       SkPorterDuff::kSrcOut_Mode },
105     { WebCore::CompositeSourceAtop,      SkPorterDuff::kSrcATop_Mode },
106     { WebCore::CompositeDestinationOver, SkPorterDuff::kDstOver_Mode },
107     { WebCore::CompositeDestinationIn,   SkPorterDuff::kDstIn_Mode },
108     { WebCore::CompositeDestinationOut,  SkPorterDuff::kDstOut_Mode },
109     { WebCore::CompositeDestinationAtop, SkPorterDuff::kDstATop_Mode },
110     { WebCore::CompositeXOR,             SkPorterDuff::kXor_Mode },
111     { WebCore::CompositePlusDarker,      SkPorterDuff::kDarken_Mode },
112     { WebCore::CompositeHighlight,       SkPorterDuff::kSrcOver_Mode },  // TODO
113     { WebCore::CompositePlusLighter,     SkPorterDuff::kLighten_Mode }
114 };
115 
android_convert_compositeOp(WebCore::CompositeOperator op)116 SkPorterDuff::Mode android_convert_compositeOp(WebCore::CompositeOperator op)
117 {
118     const CompositOpToPorterDuffMode* table = gMapCompositOpsToPorterDuffModes;
119 
120     for (unsigned i = 0; i < SK_ARRAY_COUNT(gMapCompositOpsToPorterDuffModes); i++) {
121         if (table[i].mCompositOp == op) {
122             return (SkPorterDuff::Mode)table[i].mPorterDuffMode;
123         }
124     }
125 
126     SkDEBUGF(("GraphicsContext::setCompositeOperation uknown CompositOperator %d\n", op));
127     return SkPorterDuff::kSrcOver_Mode; // fall-back
128 }
129 
android_convert_TileRule(WebCore::Image::TileRule rule)130 SkShader::TileMode android_convert_TileRule(WebCore::Image::TileRule rule)
131 {
132     // stretch == clamp
133     // repeat == repeat
134     // RoundTile???
135 
136     return WebCore::Image::RepeatTile == rule ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
137 }
138 
139 /////////////////////////////////////////////////////////////////////////////////////////////////////////
140 
InvScaleByte(U8CPU component,uint32_t scale)141 static U8CPU InvScaleByte(U8CPU component, uint32_t scale)
142 {
143     SkASSERT(component == (uint8_t)component);
144     return (component * scale + 0x8000) >> 16;
145 }
146 
147 // move this guy into SkColor.h
SkPMColorToColor(SkPMColor pm)148 static SkColor SkPMColorToColor(SkPMColor pm)
149 {
150     if (0 == pm)
151         return 0;
152 
153     unsigned a = SkGetPackedA32(pm);
154     uint32_t scale = (255 << 16) / a;
155 
156     return SkColorSetARGB(a,
157                           InvScaleByte(SkGetPackedR32(pm), scale),
158                           InvScaleByte(SkGetPackedG32(pm), scale),
159                           InvScaleByte(SkGetPackedB32(pm), scale));
160 }
161 
android_SkPMColorToWebCoreColor(SkPMColor pm)162 WebCore::Color android_SkPMColorToWebCoreColor(SkPMColor pm)
163 {
164     SkColor c = SkPMColorToColor(pm);
165 
166     // need the cast to find the right constructor
167     return WebCore::Color((int)SkColorGetR(c), (int)SkColorGetG(c),
168                           (int)SkColorGetB(c), (int)SkColorGetA(c));
169 }
170 
171 const static SkColor focusOuterColors[] = {
172     SkColorSetARGB(0xff, 0xB3, 0x3F, 0x08), // normal focus ring select
173     SkColorSetARGB(0xff, 0x46, 0xb0, 0x00), // fake focus ring select, for phone, email, text
174     SkColorSetARGB(0xff, 0xb0, 0x16, 0x00), // invalid focus ring color
175     SkColorSetARGB(0xff, 0xAD, 0x5C, 0x0A), // normal focus ring pressed
176     SkColorSetARGB(0xff, 0x36, 0xc0, 0x00)  // fake focus ring pressed
177 };
178 
179 const static SkColor focusInnerColors[] = {
180     SkColorSetARGB(0xff, 0xFE, 0x92, 0x30), // normal focus ring select
181     SkColorSetARGB(0xff, 0x8c, 0xd9, 0x00), // fake focus ring select, for phone, email, text
182     SkColorSetARGB(0xff, 0xd9, 0x2c, 0x00), // invalid focus ring color
183     SkColorSetARGB(0xff, 0xFE, 0xBD, 0x3A), // normal focus ring pressed
184     SkColorSetARGB(0xff, 0x7c, 0xe9, 0x00)  // fake focus ring pressed
185 };
186 
187 const static SkColor focusPressedColors[] = {
188     SkColorSetARGB(0x80, 0xFF, 0xC6, 0x4B), // normal focus ring pressed
189     SkColorSetARGB(0x80, 0x7c, 0xe9, 0x00)  // fake focus ring pressed
190 };
191 
192 #define FOCUS_RING_ROUNDEDNESS SkIntToScalar(5) // used to draw corners
193 #define FOCUS_RING_INNER_DIAMETER SkFixedToScalar(SkIntToFixed(3)>>1) // 3/2 == 1.5
194 #define FOCUS_RING_OUTER_OUTSET 2 // used to inflate rects added to region
195 
DrawRing(SkCanvas * canvas,const Vector<WebCore::IntRect> & rects,Flavor flavor)196 void FocusRing::DrawRing(SkCanvas* canvas,
197     const Vector<WebCore::IntRect>& rects, Flavor flavor)
198 {
199     unsigned                rectCount = rects.size();
200     SkRegion                rgn;
201     SkPath                  path;
202     for (unsigned i = 0; i < rectCount; i++)
203     {
204         SkIRect    r;
205 
206         android_setrect(&r, rects[i]);
207         r.inset(-FOCUS_RING_OUTER_OUTSET, -FOCUS_RING_OUTER_OUTSET);
208         rgn.op(r, SkRegion::kUnion_Op);
209     }
210     rgn.getBoundaryPath(&path);
211 
212     SkPaint paint;
213     paint.setAntiAlias(true);
214     paint.setPathEffect(new SkCornerPathEffect(FOCUS_RING_ROUNDEDNESS))->unref();
215     if (flavor >= NORMAL_ANIMATING) { // pressed
216         paint.setColor(focusPressedColors[flavor - NORMAL_ANIMATING]);
217         canvas->drawPath(path, paint);
218     }
219     paint.setStyle(SkPaint::kStroke_Style);
220     paint.setStrokeWidth(FOCUS_RING_OUTER_DIAMETER);
221     paint.setColor(focusOuterColors[flavor]);
222     canvas->drawPath(path, paint);
223     paint.setStrokeWidth(FOCUS_RING_INNER_DIAMETER);
224     paint.setColor(focusInnerColors[flavor]);
225     canvas->drawPath(path, paint);
226 }
227 
228 
229