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

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

Issue 25081002: Remove openglui embedder code (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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 CanvasState* CanvasState::Restore() {
51 if (next_ != NULL) {
52 // If the state we are popping has a non-empty path,
53 // apply the state's transform to the path, then
54 // add the path to the previous state's path.
55 if (path_->countPoints() > 0) {
56 path_->transform(canvas_->getTotalMatrix());
57 next_->path_->addPath(*path_);
58 }
59 canvas_->restore();
60 return next_;
61 }
62 canvas_->restore();
63 return next_; // TODO(gram): Should we assert/throw?
64 }
65
66 void CanvasState::setLineCap(const char* lc) {
67 if (strcmp(lc, "round") == 0) {
68 paint_.setStrokeCap(SkPaint::kRound_Cap);
69 } else if (strcmp(lc, "square") == 0) {
70 paint_.setStrokeCap(SkPaint::kSquare_Cap);
71 } else {
72 paint_.setStrokeCap(SkPaint::kButt_Cap);
73 }
74 }
75
76 void CanvasState::setLineJoin(const char* lj) {
77 if (strcmp(lj, "round") == 0) {
78 paint_.setStrokeJoin(SkPaint::kRound_Join);
79 } else if (strcmp(lj, "bevel") == 0) {
80 paint_.setStrokeJoin(SkPaint::kBevel_Join);
81 } else {
82 paint_.setStrokeJoin(SkPaint::kMiter_Join);
83 }
84 }
85
86 const char* CanvasState::setFont(const char*name, float size) {
87 // Font names have the form "<modifier> <size> <family>".
88 // Modifiers are "normal", "italic", "bold".
89 // Sizes have magnitude and units; e.g. "10pt", "20px".
90 const char* rtn = name;
91 if (size < 0) {
92 int pos = 0;
93 // TODO(gram): need to handle these modifiers.
94 if (strncmp(name, "normal", 6) == 0) {
95 pos = 6;
96 } else if (strncmp(name, "italic", 6) == 0) {
97 pos = 6;
98 } else if (strncmp(name, "bold", 4) == 0) {
99 pos = 4;
100 }
101 size = ParseFloat(name, pos);
102 // Font size units: px, etc. For now just px.
103 // TODO(gram): Handle other units.
104 if (strncmp(name + pos, "px", 2) == 0) {
105 pos += 2;
106 }
107 int len = strlen(name);
108 while (pos < len && isspace(name[pos])) {
109 ++pos;
110 }
111 name = name + pos;
112 }
113 SkTypeface *pTypeface = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
114 paint_.setTypeface(pTypeface);
115 paint_.setTextSize(size);
116 // TODO(gram): Must return a normalized font name incorporating size, so
117 // callers can set the Dart canvas font name to an appropriate value.
118 // Actually this may not be necessary in which case we can change this
119 // method to return void.
120 return rtn;
121 }
122
123 const char* CanvasState::setTextAlign(const char* align) {
124 // TODO(gram): What about "start" and "end"?
125 // I don't see any an analogs in Skia.
126 if (strcmp(align, "left") == 0) {
127 paint_.setTextAlign(SkPaint::kLeft_Align);
128 } else if (strcmp(align, "right") == 0) {
129 paint_.setTextAlign(SkPaint::kRight_Align);
130 } else {
131 paint_.setTextAlign(SkPaint::kCenter_Align);
132 }
133 return align;
134 }
135
136 const char* CanvasState::setTextBaseline(const char* baseline) {
137 // TODO(gram): Does skia support this? It doesn't seem like
138 // it. Right now we don't use the textBaseline value, but we
139 // may have to implement this ourselves, by adjusting the y
140 // values passed to StrokeText/FillText using the font metrics.
141 if (strcmp(baseline, "top") == 0) {
142 } else if (strcmp(baseline, "middle") == 0) {
143 } else if (strcmp(baseline, "bottom") == 0) {
144 } else if (strcmp(baseline, "hanging") == 0) {
145 } else if (strcmp(baseline, "alphabetic") == 0) {
146 } else if (strcmp(baseline, "ideographic") == 0) {
147 }
148 return baseline;
149 }
150
151 const char* CanvasState::setTextDirection(const char* direction) {
152 // TODO(gram): Add support for this if Skia does.
153 return direction;
154 }
155
156 void CanvasState::setMode(SkPaint::Style style, ColorRGBA color,
157 SkShader* shader) {
158 paint_.setStyle(style);
159 paint_.setColor(color.v);
160 paint_.setShader(shader);
161 uint8_t alpha = static_cast<uint8_t>(
162 globalAlpha_ * static_cast<float>(color.alpha()));
163 paint_.setAlpha(alpha);
164 bool drawShadow = (shadowOffsetX_ != 0 ||
165 shadowOffsetY_ != 0 ||
166 shadowBlur_ != 0) &&
167 shadowColor_.alpha() > 0;
168 if (drawShadow) {
169 // TODO(gram): should we mult shadowColor by globalAlpha?
170 paint_.setLooper(new SkBlurDrawLooper(SkFloatToScalar(shadowBlur_),
171 SkFloatToScalar(shadowOffsetX_),
172 SkFloatToScalar(shadowOffsetY_),
173 shadowColor_.v))->unref();
174 } else {
175 paint_.setLooper(NULL);
176 }
177 }
178
179 void CanvasState::setGlobalCompositeOperation(const char* op) {
180 SkXfermode::Mode mode;
181 static const struct CompositOpToXfermodeMode {
182 const char* mCompositOp;
183 uint8_t m_xfermodeMode;
184 } gMapCompositOpsToXfermodeModes[] = {
185 { "clear", SkXfermode::kClear_Mode },
186 { "copy", SkXfermode::kSrc_Mode },
187 { "source-over", SkXfermode::kSrcOver_Mode },
188 { "source-in", SkXfermode::kSrcIn_Mode },
189 { "source-out", SkXfermode::kSrcOut_Mode },
190 { "source-atop", SkXfermode::kSrcATop_Mode },
191 { "destination-over", SkXfermode::kDstOver_Mode },
192 { "destination-in", SkXfermode::kDstIn_Mode },
193 { "destination-out", SkXfermode::kDstOut_Mode },
194 { "destination-atop", SkXfermode::kDstATop_Mode },
195 { "xor", SkXfermode::kXor_Mode },
196 { "darker", SkXfermode::kDarken_Mode },
197 { "lighter", SkXfermode::kPlus_Mode }
198 };
199 for (unsigned i = 0;
200 i < SK_ARRAY_COUNT(gMapCompositOpsToXfermodeModes);
201 i++) {
202 if (strcmp(op, gMapCompositOpsToXfermodeModes[i].mCompositOp) == 0) {
203 mode = (SkXfermode::Mode)gMapCompositOpsToXfermodeModes[i].m_xfermodeMode;
204 paint_.setXfermodeMode(mode);
205 return;
206 }
207 }
208 LOGE("Unknown CompositeOperator %s\n", op);
209 paint_.setXfermodeMode(SkXfermode::kSrcOver_Mode); // fall-back
210 }
211
212 void CanvasState::Arc(float x, float y, float radius,
213 float startAngle, float endAngle,
214 bool antiClockwise) {
215 SkRect rect;
216 rect.set(x - radius, y - radius, x + radius, y + radius);
217 bool doCircle = false;
218
219 static float twoPi = 2 * M_PI;
220
221 float sweep = endAngle - startAngle;
222 if (sweep >= twoPi || sweep <= -twoPi) {
223 doCircle = true;
224 }
225
226 if (!antiClockwise && endAngle <= startAngle) {
227 endAngle += 2 * M_PI;
228 } else if (antiClockwise && startAngle <= endAngle) {
229 startAngle += 2 * M_PI;
230 }
231 sweep = endAngle - startAngle;
232
233 startAngle = fmodf(startAngle, twoPi);
234 float sa = Radians2Degrees(startAngle);
235 float ea = Radians2Degrees(sweep);
236 path_->arcTo(rect, sa, ea, false);
237 if (doCircle) {
238 SkPath tmp;
239 tmp.addOval(rect);
240 tmp.addPath(*path_);
241 path_->swap(tmp);
242 }
243 }
244
245 int hexDigit(char c) {
246 if (c >= '0' && c <= '9') return c - '0';
247 if (c <= 'Z') return c - 'A' + 10;
248 return c - 'a' + 10;
249 }
250
251 // Color parser.
252 // See http://www.w3.org/TR/CSS21/syndata.html#color-units.
253 // There is also another format: hsl(240,100%,100%) (and hsla)
254 // TODO(gram): We probably eventually want to use a table rather
255 // than a big if statement; see setGlobalCompositeOperation for
256 // an example.
257 ColorRGBA CanvasState::GetColor(const char* color) {
258 if (color[0] == '#') {
259 int r = 0, g = 0, b = 0;
260 if (strlen(color) == 7) {
261 r = hexDigit(color[1]) * 16 + hexDigit(color[2]);
262 g = hexDigit(color[3]) * 16 + hexDigit(color[4]);
263 b = hexDigit(color[5]) * 16 + hexDigit(color[6]);
264 } else if (strlen(color) == 4) {
265 r = hexDigit(color[1]) * 16 + hexDigit(color[1]);
266 g = hexDigit(color[2]) * 16 + hexDigit(color[2]);
267 b = hexDigit(color[3]) * 16 + hexDigit(color[3]);
268 }
269 return ColorRGBA(r, g, b);
270 } else if (strcmp(color, "maroon") == 0) {
271 return ColorRGBA(0x80, 0x00, 0x00);
272 } else if (strcmp(color, "red") == 0) {
273 return ColorRGBA(0xFF, 0x00, 0x00);
274 } else if (strcmp(color, "orange") == 0) {
275 return ColorRGBA(0xFF, 0xA5, 0x00);
276 } else if (strcmp(color, "yellow") == 0) {
277 return ColorRGBA(0xFF, 0xFF, 0x00);
278 } else if (strcmp(color, "olive") == 0) {
279 return ColorRGBA(0x80, 0x80, 0x00);
280 } else if (strcmp(color, "purple") == 0) {
281 return ColorRGBA(0x80, 0x00, 0x80);
282 } else if (strcmp(color, "fuschia") == 0) {
283 return ColorRGBA(0xFF, 0x00, 0xFF);
284 } else if (strcmp(color, "white") == 0) {
285 return ColorRGBA(0xFF, 0xFF, 0xFF);
286 } else if (strcmp(color, "lime") == 0) {
287 return ColorRGBA(0x00, 0xFF, 0x00);
288 } else if (strcmp(color, "green") == 0) {
289 return ColorRGBA(0x00, 0x80, 0x00);
290 } else if (strcmp(color, "navy") == 0) {
291 return ColorRGBA(0x00, 0x00, 0x80);
292 } else if (strcmp(color, "blue") == 0) {
293 return ColorRGBA(0x00, 0x00, 0xFF);
294 } else if (strcmp(color, "aqua") == 0) {
295 return ColorRGBA(0x00, 0xFF, 0xFF);
296 } else if (strcmp(color, "teal") == 0) {
297 return ColorRGBA(0x00, 0x80, 0x80);
298 } else if (strcmp(color, "silver") == 0) {
299 return ColorRGBA(0xC0, 0xC0, 0xC0);
300 } else if (strcmp(color, "gray") == 0) {
301 return ColorRGBA(0x80, 0x80, 0x80);
302 } else if (strncmp(color, "rgb(", 4) == 0) {
303 int pos = 4;
304 int r = ParseInt(color, pos);
305 ++pos;
306 int g = ParseInt(color, pos);
307 ++pos;
308 int b = ParseInt(color, pos);
309 return ColorRGBA(r, g, b);
310 } else if (strncmp(color, "rgba(", 5) == 0) {
311 int pos = 5;
312 int r = ParseInt(color, pos);
313 ++pos;
314 int g = ParseInt(color, pos);
315 ++pos;
316 int b = ParseInt(color, pos);
317 ++pos;
318 float a = ParseFloat(color, pos);
319 return ColorRGBA(r, g, b, static_cast<int>(a * 255.0));
320 }
321 // Default to black.
322 return ColorRGBA(0x00, 0x00, 0x00);
323 }
324
325 void CanvasState::DrawImage(const SkBitmap& bm,
326 int sx, int sy, int sw, int sh,
327 int dx, int dy, int dw, int dh) {
328 if (sw < 0) sw = bm.width();
329 if (dw < 0) dw = bm.width();
330 if (sh < 0) sh = bm.height();
331 if (dh < 0) dh = bm.height();
332 SkIRect src = SkIRect::MakeXYWH(sx, sy, sw, sh);
333 SkRect dst = SkRect::MakeXYWH(dx, dy, dw, dh);
334 LOGI("DrawImage(_,%d,%d,%d,%d,%d,%d,%d,%d)", sx, sy, sw, sh, dx, dy, dw, dh);
335 canvas_->drawBitmapRect(bm, &src, dst);
336 }
337
338 void CanvasState::SetFillGradient(bool is_radial,
339 double x0, double y0, double r0,
340 double x1, double y1, double r1,
341 int stops, float* positions, char** colors) {
342 if (fillShader_ != NULL) {
343 fillShader_->unref();
344 }
345 if (is_radial) {
346 fillShader_ = CreateRadialGradient(x0, y0, r0, x1, y1, r1,
347 stops, positions, colors);
348 } else {
349 fillShader_ = CreateLinearGradient(x0, y0, x1, y1,
350 stops, positions, colors);
351 }
352 fillShader_->validate();
353 }
354
355 void CanvasState::SetStrokeGradient(bool is_radial,
356 double x0, double y0, double r0,
357 double x1, double y1, double r1,
358 int stops, float* positions, char** colors) {
359 if (strokeShader_ != NULL) {
360 strokeShader_->unref();
361 }
362 if (is_radial) {
363 strokeShader_ = CreateRadialGradient(x0, y0, r0, x1, y1, r1,
364 stops, positions, colors);
365 } else {
366 strokeShader_ = CreateLinearGradient(x0, y0, x1, y1,
367 stops, positions, colors);
368 }
369 strokeShader_->validate();
370 }
371
372 SkShader* CanvasState::CreateRadialGradient(
373 double x0, double y0, double r0,
374 double x1, double y1, double r1,
375 int stops, float* positions, char** colors) {
376 SkScalar* p = new SkScalar[stops];
377 SkColor* c = new SkColor[stops];
378 for (int i = 0; i < stops; i++) {
379 p[i] = positions[i];
380 c[i] = GetColor(colors[i]).v;
381 }
382 LOGI("CreateRadialGradient(%f,%f,%f,%f,%f,%f,%d,[%f,%f],[%s,%s]",
383 x0, y0, r0, x1, y1, r1, stops, positions[0], positions[1],
384 colors[0], colors[1]);
385 SkShader* shader = SkGradientShader::CreateTwoPointRadial(
386 SkPoint::Make(x0, y0), r0, SkPoint::Make(x1, y1), r1,
387 c, p, stops, SkShader::kClamp_TileMode);
388 delete[] c;
389 delete[] p;
390 return shader;
391 }
392
393 SkShader* CanvasState::CreateLinearGradient(
394 double x0, double y0, double x1, double y1,
395 int stops, float* positions, char** colors) {
396 SkScalar* p = new SkScalar[stops];
397 SkColor* c = new SkColor[stops];
398 for (int i = 0; i < stops; i++) {
399 p[i] = positions[i];
400 c[i] = GetColor(colors[i]).v;
401 }
402 SkPoint pts[2];
403 pts[0] = SkPoint::Make(x0, y0);
404 pts[1] = SkPoint::Make(x1, y1);
405 SkShader* shader = SkGradientShader::CreateLinear(pts, c, p, stops,
406 SkShader::kClamp_TileMode);
407 delete[] c;
408 delete[] p;
409 return shader;
410 }
411
OLDNEW
« no previous file with comments | « runtime/embedders/openglui/common/canvas_state.h ('k') | runtime/embedders/openglui/common/context.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698