Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: runtime/embedders/openglui/common/canvas_state.cc

Issue 12186002: Canvas API. There are still a number of things to do: (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "embedders/openglui/common/canvas_state.h"
6
7 #include <ctype.h>
8 #include <string.h>
9
10 #include "embedders/openglui/common/support.h"
11
12 // Float parser. Does not handle exponents. This is
13 // used to parse font sizes so it doesn't need to be full-blown.
14 float ParseFloat(const char* s, int& pos) {
15 int len = strlen(s);
16 float rtn = 0.0;
17 while (pos < len && s[pos] != '.' && !isdigit(s[pos])) {
18 ++pos;
19 }
20 while (pos < len && isdigit(s[pos])) {
21 rtn = rtn * 10.0 + s[pos] - '0';
22 ++pos;
23 }
24 if (pos < len && s[pos] == '.') {
25 pos++;
26 float div = 1.0;
27 while (pos < len && isdigit(s[pos])) {
28 rtn = rtn * 10.0 + s[pos] - '0';
29 ++pos;
30 div *= 10.0;
31 }
32 rtn /= div;
33 }
34 return rtn;
35 }
36
37 int ParseInt(const char* s, int& pos) {
38 int len = strlen(s);
39 int rtn = 0;
40 while (pos < len && !isdigit(s[pos])) {
41 ++pos;
42 }
43 while (pos < len && isdigit(s[pos])) {
44 rtn = rtn * 10 + s[pos] - '0';
45 ++pos;
46 }
47 return rtn;
48 }
49
50 void CanvasState::setLineCap(const char* lc) {
51 if (strcmp(lc, "round") == 0) {
52 paint_.setStrokeCap(SkPaint::kRound_Cap);
53 } else if (strcmp(lc, "square") == 0) {
54 paint_.setStrokeCap(SkPaint::kSquare_Cap);
55 } else {
56 paint_.setStrokeCap(SkPaint::kButt_Cap);
57 }
58 }
59
60 void CanvasState::setLineJoin(const char* lj) {
61 if (strcmp(lj, "round") == 0) {
62 paint_.setStrokeJoin(SkPaint::kRound_Join);
63 } else if (strcmp(lj, "bevel") == 0) {
64 paint_.setStrokeJoin(SkPaint::kBevel_Join);
65 } else {
66 paint_.setStrokeJoin(SkPaint::kMiter_Join);
67 }
68 }
69
70 const char* CanvasState::setFont(const char*name, float size) {
71 // Font names have the form "<modifier> <size> <family>".
72 // Modifiers are "normal", "italic", "bold".
73 // Sizes have magnitude and units; e.g. "10pt", "20px".
74 const char* rtn = name;
75 if (size < 0) {
76 int pos = 0;
77 // TODO(gram): need to handle these modifiers.
78 if (strncmp(name, "normal", 6) == 0) {
79 pos = 6;
80 } else if (strncmp(name, "italic", 6) == 0) {
81 pos = 6;
82 } else if (strncmp(name, "bold", 4) == 0) {
83 pos = 4;
84 }
85 size = ParseFloat(name, pos);
86 // Font size units: px, etc. For now just px.
87 // TODO(gram): Handle other units.
88 if (strncmp(name + pos, "px", 2) == 0) {
89 pos += 2;
90 }
91 int len = strlen(name);
92 while (pos < len && isspace(name[pos])) {
93 ++pos;
94 }
95 name = name + pos;
96 }
97 SkTypeface *pTypeface = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
98 paint_.setTypeface(pTypeface);
99 paint_.setTextSize(size);
100 pTypeface->unref();
101 // TODO(gram): Must return a normalized font name incorporating size, so
102 // callers can set the Dart canvas font name to an appropriate value.
103 // Actually this may not be necessary in which case we can change this
104 // method to return void.
105 return rtn;
106 }
107
108 const char* CanvasState::setTextAlign(const char* align) {
109 // TODO(gram): What about "start" and "end"?
110 // I don't see any an analogs in Skia.
111 if (strcmp(align, "left") == 0) {
112 paint_.setTextAlign(SkPaint::kLeft_Align);
113 } else if (strcmp(align, "right") == 0) {
114 paint_.setTextAlign(SkPaint::kRight_Align);
115 } else {
116 paint_.setTextAlign(SkPaint::kCenter_Align);
117 }
118 return align;
119 }
120
121 const char* CanvasState::setTextBaseline(const char* baseline) {
122 // TODO(gram): Does skia support this? It doesn't seem like
123 // it. Right now we don't use the textBaseline value, but we
124 // may have to implement this ourselves, by adjusting the y
125 // values passed to StrokeText/FillText using the font metrics.
126 if (strcmp(baseline, "top") == 0) {
127 } else if (strcmp(baseline, "middle") == 0) {
128 } else if (strcmp(baseline, "bottom") == 0) {
129 } else if (strcmp(baseline, "hanging") == 0) {
130 } else if (strcmp(baseline, "alphabetic") == 0) {
131 } else if (strcmp(baseline, "ideographic") == 0) {
132 }
133 return baseline;
134 }
135
136 const char* CanvasState::setTextDirection(const char* direction) {
137 // TODO(gram): Add support for this if Skia does.
138 return direction;
139 }
140
141 void CanvasState::setGlobalCompositeOperation(const char* op) {
142 SkXfermode::Mode mode;
143 if (strcmp(op, "source-atop") == 0) {
144 mode = SkXfermode::kSrcATop_Mode;
145 } else if (strcmp(op, "source-in") == 0) {
146 mode = SkXfermode::kSrcIn_Mode;
147 } else if (strcmp(op, "source-out") == 0) {
148 mode = SkXfermode::kSrcOut_Mode;
149 } else if (strcmp(op, "source-over") == 0) {
150 mode = SkXfermode::kSrcOver_Mode; // Default.
151 } else if (strcmp(op, "destination-atop") == 0) {
152 mode = SkXfermode::kDstATop_Mode;
153 } else if (strcmp(op, "destination-in") == 0) {
154 mode = SkXfermode::kDstIn_Mode;
155 } else if (strcmp(op, "destination-out") == 0) {
156 mode = SkXfermode::kDstOut_Mode;
157 } else if (strcmp(op, "destination-over") == 0) {
158 mode = SkXfermode::kDstOver_Mode;
159 } else if (strcmp(op, "lighter") == 0) {
160 mode = SkXfermode::kLighten_Mode;
161 } else if (strcmp(op, "darker") == 0) {
162 mode = SkXfermode::kDarken_Mode;
163 } else if (strcmp(op, "xor") == 0) {
164 mode = SkXfermode::kXor_Mode;
165 } else if (strcmp(op, "copy") == 0) {
166 mode = SkXfermode::kSrc_Mode;
167 }
168 SkXfermode* m = SkXfermode::Create(mode);
169 // It seems we don't need unref() here. Including it causes
170 // a crash. Maybe Skia has a preallocated long-lived set of
171 // instances.
172 paint_.setXfermode(m);
173 }
174
175 void CanvasState::Arc(float x, float y, float radius,
176 float startAngle, float endAngle,
177 bool antiClockwise) {
178 SkRect rect;
179 rect.set(x - radius, y - radius, x + radius, y + radius);
180 bool doCircle = false;
181
182 static float twoPi = 2 * M_PI;
183
184 float sweep = endAngle - startAngle;
185 if (sweep >= twoPi || sweep <= -twoPi) {
186 doCircle = true;
187 }
188
189 if (!antiClockwise && endAngle <= startAngle) {
190 endAngle += 2 * M_PI;
191 } else if (antiClockwise && startAngle <= endAngle) {
192 startAngle += 2 * M_PI;
193 }
194 sweep = endAngle - startAngle;
195
196 startAngle = fmodf(startAngle, twoPi);
197 float sa = Radians2Degrees(startAngle);
198 float ea = Radians2Degrees(sweep);
199 path_->arcTo(rect, sa, ea, false);
200 if (doCircle) {
201 SkPath tmp;
202 tmp.addOval(rect);
203 tmp.addPath(*path_);
204 path_->swap(tmp);
205 }
206 }
207
208 int hexDigit(char c) {
209 if (c >= '0' && c <= '9') return c - '0';
210 if (c <= 'Z') return c - 'A' + 10;
211 return c - 'a' + 10;
212 }
213
214 // Color parser.
215 // See http://www.w3.org/TR/CSS21/syndata.html#color-units.
216 // There is also another format: hsl(240,100%,100%) (and hsla)
217 // TODO(gram): We probably eventually want to use a table rather
218 // than a big if statement.
219 ColorRGBA CanvasState::GetColor(const char* color) {
220 if (color[0] == '#') {
221 int r, g, b;
222 if (strlen(color) == 7) {
223 r = hexDigit(color[1]) * 16 + hexDigit(color[2]);
224 g = hexDigit(color[3]) * 16 + hexDigit(color[4]);
225 b = hexDigit(color[5]) * 16 + hexDigit(color[6]);
226 } else if (strlen(color) == 4) {
227 r = hexDigit(color[1]) * 16 + hexDigit(color[1]);
228 g = hexDigit(color[2]) * 16 + hexDigit(color[2]);
229 b = hexDigit(color[3]) * 16 + hexDigit(color[3]);
230 }
231 return ColorRGBA(r, g, b);
232 } else if (strcmp(color, "maroon") == 0) {
233 return ColorRGBA(0x80, 0x00, 0x00);
234 } else if (strcmp(color, "red") == 0) {
235 return ColorRGBA(0xFF, 0x00, 0x00);
236 } else if (strcmp(color, "orange") == 0) {
237 return ColorRGBA(0xFF, 0xA5, 0x00);
238 } else if (strcmp(color, "yellow") == 0) {
239 return ColorRGBA(0xFF, 0xFF, 0x00);
240 } else if (strcmp(color, "olive") == 0) {
241 return ColorRGBA(0x80, 0x80, 0x00);
242 } else if (strcmp(color, "purple") == 0) {
243 return ColorRGBA(0x80, 0x00, 0x80);
244 } else if (strcmp(color, "fuschia") == 0) {
245 return ColorRGBA(0xFF, 0x00, 0xFF);
246 } else if (strcmp(color, "white") == 0) {
247 return ColorRGBA(0xFF, 0xFF, 0xFF);
248 } else if (strcmp(color, "lime") == 0) {
249 return ColorRGBA(0x00, 0xFF, 0x00);
250 } else if (strcmp(color, "green") == 0) {
251 return ColorRGBA(0x00, 0x80, 0x00);
252 } else if (strcmp(color, "navy") == 0) {
253 return ColorRGBA(0x00, 0x00, 0x80);
254 } else if (strcmp(color, "blue") == 0) {
255 return ColorRGBA(0x00, 0x00, 0xFF);
256 } else if (strcmp(color, "aqua") == 0) {
257 return ColorRGBA(0x00, 0xFF, 0xFF);
258 } else if (strcmp(color, "teal") == 0) {
259 return ColorRGBA(0x00, 0x80, 0x80);
260 } else if (strcmp(color, "silver") == 0) {
261 return ColorRGBA(0xC0, 0xC0, 0xC0);
262 } else if (strcmp(color, "gray") == 0) {
263 return ColorRGBA(0x80, 0x80, 0x80);
264 } else if (strncmp(color, "rgb(", 4) == 0) {
265 int pos = 4;
266 int r = ParseInt(color, pos);
267 ++pos;
268 int g = ParseInt(color, pos);
269 ++pos;
270 int b = ParseInt(color, pos);
271 return ColorRGBA(r, g, b);
272 } else if (strncmp(color, "rgba(", 5) == 0) {
273 int pos = 5;
274 int r = ParseInt(color, pos);
275 ++pos;
276 int g = ParseInt(color, pos);
277 ++pos;
278 int b = ParseInt(color, pos);
279 ++pos;
280 float a = ParseFloat(color, pos);
281 return ColorRGBA(r, g, b, static_cast<int>(a * 255.0));
282 }
283 // Default to black.
284 return ColorRGBA(0x00, 0x00, 0x00);
285 }
286
287 void CanvasState::DrawImage(const SkBitmap& bm,
288 int sx, int sy, int sw, int sh,
289 int dx, int dy, int dw, int dh) {
290 if (sw < 0) sw = bm.width();
291 if (dw < 0) dw = bm.width();
292 if (sh < 0) sh = bm.height();
293 if (dh < 0) dh = bm.height();
294 SkIRect src = SkIRect::MakeXYWH(sx, sy, sw, sh);
295 SkRect dst = SkRect::MakeXYWH(dx, dy, dw, dh);
296 LOGI("DrawImage(_,%d,%d,%d,%d,%d,%d,%d,%d)", sx, sy, sw, sh, dx, dy, dw, dh);
297 canvas_->drawBitmapRect(bm, &src, dst);
298 }
299
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698