提交 1eb17996 编写于 作者: E Eric Seidel

Make it possible to custom-paint without an Element.

This adds a new abstract 'Canvas' which is similar to SkCanvas.
PaintContext implements Canvas while still having its
own commit() method to cause the paint actions to apply to
the Element for the next frame.
This adds a new PictureRecorder which also implements Canvas
and has an endRecording() method which returns a Picture
(another new interface) which can be held from Dart.

There is also now a rootPicture setter on Document which takes
a Picture and will then make the Document draw that Picture
until changed.

This piggybacks on the existing custom painting system
which adds the painting at background-and-borders paint
time so technically if you both set rootPicture as well as
construct a DOM you will draw the DOM on top of your picture. :)

R=mpcomplete@chromium.org

Review URL: https://codereview.chromium.org/1122423009
上级 2772b9e4
......@@ -833,6 +833,8 @@ sky_core_files = [
"page/PageVisibilityState.cpp",
"page/PageVisibilityState.h",
"page/SpellCheckerClient.h",
"painting/Canvas.cpp",
"painting/Canvas.h",
"painting/Paint.cpp",
"painting/Paint.h",
"painting/PaintingCallback.cpp",
......@@ -841,6 +843,10 @@ sky_core_files = [
"painting/PaintingContext.h",
"painting/PaintingTasks.cpp",
"painting/PaintingTasks.h",
"painting/Picture.cpp",
"painting/Picture.h",
"painting/PictureRecorder.cpp",
"painting/PictureRecorder.h",
"rendering/BidiRun.h",
"rendering/BidiRunForLine.cpp",
"rendering/BidiRunForLine.h",
......@@ -1095,9 +1101,12 @@ core_idl_files = get_path_info([
"html/TextMetrics.idl",
"html/VoidCallback.idl",
"layout/LayoutCallback.idl",
"painting/Canvas.idl",
"painting/Paint.idl",
"painting/PaintingCallback.idl",
"painting/PaintingContext.idl",
"painting/Picture.idl",
"painting/PictureRecorder.idl",
],
"abspath")
......
......@@ -104,6 +104,8 @@
#include "sky/engine/core/page/EventHandler.h"
#include "sky/engine/core/page/FocusController.h"
#include "sky/engine/core/page/Page.h"
#include "sky/engine/core/painting/PaintingTasks.h"
#include "sky/engine/core/painting/Picture.h"
#include "sky/engine/core/rendering/HitTestResult.h"
#include "sky/engine/core/rendering/RenderView.h"
#include "sky/engine/platform/DateComponents.h"
......@@ -2204,6 +2206,19 @@ bool Document::hasFocus() const
return focusedFrame && focusedFrame == frame();
}
Picture* Document::rootPicture() const
{
return m_picture.get();
}
void Document::setRootPicture(PassRefPtr<Picture> picture)
{
m_picture = picture;
if (m_picture)
PaintingTasks::enqueueCommit(this, m_picture->displayList());
scheduleVisualUpdate();
}
} // namespace blink
#ifndef NDEBUG
......
......@@ -63,10 +63,11 @@ namespace blink {
class AbstractModule;
class AnimationTimeline;
class Attr;
class CSSStyleDeclaration;
class CSSStyleSheet;
class Comment;
class ConsoleMessage;
class CSSStyleDeclaration;
class CSSStyleSheet;
class CustomElementRegistry;
class DocumentFragment;
class DocumentLifecycleNotifier;
class DocumentLoadTiming;
......@@ -82,28 +83,28 @@ class FloatRect;
class Frame;
class FrameHost;
class FrameView;
class HitTestRequest;
class HTMLDocumentParser;
class HTMLElement;
class HTMLImport;
class HTMLImportLoader;
class HTMLImportsController;
class HTMLScriptElement;
class HitTestRequest;
class LayoutPoint;
class LocalDOMWindow;
class LocalFrame;
class Location;
class MediaQueryListListener;
class MediaQueryMatcher;
class CustomElementRegistry;
class Page;
class Picture;
class QualifiedName;
class Range;
class RenderView;
class RequestAnimationFrameCallback;
class ResourceFetcher;
class ScriptRunner;
class ScriptedAnimationController;
class ScriptRunner;
class SegmentedString;
class SelectorQueryCache;
class Settings;
......@@ -494,6 +495,9 @@ public:
void didRecalculateStyleForElement() { ++m_styleRecalcElementCounter; }
Picture* rootPicture() const;
void setRootPicture(PassRefPtr<Picture> picture);
protected:
explicit Document(const DocumentInit&);
......@@ -678,6 +682,8 @@ private:
int m_styleRecalcElementCounter;
mutable DocumentLoadTiming m_documentLoadTiming;
RefPtr<Picture> m_picture;
};
inline void Document::scheduleRenderTreeUpdateIfNeeded()
......
......@@ -69,4 +69,6 @@ callback CustomElementConstructor = Element ();
readonly attribute boolean hidden;
readonly attribute HTMLScriptElement currentScript;
attribute Picture rootPicture;
};
// 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/PictureRecorder.h"
#include "sky/engine/core/dom/Document.h"
#include "sky/engine/core/dom/Element.h"
#include "sky/engine/core/painting/PaintingTasks.h"
#include "sky/engine/platform/geometry/IntRect.h"
#include "third_party/skia/include/core/SkCanvas.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::drawCircle(double x, double y, double radius, Paint* paint)
{
if (!m_canvas)
return;
ASSERT(paint);
ASSERT(m_displayList->isRecording());
m_canvas->drawCircle(x, y, radius, paint->paint());
}
PassRefPtr<DisplayList> Canvas::finishRecording()
{
if (!isRecording())
return nullptr;
m_canvas = nullptr;
m_displayList->endRecording();
return m_displayList.release();
}
} // 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_CANVAS_H_
#define SKY_ENGINE_CORE_PAINTING_CANVAS_H_
#include "sky/engine/core/painting/Paint.h"
#include "sky/engine/platform/graphics/DisplayList.h"
#include "sky/engine/tonic/dart_wrappable.h"
#include "sky/engine/wtf/PassRefPtr.h"
#include "sky/engine/wtf/RefCounted.h"
namespace blink {
class Element;
class Canvas : public RefCounted<Canvas>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
Canvas(const FloatSize& size);
~Canvas() override;
// Width/Height define a culling rect which Skia may use for optimizing
// out draw calls issued outside the rect.
double width() const { return m_size.width(); }
double height() const { return m_size.height(); }
void drawCircle(double x, double y, double radius, Paint* paint);
protected:
PassRefPtr<DisplayList> finishRecording();
bool isRecording() const { return m_canvas; }
private:
FloatSize m_size;
RefPtr<DisplayList> m_displayList;
SkCanvas* m_canvas;
};
} // namespace blink
#endif // SKY_ENGINE_CORE_PAINTING_CANVAS_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.
interface Canvas {
// Height and width are used for culling optimizations and do not necessarily
// imply that the Canvas is backed by a buffer with any specific bounds.
readonly attribute double height;
readonly attribute double width;
void drawCircle(double x, double y, double radius, Paint paint);
};
......@@ -9,7 +9,6 @@
#include "sky/engine/core/dom/Element.h"
#include "sky/engine/core/painting/PaintingTasks.h"
#include "sky/engine/platform/geometry/IntRect.h"
#include "third_party/skia/include/core/SkCanvas.h"
namespace blink {
......@@ -19,33 +18,20 @@ PassRefPtr<PaintingContext> PaintingContext::create(PassRefPtr<Element> element,
}
PaintingContext::PaintingContext(PassRefPtr<Element> element, const FloatSize& size)
: m_element(element)
, m_size(size)
: Canvas(size)
, m_element(element)
{
m_displayList = adoptRef(new DisplayList);
m_canvas = m_displayList->beginRecording(expandedIntSize(m_size));
}
PaintingContext::~PaintingContext()
{
}
void PaintingContext::drawCircle(double x, double y, double radius, Paint* paint)
{
if (!m_canvas)
return;
ASSERT(paint);
ASSERT(m_displayList->isRecording());
m_canvas->drawCircle(x, y, radius, paint->paint());
}
void PaintingContext::commit()
{
if (!m_canvas)
if (!isRecording())
return;
m_displayList->endRecording();
m_canvas = nullptr;
PaintingTasks::enqueueCommit(m_element, m_displayList.release());
PaintingTasks::enqueueCommit(m_element, finishRecording());
m_element->document().scheduleVisualUpdate();
}
......
......@@ -5,34 +5,23 @@
#ifndef SKY_ENGINE_CORE_PAINTING_PAINTINGCONTEXT_H_
#define SKY_ENGINE_CORE_PAINTING_PAINTINGCONTEXT_H_
#include "sky/engine/core/painting/Paint.h"
#include "sky/engine/platform/graphics/DisplayList.h"
#include "sky/engine/tonic/dart_wrappable.h"
#include "sky/engine/wtf/PassRefPtr.h"
#include "sky/engine/wtf/RefCounted.h"
#include "sky/engine/core/painting/Canvas.h"
namespace blink {
class Element;
class PaintingContext : public RefCounted<PaintingContext>, public DartWrappable {
class PaintingContext : public Canvas {
DEFINE_WRAPPERTYPEINFO();
public:
~PaintingContext() override;
static PassRefPtr<PaintingContext> create(PassRefPtr<Element> element, const FloatSize& size);
double height() const { return m_size.height(); }
double width() const { return m_size.width(); }
void drawCircle(double x, double y, double radius, Paint* paint);
void commit();
private:
PaintingContext(PassRefPtr<Element> element, const FloatSize& size);
RefPtr<Element> m_element;
FloatSize m_size;
RefPtr<DisplayList> m_displayList;
SkCanvas* m_canvas;
};
} // namespace blink
......
......@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
interface PaintingContext {
readonly attribute double height;
readonly attribute double width;
void drawCircle(double x, double y, double radius, Paint paint);
interface PaintingContext : Canvas {
void commit();
};
......@@ -29,10 +29,10 @@ struct RequestTask {
};
struct CommitTask {
CommitTask(PassRefPtr<Element> e, PassRefPtr<DisplayList> d)
: element(e), displayList(d) { }
CommitTask(PassRefPtr<Node> n, PassRefPtr<DisplayList> d)
: node(n), displayList(d) { }
RefPtr<Element> element;
RefPtr<Node> node;
RefPtr<DisplayList> displayList;
};
......@@ -55,9 +55,9 @@ void PaintingTasks::enqueueRequest(PassRefPtr<Element> element, PassOwnPtr<Paint
requests().append(adoptPtr(new RequestTask(element, callback)));
}
void PaintingTasks::enqueueCommit(PassRefPtr<Element> element, PassRefPtr<DisplayList> displayList)
void PaintingTasks::enqueueCommit(PassRefPtr<Node> node, PassRefPtr<DisplayList> displayList)
{
commits().append(CommitTask(element, displayList));
commits().append(CommitTask(node, displayList));
}
bool PaintingTasks::serviceRequests()
......@@ -86,7 +86,7 @@ bool PaintingTasks::serviceRequests()
void PaintingTasks::drainCommits()
{
for (auto& commit : commits()) {
RenderObject* renderer = commit.element->renderer();
RenderObject* renderer = commit.node->renderer();
if (!renderer || !renderer->isBox())
return;
toRenderBox(renderer)->setCustomPainting(commit.displayList.release());
......
......@@ -11,12 +11,13 @@
namespace blink {
class DisplayList;
class Element;
class Node;
class PaintingCallback;
class PaintingTasks {
public:
static void enqueueRequest(PassRefPtr<Element>, PassOwnPtr<PaintingCallback>);
static void enqueueCommit(PassRefPtr<Element>, PassRefPtr<DisplayList>);
static void enqueueCommit(PassRefPtr<Node>, PassRefPtr<DisplayList>);
static bool serviceRequests();
static void drainCommits();
......
// 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/Picture.h"
#include "base/logging.h"
namespace blink {
PassRefPtr<Picture> Picture::create(PassRefPtr<DisplayList> list)
{
ASSERT(list);
return adoptRef(new Picture(list));
}
Picture::Picture(PassRefPtr<DisplayList> list)
: m_displayList(list)
{
}
Picture::~Picture()
{
}
} // 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_PICTURE_H_
#define SKY_ENGINE_CORE_PAINTING_PICTURE_H_
#include "sky/engine/platform/graphics/DisplayList.h"
#include "sky/engine/tonic/dart_wrappable.h"
#include "sky/engine/wtf/PassRefPtr.h"
#include "sky/engine/wtf/RefCounted.h"
namespace blink {
class Picture : public RefCounted<Picture>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
~Picture() override;
static PassRefPtr<Picture> create(PassRefPtr<DisplayList>);
DisplayList* displayList() const { return m_displayList.get(); }
private:
Picture(PassRefPtr<DisplayList>);
RefPtr<DisplayList> m_displayList;
};
} // namespace blink
#endif // SKY_ENGINE_CORE_PAINTING_PICTURE_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.
interface Picture {
};
// 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/PictureRecorder.h"
#include "sky/engine/core/painting/Picture.h"
namespace blink {
PassRefPtr<PictureRecorder> PictureRecorder::create(double width, double height)
{
return adoptRef(new PictureRecorder(FloatSize(width, height)));
}
PictureRecorder::PictureRecorder(const FloatSize& size)
: Canvas(size)
{
}
PictureRecorder::~PictureRecorder()
{
}
PassRefPtr<Picture> PictureRecorder::endRecording()
{
if (!isRecording())
return nullptr;
return Picture::create(finishRecording());
}
} // 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_PICTURERECORDER_H_
#define SKY_ENGINE_CORE_PAINTING_PICTURERECORDER_H_
#include "sky/engine/core/painting/Canvas.h"
namespace blink {
class Picture;
class PictureRecorder : public Canvas {
DEFINE_WRAPPERTYPEINFO();
public:
~PictureRecorder() override;
static PassRefPtr<PictureRecorder> create(double width, double height);
PassRefPtr<Picture> endRecording();
private:
PictureRecorder(const FloatSize& size);
};
} // namespace blink
#endif // SKY_ENGINE_CORE_PAINTING_PICTURERECORDER_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.
[
Constructor(double width, double height)
] interface PictureRecorder : Canvas {
Picture endRecording();
};
......@@ -994,19 +994,24 @@ BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsCo
return BackgroundBleedClipBackground;
}
void RenderBox::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
void RenderBox::paintCustomPainting(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
LayoutRect paintRect = borderBoxRect();
paintRect.moveBy(paintOffset);
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.
// have a box decoration or a background.
if (m_customPainting)
paintInfo.context->drawDisplayList(m_customPainting.get(), paintRect.location());
}
void RenderBox::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
LayoutRect paintRect = borderBoxRect();
paintRect.moveBy(paintOffset);
paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect);
paintCustomPainting(paintInfo, paintOffset);
}
void RenderBox::paintBoxDecorationBackgroundWithRect(PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutRect& paintRect)
{
RenderStyle* style = this->style();
......
......@@ -491,6 +491,8 @@ protected:
void updateIntrinsicContentLogicalHeight(LayoutUnit intrinsicContentLogicalHeight) const { m_intrinsicContentLogicalHeight = intrinsicContentLogicalHeight; }
void paintCustomPainting(PaintInfo& paintInfo, const LayoutPoint& paintOffset);
private:
void updateTransformationMatrix();
void updateTransform(const RenderStyle* oldStyle);
......
......@@ -196,7 +196,7 @@ void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, Vec
paintObject(paintInfo, paintOffset, layers);
}
void RenderView::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint&)
void RenderView::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
if (!view())
return;
......@@ -216,6 +216,7 @@ void RenderView::paintBoxDecorationBackground(PaintInfo& paintInfo, const Layout
paintInfo.context->clearRect(paintInfo.rect);
}
}
paintCustomPainting(paintInfo, paintOffset);
}
void RenderView::absoluteQuads(Vector<FloatQuad>& quads) const
......
<script>
import "dart:math";
import 'dart:sky';
void main() {
double width = window.innerWidth.toDouble();
double height = window.innerHeight.toDouble();
PictureRecorder recorder = new PictureRecorder(width, height);
double radius = min(width, height) * 0.45;
Paint paint = new Paint()..setARGB(255, 0, 255, 0);
recorder.drawCircle(width / 2, height / 2, radius, paint);
document.rootPicture = recorder.endRecording();
}
</script>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册