| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "math.h" |
| |
| #include "sky/engine/core/painting/Canvas.h" |
| |
| #include "sky/engine/core/dom/Document.h" |
| #include "sky/engine/core/dom/Element.h" |
| #include "sky/engine/core/painting/CanvasImage.h" |
| #include "sky/engine/core/painting/Matrix.h" |
| #include "sky/engine/core/painting/PaintingTasks.h" |
| #include "sky/engine/platform/geometry/IntRect.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| |
| namespace blink { |
| |
| Canvas::Canvas(SkCanvas* skCanvas) |
| : m_canvas(skCanvas) |
| { |
| } |
| |
| Canvas::~Canvas() |
| { |
| } |
| |
| void Canvas::save() |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->save(); |
| } |
| |
| void Canvas::saveLayer(const Rect& bounds, const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->saveLayer(!bounds.is_null ? &bounds.sk_rect : nullptr, |
| paint.paint()); |
| } |
| |
| void Canvas::restore() |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->restore(); |
| } |
| |
| int Canvas::getSaveCount() |
| { |
| if (!m_canvas) |
| return 0; |
| return m_canvas->getSaveCount(); |
| } |
| |
| void Canvas::translate(float dx, float dy) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->translate(dx, dy); |
| } |
| |
| void Canvas::scale(float sx, float sy) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->scale(sx, sy); |
| } |
| |
| void Canvas::rotate(float radians) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->rotate(radians * 180.0/M_PI); |
| } |
| |
| void Canvas::skew(float sx, float sy) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->skew(sx, sy); |
| } |
| |
| void Canvas::concat(const Float32List& matrix4, ExceptionState& es) |
| { |
| if (!m_canvas) |
| return es.ThrowTypeError("No canvas"); |
| |
| SkMatrix sk_matrix = toSkMatrix(matrix4, es); |
| if (es.had_exception()) |
| return; |
| m_canvas->concat(sk_matrix); |
| } |
| |
| void Canvas::setMatrix(const Float32List& matrix4, ExceptionState& es) |
| { |
| if (!m_canvas) |
| return es.ThrowTypeError("No canvas"); |
| |
| SkMatrix sk_matrix = toSkMatrix(matrix4, es); |
| if (es.had_exception()) |
| return; |
| m_canvas->setMatrix(sk_matrix); |
| } |
| |
| Float32List Canvas::getTotalMatrix() const |
| { |
| // Maybe we should throw an exception instead of returning an empty matrix? |
| SkMatrix sk_matrix; |
| if (m_canvas) |
| sk_matrix = m_canvas->getTotalMatrix(); |
| return toMatrix4(sk_matrix); |
| } |
| |
| void Canvas::clipRect(const Rect& rect) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->clipRect(rect.sk_rect); |
| } |
| |
| void Canvas::clipRRect(const RRect* rrect) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->clipRRect(rrect->rrect(), SkRegion::kIntersect_Op, true); |
| } |
| |
| void Canvas::clipPath(const CanvasPath* path) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->clipPath(path->path(), SkRegion::kIntersect_Op, true); |
| } |
| |
| void Canvas::drawColor(SkColor color, SkXfermode::Mode transferMode) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->drawColor(color, transferMode); |
| } |
| |
| void Canvas::drawLine(const Point& p1, const Point& p2, const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->drawLine(p1.sk_point.x(), p1.sk_point.y(), p2.sk_point.x(), p2.sk_point.y(), paint.sk_paint); |
| } |
| |
| void Canvas::drawPaint(const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->drawPaint(paint.sk_paint); |
| } |
| |
| void Canvas::drawRect(const Rect& rect, const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->drawRect(rect.sk_rect, paint.sk_paint); |
| } |
| |
| void Canvas::drawRRect(const RRect* rrect, const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(rrect); |
| m_canvas->drawRRect(rrect->rrect(), paint.sk_paint); |
| } |
| |
| void Canvas::drawDRRect(const RRect* outer, const RRect* inner, const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(outer); |
| ASSERT(inner); |
| m_canvas->drawDRRect(outer->rrect(), inner->rrect(), paint.sk_paint); |
| } |
| |
| void Canvas::drawOval(const Rect& rect, const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->drawOval(rect.sk_rect, paint.sk_paint); |
| } |
| |
| void Canvas::drawCircle(const Point& c, float radius, const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| m_canvas->drawCircle(c.sk_point.x(), c.sk_point.y(), radius, paint.sk_paint); |
| } |
| |
| void Canvas::drawPath(const CanvasPath* path, const Paint& paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(path); |
| m_canvas->drawPath(path->path(), paint.sk_paint); |
| } |
| |
| void Canvas::drawImage(const CanvasImage* image, const Point& p, const Paint& paint) { |
| if (!m_canvas) |
| return; |
| ASSERT(image); |
| m_canvas->drawImage(image->image(), p.sk_point.x(), p.sk_point.y(), paint.paint()); |
| } |
| |
| void Canvas::drawImageRect(const CanvasImage* image, Rect& src, Rect& dst, const Paint& paint) { |
| if (!m_canvas) |
| return; |
| ASSERT(image); |
| m_canvas->drawImageRect(image->image(), &src.sk_rect, dst.sk_rect, paint.paint()); |
| } |
| |
| void Canvas::drawPicture(Picture* picture) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(picture); |
| m_canvas->drawPicture(picture->toSkia()); |
| } |
| |
| void Canvas::drawDrawable(Drawable* drawable) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(drawable); |
| m_canvas->drawDrawable(drawable->toSkia()); |
| } |
| |
| void Canvas::drawPaintingNode(PaintingNode* paintingNode, const Point& p) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(paintingNode); |
| translate(p.sk_point.x(), p.sk_point.y()); |
| m_canvas->drawDrawable(paintingNode->toSkia()); |
| translate(-p.sk_point.x(), -p.sk_point.y()); |
| } |
| |
| void Canvas::drawAtlas(CanvasImage* atlas, |
| const Vector<RSTransform>& transforms, const Vector<Rect>& rects, |
| const Vector<SkColor>& colors, SkXfermode::Mode mode, |
| const Rect& cullRect, const Paint& paint, ExceptionState& es) |
| { |
| if (!m_canvas) |
| return; |
| RefPtr<SkImage> skImage = atlas->image(); |
| if (transforms.size() != rects.size()) |
| return es.ThrowRangeError("transforms and rects lengths must match"); |
| if (colors.size() && colors.size() != rects.size()) |
| return es.ThrowRangeError("if supplied, colors length must match that of transforms and rects"); |
| |
| Vector<SkRSXform> skXForms; |
| for (size_t x = 0; x < transforms.size(); x++) { |
| const RSTransform& transform = transforms[x]; |
| if (transform.is_null) |
| return es.ThrowRangeError("transforms contained a null"); |
| skXForms.append(transform.sk_xform); |
| } |
| |
| Vector<SkRect> skRects; |
| for (size_t x = 0; x < rects.size(); x++) { |
| const Rect& rect = rects[x]; |
| if (rect.is_null) |
| return es.ThrowRangeError("rects contained a null"); |
| skRects.append(rect.sk_rect); |
| } |
| |
| m_canvas->drawAtlas( |
| skImage.get(), |
| skXForms.data(), |
| skRects.data(), |
| colors.isEmpty() ? nullptr : colors.data(), |
| skXForms.size(), |
| mode, |
| cullRect.is_null ? nullptr : &cullRect.sk_rect, |
| paint.paint() |
| ); |
| } |
| |
| |
| } // namespace blink |