提交 81233b6d 编写于 作者: A Adam Barth

Add a basic custom painting facility to Sky

This CL adds just enough custom painting to Sky to make
sky/examples/painting/circle.sky draw a circle. Over time, we should be able to
elaborate this system into something interesting and to make it actually work
in a reasonable way.

R=ojan@chromium.org

Review URL: https://codereview.chromium.org/1017593005
上级 2239d670
...@@ -124,7 +124,12 @@ def generate_arguments_contents(arguments, call_with_this_handle): ...@@ -124,7 +124,12 @@ def generate_arguments_contents(arguments, call_with_this_handle):
for argument in arguments] for argument in arguments]
if call_with_this_handle: if call_with_this_handle:
argument_declarations.insert(0, 'ScriptValue thisValue') argument_declarations.insert(0, 'ScriptValue thisValue')
dart_argument_declarations = [
'%s %s' % (dart_types.idl_type_to_dart_type(argument.idl_type), argument.name)
for argument in arguments]
return { return {
'argument_declarations': argument_declarations, 'argument_declarations': argument_declarations,
'dart_argument_declarations': dart_argument_declarations,
'arguments': [generate_argument(argument) for argument in arguments], 'arguments': [generate_argument(argument) for argument in arguments],
} }
...@@ -718,7 +718,7 @@ CPP_VALUE_TO_DART_VALUE = { ...@@ -718,7 +718,7 @@ CPP_VALUE_TO_DART_VALUE = {
'DartValue': 'DartConverter<DartValue*>::ToDart({cpp_value})', 'DartValue': 'DartConverter<DartValue*>::ToDart({cpp_value})',
# General # General
'array': 'VectorToDart({cpp_value})', 'array': 'VectorToDart({cpp_value})',
'DOMWrapper': 'Dart{idl_type}::toDart({cpp_value})', 'DOMWrapper': 'DartConverter<{idl_type}*>::ToDart({cpp_value})',
} }
......
...@@ -5,4 +5,4 @@ ...@@ -5,4 +5,4 @@
// WARNING: Do not edit - generated code. // WARNING: Do not edit - generated code.
part of dart.sky; part of dart.sky;
typedef void {{cpp_class}}({{methods[0].argument_declarations | join(', ')}}); typedef void {{cpp_class}}({{methods[0].dart_argument_declarations | join(', ')}});
\ No newline at end of file \ No newline at end of file
...@@ -942,6 +942,8 @@ sky_core_files = [ ...@@ -942,6 +942,8 @@ sky_core_files = [
"page/SpellCheckerClient.h", "page/SpellCheckerClient.h",
"painting/Paint.cpp", "painting/Paint.cpp",
"painting/Paint.h", "painting/Paint.h",
"painting/PaintingCallback.cpp",
"painting/PaintingCallback.h",
"painting/PaintingContext.cpp", "painting/PaintingContext.cpp",
"painting/PaintingContext.h", "painting/PaintingContext.h",
"rendering/BidiRun.h", "rendering/BidiRun.h",
...@@ -1239,6 +1241,7 @@ core_idl_files = get_path_info([ ...@@ -1239,6 +1241,7 @@ core_idl_files = get_path_info([
"html/TextMetrics.idl", "html/TextMetrics.idl",
"html/VoidCallback.idl", "html/VoidCallback.idl",
"painting/Paint.idl", "painting/Paint.idl",
"painting/PaintingCallback.idl",
"painting/PaintingContext.idl", "painting/PaintingContext.idl",
], ],
"abspath") "abspath")
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "sky/engine/config.h" #include "sky/engine/config.h"
#include "sky/engine/core/dom/Element.h" #include "sky/engine/core/dom/Element.h"
#include "base/bind.h"
#include "gen/sky/core/CSSValueKeywords.h" #include "gen/sky/core/CSSValueKeywords.h"
#include "gen/sky/core/HTMLNames.h" #include "gen/sky/core/HTMLNames.h"
#include "gen/sky/platform/RuntimeEnabledFeatures.h" #include "gen/sky/platform/RuntimeEnabledFeatures.h"
...@@ -49,6 +50,7 @@ ...@@ -49,6 +50,7 @@
#include "sky/engine/core/dom/ElementRareData.h" #include "sky/engine/core/dom/ElementRareData.h"
#include "sky/engine/core/dom/ElementTraversal.h" #include "sky/engine/core/dom/ElementTraversal.h"
#include "sky/engine/core/dom/ExceptionCode.h" #include "sky/engine/core/dom/ExceptionCode.h"
#include "sky/engine/core/dom/Microtask.h"
#include "sky/engine/core/dom/MutationObserverInterestGroup.h" #include "sky/engine/core/dom/MutationObserverInterestGroup.h"
#include "sky/engine/core/dom/MutationRecord.h" #include "sky/engine/core/dom/MutationRecord.h"
#include "sky/engine/core/dom/NodeRenderStyle.h" #include "sky/engine/core/dom/NodeRenderStyle.h"
...@@ -75,6 +77,8 @@ ...@@ -75,6 +77,8 @@
#include "sky/engine/core/page/ChromeClient.h" #include "sky/engine/core/page/ChromeClient.h"
#include "sky/engine/core/page/FocusController.h" #include "sky/engine/core/page/FocusController.h"
#include "sky/engine/core/page/Page.h" #include "sky/engine/core/page/Page.h"
#include "sky/engine/core/painting/PaintingContext.h"
#include "sky/engine/core/painting/PaintingCallback.h"
#include "sky/engine/core/rendering/RenderLayer.h" #include "sky/engine/core/rendering/RenderLayer.h"
#include "sky/engine/core/rendering/RenderView.h" #include "sky/engine/core/rendering/RenderView.h"
#include "sky/engine/platform/EventDispatchForbiddenScope.h" #include "sky/engine/platform/EventDispatchForbiddenScope.h"
...@@ -413,6 +417,38 @@ PassRefPtr<ClientRect> Element::getBoundingClientRect() ...@@ -413,6 +417,38 @@ PassRefPtr<ClientRect> Element::getBoundingClientRect()
return ClientRect::create(result); return ClientRect::create(result);
} }
// TODO(abarth): We should schedule this work at a more reasonable time.
static void handlePaintingCommit(RefPtr<Element> element, RefPtr<PaintingContext> context)
{
if (!element->document().isActive())
return;
element->document().updateLayout();
RenderObject* renderer = element->renderer();
if (!renderer || !renderer->isBox())
return;
toRenderBox(renderer)->setCustomPainting(context->takeDisplayList());
element->document().scheduleVisualUpdate();
}
// TODO(abarth): We should schedule this work at a more reasonable time.
static void runPaintingCallback(RefPtr<Element> element, PassOwnPtr<PaintingCallback> callback)
{
if (!element->document().isActive())
return;
element->document().updateLayout();
RenderObject* renderer = element->renderer();
if (!renderer || !renderer->isBox())
return;
RefPtr<PaintingContext> context = PaintingContext::create(
toRenderBox(renderer)->size(), base::Bind(&handlePaintingCommit, element));
callback->handleEvent(context.get());
}
void Element::requestPaint(PassOwnPtr<PaintingCallback> callback)
{
Microtask::enqueueMicrotask(base::Bind(&runPaintingCallback, this, callback));
}
void Element::setAttribute(const AtomicString& localName, const AtomicString& value, ExceptionState& exceptionState) void Element::setAttribute(const AtomicString& localName, const AtomicString& value, ExceptionState& exceptionState)
{ {
if (!Document::isValidName(localName)) { if (!Document::isValidName(localName)) {
......
...@@ -51,6 +51,7 @@ class ExceptionState; ...@@ -51,6 +51,7 @@ class ExceptionState;
class Image; class Image;
class IntSize; class IntSize;
class MutableStylePropertySet; class MutableStylePropertySet;
class PaintingCallback;
class PropertySetCSSStyleDeclaration; class PropertySetCSSStyleDeclaration;
class PseudoElement; class PseudoElement;
class ShadowRoot; class ShadowRoot;
...@@ -126,6 +127,8 @@ public: ...@@ -126,6 +127,8 @@ public:
PassRefPtr<ClientRectList> getClientRects(); PassRefPtr<ClientRectList> getClientRects();
PassRefPtr<ClientRect> getBoundingClientRect(); PassRefPtr<ClientRect> getBoundingClientRect();
void requestPaint(PassOwnPtr<PaintingCallback>);
virtual void didMoveToNewDocument(Document&) override; virtual void didMoveToNewDocument(Document&) override;
CSSStyleDeclaration* style(); CSSStyleDeclaration* style();
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
readonly attribute ShadowRoot shadowRoot; readonly attribute ShadowRoot shadowRoot;
void requestPaint(PaintingCallback callback);
// TODO(abarth): Move to Node. // TODO(abarth): Move to Node.
readonly attribute CSSStyleDeclaration style; readonly attribute CSSStyleDeclaration style;
......
...@@ -29,7 +29,7 @@ public: ...@@ -29,7 +29,7 @@ public:
void setARGB(unsigned a, unsigned r, unsigned g, unsigned b) void setARGB(unsigned a, unsigned r, unsigned g, unsigned b)
{ {
m_paint.setARGB(r, g, b, a); m_paint.setARGB(a, r, g, b);
} }
const SkPaint& paint() const { return m_paint; } const SkPaint& paint() const { return m_paint; }
......
// 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 "sky/engine/config.h"
#include "sky/engine/core/painting/PaintingCallback.h"
namespace blink {
PaintingCallback::~PaintingCallback()
{
}
} // namespace blink
// 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.
#ifndef SKY_ENGINE_CORE_PAINTING_PAINTINGCALLBACK_H_
#define SKY_ENGINE_CORE_PAINTING_PAINTINGCALLBACK_H_
namespace blink {
class PaintingContext;
class PaintingCallback {
public:
virtual ~PaintingCallback();
virtual void handleEvent(PaintingContext* context) = 0;
};
} // namespace blink
#endif // SKY_ENGINE_CORE_PAINTING_PAINTINGCALLBACK_H_
// 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.
callback interface PaintingCallback {
void handleEvent(PaintingContext context);
};
...@@ -5,15 +5,19 @@ ...@@ -5,15 +5,19 @@
#include "sky/engine/config.h" #include "sky/engine/config.h"
#include "sky/engine/core/painting/PaintingContext.h" #include "sky/engine/core/painting/PaintingContext.h"
#include "base/bind.h"
#include "sky/engine/core/dom/Microtask.h"
#include "sky/engine/platform/geometry/IntRect.h" #include "sky/engine/platform/geometry/IntRect.h"
#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkCanvas.h"
namespace blink { namespace blink {
PaintingContext::PaintingContext(const FloatRect& bounds) PaintingContext::PaintingContext(const FloatSize& size, const CommitCallback& commitCallback)
: m_size(size)
, m_commitCallback(commitCallback)
{ {
m_displayList = adoptRef(new DisplayList(bounds)); m_displayList = adoptRef(new DisplayList);
m_canvas = m_displayList->beginRecording(enclosingIntRect(bounds).size()); m_canvas = m_displayList->beginRecording(expandedIntSize(size));
} }
PaintingContext::~PaintingContext() PaintingContext::~PaintingContext()
...@@ -31,8 +35,11 @@ void PaintingContext::drawCircle(double x, double y, double radius, Paint* paint ...@@ -31,8 +35,11 @@ void PaintingContext::drawCircle(double x, double y, double radius, Paint* paint
void PaintingContext::commit() void PaintingContext::commit()
{ {
if (!m_canvas)
return;
m_displayList->endRecording(); m_displayList->endRecording();
m_canvas = nullptr; m_canvas = nullptr;
Microtask::enqueueMicrotask(base::Bind(m_commitCallback, this));
} }
} // namespace blink } // namespace blink
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef SKY_ENGINE_CORE_PAINTING_PAINTINGCONTEXT_H_ #ifndef SKY_ENGINE_CORE_PAINTING_PAINTINGCONTEXT_H_
#define SKY_ENGINE_CORE_PAINTING_PAINTINGCONTEXT_H_ #define SKY_ENGINE_CORE_PAINTING_PAINTINGCONTEXT_H_
#include "base/callback.h"
#include "sky/engine/core/painting/Paint.h" #include "sky/engine/core/painting/Paint.h"
#include "sky/engine/platform/graphics/DisplayList.h" #include "sky/engine/platform/graphics/DisplayList.h"
#include "sky/engine/tonic/dart_wrappable.h" #include "sky/engine/tonic/dart_wrappable.h"
...@@ -16,18 +17,31 @@ namespace blink { ...@@ -16,18 +17,31 @@ namespace blink {
class PaintingContext : public RefCounted<PaintingContext>, public DartWrappable { class PaintingContext : public RefCounted<PaintingContext>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
public: public:
typedef base::Callback<void (RefPtr<PaintingContext>)> CommitCallback;
~PaintingContext() override; ~PaintingContext() override;
PassRefPtr<PaintingContext> create(const FloatRect& bounds) { return adoptRef(new PaintingContext(bounds)); } static PassRefPtr<PaintingContext> create(const FloatSize& size, const CommitCallback& commitCallback)
{
return adoptRef(new PaintingContext(size, commitCallback));
}
double height() const { return m_displayList->bounds().height(); } double height() const { return m_size.height(); }
double width() const { return m_displayList->bounds().width(); } double width() const { return m_size.width(); }
void drawCircle(double x, double y, double radius, Paint* paint); void drawCircle(double x, double y, double radius, Paint* paint);
void commit(); void commit();
PassRefPtr<DisplayList> takeDisplayList()
{
ASSERT(!m_canvas);
return m_displayList.release();
}
private: private:
PaintingContext(const FloatRect& bounds); PaintingContext(const FloatSize& size, const CommitCallback& commitCallback);
FloatSize m_size;
CommitCallback m_commitCallback;
RefPtr<DisplayList> m_displayList; RefPtr<DisplayList> m_displayList;
SkCanvas* m_canvas; SkCanvas* m_canvas;
}; };
......
...@@ -7,6 +7,5 @@ interface PaintingContext { ...@@ -7,6 +7,5 @@ interface PaintingContext {
readonly attribute double width; readonly attribute double width;
void drawCircle(double x, double y, double radius, Paint paint); void drawCircle(double x, double y, double radius, Paint paint);
void commit(); void commit();
}; };
...@@ -989,6 +989,12 @@ void RenderBox::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutP ...@@ -989,6 +989,12 @@ void RenderBox::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutP
LayoutRect paintRect = borderBoxRect(); LayoutRect paintRect = borderBoxRect();
paintRect.moveBy(paintOffset); paintRect.moveBy(paintOffset);
paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect); paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect);
// TODO(abarth): Currently we only draw m_customPainting if we happen to
// have a box decoration or a background. Instead, we should probably have
// another function like paintBoxDecorationBackground that subclasses can
// call to draw m_customPainting.
if (m_customPainting)
paintInfo.context->drawDisplayList(m_customPainting.get(), paintRect.location());
} }
void RenderBox::paintBoxDecorationBackgroundWithRect(PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutRect& paintRect) void RenderBox::paintBoxDecorationBackgroundWithRect(PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutRect& paintRect)
......
...@@ -450,6 +450,8 @@ public: ...@@ -450,6 +450,8 @@ public:
bool hasSameDirectionAs(const RenderBox* object) const { return style()->direction() == object->style()->direction(); } bool hasSameDirectionAs(const RenderBox* object) const { return style()->direction() == object->style()->direction(); }
void setCustomPainting(PassRefPtr<DisplayList> customPainting) { m_customPainting = customPainting; }
protected: protected:
virtual void willBeDestroyed() override; virtual void willBeDestroyed() override;
...@@ -569,6 +571,7 @@ protected: ...@@ -569,6 +571,7 @@ protected:
OwnPtr<TransformationMatrix> m_transform; OwnPtr<TransformationMatrix> m_transform;
private: private:
RefPtr<DisplayList> m_customPainting;
OwnPtr<RenderLayer> m_layer; OwnPtr<RenderLayer> m_layer;
OwnPtr<RenderBoxRareData> m_rareData; OwnPtr<RenderBoxRareData> m_rareData;
}; };
......
...@@ -38,8 +38,7 @@ ...@@ -38,8 +38,7 @@
namespace blink { namespace blink {
DisplayList::DisplayList(const FloatRect& bounds) DisplayList::DisplayList()
: m_bounds(bounds)
{ {
} }
...@@ -47,11 +46,6 @@ DisplayList::~DisplayList() ...@@ -47,11 +46,6 @@ DisplayList::~DisplayList()
{ {
} }
const FloatRect& DisplayList::bounds() const
{
return m_bounds;
}
SkPicture* DisplayList::picture() const SkPicture* DisplayList::picture() const
{ {
return m_picture.get(); return m_picture.get();
......
...@@ -49,11 +49,9 @@ class PLATFORM_EXPORT DisplayList final : public WTF::RefCounted<DisplayList> { ...@@ -49,11 +49,9 @@ class PLATFORM_EXPORT DisplayList final : public WTF::RefCounted<DisplayList> {
WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(DisplayList); WTF_MAKE_NONCOPYABLE(DisplayList);
public: public:
DisplayList(const FloatRect&); DisplayList();
~DisplayList(); ~DisplayList();
const FloatRect& bounds() const;
// This entry point will return 0 when the DisplayList is in the // This entry point will return 0 when the DisplayList is in the
// midst of recording (i.e., between a beginRecording/endRecording pair) // midst of recording (i.e., between a beginRecording/endRecording pair)
// and if no recording has ever been completed. Otherwise it will return // and if no recording has ever been completed. Otherwise it will return
...@@ -65,7 +63,6 @@ public: ...@@ -65,7 +63,6 @@ public:
void endRecording(); void endRecording();
private: private:
FloatRect m_bounds;
RefPtr<SkPicture> m_picture; RefPtr<SkPicture> m_picture;
OwnPtr<SkPictureRecorder> m_recorder; OwnPtr<SkPictureRecorder> m_recorder;
}; };
......
...@@ -98,19 +98,6 @@ struct GraphicsContext::CanvasSaveState { ...@@ -98,19 +98,6 @@ struct GraphicsContext::CanvasSaveState {
int m_restoreCount; int m_restoreCount;
}; };
struct GraphicsContext::RecordingState {
RecordingState(SkCanvas* currentCanvas, const SkMatrix& currentMatrix, PassRefPtr<DisplayList> displayList)
: m_savedCanvas(currentCanvas)
, m_displayList(displayList)
, m_savedMatrix(currentMatrix)
{
}
SkCanvas* m_savedCanvas;
RefPtr<DisplayList> m_displayList;
const SkMatrix m_savedMatrix;
};
GraphicsContext::GraphicsContext(SkCanvas* canvas, DisabledMode disableContextOrPainting) GraphicsContext::GraphicsContext(SkCanvas* canvas, DisabledMode disableContextOrPainting)
: m_canvas(canvas) : m_canvas(canvas)
, m_paintStateStack() , m_paintStateStack()
...@@ -144,7 +131,6 @@ GraphicsContext::~GraphicsContext() ...@@ -144,7 +131,6 @@ GraphicsContext::~GraphicsContext()
ASSERT(!m_paintStateIndex); ASSERT(!m_paintStateIndex);
ASSERT(!m_paintState->saveCount()); ASSERT(!m_paintState->saveCount());
ASSERT(!m_layerCount); ASSERT(!m_layerCount);
ASSERT(m_recordingStateStack.isEmpty());
ASSERT(m_canvasStateStack.isEmpty()); ASSERT(m_canvasStateStack.isEmpty());
} }
#endif #endif
...@@ -332,14 +318,7 @@ SkMatrix GraphicsContext::getTotalMatrix() const ...@@ -332,14 +318,7 @@ SkMatrix GraphicsContext::getTotalMatrix() const
if (contextDisabled()) if (contextDisabled())
return SkMatrix::I(); return SkMatrix::I();
if (!isRecording()) return m_canvas->getTotalMatrix();
return m_canvas->getTotalMatrix();
const RecordingState& recordingState = m_recordingStateStack.last();
SkMatrix totalMatrix = recordingState.m_savedMatrix;
totalMatrix.preConcat(m_canvas->getTotalMatrix());
return totalMatrix;
} }
void GraphicsContext::adjustTextRenderMode(SkPaint* paint) void GraphicsContext::adjustTextRenderMode(SkPaint* paint)
...@@ -447,64 +426,18 @@ void GraphicsContext::endLayer() ...@@ -447,64 +426,18 @@ void GraphicsContext::endLayer()
#endif #endif
} }
void GraphicsContext::beginRecording(const FloatRect& bounds) void GraphicsContext::drawDisplayList(DisplayList* displayList, const FloatPoint& point)
{
RefPtr<DisplayList> displayList = adoptRef(new DisplayList(bounds));
SkCanvas* savedCanvas = m_canvas;
SkMatrix savedMatrix = getTotalMatrix();
if (!contextDisabled()) {
IntRect recordingRect = enclosingIntRect(bounds);
m_canvas = displayList->beginRecording(recordingRect.size());
// We want the bounds offset mapped to (0, 0), such that the display list content
// is fully contained within the SkPictureRecord's bounds.
if (!toFloatSize(bounds.location()).isZero()) {
m_canvas->translate(-bounds.x(), -bounds.y());
// To avoid applying the offset repeatedly in getTotalMatrix(), we pre-apply it here.
savedMatrix.preTranslate(bounds.x(), bounds.y());
}
}
m_recordingStateStack.append(RecordingState(savedCanvas, savedMatrix, displayList));
}
PassRefPtr<DisplayList> GraphicsContext::endRecording()
{
ASSERT(!m_recordingStateStack.isEmpty());
RecordingState recording = m_recordingStateStack.last();
if (!contextDisabled()) {
ASSERT(recording.m_displayList->isRecording());
recording.m_displayList->endRecording();
}
m_recordingStateStack.removeLast();
m_canvas = recording.m_savedCanvas;
return recording.m_displayList.release();
}
bool GraphicsContext::isRecording() const
{
return !m_recordingStateStack.isEmpty();
}
void GraphicsContext::drawDisplayList(DisplayList* displayList)
{ {
ASSERT(displayList); ASSERT(displayList);
ASSERT(!displayList->isRecording());
if (contextDisabled() || displayList->bounds().isEmpty()) if (contextDisabled())
return; return;
realizeCanvasSave(); realizeCanvasSave();
const FloatRect& bounds = displayList->bounds(); if (point.x() || point.y()) {
if (bounds.x() || bounds.y()) {
SkMatrix m; SkMatrix m;
m.setTranslate(bounds.x(), bounds.y()); m.setTranslate(point.x(), point.y());
m_canvas->drawPicture(displayList->picture(), &m, 0); m_canvas->drawPicture(displayList->picture(), &m, 0);
} else { } else {
m_canvas->drawPicture(displayList->picture()); m_canvas->drawPicture(displayList->picture());
......
...@@ -155,7 +155,7 @@ public: ...@@ -155,7 +155,7 @@ public:
// rotations of thin ("hairline") images. // rotations of thin ("hairline") images.
// Note: This will only be reliable when the device pixel scale/ratio is // Note: This will only be reliable when the device pixel scale/ratio is
// fixed (e.g. when drawing to context backed by an ImageBuffer). // fixed (e.g. when drawing to context backed by an ImageBuffer).
void disableAntialiasingOptimizationForHairlineImages() { ASSERT(!isRecording()); m_antialiasHairlineImages = true; } void disableAntialiasingOptimizationForHairlineImages() { m_antialiasHairlineImages = true; }
bool shouldAntialiasHairlineImages() const { return m_antialiasHairlineImages; } bool shouldAntialiasHairlineImages() const { return m_antialiasHairlineImages; }
void setShouldClampToSourceRect(bool clampToSourceRect) { mutableState()->setShouldClampToSourceRect(clampToSourceRect); } void setShouldClampToSourceRect(bool clampToSourceRect) { mutableState()->setShouldClampToSourceRect(clampToSourceRect); }
...@@ -258,7 +258,7 @@ public: ...@@ -258,7 +258,7 @@ public:
const IntRect&, const IntSize& innerTopLeft, const IntSize& innerTopRight, const IntSize& innerBottomLeft, const IntSize& innerBottomRight, const Color&); const IntRect&, const IntSize& innerTopLeft, const IntSize& innerTopRight, const IntSize& innerBottomLeft, const IntSize& innerBottomRight, const Color&);
void fillBetweenRoundedRects(const RoundedRect&, const RoundedRect&, const Color&); void fillBetweenRoundedRects(const RoundedRect&, const RoundedRect&, const Color&);
void drawDisplayList(DisplayList*); void drawDisplayList(DisplayList*, const FloatPoint&);
void drawImage(Image*, const IntPoint&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation); void drawImage(Image*, const IntPoint&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation); void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
...@@ -319,11 +319,6 @@ public: ...@@ -319,11 +319,6 @@ public:
void beginLayer(float opacity, CompositeOperator, const FloatRect* = 0, ColorFilter = ColorFilterNone, ImageFilter* = 0); void beginLayer(float opacity, CompositeOperator, const FloatRect* = 0, ColorFilter = ColorFilterNone, ImageFilter* = 0);
void endLayer(); void endLayer();
// Instead of being dispatched to the active canvas, draw commands following beginRecording()
// are stored in a display list that can be replayed at a later time.
void beginRecording(const FloatRect& bounds);
PassRefPtr<DisplayList> endRecording();
bool hasShadow() const; bool hasShadow() const;
void setShadow(const FloatSize& offset, float blur, const Color&, void setShadow(const FloatSize& offset, float blur, const Color&,
DrawLooperBuilder::ShadowTransformMode = DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowTransformMode = DrawLooperBuilder::ShadowRespectsTransforms,
...@@ -466,8 +461,6 @@ private: ...@@ -466,8 +461,6 @@ private:
void fillRectWithRoundedHole(const IntRect&, const RoundedRect& roundedHoleRect, const Color&); void fillRectWithRoundedHole(const IntRect&, const RoundedRect& roundedHoleRect, const Color&);
bool isRecording() const;
// null indicates painting is contextDisabled. Never delete this object. // null indicates painting is contextDisabled. Never delete this object.
SkCanvas* m_canvas; SkCanvas* m_canvas;
...@@ -487,9 +480,6 @@ private: ...@@ -487,9 +480,6 @@ private:
Vector<CanvasSaveState> m_canvasStateStack; Vector<CanvasSaveState> m_canvasStateStack;
bool m_pendingCanvasSave; bool m_pendingCanvasSave;
struct RecordingState;
Vector<RecordingState> m_recordingStateStack;
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
unsigned m_layerCount; unsigned m_layerCount;
bool m_disableDestructionChecks; bool m_disableDestructionChecks;
......
...@@ -1117,82 +1117,4 @@ TEST(GraphicsContextTest, OpaqueRegionForLayerWithRectDeviceClip) ...@@ -1117,82 +1117,4 @@ TEST(GraphicsContextTest, OpaqueRegionForLayerWithRectDeviceClip)
EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
} }
#define DISPATCH1(c1, c2, op, param1) do { c1.op(param1); c2.op(param1); } while (0);
#define DISPATCH2(c1, c2, op, param1, param2) do { c1.op(param1, param2); c2.op(param1, param2); } while (0);
TEST(GraphicsContextTest, RecordingTotalMatrix)
{
SkBitmap bitmap;
bitmap.allocN32Pixels(400, 400);
bitmap.eraseColor(0);
SkCanvas canvas(bitmap);
GraphicsContext context(&canvas);
SkCanvas controlCanvas(400, 400);
GraphicsContext controlContext(&controlCanvas);
EXPECT_EQ(context.getCTM(), controlContext.getCTM());
DISPATCH2(context, controlContext, scale, 2, 2);
EXPECT_EQ(context.getCTM(), controlContext.getCTM());
controlContext.save();
context.beginRecording(FloatRect(0, 0, 200, 200));
DISPATCH2(context, controlContext, translate, 10, 10);
EXPECT_EQ(context.getCTM(), controlContext.getCTM());
controlContext.save();
context.beginRecording(FloatRect(10, 10, 100, 100));
DISPATCH1(context, controlContext, rotate, 45);
EXPECT_EQ(context.getCTM(), controlContext.getCTM());
controlContext.restore();
context.endRecording();
EXPECT_EQ(context.getCTM(), controlContext.getCTM());
controlContext.restore();
context.endRecording();
EXPECT_EQ(context.getCTM(), controlContext.getCTM());
}
TEST(GraphicsContextTest, DisplayList)
{
FloatRect rect(0, 0, 1, 1);
RefPtr<DisplayList> dl = adoptRef(new DisplayList(rect));
// picture() returns 0 initially
SkPicture* pic = dl->picture();
EXPECT_FALSE(pic);
// endRecording without a beginRecording does nothing
dl->endRecording();
pic = dl->picture();
EXPECT_FALSE(pic);
// Two beginRecordings in a row generate two canvases.
// Unfortunately the new one could be allocated in the same
// spot as the old one so ref the first one to prolong its life.
IntSize size(1, 1);
SkCanvas* canvas1 = dl->beginRecording(size);
EXPECT_TRUE(canvas1);
canvas1->ref();
SkCanvas* canvas2 = dl->beginRecording(size);
EXPECT_TRUE(canvas2);
EXPECT_NE(canvas1, canvas2);
EXPECT_TRUE(canvas1->unique());
canvas1->unref();
EXPECT_TRUE(dl->isRecording());
// picture() returns 0 during recording
pic = dl->picture();
EXPECT_FALSE(pic);
// endRecording finally makes the picture accessible
dl->endRecording();
pic = dl->picture();
EXPECT_TRUE(pic);
EXPECT_TRUE(pic->unique());
}
} // namespace } // namespace
...@@ -63,17 +63,9 @@ void SourceGraphic::applySoftware() ...@@ -63,17 +63,9 @@ void SourceGraphic::applySoftware()
} }
} }
void SourceGraphic::setDisplayList(PassRefPtr<DisplayList> displayList)
{
m_displayList = displayList;
}
PassRefPtr<SkImageFilter> SourceGraphic::createImageFilter(SkiaImageFilterBuilder*) PassRefPtr<SkImageFilter> SourceGraphic::createImageFilter(SkiaImageFilterBuilder*)
{ {
if (!m_displayList) return nullptr;
return nullptr;
return adoptRef(SkPictureImageFilter::Create(m_displayList->picture(), m_displayList->bounds()));
} }
TextStream& SourceGraphic::externalRepresentation(TextStream& ts, int indent) const TextStream& SourceGraphic::externalRepresentation(TextStream& ts, int indent) const
......
...@@ -41,9 +41,6 @@ public: ...@@ -41,9 +41,6 @@ public:
virtual TextStream& externalRepresentation(TextStream&, int indention) const override; virtual TextStream& externalRepresentation(TextStream&, int indention) const override;
PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) override; PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) override;
void setDisplayList(PassRefPtr<DisplayList>);
private: private:
SourceGraphic(Filter* filter) SourceGraphic(Filter* filter)
: FilterEffect(filter) : FilterEffect(filter)
...@@ -52,7 +49,7 @@ private: ...@@ -52,7 +49,7 @@ private:
} }
virtual void applySoftware() override; virtual void applySoftware() override;
RefPtr<DisplayList> m_displayList; // TODO(sky): This class appears to be broken...
}; };
} //namespace blink } //namespace blink
......
<sky>
<style>
div {
height: 200px;
background-color: lightblue;
}
</style>
<div id="canvas" />
<script>
import 'dart:math' as math;
import 'dart:sky';
void main() {
var element = document.getElementById('canvas');
element.requestPaint((PaintingContext context) {
Paint paint = new Paint();
paint.setARGB(128, 0, 255, 0);
double radius = math.min(context.width, context.height) / 2.0;
context.drawCircle(context.width / 2.0, context.height / 2.0, radius, paint);
context.commit();
});
}
</script>
</sky>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册