Chromium Code Reviews| Index: runtime/embedders/openglui/common/canvas_state.h |
| =================================================================== |
| --- runtime/embedders/openglui/common/canvas_state.h (revision 0) |
| +++ runtime/embedders/openglui/common/canvas_state.h (revision 0) |
| @@ -0,0 +1,309 @@ |
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +#ifndef EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_ |
| +#define EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_ |
| + |
| +#include "embedders/openglui/common/graphics_handler.h" |
| +#include "embedders/openglui/common/log.h" |
| +#include "embedders/openglui/common/opengl.h" |
| +#include "embedders/openglui/common/support.h" |
| + |
| +typedef struct CanvasState { |
| + SkPaint paint_; |
| + float globalAlpha_; |
| + float miterLimit_; |
| + ColorRGBA fillColor_; |
| + ColorRGBA strokeColor_; |
| + ColorRGBA shadowColor_; |
| + float shadowBlur_; |
| + float shadowOffsetX_; |
| + float shadowOffsetY_; |
| + float* lineDash_; |
| + int lineDashCount_; |
| + int lineDashOffset_; |
| + |
| + SkPath* path_; |
| + SkCanvas* canvas_; |
| + CanvasState* next_; // For stack. |
| + |
| + CanvasState(SkCanvas* canvas) |
| + : paint_(), |
| + globalAlpha_(1.0), |
| + miterLimit_(10), |
| + fillColor_(ColorRGBA(255, 0, 0, 255)), |
| + strokeColor_(fillColor_), |
| + shadowColor_(ColorRGBA(0, 0, 0, 0)), |
| + shadowBlur_(0.0), |
| + shadowOffsetX_(0.0), |
| + shadowOffsetY_(0.0), |
| + lineDash_(NULL), |
| + lineDashCount_(0), |
| + lineDashOffset_(0), |
| + path_(new SkPath()), |
| + canvas_(canvas), |
| + next_(NULL) { |
| + paint_.setStrokeCap(SkPaint::kButt_Cap); |
| + paint_.setStrokeJoin(SkPaint::kMiter_Join); |
| + paint_.setStrokeWidth(1); |
| + paint_.setTextAlign(SkPaint::kLeft_Align); |
| + paint_.setAntiAlias(true); |
| + paint_.setStyle(SkPaint::kStroke_Style); |
| + setFont("Helvetica", 10); |
| + } |
| + |
| + CanvasState(const CanvasState& state) |
| + : paint_(state.paint_), |
| + globalAlpha_(state.globalAlpha_), |
| + miterLimit_(state.miterLimit_), |
| + fillColor_(state.fillColor_), |
| + strokeColor_(state.strokeColor_), |
| + shadowColor_(state.shadowColor_), |
| + shadowBlur_(state.shadowBlur_), |
| + shadowOffsetX_(state.shadowOffsetX_), |
| + shadowOffsetY_(state.shadowOffsetY_), |
| + lineDash_(NULL), |
| + lineDashCount_(state.lineDashCount_), |
| + lineDashOffset_(state.lineDashOffset_), |
| + path_(new SkPath()), |
| + canvas_(state.canvas_), |
| + next_(NULL) { |
| + setLineDash(state.lineDash_, lineDashCount_); |
| + } |
| + |
| + ~CanvasState() { |
| + delete path_; |
| + delete[] lineDash_; |
|
vsm
2013/02/04 18:18:41
Note, lineDash_ is init NULL in the constructor.
|
| + } |
| + |
| + static ColorRGBA GetColor(const char* color); |
| + |
| + inline CanvasState* Save() { |
| + canvas_->save(); // For clip and transform. |
| + CanvasState *new_state = new CanvasState(*this); |
| + new_state->next_ = this; |
| + // If the old state has a non-empty path, use its |
| + // last point as the new states first point. |
| + int np = path_->countPoints(); |
| + if (np > 0) { |
| + new_state->path_->moveTo(path_->getPoint(np-1)); |
| + } |
| + return new_state; |
| + } |
| + |
| + inline CanvasState* Restore() { |
| + if (next_ != NULL) { |
| + // If the state we are popping has a non-empty path, |
| + // apply the state's transform to the path, then |
| + // add the path to the previous state's path. |
| + if (path_->countPoints() > 0) { |
| + path_->transform(canvas_->getTotalMatrix()); |
| + next_->path_->addPath(*path_); |
| + } |
| + canvas_->restore(); |
| + return next_; |
| + } |
| + canvas_->restore(); |
| + return next_; // TODO(gram): Should we assert/throw? |
| + } |
| + |
| + inline float Radians2Degrees(float angle) { |
| + return 180.0 * angle / M_PI; |
| + } |
| + |
| + inline void setGlobalAlpha(float alpha) { |
| + globalAlpha_ = alpha; |
| + } |
| + |
| + inline void setFillColor(const char* color) { |
| + fillColor_ = GetColor(color); |
| + } |
| + |
| + inline void setStrokeColor(const char* color) { |
| + strokeColor_ = GetColor(color); |
| + } |
| + |
| + const char* setFont(const char*name, float size = -1); |
| + void setLineCap(const char* lc); |
| + void setLineJoin(const char* lj); |
| + |
| + inline void setMiterLimit(float limit) { |
| + miterLimit_ = limit; |
| + } |
| + |
| + const char* setTextAlign(const char* align); |
| + const char* setTextBaseline(const char* baseline); |
| + const char* setTextDirection(const char* direction); |
| + |
| + inline void FillText(const char* text, float x, float y, float maxWidth) { |
| + setFillMode(); |
| + canvas_->drawText(text, strlen(text), x, y, paint_); |
| + } |
| + |
| + inline void StrokeText(const char* text, float x, float y, float maxWidth) { |
| + setStrokeMode(); |
| + canvas_->drawText(text, strlen(text), x, y, paint_); |
| + } |
| + |
| + inline float MeasureText(const char *text) { |
| + // TODO(gram): make sure this is not supposed to be affected |
| + // by the canvas transform. |
| + return paint_.measureText(text, strlen(text)); |
| + } |
| + |
| + inline void setLineWidth(float w) { |
| + paint_.setStrokeWidth(w); |
| + } |
| + |
| + inline void setMode(SkPaint::Style style, ColorRGBA color) { |
| + paint_.setStyle(style); |
| + paint_.setColor(color.v); |
| + uint8_t alpha = static_cast<uint8_t>( |
| + globalAlpha_ * static_cast<float>(color.alpha())); |
| + paint_.setAlpha(alpha); |
| + bool drawShadow = (shadowOffsetX_ != 0 || |
| + shadowOffsetY_ != 0 || |
| + shadowBlur_ != 0) && |
| + shadowColor_.alpha() > 0; |
| + if (drawShadow) { |
| + // TODO(gram): should we mult shadowColor by globalAlpha? |
| + paint_.setLooper(new SkBlurDrawLooper(SkFloatToScalar(shadowBlur_), |
| + SkFloatToScalar(shadowOffsetX_), |
| + SkFloatToScalar(shadowOffsetY_), |
| + shadowColor_.v))->unref(); |
| + } else { |
| + paint_.setLooper(NULL); |
| + } |
| + } |
| + |
| + inline void setLineDashEffect() { |
| + if (lineDashCount_ > 0) { |
| + SkDashPathEffect* dashPathEffect = |
| + new SkDashPathEffect(lineDash_, lineDashCount_, lineDashOffset_); |
| + paint_.setPathEffect(dashPathEffect)->unref(); |
| + } else { |
| + paint_.setPathEffect(NULL); |
| + } |
| + } |
| + |
| + inline void setLineDash(float* dashes, int len) { |
| + if (len == 0) { |
| + lineDashCount_ = 0; |
| + delete[] lineDash_; |
| + lineDash_ = NULL; |
| + } else { |
| + lineDash_ = new float[lineDashCount_ = len]; |
| + for (int i = 0; i < len; i++) { |
| + lineDash_[i] = dashes[i]; |
| + } |
| + } |
| + setLineDashEffect(); |
| + } |
| + |
| + inline void setLineDashOffset(int offset) { |
| + if (offset != lineDashOffset_) { |
| + lineDashOffset_ = offset; |
| + setLineDashEffect(); |
| + } |
| + } |
| + |
| + inline void setShadowColor(const char* color) { |
| + shadowColor_ = GetColor(color); |
| + } |
| + |
| + inline void setShadowBlur(float blur) { |
| + shadowBlur_ = blur; |
| + } |
| + |
| + inline void setShadowOffsetX(float ox) { |
| + shadowOffsetX_ = ox; |
| + } |
| + |
| + inline void setShadowOffsetY(float oy) { |
| + shadowOffsetY_ = oy; |
| + } |
| + |
| + inline void setFillMode() { |
| + setMode(SkPaint::kFill_Style, fillColor_); |
| + } |
| + |
| + inline void setStrokeMode() { |
| + setMode(SkPaint::kStroke_Style, strokeColor_); |
| + } |
| + |
| + inline void FillRect(float left, float top, |
| + float width, float height) { |
| + // Does not affect the path. |
| + setFillMode(); |
| + canvas_->drawRectCoords(left, top, left + width, top + height, paint_); |
| + } |
| + |
| + inline void StrokeRect(float left, float top, |
| + float width, float height) { |
| + // Does not affect the path. |
| + setStrokeMode(); |
| + canvas_->drawRectCoords(left, top, left + width, top + height, paint_); |
| + } |
| + |
| + inline void BeginPath() { |
| + path_->rewind(); |
| + } |
| + |
| + inline void Fill() { |
| + setFillMode(); |
| + canvas_->drawPath(*path_, paint_); |
| + } |
| + |
| + inline void Stroke() { |
| + setStrokeMode(); |
| + canvas_->drawPath(*path_, paint_); |
| + } |
| + |
| + inline void ClosePath() { |
| + path_->close(); |
| + } |
| + |
| + inline void MoveTo(float x, float y) { |
| + path_->moveTo(x, y); |
| + } |
| + |
| + inline void LineTo(float x, float y) { |
| + path_->lineTo(x, y); |
| + } |
| + |
| + void Arc(float x, float y, float radius, float startAngle, float endAngle, |
| + bool antiClockwise); |
| + |
| + inline void QuadraticCurveTo(float cpx, float cpy, float x, float y) { |
| + path_->quadTo(cpx, cpy, x, y); |
| + } |
| + |
| + inline void BezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, |
| + float x, float y) { |
| + path_->cubicTo(cp1x, cp1y, cp2x, cp2y, x, y); |
| + } |
| + |
| + inline void ArcTo(float x1, float y1, float x2, float y2, float radius) { |
| + path_->arcTo(x1, y1, x2, y2, radius); |
| + } |
| + |
| + inline void Rect(float x, float y, float w, float h) { |
| + // TODO(gram): Should we draw this directly? If so, what happens with the |
| + // path? |
| + path_->addRect(x, y, x + w, y + h); |
| + } |
| + |
| + void setGlobalCompositeOperation(const char* op); |
| + |
| + void DrawImage(const SkBitmap& bm, |
| + int sx, int sy, int sw, int sh, |
| + int dx, int dy, int dw, int dh); |
| + |
| + inline void Clip() { |
| + canvas_->clipPath(*path_); |
| + } |
| +} CanvasState; |
| + |
| +#endif // EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_ |
| + |