| // 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/config.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/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(const FloatSize& size) |
| : m_size(size) |
| { |
| m_displayList = adoptRef(new DisplayList); |
| m_canvas = m_displayList->beginRecording(expandedIntSize(m_size)); |
| } |
| |
| Canvas::~Canvas() |
| { |
| } |
| |
| void Canvas::save() |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->save(); |
| } |
| |
| void Canvas::saveLayer(const Rect& bounds, const Paint* paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->saveLayer(!bounds.is_null ? &bounds.sk_rect : nullptr, |
| paint ? &paint->paint() : nullptr); |
| } |
| |
| void Canvas::restore() |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->restore(); |
| } |
| |
| void Canvas::translate(float dx, float dy) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->translate(dx, dy); |
| } |
| |
| void Canvas::scale(float sx, float sy) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->scale(sx, sy); |
| } |
| |
| void Canvas::rotate(float radians) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->rotate(radians * 180.0/M_PI); |
| } |
| |
| void Canvas::skew(float sx, float sy) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->skew(sx, sy); |
| } |
| |
| void Canvas::concat(const Float32List& matrix4) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| ASSERT(matrix4.data()); |
| |
| // TODO(mpcomplete): how can we raise an error in this case? |
| if (matrix4.num_elements() != 16) |
| return; |
| |
| SkMatrix sk_matrix; |
| // Mappings from SkMatrix-index to input-index. |
| static const int kMappings[] = { |
| 0, 4, 12, |
| 1, 5, 13, |
| 3, 7, 15, |
| }; |
| for (intptr_t i = 0; i < 9; ++i) |
| sk_matrix[i] = matrix4.data()[kMappings[i]]; |
| |
| m_canvas->concat(sk_matrix); |
| } |
| |
| void Canvas::clipRect(const Rect& rect) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->clipRect(rect.sk_rect); |
| } |
| |
| void Canvas::clipRRect(const RRect* rrect) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->clipRRect(rrect->rrect()); |
| } |
| |
| void Canvas::clipPath(const CanvasPath* path) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->clipPath(path->path()); |
| } |
| |
| void Canvas::drawLine(float x0, float y0, float x1, float y1, const Paint* paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(paint); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawLine(x0, y0, x1, y1, paint->paint()); |
| } |
| |
| void Canvas::drawPicture(Picture* picture) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(picture); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawPicture(picture->toSkia()); |
| } |
| |
| void Canvas::drawPaint(const Paint* paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(paint); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawPaint(paint->paint()); |
| } |
| |
| void Canvas::drawRect(const Rect& rect, const Paint* paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(paint); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawRect(rect.sk_rect, paint->paint()); |
| } |
| |
| void Canvas::drawRRect(const RRect* rrect, const Paint* paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(rrect); |
| ASSERT(paint); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawRRect(rrect->rrect(), paint->paint()); |
| } |
| |
| void Canvas::drawOval(const Rect& rect, const Paint* paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(paint); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawOval(rect.sk_rect, paint->paint()); |
| } |
| |
| void Canvas::drawCircle(float x, float y, float radius, const Paint* paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(paint); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawCircle(x, y, radius, paint->paint()); |
| } |
| |
| void Canvas::drawPath(const CanvasPath* path, const Paint* paint) |
| { |
| if (!m_canvas) |
| return; |
| ASSERT(path); |
| ASSERT(paint); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawPath(path->path(), paint->paint()); |
| } |
| |
| void Canvas::drawImage(const CanvasImage* image, |
| float x, |
| float y, |
| const Paint* paint) { |
| if (!m_canvas) |
| return; |
| ASSERT(image); |
| ASSERT(m_displayList->isRecording()); |
| m_canvas->drawBitmap(image->bitmap(), x, y, &paint->paint()); |
| } |
| |
| PassRefPtr<DisplayList> Canvas::finishRecording() |
| { |
| if (!isRecording()) |
| return nullptr; |
| m_canvas = nullptr; |
| m_displayList->endRecording(); |
| return m_displayList.release(); |
| } |
| |
| } // namespace blink |