mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reland "Sequester all Skia<->DL interactions into the skia sub-module" (flutter/engine#40114)
Reland "Sequester all Skia<->DL interactions into the skia sub-module"
This commit is contained in:
parent
9369c1ed1f
commit
53a80bdedf
@ -29,12 +29,10 @@
|
||||
../../../flutter/build
|
||||
../../../flutter/ci
|
||||
../../../flutter/common/README.md
|
||||
../../../flutter/display_list/display_list_canvas_unittests.cc
|
||||
../../../flutter/display_list/display_list_color_filter_unittests.cc
|
||||
../../../flutter/display_list/display_list_color_source_unittests.cc
|
||||
../../../flutter/display_list/display_list_color_unittests.cc
|
||||
../../../flutter/display_list/display_list_complexity_unittests.cc
|
||||
../../../flutter/display_list/display_list_enum_unittests.cc
|
||||
../../../flutter/display_list/display_list_image_filter_unittests.cc
|
||||
../../../flutter/display_list/display_list_mask_filter_unittests.cc
|
||||
../../../flutter/display_list/display_list_matrix_clip_tracker_unittests.cc
|
||||
@ -42,8 +40,10 @@
|
||||
../../../flutter/display_list/display_list_path_effect_unittests.cc
|
||||
../../../flutter/display_list/display_list_rtree_unittests.cc
|
||||
../../../flutter/display_list/display_list_unittests.cc
|
||||
../../../flutter/display_list/display_list_utils_unittests.cc
|
||||
../../../flutter/display_list/display_list_vertices_unittests.cc
|
||||
../../../flutter/display_list/dl_rendering_unittests.cc
|
||||
../../../flutter/display_list/skia/dl_sk_conversions_unittests.cc
|
||||
../../../flutter/display_list/skia/dl_sk_utils_unittests.cc
|
||||
../../../flutter/display_list/testing
|
||||
../../../flutter/docs
|
||||
../../../flutter/examples
|
||||
|
||||
@ -714,8 +714,6 @@ ORIGIN: ../../../flutter/display_list/display_list_blend_mode.h + ../../../flutt
|
||||
ORIGIN: ../../../flutter/display_list/display_list_builder.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_builder.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_builder_benchmarks.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_canvas_dispatcher.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_canvas_dispatcher.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_color.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_color_filter.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_color_filter.h + ../../../flutter/LICENSE
|
||||
@ -729,8 +727,6 @@ ORIGIN: ../../../flutter/display_list/display_list_complexity_gl.h + ../../../fl
|
||||
ORIGIN: ../../../flutter/display_list/display_list_complexity_helper.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_complexity_metal.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_complexity_metal.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_dispatcher.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_dispatcher.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_flags.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_flags.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_image.cc + ../../../flutter/LICENSE
|
||||
@ -759,9 +755,18 @@ ORIGIN: ../../../flutter/display_list/display_list_utils.cc + ../../../flutter/L
|
||||
ORIGIN: ../../../flutter/display_list/display_list_utils.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_vertices.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/display_list_vertices.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/dl_canvas.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/dl_canvas.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/dl_op_receiver.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/dl_op_receiver.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/skia/dl_sk_canvas.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/skia/dl_sk_canvas.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/skia/dl_sk_conversions.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/skia/dl_sk_conversions.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/skia/dl_sk_dispatcher.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/skia/dl_sk_dispatcher.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/skia/dl_sk_utils.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/skia/dl_sk_utils.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/display_list/types.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/flow/compositor_context.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/flow/compositor_context.h + ../../../flutter/LICENSE
|
||||
@ -3244,8 +3249,6 @@ FILE: ../../../flutter/display_list/display_list_blend_mode.h
|
||||
FILE: ../../../flutter/display_list/display_list_builder.cc
|
||||
FILE: ../../../flutter/display_list/display_list_builder.h
|
||||
FILE: ../../../flutter/display_list/display_list_builder_benchmarks.cc
|
||||
FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.cc
|
||||
FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.h
|
||||
FILE: ../../../flutter/display_list/display_list_color.h
|
||||
FILE: ../../../flutter/display_list/display_list_color_filter.cc
|
||||
FILE: ../../../flutter/display_list/display_list_color_filter.h
|
||||
@ -3259,8 +3262,6 @@ FILE: ../../../flutter/display_list/display_list_complexity_gl.h
|
||||
FILE: ../../../flutter/display_list/display_list_complexity_helper.h
|
||||
FILE: ../../../flutter/display_list/display_list_complexity_metal.cc
|
||||
FILE: ../../../flutter/display_list/display_list_complexity_metal.h
|
||||
FILE: ../../../flutter/display_list/display_list_dispatcher.cc
|
||||
FILE: ../../../flutter/display_list/display_list_dispatcher.h
|
||||
FILE: ../../../flutter/display_list/display_list_flags.cc
|
||||
FILE: ../../../flutter/display_list/display_list_flags.h
|
||||
FILE: ../../../flutter/display_list/display_list_image.cc
|
||||
@ -3289,9 +3290,18 @@ FILE: ../../../flutter/display_list/display_list_utils.cc
|
||||
FILE: ../../../flutter/display_list/display_list_utils.h
|
||||
FILE: ../../../flutter/display_list/display_list_vertices.cc
|
||||
FILE: ../../../flutter/display_list/display_list_vertices.h
|
||||
FILE: ../../../flutter/display_list/dl_canvas.cc
|
||||
FILE: ../../../flutter/display_list/dl_canvas.h
|
||||
FILE: ../../../flutter/display_list/dl_op_receiver.cc
|
||||
FILE: ../../../flutter/display_list/dl_op_receiver.h
|
||||
FILE: ../../../flutter/display_list/skia/dl_sk_canvas.cc
|
||||
FILE: ../../../flutter/display_list/skia/dl_sk_canvas.h
|
||||
FILE: ../../../flutter/display_list/skia/dl_sk_conversions.cc
|
||||
FILE: ../../../flutter/display_list/skia/dl_sk_conversions.h
|
||||
FILE: ../../../flutter/display_list/skia/dl_sk_dispatcher.cc
|
||||
FILE: ../../../flutter/display_list/skia/dl_sk_dispatcher.h
|
||||
FILE: ../../../flutter/display_list/skia/dl_sk_utils.cc
|
||||
FILE: ../../../flutter/display_list/skia/dl_sk_utils.h
|
||||
FILE: ../../../flutter/display_list/types.h
|
||||
FILE: ../../../flutter/flow/compositor_context.cc
|
||||
FILE: ../../../flutter/flow/compositor_context.h
|
||||
|
||||
@ -16,8 +16,6 @@ source_set("display_list") {
|
||||
"display_list_blend_mode.h",
|
||||
"display_list_builder.cc",
|
||||
"display_list_builder.h",
|
||||
"display_list_canvas_dispatcher.cc",
|
||||
"display_list_canvas_dispatcher.h",
|
||||
"display_list_color.h",
|
||||
"display_list_color_filter.cc",
|
||||
"display_list_color_filter.h",
|
||||
@ -29,8 +27,6 @@ source_set("display_list") {
|
||||
"display_list_complexity_gl.h",
|
||||
"display_list_complexity_metal.cc",
|
||||
"display_list_complexity_metal.h",
|
||||
"display_list_dispatcher.cc",
|
||||
"display_list_dispatcher.h",
|
||||
"display_list_flags.cc",
|
||||
"display_list_flags.h",
|
||||
"display_list_image.cc",
|
||||
@ -59,9 +55,18 @@ source_set("display_list") {
|
||||
"display_list_utils.h",
|
||||
"display_list_vertices.cc",
|
||||
"display_list_vertices.h",
|
||||
"dl_canvas.cc",
|
||||
"dl_canvas.h",
|
||||
"dl_op_receiver.cc",
|
||||
"dl_op_receiver.h",
|
||||
"skia/dl_sk_canvas.cc",
|
||||
"skia/dl_sk_canvas.h",
|
||||
"skia/dl_sk_conversions.cc",
|
||||
"skia/dl_sk_conversions.h",
|
||||
"skia/dl_sk_dispatcher.cc",
|
||||
"skia/dl_sk_dispatcher.h",
|
||||
"skia/dl_sk_utils.cc",
|
||||
"skia/dl_sk_utils.h",
|
||||
"types.h",
|
||||
]
|
||||
|
||||
@ -93,7 +98,6 @@ if (enable_unittests) {
|
||||
"display_list_color_source_unittests.cc",
|
||||
"display_list_color_unittests.cc",
|
||||
"display_list_complexity_unittests.cc",
|
||||
"display_list_enum_unittests.cc",
|
||||
"display_list_image_filter_unittests.cc",
|
||||
"display_list_mask_filter_unittests.cc",
|
||||
"display_list_matrix_clip_tracker_unittests.cc",
|
||||
@ -101,8 +105,9 @@ if (enable_unittests) {
|
||||
"display_list_path_effect_unittests.cc",
|
||||
"display_list_rtree_unittests.cc",
|
||||
"display_list_unittests.cc",
|
||||
"display_list_utils_unittests.cc",
|
||||
"display_list_vertices_unittests.cc",
|
||||
"skia/dl_sk_conversions_unittests.cc",
|
||||
"skia/dl_sk_utils_unittests.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@ -130,7 +135,7 @@ if (enable_unittests) {
|
||||
executable("display_list_rendertests") {
|
||||
testonly = true
|
||||
|
||||
sources = [ "display_list_canvas_unittests.cc" ]
|
||||
sources = [ "dl_rendering_unittests.cc" ]
|
||||
|
||||
deps = [
|
||||
":display_list",
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
|
||||
#include "flutter/display_list/display_list.h"
|
||||
#include "flutter/display_list/display_list_builder.h"
|
||||
#include "flutter/display_list/display_list_canvas_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_ops.h"
|
||||
#include "flutter/fml/trace_event.h"
|
||||
|
||||
@ -134,38 +133,40 @@ class VectorCuller final : public Culler {
|
||||
std::vector<int>::const_iterator end_;
|
||||
};
|
||||
|
||||
void DisplayList::Dispatch(Dispatcher& ctx) const {
|
||||
void DisplayList::Dispatch(DlOpReceiver& receiver) const {
|
||||
uint8_t* ptr = storage_.get();
|
||||
Dispatch(ctx, ptr, ptr + byte_count_, NopCuller::instance);
|
||||
Dispatch(receiver, ptr, ptr + byte_count_, NopCuller::instance);
|
||||
}
|
||||
void DisplayList::Dispatch(Dispatcher& ctx, const SkRect& cull_rect) const {
|
||||
|
||||
void DisplayList::Dispatch(DlOpReceiver& receiver,
|
||||
const SkRect& cull_rect) const {
|
||||
if (cull_rect.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (cull_rect.contains(bounds())) {
|
||||
Dispatch(ctx);
|
||||
Dispatch(receiver);
|
||||
return;
|
||||
}
|
||||
const DlRTree* rtree = this->rtree().get();
|
||||
FML_DCHECK(rtree != nullptr);
|
||||
if (rtree == nullptr) {
|
||||
FML_LOG(ERROR) << "dispatched with culling rect on DL with no rtree";
|
||||
Dispatch(ctx);
|
||||
Dispatch(receiver);
|
||||
return;
|
||||
}
|
||||
uint8_t* ptr = storage_.get();
|
||||
std::vector<int> rect_indices;
|
||||
rtree->search(cull_rect, &rect_indices);
|
||||
VectorCuller culler(rtree, rect_indices);
|
||||
Dispatch(ctx, ptr, ptr + byte_count_, culler);
|
||||
Dispatch(receiver, ptr, ptr + byte_count_, culler);
|
||||
}
|
||||
|
||||
void DisplayList::Dispatch(Dispatcher& dispatcher,
|
||||
void DisplayList::Dispatch(DlOpReceiver& receiver,
|
||||
uint8_t* ptr,
|
||||
uint8_t* end,
|
||||
Culler& culler) const {
|
||||
DispatchContext context = {
|
||||
.dispatcher = dispatcher,
|
||||
.receiver = receiver,
|
||||
.cur_index = 0,
|
||||
// next_render_index will be initialized by culler.init()
|
||||
.next_restore_index = std::numeric_limits<int>::max(),
|
||||
@ -294,27 +295,6 @@ static bool CompareOps(uint8_t* ptrA,
|
||||
return true;
|
||||
}
|
||||
|
||||
void DisplayList::RenderTo(DisplayListBuilder* builder) const {
|
||||
if (!builder) {
|
||||
return;
|
||||
}
|
||||
if (has_rtree()) {
|
||||
Dispatch(builder->asDispatcher(), builder->GetLocalClipBounds());
|
||||
} else {
|
||||
Dispatch(builder->asDispatcher());
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayList::RenderTo(SkCanvas* canvas, SkScalar opacity) const {
|
||||
FML_DCHECK(can_apply_group_opacity() || opacity >= SK_Scalar1);
|
||||
DisplayListCanvasDispatcher dispatcher(canvas, opacity);
|
||||
if (has_rtree()) {
|
||||
Dispatch(dispatcher, canvas->getLocalClipBounds());
|
||||
} else {
|
||||
Dispatch(dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
bool DisplayList::Equals(const DisplayList* other) const {
|
||||
if (this == other) {
|
||||
return true;
|
||||
|
||||
@ -18,41 +18,36 @@
|
||||
//
|
||||
// This file contains the definitions for:
|
||||
// DisplayList: the base class that holds the information about the
|
||||
// sequence of operations and can dispatch them to a Dispatcher
|
||||
// Dispatcher: a pure virtual interface which can be implemented to field
|
||||
// the requests for purposes such as sending them to an SkCanvas
|
||||
// or detecting various rendering optimization scenarios
|
||||
// DisplayListBuilder: a class for constructing a DisplayList from the same
|
||||
// calls defined in the Dispatcher
|
||||
// sequence of operations and can dispatch them to a DlOpReceiver
|
||||
// DlOpReceiver: a pure virtual interface which can be implemented to field
|
||||
// the requests for purposes such as sending them to an SkCanvas
|
||||
// or detecting various rendering optimization scenarios
|
||||
// DisplayListBuilder: a class for constructing a DisplayList from DlCanvas
|
||||
// method calls and which can act as a DlOpReceiver as well
|
||||
//
|
||||
// Other files include various class definitions for dealing with display
|
||||
// lists, such as:
|
||||
// display_list_canvas.h: classes to interact between SkCanvas and DisplayList
|
||||
// (SkCanvas->DisplayList adapter and vice versa)
|
||||
// skia/dl_sk_*.h: classes to interact between SkCanvas and DisplayList
|
||||
// (SkCanvas->DisplayList adapter and vice versa)
|
||||
//
|
||||
// display_list_utils.h: various utility classes to ease implementing
|
||||
// a Dispatcher, including NOP implementations of
|
||||
// a DlOpReceiver, including NOP implementations of
|
||||
// the attribute, clip, and transform methods,
|
||||
// classes to track attributes, clips, and transforms
|
||||
// and a class to compute the bounds of a DisplayList
|
||||
// Any class implementing Dispatcher can inherit from
|
||||
// Any class implementing DlOpReceiver can inherit from
|
||||
// these utility classes to simplify its creation
|
||||
//
|
||||
// The Flutter DisplayList mechanism is used in a similar manner to the Skia
|
||||
// SkPicture mechanism. The primary means of communication into and out
|
||||
// of the DisplayList is through the Dispatcher virtual class which
|
||||
// provides a nearly 1:1 translation between the records of the DisplayList
|
||||
// to method calls.
|
||||
// SkPicture mechanism.
|
||||
//
|
||||
// A DisplayList must be created using a DisplayListBuilder using either its
|
||||
// stateful methods inherited from Dispatcher, or from its stateless methods
|
||||
// inherited from DlCanvas.
|
||||
// A DisplayList must be created using a DisplayListBuilder using its stateless
|
||||
// methods inherited from DlCanvas.
|
||||
//
|
||||
// A DisplayList can be read back by implementing the Dispatcher virtual
|
||||
// A DisplayList can be read back by implementing the DlOpReceiver virtual
|
||||
// methods (with help from some of the classes in the utils file) and
|
||||
// passing an instance to the dispatch() method, or it can be rendered
|
||||
// to Skia using a DisplayListCanvasDispatcher or simply by passing an
|
||||
// SkCanvas pointer to its renderTo() method.
|
||||
// passing an instance to the Dispatch() method, or it can be rendered
|
||||
// to Skia using a DlSkCanvasDispatcher.
|
||||
//
|
||||
// The mechanism is inspired by the SkLiteDL class that is not directly
|
||||
// supported by Skia, but has been recommended as a basis for custom
|
||||
@ -155,7 +150,7 @@ enum class DisplayListOpType {
|
||||
};
|
||||
#undef DL_OP_TO_ENUM_VALUE
|
||||
|
||||
class Dispatcher;
|
||||
class DlOpReceiver;
|
||||
class DisplayListBuilder;
|
||||
|
||||
class SaveLayerOptions {
|
||||
@ -231,7 +226,7 @@ class DisplayListStorage {
|
||||
class Culler;
|
||||
|
||||
// The base class that contains a sequence of rendering operations
|
||||
// for dispatch to a Dispatcher. These objects must be instantiated
|
||||
// for dispatch to a DlOpReceiver. These objects must be instantiated
|
||||
// through an instance of DisplayListBuilder::build().
|
||||
class DisplayList : public SkRefCnt {
|
||||
public:
|
||||
@ -239,12 +234,8 @@ class DisplayList : public SkRefCnt {
|
||||
|
||||
~DisplayList();
|
||||
|
||||
void Dispatch(Dispatcher& ctx) const;
|
||||
void Dispatch(Dispatcher& ctx, const SkRect& cull_rect) const;
|
||||
|
||||
void RenderTo(DisplayListBuilder* builder) const;
|
||||
|
||||
void RenderTo(SkCanvas* canvas, SkScalar opacity = SK_Scalar1) const;
|
||||
void Dispatch(DlOpReceiver& ctx) const;
|
||||
void Dispatch(DlOpReceiver& ctx, const SkRect& cull_rect) const;
|
||||
|
||||
// From historical behavior, SkPicture always included nested bytes,
|
||||
// but nested ops are only included if requested. The defaults used
|
||||
@ -300,7 +291,7 @@ class DisplayList : public SkRefCnt {
|
||||
const bool can_apply_group_opacity_;
|
||||
const sk_sp<const DlRTree> rtree_;
|
||||
|
||||
void Dispatch(Dispatcher& ctx,
|
||||
void Dispatch(DlOpReceiver& ctx,
|
||||
uint8_t* ptr,
|
||||
uint8_t* end,
|
||||
Culler& culler) const;
|
||||
|
||||
@ -36,10 +36,6 @@ namespace flutter {
|
||||
// wrong type of instance.
|
||||
// (eg. DlColorFilter::asBlend() or DlMaskFilter::asBlur())
|
||||
//
|
||||
// - Skiafiable:
|
||||
// The classes override an |skia_object| method to easily obtain a Skia
|
||||
// version of the attribute on demand.
|
||||
//
|
||||
// - Immutable:
|
||||
// Neither the base class or any of the subclasses specify any mutation
|
||||
// methods. Instances are often passed around as const as a reminder,
|
||||
@ -56,7 +52,7 @@ namespace flutter {
|
||||
// compared using a |memcmp| when performing a |DisplayList::Equals|.
|
||||
//
|
||||
// - Passed by Pointer:
|
||||
// The data shared via the |Dispatcher::set<Attribute>| calls are stored
|
||||
// The data shared via the |DlOpReceiver::set<Attribute>| calls are stored
|
||||
// in the buffer itself and so their lifetime is controlled by the
|
||||
// DisplayList. That memory cannot be shared as by a |shared_ptr|
|
||||
// because the memory may be freed outside the control of the shared
|
||||
@ -70,7 +66,7 @@ namespace flutter {
|
||||
// - Shared_Ptr-able:
|
||||
// The classes support a method to return a |std::shared_ptr| version of
|
||||
// themselves, safely instantiating a new copy of the object into a
|
||||
// shared_ptr using |std::make_shared|. For those dispatcher objects
|
||||
// shared_ptr using |std::make_shared|. For those receiver objects
|
||||
// that may want to hold on to the contents of the object (typically
|
||||
// in a |current_attribute_| field), they can obtain a shared_ptr
|
||||
// copy safely and easily using the |shared| method.
|
||||
@ -79,11 +75,9 @@ namespace flutter {
|
||||
|
||||
// |D| is the base type for the attribute
|
||||
// (i.e. DlColorFilter, etc.)
|
||||
// |S| is the base type for the Skia version of the attribute
|
||||
// (i.e. SkColorFilter, etc.)
|
||||
// |T| is the enum that describes the specific subclasses
|
||||
// (i.e DlColorFilterType, etc.)
|
||||
template <class D, class S, typename T>
|
||||
template <class D, typename T>
|
||||
class DlAttribute {
|
||||
public:
|
||||
// Return the recognized specific type of the attribute.
|
||||
@ -98,9 +92,6 @@ class DlAttribute {
|
||||
// version is not tied to the storage of this particular instance.
|
||||
virtual std::shared_ptr<D> shared() const = 0;
|
||||
|
||||
// Return an equivalent sk_sp<Skia> version of this object.
|
||||
virtual sk_sp<S> skia_object() const = 0;
|
||||
|
||||
// Perform a content aware |==| comparison of the Attribute.
|
||||
bool operator==(D const& other) const {
|
||||
return type() == other.type() && equals_(other);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "flutter/display_list/display_list_benchmarks.h"
|
||||
#include "flutter/display_list/display_list_builder.h"
|
||||
#include "flutter/display_list/display_list_flags.h"
|
||||
#include "flutter/display_list/skia/dl_sk_canvas.h"
|
||||
|
||||
#include "third_party/skia/include/core/SkPoint.h"
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
@ -76,27 +77,27 @@ void BM_DrawLine(benchmark::State& state,
|
||||
unsigned attributes) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawLineFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawLineFlags);
|
||||
|
||||
size_t length = state.range(0);
|
||||
|
||||
surface_provider->InitializeSurface(length, length);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
state.counters["DrawCallCount"] = kLinesToDraw;
|
||||
for (size_t i = 0; i < kLinesToDraw; i++) {
|
||||
builder.drawLine(SkPoint::Make(i % length, 0),
|
||||
SkPoint::Make(length - i % length, length));
|
||||
builder.DrawLine(SkPoint::Make(i % length, 0),
|
||||
SkPoint::Make(length - i % length, length), paint);
|
||||
}
|
||||
|
||||
auto display_list = builder.Build();
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -114,15 +115,15 @@ void BM_DrawRect(benchmark::State& state,
|
||||
unsigned attributes) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawRectFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawRectFlags);
|
||||
|
||||
size_t length = state.range(0);
|
||||
size_t canvas_size = length * 2;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
// As rects have SkScalar dimensions, we want to ensure that we also
|
||||
// draw rects with non-integer position and size
|
||||
@ -131,7 +132,7 @@ void BM_DrawRect(benchmark::State& state,
|
||||
|
||||
state.counters["DrawCallCount"] = kRectsToDraw;
|
||||
for (size_t i = 0; i < kRectsToDraw; i++) {
|
||||
builder.drawRect(rect);
|
||||
builder.DrawRect(rect, paint);
|
||||
rect.offset(offset, offset);
|
||||
if (rect.right() > canvas_size) {
|
||||
rect.offset(-canvas_size, 0);
|
||||
@ -145,7 +146,7 @@ void BM_DrawRect(benchmark::State& state,
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -163,22 +164,22 @@ void BM_DrawOval(benchmark::State& state,
|
||||
unsigned attributes) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawOvalFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawOvalFlags);
|
||||
|
||||
size_t length = state.range(0);
|
||||
size_t canvas_size = length * 2;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkRect rect = SkRect::MakeXYWH(0, 0, length * 1.5f, length);
|
||||
const SkScalar offset = 0.5f;
|
||||
|
||||
state.counters["DrawCallCount"] = kOvalsToDraw;
|
||||
for (size_t i = 0; i < kOvalsToDraw; i++) {
|
||||
builder.drawOval(rect);
|
||||
builder.DrawOval(rect, paint);
|
||||
rect.offset(offset, offset);
|
||||
if (rect.right() > canvas_size) {
|
||||
rect.offset(-canvas_size, 0);
|
||||
@ -191,7 +192,7 @@ void BM_DrawOval(benchmark::State& state,
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -209,15 +210,15 @@ void BM_DrawCircle(benchmark::State& state,
|
||||
unsigned attributes) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawCircleFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawCircleFlags);
|
||||
|
||||
size_t length = state.range(0);
|
||||
size_t canvas_size = length * 2;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkScalar radius = length / 2.0f;
|
||||
const SkScalar offset = 0.5f;
|
||||
@ -226,7 +227,7 @@ void BM_DrawCircle(benchmark::State& state,
|
||||
|
||||
state.counters["DrawCallCount"] = kCirclesToDraw;
|
||||
for (size_t i = 0; i < kCirclesToDraw; i++) {
|
||||
builder.drawCircle(center, radius);
|
||||
builder.DrawCircle(center, radius, paint);
|
||||
center.offset(offset, offset);
|
||||
if (center.x() + radius > canvas_size) {
|
||||
center.set(radius, center.y());
|
||||
@ -239,7 +240,7 @@ void BM_DrawCircle(benchmark::State& state,
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -258,15 +259,15 @@ void BM_DrawRRect(benchmark::State& state,
|
||||
SkRRect::Type type) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawRRectFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawRRectFlags);
|
||||
|
||||
size_t length = state.range(0);
|
||||
size_t canvas_size = length * 2;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkVector radii[4] = {};
|
||||
switch (type) {
|
||||
@ -304,7 +305,7 @@ void BM_DrawRRect(benchmark::State& state,
|
||||
|
||||
state.counters["DrawCallCount"] = kRRectsToDraw;
|
||||
for (size_t i = 0; i < kRRectsToDraw; i++) {
|
||||
builder.drawRRect(rrect);
|
||||
builder.DrawRRect(rrect, paint);
|
||||
rrect.offset(offset, offset);
|
||||
if (rrect.rect().right() > canvas_size) {
|
||||
rrect.offset(-canvas_size, 0);
|
||||
@ -317,7 +318,7 @@ void BM_DrawRRect(benchmark::State& state,
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -339,15 +340,15 @@ void BM_DrawDRRect(benchmark::State& state,
|
||||
SkRRect::Type type) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawDRRectFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawDRRectFlags);
|
||||
|
||||
size_t length = state.range(0);
|
||||
size_t canvas_size = length * 2;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkVector radii[4] = {};
|
||||
switch (type) {
|
||||
@ -386,7 +387,7 @@ void BM_DrawDRRect(benchmark::State& state,
|
||||
state.counters["DrawCallCount"] = kDRRectsToDraw;
|
||||
for (size_t i = 0; i < kDRRectsToDraw; i++) {
|
||||
rrect.inset(0.1f * length, 0.1f * length, &rrect_2);
|
||||
builder.drawDRRect(rrect, rrect_2);
|
||||
builder.DrawDRRect(rrect, rrect_2, paint);
|
||||
rrect.offset(offset, offset);
|
||||
if (rrect.rect().right() > canvas_size) {
|
||||
rrect.offset(-canvas_size, 0);
|
||||
@ -399,7 +400,7 @@ void BM_DrawDRRect(benchmark::State& state,
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -413,8 +414,8 @@ void BM_DrawArc(benchmark::State& state,
|
||||
unsigned attributes) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawArcNoCenterFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state,
|
||||
DisplayListOpFlags::kDrawArcNoCenterFlags);
|
||||
|
||||
@ -422,7 +423,7 @@ void BM_DrawArc(benchmark::State& state,
|
||||
size_t canvas_size = length * 2;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkScalar starting_angle = 0.0f;
|
||||
SkScalar offset = 0.5f;
|
||||
@ -436,7 +437,7 @@ void BM_DrawArc(benchmark::State& state,
|
||||
state.counters["DrawCallCount"] = kArcSweepSetsToDraw * segment_sweeps.size();
|
||||
for (size_t i = 0; i < kArcSweepSetsToDraw; i++) {
|
||||
for (SkScalar sweep : segment_sweeps) {
|
||||
builder.drawArc(bounds, starting_angle, sweep, false);
|
||||
builder.DrawArc(bounds, starting_angle, sweep, false, paint);
|
||||
starting_angle += sweep + 5.0f;
|
||||
}
|
||||
bounds.offset(offset, offset);
|
||||
@ -452,7 +453,7 @@ void BM_DrawArc(benchmark::State& state,
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -629,14 +630,14 @@ void BM_DrawPath(benchmark::State& state,
|
||||
SkPath::Verb type) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawPathFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawPathFlags);
|
||||
|
||||
size_t length = kFixedCanvasSize;
|
||||
surface_provider->InitializeSurface(length, length);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkPath path;
|
||||
|
||||
@ -650,12 +651,12 @@ void BM_DrawPath(benchmark::State& state,
|
||||
state.counters["VerbCount"] = path.countVerbs();
|
||||
state.counters["DrawCallCount"] = 1;
|
||||
|
||||
builder.drawPath(path);
|
||||
builder.DrawPath(path, paint);
|
||||
auto display_list = builder.Build();
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -767,14 +768,14 @@ void BM_DrawVertices(benchmark::State& state,
|
||||
DlVertexMode mode) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawVerticesFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawVerticesFlags);
|
||||
|
||||
size_t length = kFixedCanvasSize;
|
||||
surface_provider->InitializeSurface(length, length);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);
|
||||
|
||||
@ -791,7 +792,7 @@ void BM_DrawVertices(benchmark::State& state,
|
||||
std::shared_ptr<DlVertices> vertices =
|
||||
GetTestVertices(p, radius, 50, mode, vertex_count);
|
||||
total_vertex_count += vertex_count;
|
||||
builder.drawVertices(vertices, DlBlendMode::kSrc);
|
||||
builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, paint);
|
||||
}
|
||||
|
||||
state.counters["VertexCount"] = total_vertex_count;
|
||||
@ -801,7 +802,7 @@ void BM_DrawVertices(benchmark::State& state,
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -863,26 +864,18 @@ void BM_DrawPoints(benchmark::State& state,
|
||||
DlCanvas::PointMode mode) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
SkPaint paint;
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
switch (mode) {
|
||||
case DlCanvas::PointMode::kPoints:
|
||||
builder.SetAttributesFromPaint(
|
||||
GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawPointsAsPointsFlags);
|
||||
AnnotateAttributes(attributes, state,
|
||||
DisplayListOpFlags::kDrawPointsAsPointsFlags);
|
||||
break;
|
||||
case DlCanvas::PointMode::kLines:
|
||||
builder.SetAttributesFromPaint(
|
||||
GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawPointsAsLinesFlags);
|
||||
AnnotateAttributes(attributes, state,
|
||||
DisplayListOpFlags::kDrawPointsAsLinesFlags);
|
||||
break;
|
||||
case DlCanvas::PointMode::kPolygon:
|
||||
builder.SetAttributesFromPaint(
|
||||
GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawPointsAsPolygonFlags);
|
||||
AnnotateAttributes(attributes, state,
|
||||
DisplayListOpFlags::kDrawPointsAsPolygonFlags);
|
||||
break;
|
||||
@ -891,7 +884,7 @@ void BM_DrawPoints(benchmark::State& state,
|
||||
size_t length = kFixedCanvasSize;
|
||||
surface_provider->InitializeSurface(length, length);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
size_t point_count = state.range(0);
|
||||
state.SetComplexityN(point_count);
|
||||
@ -900,12 +893,12 @@ void BM_DrawPoints(benchmark::State& state,
|
||||
|
||||
std::vector<SkPoint> points =
|
||||
GetTestPoints(point_count, SkISize::Make(length, length));
|
||||
builder.drawPoints(mode, points.size(), points.data());
|
||||
builder.DrawPoints(mode, points.size(), points.data(), paint);
|
||||
|
||||
auto display_list = builder.Build();
|
||||
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -933,8 +926,8 @@ void BM_DrawImage(benchmark::State& state,
|
||||
bool upload_bitmap) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawImageWithPaintFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state,
|
||||
DisplayListOpFlags::kDrawImageWithPaintFlags);
|
||||
|
||||
@ -942,7 +935,7 @@ void BM_DrawImage(benchmark::State& state,
|
||||
size_t canvas_size = 2 * bitmap_size;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
sk_sp<SkImage> image;
|
||||
std::shared_ptr<DlSurfaceInstance> offscreen_instance;
|
||||
@ -969,7 +962,7 @@ void BM_DrawImage(benchmark::State& state,
|
||||
for (size_t i = 0; i < kImagesToDraw; i++) {
|
||||
image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
|
||||
: offscreen->makeImageSnapshot();
|
||||
builder.drawImage(DlImage::Make(image), dst, options, true);
|
||||
builder.DrawImage(DlImage::Make(image), dst, options, &paint);
|
||||
|
||||
dst.offset(offset, offset);
|
||||
if (dst.x() + bitmap_size > canvas_size) {
|
||||
@ -983,7 +976,7 @@ void BM_DrawImage(benchmark::State& state,
|
||||
auto display_list = builder.Build();
|
||||
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -993,11 +986,11 @@ void BM_DrawImage(benchmark::State& state,
|
||||
surface_provider->Snapshot(filename);
|
||||
}
|
||||
|
||||
std::string ConstraintToString(SkCanvas::SrcRectConstraint constraint) {
|
||||
std::string ConstraintToString(DlCanvas::SrcRectConstraint constraint) {
|
||||
switch (constraint) {
|
||||
case SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint:
|
||||
case DlCanvas::SrcRectConstraint::kStrict:
|
||||
return "Strict";
|
||||
case SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint:
|
||||
case DlCanvas::SrcRectConstraint::kFast:
|
||||
return "Fast";
|
||||
default:
|
||||
return "Unknown";
|
||||
@ -1012,13 +1005,12 @@ void BM_DrawImageRect(benchmark::State& state,
|
||||
BackendType backend_type,
|
||||
unsigned attributes,
|
||||
DlImageSampling options,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
DlCanvas::SrcRectConstraint constraint,
|
||||
bool upload_bitmap) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(
|
||||
GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawImageRectWithPaintFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state,
|
||||
DisplayListOpFlags::kDrawImageRectWithPaintFlags);
|
||||
|
||||
@ -1026,7 +1018,7 @@ void BM_DrawImageRect(benchmark::State& state,
|
||||
size_t canvas_size = 2 * bitmap_size;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
sk_sp<SkImage> image;
|
||||
std::shared_ptr<DlSurfaceInstance> offscreen_instance;
|
||||
@ -1056,7 +1048,7 @@ void BM_DrawImageRect(benchmark::State& state,
|
||||
for (size_t i = 0; i < kImagesToDraw; i++) {
|
||||
image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
|
||||
: offscreen->makeImageSnapshot();
|
||||
builder.drawImageRect(DlImage::Make(image), src, dst, options, true,
|
||||
builder.DrawImageRect(DlImage::Make(image), src, dst, options, &paint,
|
||||
constraint);
|
||||
dst.offset(offset, offset);
|
||||
if (dst.right() > canvas_size) {
|
||||
@ -1070,7 +1062,7 @@ void BM_DrawImageRect(benchmark::State& state,
|
||||
auto display_list = builder.Build();
|
||||
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -1104,9 +1096,8 @@ void BM_DrawImageNine(benchmark::State& state,
|
||||
bool upload_bitmap) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(
|
||||
GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawImageNineWithPaintFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state,
|
||||
DisplayListOpFlags::kDrawImageNineWithPaintFlags);
|
||||
|
||||
@ -1114,7 +1105,7 @@ void BM_DrawImageNine(benchmark::State& state,
|
||||
size_t canvas_size = 2 * bitmap_size;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkIRect center = SkIRect::MakeXYWH(bitmap_size / 4, bitmap_size / 4,
|
||||
bitmap_size / 2, bitmap_size / 2);
|
||||
@ -1145,7 +1136,7 @@ void BM_DrawImageNine(benchmark::State& state,
|
||||
for (size_t i = 0; i < kImagesToDraw; i++) {
|
||||
image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
|
||||
: offscreen->makeImageSnapshot();
|
||||
builder.drawImageNine(DlImage::Make(image), center, dst, filter, true);
|
||||
builder.DrawImageNine(DlImage::Make(image), center, dst, filter, &paint);
|
||||
dst.offset(offset, offset);
|
||||
if (dst.right() > canvas_size) {
|
||||
dst.offsetTo(0, dst.y());
|
||||
@ -1158,7 +1149,7 @@ void BM_DrawImageNine(benchmark::State& state,
|
||||
auto display_list = builder.Build();
|
||||
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -1181,15 +1172,15 @@ void BM_DrawTextBlob(benchmark::State& state,
|
||||
unsigned attributes) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawTextBlobFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawTextBlobFlags);
|
||||
|
||||
size_t draw_calls = state.range(0);
|
||||
size_t canvas_size = kFixedCanvasSize;
|
||||
surface_provider->InitializeSurface(canvas_size, canvas_size);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
state.counters["DrawCallCount_Varies"] = draw_calls;
|
||||
state.counters["GlyphCount"] = draw_calls;
|
||||
@ -1198,13 +1189,13 @@ void BM_DrawTextBlob(benchmark::State& state,
|
||||
for (size_t i = 0; i < draw_calls; i++) {
|
||||
character[0] = 'A' + (i % 26);
|
||||
auto blob = SkTextBlob::MakeFromString(character, SkFont());
|
||||
builder.drawTextBlob(blob, 50.0f, 50.0f);
|
||||
builder.DrawTextBlob(blob, 50.0f, 50.0f, paint);
|
||||
}
|
||||
|
||||
auto display_list = builder.Build();
|
||||
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -1228,14 +1219,14 @@ void BM_DrawShadow(benchmark::State& state,
|
||||
SkPath::Verb type) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kDrawShadowFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawShadowFlags);
|
||||
|
||||
size_t length = kFixedCanvasSize;
|
||||
surface_provider->InitializeSurface(length, length);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
SkPath path;
|
||||
|
||||
@ -1264,12 +1255,12 @@ void BM_DrawShadow(benchmark::State& state,
|
||||
|
||||
// We can hardcode dpr to 1.0f as we're varying elevation, and dpr is only
|
||||
// ever used in conjunction with elevation.
|
||||
builder.drawShadow(path, SK_ColorBLUE, elevation, transparent_occluder, 1.0f);
|
||||
builder.DrawShadow(path, SK_ColorBLUE, elevation, transparent_occluder, 1.0f);
|
||||
auto display_list = builder.Build();
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
@ -1292,14 +1283,14 @@ void BM_SaveLayer(benchmark::State& state,
|
||||
size_t save_depth) {
|
||||
auto surface_provider = DlSurfaceProvider::Create(backend_type);
|
||||
DisplayListBuilder builder;
|
||||
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
|
||||
DisplayListOpFlags::kSaveLayerFlags);
|
||||
DlPaint paint = GetPaintForRun(attributes);
|
||||
|
||||
AnnotateAttributes(attributes, state, DisplayListOpFlags::kSaveLayerFlags);
|
||||
|
||||
size_t length = kFixedCanvasSize;
|
||||
surface_provider->InitializeSurface(length, length);
|
||||
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
|
||||
auto canvas = surface->getCanvas();
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
|
||||
size_t save_layer_calls = state.range(0);
|
||||
|
||||
@ -1311,19 +1302,19 @@ void BM_SaveLayer(benchmark::State& state,
|
||||
state.counters["DrawCallCount_Varies"] = save_layer_calls * save_depth;
|
||||
for (size_t i = 0; i < save_layer_calls; i++) {
|
||||
for (size_t j = 0; j < save_depth; j++) {
|
||||
builder.saveLayer(nullptr, false);
|
||||
builder.drawRect(rect1);
|
||||
builder.drawRect(rect2);
|
||||
builder.SaveLayer(nullptr, nullptr);
|
||||
builder.DrawRect(rect1, paint);
|
||||
builder.DrawRect(rect2, paint);
|
||||
}
|
||||
for (size_t j = 0; j < save_depth; j++) {
|
||||
builder.restore();
|
||||
builder.Restore();
|
||||
}
|
||||
}
|
||||
auto display_list = builder.Build();
|
||||
|
||||
// We only want to time the actual rasterization.
|
||||
for ([[maybe_unused]] auto _ : state) {
|
||||
display_list->RenderTo(canvas);
|
||||
canvas.DrawDisplayList(display_list);
|
||||
surface->flushAndSubmit(true);
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ void BM_DrawImageRect(benchmark::State& state,
|
||||
BackendType backend_type,
|
||||
unsigned attributes,
|
||||
DlImageSampling options,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
DlCanvas::SrcRectConstraint constraint,
|
||||
bool upload_bitmap);
|
||||
void BM_DrawImageNine(benchmark::State& state,
|
||||
BackendType backend_type,
|
||||
@ -343,8 +343,8 @@ void BM_SaveLayer(benchmark::State& state,
|
||||
BM_DrawImageRect, Texture/Strict/BACKEND, \
|
||||
BackendType::k##BACKEND##_Backend, \
|
||||
ATTRIBUTES, \
|
||||
DlImageSampling::kNearestNeighbor, \
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, false) \
|
||||
DlImageSampling::kNearestNeighbor, \
|
||||
DlCanvas::SrcRectConstraint::kStrict, false) \
|
||||
->RangeMultiplier(2) \
|
||||
->Range(32, 256) \
|
||||
->UseRealTime() \
|
||||
@ -354,8 +354,8 @@ void BM_SaveLayer(benchmark::State& state,
|
||||
BM_DrawImageRect, Texture/Fast/BACKEND, \
|
||||
BackendType::k##BACKEND##_Backend, \
|
||||
ATTRIBUTES, \
|
||||
DlImageSampling::kNearestNeighbor, \
|
||||
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint, false) \
|
||||
DlImageSampling::kNearestNeighbor, \
|
||||
DlCanvas::SrcRectConstraint::kFast, false) \
|
||||
->RangeMultiplier(2) \
|
||||
->Range(32, 256) \
|
||||
->UseRealTime() \
|
||||
@ -365,8 +365,8 @@ void BM_SaveLayer(benchmark::State& state,
|
||||
BM_DrawImageRect, Upload/Strict/BACKEND, \
|
||||
BackendType::k##BACKEND##_Backend, \
|
||||
ATTRIBUTES, \
|
||||
DlImageSampling::kNearestNeighbor, \
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, true) \
|
||||
DlImageSampling::kNearestNeighbor, \
|
||||
DlCanvas::SrcRectConstraint::kStrict, true) \
|
||||
->RangeMultiplier(2) \
|
||||
->Range(32, 256) \
|
||||
->UseRealTime() \
|
||||
@ -376,8 +376,8 @@ void BM_SaveLayer(benchmark::State& state,
|
||||
BM_DrawImageRect, Upload/Fast/BACKEND, \
|
||||
BackendType::k##BACKEND##_Backend, \
|
||||
ATTRIBUTES, \
|
||||
DlImageSampling::kNearestNeighbor, \
|
||||
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint, true) \
|
||||
DlImageSampling::kNearestNeighbor, \
|
||||
DlCanvas::SrcRectConstraint::kFast, true) \
|
||||
->RangeMultiplier(2) \
|
||||
->Range(32, 256) \
|
||||
->UseRealTime() \
|
||||
|
||||
@ -66,14 +66,6 @@ enum class DlBlendMode {
|
||||
kDefaultMode = kSrcOver,
|
||||
};
|
||||
|
||||
inline DlBlendMode ToDl(SkBlendMode mode) {
|
||||
return static_cast<DlBlendMode>(mode);
|
||||
}
|
||||
|
||||
inline SkBlendMode ToSk(DlBlendMode mode) {
|
||||
return static_cast<SkBlendMode>(mode);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BLEND_MODE_H_
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
|
||||
#include "flutter/display_list/display_list.h"
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_canvas_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_color_source.h"
|
||||
#include "flutter/display_list/display_list_ops.h"
|
||||
#include "fml/logging.h"
|
||||
@ -250,8 +249,8 @@ void DisplayListBuilder::onSetImageFilter(const DlImageFilter* filter) {
|
||||
new (pod) DlMatrixImageFilter(matrix_filter);
|
||||
break;
|
||||
}
|
||||
case DlImageFilterType::kComposeFilter:
|
||||
case DlImageFilterType::kLocalMatrixFilter:
|
||||
case DlImageFilterType::kCompose:
|
||||
case DlImageFilterType::kLocalMatrix:
|
||||
case DlImageFilterType::kColorFilter: {
|
||||
Push<SetSharedImageFilterOp>(0, 0, filter);
|
||||
break;
|
||||
@ -843,7 +842,7 @@ void DisplayListBuilder::drawPoints(PointMode mode,
|
||||
}
|
||||
|
||||
void* data_ptr;
|
||||
FML_DCHECK(count < Dispatcher::kMaxDrawPointsCount);
|
||||
FML_DCHECK(count < DlOpReceiver::kMaxDrawPointsCount);
|
||||
int bytes = count * sizeof(SkPoint);
|
||||
RectBoundsAccumulator ptBounds;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
@ -947,7 +946,7 @@ void DisplayListBuilder::drawImageRect(const sk_sp<DlImage> image,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) {
|
||||
SrcRectConstraint constraint) {
|
||||
Push<DrawImageRectOp>(0, 1, image, src, dst, sampling, render_with_attributes,
|
||||
constraint);
|
||||
CheckLayerOpacityCompatibility(render_with_attributes);
|
||||
@ -961,10 +960,7 @@ void DisplayListBuilder::DrawImageRect(const sk_sp<DlImage>& image,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint,
|
||||
bool enforce_src_edges) {
|
||||
SkCanvas::SrcRectConstraint constraint =
|
||||
enforce_src_edges ? SkCanvas::kStrict_SrcRectConstraint
|
||||
: SkCanvas::kFast_SrcRectConstraint;
|
||||
SrcRectConstraint constraint) {
|
||||
if (paint != nullptr) {
|
||||
SetAttributesFromPaint(*paint,
|
||||
DisplayListOpFlags::kDrawImageRectWithPaintFlags);
|
||||
@ -1077,18 +1073,12 @@ void DisplayListBuilder::DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
void DisplayListBuilder::DrawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) {
|
||||
DlPaint current_paint = current_;
|
||||
if (opacity < SK_Scalar1) {
|
||||
SaveLayer(&display_list->bounds(), &DlPaint().setOpacity(opacity));
|
||||
}
|
||||
Push<DrawDisplayListOp>(0, 1, display_list);
|
||||
if (opacity < SK_Scalar1) {
|
||||
Restore();
|
||||
// Not really necessary if the developer is interacting with us via
|
||||
// our attribute-state-less DlCanvas methods, but this avoids surprises
|
||||
// for those who may have been using the stateful Dispatcher methods.
|
||||
SetAttributesFromPaint(current_paint,
|
||||
DisplayListOpFlags::kSaveLayerWithPaintFlags);
|
||||
}
|
||||
Push<DrawDisplayListOp>(0, 1, display_list, opacity);
|
||||
// Not really necessary if the developer is interacting with us via
|
||||
// our attribute-state-less DlCanvas methods, but this avoids surprises
|
||||
// for those who may have been using the stateful Dispatcher methods.
|
||||
SetAttributesFromPaint(current_paint,
|
||||
DisplayListOpFlags::kSaveLayerWithPaintFlags);
|
||||
|
||||
const SkRect bounds = display_list->bounds();
|
||||
switch (accumulator()->type()) {
|
||||
@ -1142,8 +1132,8 @@ void DisplayListBuilder::DrawShadow(const SkPath& path,
|
||||
? Push<DrawShadowTransparentOccluderOp>(0, 1, path, color, elevation, dpr)
|
||||
: Push<DrawShadowOp>(0, 1, path, color, elevation, dpr);
|
||||
|
||||
SkRect shadow_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
|
||||
path, elevation, dpr, GetTransform());
|
||||
SkRect shadow_bounds =
|
||||
DlCanvas::ComputeShadowBounds(path, elevation, dpr, GetTransform());
|
||||
AccumulateOpBounds(shadow_bounds, kDrawShadowFlags);
|
||||
UpdateLayerOpacityCompatibility(false);
|
||||
}
|
||||
@ -1190,7 +1180,7 @@ bool DisplayListBuilder::AdjustBoundsForPaint(SkRect& bounds,
|
||||
pad = std::max(pad, SK_ScalarSqrt2);
|
||||
}
|
||||
SkScalar min_stroke_width = 0.01;
|
||||
pad *= std::max(getStrokeWidth() * 0.5f, min_stroke_width);
|
||||
pad *= std::max(current_.getStrokeWidth() * 0.5f, min_stroke_width);
|
||||
bounds.outset(pad, pad);
|
||||
}
|
||||
}
|
||||
@ -1259,7 +1249,7 @@ bool DisplayListBuilder::paint_nops_on_transparency() {
|
||||
// For example, DstIn is used by masking layers.
|
||||
// https://code.google.com/p/skia/issues/detail?id=1291
|
||||
// https://crbug.com/401593
|
||||
switch (getBlendMode()) {
|
||||
switch (current_.getBlendMode()) {
|
||||
// For each of the following transfer modes, if the source
|
||||
// alpha is zero (our transparent black), the resulting
|
||||
// blended pixel is not necessarily equal to the original
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#include "flutter/display_list/display_list.h"
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_comparable.h"
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_flags.h"
|
||||
#include "flutter/display_list/display_list_image.h"
|
||||
#include "flutter/display_list/display_list_matrix_clip_tracker.h"
|
||||
@ -17,17 +16,18 @@
|
||||
#include "flutter/display_list/display_list_sampling_options.h"
|
||||
#include "flutter/display_list/display_list_utils.h"
|
||||
#include "flutter/display_list/dl_canvas.h"
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
#include "flutter/display_list/types.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// The primary class used to build a display list. The list of methods
|
||||
// here matches the list of methods invoked on a |Dispatcher| combined
|
||||
// here matches the list of methods invoked on a |DlOpReceiver| combined
|
||||
// with the list of methods invoked on a |DlCanvas|.
|
||||
class DisplayListBuilder final : public virtual DlCanvas,
|
||||
public SkRefCnt,
|
||||
virtual Dispatcher,
|
||||
virtual DlOpReceiver,
|
||||
DisplayListOpFlags {
|
||||
public:
|
||||
static constexpr SkRect kMaxCullRect =
|
||||
@ -39,168 +39,331 @@ class DisplayListBuilder final : public virtual DlCanvas,
|
||||
explicit DisplayListBuilder(const SkRect& cull_rect = kMaxCullRect,
|
||||
bool prepare_rtree = false);
|
||||
|
||||
SkISize GetBaseLayerSize() const override;
|
||||
SkImageInfo GetImageInfo() const override;
|
||||
|
||||
~DisplayListBuilder();
|
||||
|
||||
Dispatcher& asDispatcher() { return *this; }
|
||||
// |DlCanvas|
|
||||
SkISize GetBaseLayerSize() const override;
|
||||
// |DlCanvas|
|
||||
SkImageInfo GetImageInfo() const override;
|
||||
|
||||
// |DlCanvas|
|
||||
void Save() override;
|
||||
|
||||
// |DlCanvas|
|
||||
void SaveLayer(const SkRect* bounds,
|
||||
const DlPaint* paint = nullptr,
|
||||
const DlImageFilter* backdrop = nullptr) override;
|
||||
// |DlCanvas|
|
||||
void Restore() override;
|
||||
// |DlCanvas|
|
||||
int GetSaveCount() const override { return layer_stack_.size(); }
|
||||
// |DlCanvas|
|
||||
void RestoreToCount(int restore_count) override;
|
||||
|
||||
// |DlCanvas|
|
||||
void Translate(SkScalar tx, SkScalar ty) override;
|
||||
// |DlCanvas|
|
||||
void Scale(SkScalar sx, SkScalar sy) override;
|
||||
// |DlCanvas|
|
||||
void Rotate(SkScalar degrees) override;
|
||||
// |DlCanvas|
|
||||
void Skew(SkScalar sx, SkScalar sy) override;
|
||||
|
||||
// clang-format off
|
||||
// 2x3 2D affine subset of a 4x4 transform in row major order
|
||||
// |DlCanvas|
|
||||
void Transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myt) override;
|
||||
// full 4x4 transform in row major order
|
||||
// |DlCanvas|
|
||||
void TransformFullPerspective(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
|
||||
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
|
||||
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override;
|
||||
// clang-format on
|
||||
// |DlCanvas|
|
||||
void TransformReset() override;
|
||||
// |DlCanvas|
|
||||
void Transform(const SkMatrix* matrix) override;
|
||||
// |DlCanvas|
|
||||
void Transform(const SkM44* matrix44) override;
|
||||
// |DlCanvas|
|
||||
void SetTransform(const SkMatrix* matrix) override {
|
||||
TransformReset();
|
||||
Transform(matrix);
|
||||
}
|
||||
// |DlCanvas|
|
||||
void SetTransform(const SkM44* matrix44) override {
|
||||
TransformReset();
|
||||
Transform(matrix44);
|
||||
}
|
||||
using DlCanvas::Transform;
|
||||
|
||||
/// Returns the 4x4 full perspective transform representing all transform
|
||||
/// operations executed so far in this DisplayList within the enclosing
|
||||
/// save stack.
|
||||
// |DlCanvas|
|
||||
SkM44 GetTransformFullPerspective() const override {
|
||||
return tracker_.matrix_4x4();
|
||||
}
|
||||
/// Returns the 3x3 partial perspective transform representing all transform
|
||||
/// operations executed so far in this DisplayList within the enclosing
|
||||
/// save stack.
|
||||
// |DlCanvas|
|
||||
SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); }
|
||||
|
||||
// |DlCanvas|
|
||||
void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override;
|
||||
// |DlCanvas|
|
||||
void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
|
||||
// |DlCanvas|
|
||||
void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
|
||||
|
||||
/// Conservative estimate of the bounds of all outstanding clip operations
|
||||
/// measured in the coordinate space within which this DisplayList will
|
||||
/// be rendered.
|
||||
// |DlCanvas|
|
||||
SkRect GetDestinationClipBounds() const override {
|
||||
return tracker_.device_cull_rect();
|
||||
}
|
||||
/// Conservative estimate of the bounds of all outstanding clip operations
|
||||
/// transformed into the local coordinate space in which currently
|
||||
/// recorded rendering operations are interpreted.
|
||||
// |DlCanvas|
|
||||
SkRect GetLocalClipBounds() const override {
|
||||
return tracker_.local_cull_rect();
|
||||
}
|
||||
|
||||
/// Return true iff the supplied bounds are easily shown to be outside
|
||||
/// of the current clip bounds. This method may conservatively return
|
||||
/// false if it cannot make the determination.
|
||||
// |DlCanvas|
|
||||
bool QuickReject(const SkRect& bounds) const override;
|
||||
|
||||
// |DlCanvas|
|
||||
void DrawPaint(const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawColor(DlColor color, DlBlendMode mode) override;
|
||||
// |DlCanvas|
|
||||
void DrawLine(const SkPoint& p0,
|
||||
const SkPoint& p1,
|
||||
const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawRect(const SkRect& rect, const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawOval(const SkRect& bounds, const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawCircle(const SkPoint& center,
|
||||
SkScalar radius,
|
||||
const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawRRect(const SkRRect& rrect, const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawDRRect(const SkRRect& outer,
|
||||
const SkRRect& inner,
|
||||
const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawPath(const SkPath& path, const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawArc(const SkRect& bounds,
|
||||
SkScalar start,
|
||||
SkScalar sweep,
|
||||
bool useCenter,
|
||||
const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawPoints(PointMode mode,
|
||||
uint32_t count,
|
||||
const SkPoint pts[],
|
||||
const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawVertices(const DlVertices* vertices,
|
||||
DlBlendMode mode,
|
||||
const DlPaint& paint) override;
|
||||
using DlCanvas::DrawVertices;
|
||||
// |DlCanvas|
|
||||
void DrawImage(const sk_sp<DlImage>& image,
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
// |DlCanvas|
|
||||
void DrawImageRect(
|
||||
const sk_sp<DlImage>& image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
|
||||
// |DlCanvas|
|
||||
void DrawImageNine(const sk_sp<DlImage>& image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
DlFilterMode filter,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
// |DlCanvas|
|
||||
void DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
const SkRSXform xform[],
|
||||
const SkRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
DlBlendMode mode,
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cullRect,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
// |DlCanvas|
|
||||
void DrawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity = SK_Scalar1) override;
|
||||
// |DlCanvas|
|
||||
void DrawTextBlob(const sk_sp<SkTextBlob>& blob,
|
||||
SkScalar x,
|
||||
SkScalar y,
|
||||
const DlPaint& paint) override;
|
||||
// |DlCanvas|
|
||||
void DrawShadow(const SkPath& path,
|
||||
const DlColor color,
|
||||
const SkScalar elevation,
|
||||
bool transparent_occluder,
|
||||
SkScalar dpr) override;
|
||||
|
||||
// |DlCanvas|
|
||||
void Flush() override {}
|
||||
|
||||
sk_sp<DisplayList> Build();
|
||||
|
||||
private:
|
||||
// This method exposes the internal stateful DlOpReceiver implementation
|
||||
// of the DisplayListBuilder, primarily for testing purposes. Its use
|
||||
// is obsolete and forbidden in every other case and is only shared to a
|
||||
// pair of "friend" accessors in the benchmark/unittest files.
|
||||
DlOpReceiver& asReceiver() { return *this; }
|
||||
|
||||
friend DlOpReceiver& DisplayListBuilderBenchmarkAccessor(
|
||||
DisplayListBuilder& builder);
|
||||
friend DlOpReceiver& DisplayListBuilderTestingAccessor(
|
||||
DisplayListBuilder& builder);
|
||||
|
||||
void SetAttributesFromPaint(const DlPaint& paint,
|
||||
const DisplayListAttributeFlags flags);
|
||||
|
||||
// |DlOpReceiver|
|
||||
void setAntiAlias(bool aa) override {
|
||||
if (current_.isAntiAlias() != aa) {
|
||||
onSetAntiAlias(aa);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setDither(bool dither) override {
|
||||
if (current_.isDither() != dither) {
|
||||
onSetDither(dither);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setInvertColors(bool invert) override {
|
||||
if (current_.isInvertColors() != invert) {
|
||||
onSetInvertColors(invert);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setStrokeCap(DlStrokeCap cap) override {
|
||||
if (current_.getStrokeCap() != cap) {
|
||||
onSetStrokeCap(cap);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setStrokeJoin(DlStrokeJoin join) override {
|
||||
if (current_.getStrokeJoin() != join) {
|
||||
onSetStrokeJoin(join);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setStyle(DlDrawStyle style) override {
|
||||
if (current_.getDrawStyle() != style) {
|
||||
onSetStyle(style);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setStrokeWidth(float width) override {
|
||||
if (current_.getStrokeWidth() != width) {
|
||||
onSetStrokeWidth(width);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setStrokeMiter(float limit) override {
|
||||
if (current_.getStrokeMiter() != limit) {
|
||||
onSetStrokeMiter(limit);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setColor(DlColor color) override {
|
||||
if (current_.getColor() != color) {
|
||||
onSetColor(color);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setBlendMode(DlBlendMode mode) override {
|
||||
if (current_.getBlendMode() != mode) {
|
||||
onSetBlendMode(mode);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setColorSource(const DlColorSource* source) override {
|
||||
if (NotEquals(current_.getColorSource(), source)) {
|
||||
onSetColorSource(source);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setImageFilter(const DlImageFilter* filter) override {
|
||||
if (NotEquals(current_.getImageFilter(), filter)) {
|
||||
onSetImageFilter(filter);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setColorFilter(const DlColorFilter* filter) override {
|
||||
if (NotEquals(current_.getColorFilter(), filter)) {
|
||||
onSetColorFilter(filter);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setPathEffect(const DlPathEffect* effect) override {
|
||||
if (NotEquals(current_.getPathEffect(), effect)) {
|
||||
onSetPathEffect(effect);
|
||||
}
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void setMaskFilter(const DlMaskFilter* filter) override {
|
||||
if (NotEquals(current_.getMaskFilter(), filter)) {
|
||||
onSetMaskFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
bool isAntiAlias() const { return current_.isAntiAlias(); }
|
||||
bool isDither() const { return current_.isDither(); }
|
||||
DlDrawStyle getStyle() const { return current_.getDrawStyle(); }
|
||||
DlColor getColor() const { return current_.getColor(); }
|
||||
float getStrokeWidth() const { return current_.getStrokeWidth(); }
|
||||
float getStrokeMiter() const { return current_.getStrokeMiter(); }
|
||||
DlStrokeCap getStrokeCap() const { return current_.getStrokeCap(); }
|
||||
DlStrokeJoin getStrokeJoin() const { return current_.getStrokeJoin(); }
|
||||
std::shared_ptr<const DlColorSource> getColorSource() const {
|
||||
return current_.getColorSource();
|
||||
}
|
||||
std::shared_ptr<const DlColorFilter> getColorFilter() const {
|
||||
return current_.getColorFilter();
|
||||
}
|
||||
bool isInvertColors() const { return current_.isInvertColors(); }
|
||||
DlBlendMode getBlendMode() const { return current_.getBlendMode(); }
|
||||
std::shared_ptr<const DlPathEffect> getPathEffect() const {
|
||||
return current_.getPathEffect();
|
||||
}
|
||||
std::shared_ptr<const DlMaskFilter> getMaskFilter() const {
|
||||
return current_.getMaskFilter();
|
||||
}
|
||||
std::shared_ptr<const DlImageFilter> getImageFilter() const {
|
||||
return current_.getImageFilter();
|
||||
}
|
||||
|
||||
void Save() override;
|
||||
// |DlOpReceiver|
|
||||
void save() override { Save(); }
|
||||
|
||||
// Only the |renders_with_attributes()| option will be accepted here. Any
|
||||
// other flags will be ignored and calculated anew as the DisplayList is
|
||||
// built. Alternatively, use the |saveLayer(SkRect, bool)| method.
|
||||
// |DlOpReceiver|
|
||||
void saveLayer(const SkRect* bounds,
|
||||
const SaveLayerOptions options,
|
||||
const DlImageFilter* backdrop) override;
|
||||
// Convenience method with just a boolean to indicate whether the saveLayer
|
||||
// should apply the rendering attributes.
|
||||
void saveLayer(const SkRect* bounds, bool renders_with_attributes) {
|
||||
saveLayer(bounds,
|
||||
renders_with_attributes ? SaveLayerOptions::kWithAttributes
|
||||
: SaveLayerOptions::kNoAttributes,
|
||||
nullptr);
|
||||
}
|
||||
void SaveLayer(const SkRect* bounds,
|
||||
const DlPaint* paint = nullptr,
|
||||
const DlImageFilter* backdrop = nullptr) override;
|
||||
void Restore() override;
|
||||
// |DlOpReceiver|
|
||||
void restore() override { Restore(); }
|
||||
int GetSaveCount() const override { return layer_stack_.size(); }
|
||||
void RestoreToCount(int restore_count) override;
|
||||
void restoreToCount(int restore_count) { RestoreToCount(restore_count); }
|
||||
|
||||
void Translate(SkScalar tx, SkScalar ty) override;
|
||||
void Scale(SkScalar sx, SkScalar sy) override;
|
||||
void Rotate(SkScalar degrees) override;
|
||||
void Skew(SkScalar sx, SkScalar sy) override;
|
||||
// |DlOpReceiver|
|
||||
void translate(SkScalar tx, SkScalar ty) override { Translate(tx, ty); }
|
||||
// |DlOpReceiver|
|
||||
void scale(SkScalar sx, SkScalar sy) override { Scale(sx, sy); }
|
||||
// |DlOpReceiver|
|
||||
void rotate(SkScalar degrees) override { Rotate(degrees); }
|
||||
// |DlOpReceiver|
|
||||
void skew(SkScalar sx, SkScalar sy) override { Skew(sx, sy); }
|
||||
|
||||
void SetAttributesFromPaint(const DlPaint& paint,
|
||||
const DisplayListAttributeFlags flags);
|
||||
|
||||
// clang-format off
|
||||
|
||||
// 2x3 2D affine subset of a 4x4 transform in row major order
|
||||
void Transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myt) override;
|
||||
// |DlOpReceiver|
|
||||
void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myt) override {
|
||||
Transform2DAffine(mxx, mxy, mxt, myx, myy, myt);
|
||||
}
|
||||
// full 4x4 transform in row major order
|
||||
void TransformFullPerspective(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
|
||||
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
|
||||
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override;
|
||||
// |DlOpReceiver|
|
||||
void transformFullPerspective(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
|
||||
@ -211,148 +374,73 @@ class DisplayListBuilder final : public virtual DlCanvas,
|
||||
mzx, mzy, mzz, mzt,
|
||||
mwx, mwy, mwz, mwt);
|
||||
}
|
||||
// clang-format on
|
||||
void TransformReset() override;
|
||||
void Transform(const SkMatrix* matrix) override;
|
||||
void Transform(const SkM44* matrix44) override;
|
||||
void SetTransform(const SkMatrix* matrix) override {
|
||||
TransformReset();
|
||||
Transform(matrix);
|
||||
}
|
||||
void SetTransform(const SkM44* matrix44) override {
|
||||
TransformReset();
|
||||
Transform(matrix44);
|
||||
}
|
||||
using DlCanvas::Transform;
|
||||
// clang-format off
|
||||
// |DlOpReceiver|
|
||||
void transformReset() override { TransformReset(); }
|
||||
void transform(const SkMatrix* matrix) { Transform(matrix); }
|
||||
void transform(const SkM44* matrix44) { Transform(matrix44); }
|
||||
void transform(const SkMatrix& matrix) { Transform(&matrix); }
|
||||
void transform(const SkM44& matrix44) { Transform(&matrix44); }
|
||||
|
||||
/// Returns the 4x4 full perspective transform representing all transform
|
||||
/// operations executed so far in this DisplayList within the enclosing
|
||||
/// save stack.
|
||||
SkM44 GetTransformFullPerspective() const override {
|
||||
return tracker_.matrix_4x4();
|
||||
}
|
||||
/// Returns the 3x3 partial perspective transform representing all transform
|
||||
/// operations executed so far in this DisplayList within the enclosing
|
||||
/// save stack.
|
||||
SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); }
|
||||
|
||||
void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override;
|
||||
void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
|
||||
void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
|
||||
// |DlOpReceiver|
|
||||
void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override {
|
||||
ClipRect(rect, clip_op, is_aa);
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override {
|
||||
ClipRRect(rrect, clip_op, is_aa);
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override {
|
||||
ClipPath(path, clip_op, is_aa);
|
||||
}
|
||||
|
||||
/// Conservative estimate of the bounds of all outstanding clip operations
|
||||
/// measured in the coordinate space within which this DisplayList will
|
||||
/// be rendered.
|
||||
SkRect GetDestinationClipBounds() const override {
|
||||
return tracker_.device_cull_rect();
|
||||
}
|
||||
/// Conservative estimate of the bounds of all outstanding clip operations
|
||||
/// transformed into the local coordinate space in which currently
|
||||
/// recorded rendering operations are interpreted.
|
||||
SkRect GetLocalClipBounds() const override {
|
||||
return tracker_.local_cull_rect();
|
||||
}
|
||||
|
||||
/// Return true iff the supplied bounds are easily shown to be outside
|
||||
/// of the current clip bounds. This method may conservatively return
|
||||
/// false if it cannot make the determination.
|
||||
bool QuickReject(const SkRect& bounds) const override;
|
||||
|
||||
// |DlOpReceiver|
|
||||
void drawPaint() override;
|
||||
void DrawPaint(const DlPaint& paint) override;
|
||||
void DrawColor(DlColor color, DlBlendMode mode) override;
|
||||
// |DlOpReceiver|
|
||||
void drawColor(DlColor color, DlBlendMode mode) override {
|
||||
DrawColor(color, mode);
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void drawLine(const SkPoint& p0, const SkPoint& p1) override;
|
||||
void DrawLine(const SkPoint& p0,
|
||||
const SkPoint& p1,
|
||||
const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawRect(const SkRect& rect) override;
|
||||
void DrawRect(const SkRect& rect, const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawOval(const SkRect& bounds) override;
|
||||
void DrawOval(const SkRect& bounds, const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawCircle(const SkPoint& center, SkScalar radius) override;
|
||||
void DrawCircle(const SkPoint& center,
|
||||
SkScalar radius,
|
||||
const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawRRect(const SkRRect& rrect) override;
|
||||
void DrawRRect(const SkRRect& rrect, const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
|
||||
void DrawDRRect(const SkRRect& outer,
|
||||
const SkRRect& inner,
|
||||
const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawPath(const SkPath& path) override;
|
||||
void DrawPath(const SkPath& path, const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawArc(const SkRect& bounds,
|
||||
SkScalar start,
|
||||
SkScalar sweep,
|
||||
bool useCenter) override;
|
||||
void DrawArc(const SkRect& bounds,
|
||||
SkScalar start,
|
||||
SkScalar sweep,
|
||||
bool useCenter,
|
||||
const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawPoints(PointMode mode, uint32_t count, const SkPoint pts[]) override;
|
||||
void DrawPoints(PointMode mode,
|
||||
uint32_t count,
|
||||
const SkPoint pts[],
|
||||
const DlPaint& paint) override;
|
||||
// |DlOpReceiver|
|
||||
void drawVertices(const DlVertices* vertices, DlBlendMode mode) override;
|
||||
void drawVertices(const std::shared_ptr<const DlVertices> vertices,
|
||||
DlBlendMode mode) {
|
||||
drawVertices(vertices.get(), mode);
|
||||
}
|
||||
void DrawVertices(const DlVertices* vertices,
|
||||
DlBlendMode mode,
|
||||
const DlPaint& paint) override;
|
||||
using DlCanvas::DrawVertices;
|
||||
|
||||
// |DlOpReceiver|
|
||||
void drawImage(const sk_sp<DlImage> image,
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes) override;
|
||||
void DrawImage(const sk_sp<DlImage>& image,
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
// |DlOpReceiver|
|
||||
void drawImageRect(
|
||||
const sk_sp<DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint =
|
||||
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint) override;
|
||||
void DrawImageRect(const sk_sp<DlImage>& image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
bool enforce_src_edges = false) override;
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
|
||||
// |DlOpReceiver|
|
||||
void drawImageNine(const sk_sp<DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) override;
|
||||
void DrawImageNine(const sk_sp<DlImage>& image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
DlFilterMode filter,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
// |DlOpReceiver|
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const SkRect tex[],
|
||||
@ -362,32 +450,17 @@ class DisplayListBuilder final : public virtual DlCanvas,
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cullRect,
|
||||
bool render_with_attributes) override;
|
||||
void DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
const SkRSXform xform[],
|
||||
const SkRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
DlBlendMode mode,
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cullRect,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
void DrawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list) override {
|
||||
DrawDisplayList(display_list, SK_Scalar1);
|
||||
|
||||
// |DlOpReceiver|
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) override {
|
||||
DrawDisplayList(display_list, opacity);
|
||||
}
|
||||
// |DlOpReceiver|
|
||||
void drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) override;
|
||||
void DrawTextBlob(const sk_sp<SkTextBlob>& blob,
|
||||
SkScalar x,
|
||||
SkScalar y,
|
||||
const DlPaint& paint) override;
|
||||
void DrawShadow(const SkPath& path,
|
||||
const DlColor color,
|
||||
const SkScalar elevation,
|
||||
bool transparent_occluder,
|
||||
SkScalar dpr) override;
|
||||
// |DlOpReceiver|
|
||||
void drawShadow(const SkPath& path,
|
||||
const DlColor color,
|
||||
const SkScalar elevation,
|
||||
@ -396,11 +469,6 @@ class DisplayListBuilder final : public virtual DlCanvas,
|
||||
DrawShadow(path, color, elevation, transparent_occluder, dpr);
|
||||
}
|
||||
|
||||
void Flush() override {}
|
||||
|
||||
sk_sp<DisplayList> Build();
|
||||
|
||||
private:
|
||||
void checkForDeferredSave();
|
||||
|
||||
DisplayListStorage storage_;
|
||||
|
||||
@ -6,6 +6,11 @@
|
||||
#include "flutter/display_list/testing/dl_test_snippets.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
DlOpReceiver& DisplayListBuilderBenchmarkAccessor(DisplayListBuilder& builder) {
|
||||
return builder.asReceiver();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static std::vector<testing::DisplayListInvocationGroup> allRenderingOps =
|
||||
@ -19,10 +24,11 @@ enum class DisplayListBuilderBenchmarkType {
|
||||
};
|
||||
|
||||
static void InvokeAllRenderingOps(DisplayListBuilder& builder) {
|
||||
DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder);
|
||||
for (auto& group : allRenderingOps) {
|
||||
for (size_t i = 0; i < group.variants.size(); i++) {
|
||||
auto& invocation = group.variants[i];
|
||||
invocation.Invoke(builder);
|
||||
invocation.Invoke(receiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,8 +75,8 @@ static void BM_DisplayListBuilderWithScaleAndTranslate(
|
||||
bool prepare_rtree = NeedPrepareRTree(type);
|
||||
while (state.KeepRunning()) {
|
||||
DisplayListBuilder builder(prepare_rtree);
|
||||
builder.scale(3.5, 3.5);
|
||||
builder.translate(10.3, 6.9);
|
||||
builder.Scale(3.5, 3.5);
|
||||
builder.Translate(10.3, 6.9);
|
||||
InvokeAllRenderingOps(builder);
|
||||
Complete(builder, type);
|
||||
}
|
||||
@ -82,7 +88,7 @@ static void BM_DisplayListBuilderWithPerspective(
|
||||
bool prepare_rtree = NeedPrepareRTree(type);
|
||||
while (state.KeepRunning()) {
|
||||
DisplayListBuilder builder(prepare_rtree);
|
||||
builder.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0,
|
||||
builder.TransformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0,
|
||||
0, 0, 12);
|
||||
InvokeAllRenderingOps(builder);
|
||||
Complete(builder, type);
|
||||
@ -96,7 +102,7 @@ static void BM_DisplayListBuilderWithClipRect(
|
||||
bool prepare_rtree = NeedPrepareRTree(type);
|
||||
while (state.KeepRunning()) {
|
||||
DisplayListBuilder builder(prepare_rtree);
|
||||
builder.clipRect(clip_bounds, DlCanvas::ClipOp::kIntersect, true);
|
||||
builder.ClipRect(clip_bounds, DlCanvas::ClipOp::kIntersect, true);
|
||||
InvokeAllRenderingOps(builder);
|
||||
Complete(builder, type);
|
||||
}
|
||||
@ -108,12 +114,13 @@ static void BM_DisplayListBuilderWithSaveLayer(
|
||||
bool prepare_rtree = NeedPrepareRTree(type);
|
||||
while (state.KeepRunning()) {
|
||||
DisplayListBuilder builder(prepare_rtree);
|
||||
DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder);
|
||||
for (auto& group : allRenderingOps) {
|
||||
for (size_t i = 0; i < group.variants.size(); i++) {
|
||||
auto& invocation = group.variants[i];
|
||||
builder.saveLayer(nullptr, false);
|
||||
invocation.Invoke(builder);
|
||||
builder.restore();
|
||||
builder.SaveLayer(nullptr, nullptr);
|
||||
invocation.Invoke(receiver);
|
||||
builder.Restore();
|
||||
}
|
||||
}
|
||||
Complete(builder, type);
|
||||
@ -129,11 +136,12 @@ static void BM_DisplayListBuilderWithSaveLayerAndImageFilter(
|
||||
bool prepare_rtree = NeedPrepareRTree(type);
|
||||
while (state.KeepRunning()) {
|
||||
DisplayListBuilder builder(prepare_rtree);
|
||||
DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder);
|
||||
for (auto& group : allRenderingOps) {
|
||||
for (size_t i = 0; i < group.variants.size(); i++) {
|
||||
auto& invocation = group.variants[i];
|
||||
builder.SaveLayer(&layer_bounds, &layer_paint);
|
||||
invocation.Invoke(builder);
|
||||
invocation.Invoke(receiver);
|
||||
builder.Restore();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,305 +0,0 @@
|
||||
// Copyright 2013 The Flutter 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 "flutter/display_list/display_list_canvas_dispatcher.h"
|
||||
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/fml/trace_event.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
const SkScalar kLightHeight = 600;
|
||||
const SkScalar kLightRadius = 800;
|
||||
|
||||
static SkClipOp ToSk(DlCanvas::ClipOp op) {
|
||||
return static_cast<SkClipOp>(op);
|
||||
}
|
||||
|
||||
static SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) {
|
||||
return static_cast<SkCanvas::PointMode>(mode);
|
||||
}
|
||||
|
||||
const SkPaint* DisplayListCanvasDispatcher::safe_paint(bool use_attributes) {
|
||||
if (use_attributes) {
|
||||
// The accumulated SkPaint object will already have incorporated
|
||||
// any attribute overrides.
|
||||
return &paint();
|
||||
} else if (has_opacity()) {
|
||||
temp_paint_.setAlphaf(opacity());
|
||||
return &temp_paint_;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayListCanvasDispatcher::save() {
|
||||
canvas_->save();
|
||||
// save has no impact on attributes, but it needs to register a record
|
||||
// on the restore stack so that the eventual call to restore() will
|
||||
// know what to do at that time. We could annotate the restore record
|
||||
// with a flag that the record came from a save call, but it is simpler
|
||||
// to just pass in the current opacity value as the value to be used by
|
||||
// the children and let the utility calls notice that it didn't change.
|
||||
save_opacity(opacity());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::restore() {
|
||||
canvas_->restore();
|
||||
restore_opacity();
|
||||
}
|
||||
void DisplayListCanvasDispatcher::saveLayer(const SkRect* bounds,
|
||||
const SaveLayerOptions options,
|
||||
const DlImageFilter* backdrop) {
|
||||
if (bounds == nullptr && options.can_distribute_opacity() &&
|
||||
backdrop == nullptr) {
|
||||
// We know that:
|
||||
// - no bounds is needed for clipping here
|
||||
// - no backdrop filter is used to initialize the layer
|
||||
// - the current attributes only have an alpha
|
||||
// - the children are compatible with individually rendering with
|
||||
// an inherited opacity
|
||||
// Therefore we can just use a save instead of a saveLayer and pass the
|
||||
// intended opacity to the children.
|
||||
canvas_->save();
|
||||
// If the saveLayer does not use attributes, the children should continue
|
||||
// to render with the inherited opacity unmodified. If attributes are to
|
||||
// be applied, the children should render with the combination of the
|
||||
// inherited opacity combined with the alpha from the current color.
|
||||
save_opacity(options.renders_with_attributes() ? combined_opacity()
|
||||
: opacity());
|
||||
} else {
|
||||
TRACE_EVENT0("flutter", "Canvas::saveLayer");
|
||||
const SkPaint* paint = safe_paint(options.renders_with_attributes());
|
||||
const sk_sp<SkImageFilter> sk_backdrop =
|
||||
backdrop ? backdrop->skia_object() : nullptr;
|
||||
canvas_->saveLayer(
|
||||
SkCanvas::SaveLayerRec(bounds, paint, sk_backdrop.get(), 0));
|
||||
// saveLayer will apply the current opacity on behalf of the children
|
||||
// so they will inherit an opaque opacity.
|
||||
save_opacity(SK_Scalar1);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayListCanvasDispatcher::translate(SkScalar tx, SkScalar ty) {
|
||||
canvas_->translate(tx, ty);
|
||||
}
|
||||
void DisplayListCanvasDispatcher::scale(SkScalar sx, SkScalar sy) {
|
||||
canvas_->scale(sx, sy);
|
||||
}
|
||||
void DisplayListCanvasDispatcher::rotate(SkScalar degrees) {
|
||||
canvas_->rotate(degrees);
|
||||
}
|
||||
void DisplayListCanvasDispatcher::skew(SkScalar sx, SkScalar sy) {
|
||||
canvas_->skew(sx, sy);
|
||||
}
|
||||
// clang-format off
|
||||
// 2x3 2D affine subset of a 4x4 transform in row major order
|
||||
void DisplayListCanvasDispatcher::transform2DAffine(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myt) {
|
||||
// Internally concat(SkMatrix) gets redirected to concat(SkM44)
|
||||
// so we just jump directly to the SkM44 version
|
||||
canvas_->concat(SkM44(mxx, mxy, 0, mxt,
|
||||
myx, myy, 0, myt,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1));
|
||||
}
|
||||
// full 4x4 transform in row major order
|
||||
void DisplayListCanvasDispatcher::transformFullPerspective(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
|
||||
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
|
||||
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) {
|
||||
canvas_->concat(SkM44(mxx, mxy, mxz, mxt,
|
||||
myx, myy, myz, myt,
|
||||
mzx, mzy, mzz, mzt,
|
||||
mwx, mwy, mwz, mwt));
|
||||
}
|
||||
// clang-format on
|
||||
void DisplayListCanvasDispatcher::transformReset() {
|
||||
canvas_->setMatrix(original_transform_);
|
||||
}
|
||||
|
||||
void DisplayListCanvasDispatcher::clipRect(const SkRect& rect,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
canvas_->clipRect(rect, ToSk(clip_op), is_aa);
|
||||
}
|
||||
void DisplayListCanvasDispatcher::clipRRect(const SkRRect& rrect,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
canvas_->clipRRect(rrect, ToSk(clip_op), is_aa);
|
||||
}
|
||||
void DisplayListCanvasDispatcher::clipPath(const SkPath& path,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
canvas_->clipPath(path, ToSk(clip_op), is_aa);
|
||||
}
|
||||
|
||||
void DisplayListCanvasDispatcher::drawPaint() {
|
||||
const SkPaint& sk_paint = paint();
|
||||
SkImageFilter* filter = sk_paint.getImageFilter();
|
||||
if (filter && !filter->asColorFilter(nullptr)) {
|
||||
// drawPaint does an implicit saveLayer if an SkImageFilter is
|
||||
// present that cannot be replaced by an SkColorFilter.
|
||||
TRACE_EVENT0("flutter", "Canvas::saveLayer");
|
||||
}
|
||||
canvas_->drawPaint(sk_paint);
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawColor(DlColor color, DlBlendMode mode) {
|
||||
// SkCanvas::drawColor(SkColor) does the following conversion anyway
|
||||
// We do it here manually to increase precision on applying opacity
|
||||
SkColor4f color4f = SkColor4f::FromColor(color);
|
||||
color4f.fA *= opacity();
|
||||
canvas_->drawColor(color4f, ToSk(mode));
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawLine(const SkPoint& p0,
|
||||
const SkPoint& p1) {
|
||||
canvas_->drawLine(p0, p1, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawRect(const SkRect& rect) {
|
||||
canvas_->drawRect(rect, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawOval(const SkRect& bounds) {
|
||||
canvas_->drawOval(bounds, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawCircle(const SkPoint& center,
|
||||
SkScalar radius) {
|
||||
canvas_->drawCircle(center, radius, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawRRect(const SkRRect& rrect) {
|
||||
canvas_->drawRRect(rrect, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawDRRect(const SkRRect& outer,
|
||||
const SkRRect& inner) {
|
||||
canvas_->drawDRRect(outer, inner, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawPath(const SkPath& path) {
|
||||
canvas_->drawPath(path, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawArc(const SkRect& bounds,
|
||||
SkScalar start,
|
||||
SkScalar sweep,
|
||||
bool useCenter) {
|
||||
canvas_->drawArc(bounds, start, sweep, useCenter, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawPoints(PointMode mode,
|
||||
uint32_t count,
|
||||
const SkPoint pts[]) {
|
||||
canvas_->drawPoints(ToSk(mode), count, pts, paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawVertices(const DlVertices* vertices,
|
||||
DlBlendMode mode) {
|
||||
canvas_->drawVertices(vertices->skia_object(), ToSk(mode), paint());
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawImage(const sk_sp<DlImage> image,
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes) {
|
||||
canvas_->drawImage(image ? image->skia_image() : nullptr, point.fX, point.fY,
|
||||
ToSk(sampling), safe_paint(render_with_attributes));
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawImageRect(
|
||||
const sk_sp<DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) {
|
||||
canvas_->drawImageRect(image ? image->skia_image() : nullptr, src, dst,
|
||||
ToSk(sampling), safe_paint(render_with_attributes),
|
||||
constraint);
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawImageNine(const sk_sp<DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) {
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
auto skia_image = image->skia_image();
|
||||
if (!skia_image) {
|
||||
return;
|
||||
}
|
||||
canvas_->drawImageNine(skia_image.get(), center, dst, ToSk(filter),
|
||||
safe_paint(render_with_attributes));
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const SkRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
DlBlendMode mode,
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cullRect,
|
||||
bool render_with_attributes) {
|
||||
if (!atlas) {
|
||||
return;
|
||||
}
|
||||
auto skia_atlas = atlas->skia_image();
|
||||
if (!skia_atlas) {
|
||||
return;
|
||||
}
|
||||
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors);
|
||||
canvas_->drawAtlas(skia_atlas.get(), xform, tex, sk_colors, count, ToSk(mode),
|
||||
ToSk(sampling), cullRect,
|
||||
safe_paint(render_with_attributes));
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawDisplayList(
|
||||
const sk_sp<DisplayList> display_list) {
|
||||
int save_count = canvas_->save();
|
||||
display_list->RenderTo(canvas_, opacity());
|
||||
canvas_->restoreToCount(save_count);
|
||||
}
|
||||
void DisplayListCanvasDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) {
|
||||
canvas_->drawTextBlob(blob, x, y, paint());
|
||||
}
|
||||
|
||||
SkRect DisplayListCanvasDispatcher::ComputeShadowBounds(const SkPath& path,
|
||||
float elevation,
|
||||
SkScalar dpr,
|
||||
const SkMatrix& ctm) {
|
||||
SkRect shadow_bounds(path.getBounds());
|
||||
SkShadowUtils::GetLocalBounds(
|
||||
ctm, path, SkPoint3::Make(0, 0, dpr * elevation),
|
||||
SkPoint3::Make(0, -1, 1), kLightRadius / kLightHeight,
|
||||
SkShadowFlags::kDirectionalLight_ShadowFlag, &shadow_bounds);
|
||||
return shadow_bounds;
|
||||
}
|
||||
|
||||
void DisplayListCanvasDispatcher::DrawShadow(SkCanvas* canvas,
|
||||
const SkPath& path,
|
||||
DlColor color,
|
||||
float elevation,
|
||||
bool transparentOccluder,
|
||||
SkScalar dpr) {
|
||||
const SkScalar kAmbientAlpha = 0.039f;
|
||||
const SkScalar kSpotAlpha = 0.25f;
|
||||
|
||||
uint32_t flags = transparentOccluder
|
||||
? SkShadowFlags::kTransparentOccluder_ShadowFlag
|
||||
: SkShadowFlags::kNone_ShadowFlag;
|
||||
flags |= SkShadowFlags::kDirectionalLight_ShadowFlag;
|
||||
SkColor in_ambient = SkColorSetA(color, kAmbientAlpha * SkColorGetA(color));
|
||||
SkColor in_spot = SkColorSetA(color, kSpotAlpha * SkColorGetA(color));
|
||||
SkColor ambient_color, spot_color;
|
||||
SkShadowUtils::ComputeTonalColors(in_ambient, in_spot, &ambient_color,
|
||||
&spot_color);
|
||||
SkShadowUtils::DrawShadow(canvas, path, SkPoint3::Make(0, 0, dpr * elevation),
|
||||
SkPoint3::Make(0, -1, 1),
|
||||
kLightRadius / kLightHeight, ambient_color,
|
||||
spot_color, flags);
|
||||
}
|
||||
|
||||
void DisplayListCanvasDispatcher::drawShadow(const SkPath& path,
|
||||
const DlColor color,
|
||||
const SkScalar elevation,
|
||||
bool transparent_occluder,
|
||||
SkScalar dpr) {
|
||||
DrawShadow(canvas_, path, color, elevation, transparent_occluder, dpr);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@ -35,6 +35,7 @@ struct DlColor {
|
||||
uint32_t argb;
|
||||
|
||||
bool isOpaque() const { return getAlpha() == 0xFF; }
|
||||
bool isTransparent() const { return getAlpha() == 0; }
|
||||
|
||||
int getAlpha() const { return argb >> 24; }
|
||||
int getRed() const { return (argb >> 16) & 0xFF; }
|
||||
|
||||
@ -8,16 +8,193 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
std::shared_ptr<DlColorFilter> DlBlendColorFilter::Make(DlColor color,
|
||||
DlBlendMode mode) {
|
||||
switch (mode) {
|
||||
case DlBlendMode::kDst: {
|
||||
return nullptr;
|
||||
}
|
||||
case DlBlendMode::kSrcOver: {
|
||||
if (color.isTransparent()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (color.isOpaque()) {
|
||||
mode = DlBlendMode::kSrc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DlBlendMode::kDstOver:
|
||||
case DlBlendMode::kDstOut:
|
||||
case DlBlendMode::kSrcATop:
|
||||
case DlBlendMode::kXor:
|
||||
case DlBlendMode::kDarken: {
|
||||
if (color.isTransparent()) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DlBlendMode::kDstIn: {
|
||||
if (color.isOpaque()) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::make_shared<DlBlendColorFilter>(color, mode);
|
||||
}
|
||||
|
||||
bool DlBlendColorFilter::modifies_transparent_black() const {
|
||||
switch (mode_) {
|
||||
// These modes all act like kSrc when the dest is all 0s.
|
||||
// So they modify transparent black when the src color is
|
||||
// not transparent.
|
||||
case DlBlendMode::kSrc:
|
||||
case DlBlendMode::kSrcOver:
|
||||
case DlBlendMode::kDstOver:
|
||||
case DlBlendMode::kSrcOut:
|
||||
case DlBlendMode::kDstATop:
|
||||
case DlBlendMode::kXor:
|
||||
case DlBlendMode::kPlus:
|
||||
case DlBlendMode::kScreen:
|
||||
case DlBlendMode::kOverlay:
|
||||
case DlBlendMode::kDarken:
|
||||
case DlBlendMode::kLighten:
|
||||
case DlBlendMode::kColorDodge:
|
||||
case DlBlendMode::kColorBurn:
|
||||
case DlBlendMode::kHardLight:
|
||||
case DlBlendMode::kSoftLight:
|
||||
case DlBlendMode::kDifference:
|
||||
case DlBlendMode::kExclusion:
|
||||
case DlBlendMode::kMultiply:
|
||||
case DlBlendMode::kHue:
|
||||
case DlBlendMode::kSaturation:
|
||||
case DlBlendMode::kColor:
|
||||
case DlBlendMode::kLuminosity:
|
||||
return !color_.isTransparent();
|
||||
|
||||
// These modes are all like kDst when the dest is all 0s.
|
||||
// So they never modify transparent black.
|
||||
case DlBlendMode::kClear:
|
||||
case DlBlendMode::kDst:
|
||||
case DlBlendMode::kSrcIn:
|
||||
case DlBlendMode::kDstIn:
|
||||
case DlBlendMode::kDstOut:
|
||||
case DlBlendMode::kSrcATop:
|
||||
case DlBlendMode::kModulate:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DlBlendColorFilter::can_commute_with_opacity() const {
|
||||
switch (mode_) {
|
||||
case DlBlendMode::kClear:
|
||||
case DlBlendMode::kDst:
|
||||
case DlBlendMode::kSrcIn:
|
||||
case DlBlendMode::kDstIn:
|
||||
case DlBlendMode::kDstOut:
|
||||
case DlBlendMode::kSrcATop:
|
||||
case DlBlendMode::kModulate:
|
||||
return true;
|
||||
|
||||
case DlBlendMode::kSrc:
|
||||
case DlBlendMode::kSrcOver:
|
||||
case DlBlendMode::kDstOver:
|
||||
case DlBlendMode::kSrcOut:
|
||||
case DlBlendMode::kDstATop:
|
||||
case DlBlendMode::kXor:
|
||||
case DlBlendMode::kPlus:
|
||||
case DlBlendMode::kScreen:
|
||||
case DlBlendMode::kOverlay:
|
||||
case DlBlendMode::kDarken:
|
||||
case DlBlendMode::kLighten:
|
||||
case DlBlendMode::kColorDodge:
|
||||
case DlBlendMode::kColorBurn:
|
||||
case DlBlendMode::kHardLight:
|
||||
case DlBlendMode::kSoftLight:
|
||||
case DlBlendMode::kDifference:
|
||||
case DlBlendMode::kExclusion:
|
||||
case DlBlendMode::kMultiply:
|
||||
case DlBlendMode::kHue:
|
||||
case DlBlendMode::kSaturation:
|
||||
case DlBlendMode::kColor:
|
||||
case DlBlendMode::kLuminosity:
|
||||
return color_.isTransparent();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<DlColorFilter> DlMatrixColorFilter::Make(
|
||||
const float matrix[20]) {
|
||||
float product = 0;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
product *= matrix[i];
|
||||
}
|
||||
// If any of the elements of the matrix are infinity or NaN, then
|
||||
// |product| will be NaN, otherwise 0.
|
||||
if (product == 0) {
|
||||
return std::make_shared<DlMatrixColorFilter>(matrix);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DlMatrixColorFilter::modifies_transparent_black() const {
|
||||
// Values are considered in non-premultiplied form when the matrix is
|
||||
// applied, but we only care about this answer for whether it leaves
|
||||
// an incoming color with a transparent alpha as transparent on output.
|
||||
// Thus, we only need to consider the alpha part of the matrix equation,
|
||||
// which is the last row. Since the incoming alpha value is 0, the last
|
||||
// equation ends up becoming A' = matrix_[19]. Negative results will be
|
||||
// clamped to the range [0,1] so we only care about positive values.
|
||||
// Non-finite values are clamped to a zero alpha.
|
||||
return (SkScalarIsFinite(matrix_[19]) && matrix_[19] > 0);
|
||||
}
|
||||
|
||||
bool DlMatrixColorFilter::can_commute_with_opacity() const {
|
||||
// We need to check if:
|
||||
// filter(color) * opacity == filter(color * opacity).
|
||||
//
|
||||
// filter(RGBA) = R' = [ R*m[ 0] + G*m[ 1] + B*m[ 2] + A*m[ 3] + m[ 4] ]
|
||||
// G' = [ R*m[ 5] + G*m[ 6] + B*m[ 7] + A*m[ 8] + m[ 9] ]
|
||||
// B' = [ R*m[10] + G*m[11] + B*m[12] + A*m[13] + m[14] ]
|
||||
// A' = [ R*m[15] + G*m[16] + B*m[17] + A*m[18] + m[19] ]
|
||||
//
|
||||
// Applying the opacity only affects the alpha value since the operations
|
||||
// are performed on non-premultiplied colors. (If the data is stored in
|
||||
// premultiplied form, though, there may be rounding errors due to
|
||||
// premul->unpremul->premul conversions.)
|
||||
|
||||
// We test for the successful cases and return false if they fail so that
|
||||
// we fail and return false if any matrix values are NaN.
|
||||
|
||||
// If any of the alpha column are non-zero then the prior alpha affects
|
||||
// the result color, so applying opacity before the filter will change
|
||||
// the incoming alpha and therefore the colors that are produced.
|
||||
if (!(matrix_[3] == 0 && // A does not affect R'
|
||||
matrix_[8] == 0 && // A does not affect G'
|
||||
matrix_[13] == 0)) { // A does not affect B'
|
||||
return false;
|
||||
}
|
||||
|
||||
// Similarly, if any of the alpha row are non-zero then the prior colors
|
||||
// affect the result alpha in a way that prevents opacity from commuting
|
||||
// through the filter operation.
|
||||
if (!(matrix_[15] == 0 && // R does not affect A'
|
||||
matrix_[16] == 0 && // G does not affect A'
|
||||
matrix_[17] == 0 && // B does not affect A'
|
||||
matrix_[19] == 0)) { // A' is not offset by an absolute value
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::shared_ptr<DlSrgbToLinearGammaColorFilter>
|
||||
DlSrgbToLinearGammaColorFilter::instance =
|
||||
std::make_shared<DlSrgbToLinearGammaColorFilter>();
|
||||
const sk_sp<SkColorFilter> DlSrgbToLinearGammaColorFilter::sk_filter_ =
|
||||
SkColorFilters::SRGBToLinearGamma();
|
||||
|
||||
const std::shared_ptr<DlLinearToSrgbGammaColorFilter>
|
||||
DlLinearToSrgbGammaColorFilter::instance =
|
||||
std::make_shared<DlLinearToSrgbGammaColorFilter>();
|
||||
const sk_sp<SkColorFilter> DlLinearToSrgbGammaColorFilter::sk_filter_ =
|
||||
SkColorFilters::LinearToSRGBGamma();
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -28,8 +28,7 @@ enum class DlColorFilterType {
|
||||
kLinearToSrgbGamma,
|
||||
};
|
||||
|
||||
class DlColorFilter
|
||||
: public DlAttribute<DlColorFilter, SkColorFilter, DlColorFilterType> {
|
||||
class DlColorFilter : public DlAttribute<DlColorFilter, DlColorFilterType> {
|
||||
public:
|
||||
// Return a boolean indicating whether the color filtering operation will
|
||||
// modify transparent black. This is typically used to determine if applying
|
||||
@ -68,23 +67,18 @@ class DlBlendColorFilter final : public DlColorFilter {
|
||||
DlBlendColorFilter(const DlBlendColorFilter* filter)
|
||||
: DlBlendColorFilter(filter->color_, filter->mode_) {}
|
||||
|
||||
static std::shared_ptr<DlColorFilter> Make(DlColor color, DlBlendMode mode);
|
||||
|
||||
DlColorFilterType type() const override { return DlColorFilterType::kBlend; }
|
||||
size_t size() const override { return sizeof(*this); }
|
||||
bool modifies_transparent_black() const override {
|
||||
// Look at blend and color to make a faster determination?
|
||||
sk_sp<SkColorFilter> sk_filter = skia_object();
|
||||
return sk_filter &&
|
||||
sk_filter->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
|
||||
}
|
||||
|
||||
bool modifies_transparent_black() const override;
|
||||
bool can_commute_with_opacity() const override;
|
||||
|
||||
std::shared_ptr<DlColorFilter> shared() const override {
|
||||
return std::make_shared<DlBlendColorFilter>(this);
|
||||
}
|
||||
|
||||
sk_sp<SkColorFilter> skia_object() const override {
|
||||
return SkColorFilters::Blend(color_, ToSk(mode_));
|
||||
}
|
||||
|
||||
const DlBlendColorFilter* asBlend() const override { return this; }
|
||||
|
||||
DlColor color() const { return color_; }
|
||||
@ -114,6 +108,10 @@ class DlBlendColorFilter final : public DlColorFilter {
|
||||
//
|
||||
// The resulting color [oR,oG,oB,oA] is then clamped to the range of
|
||||
// valid pixel components before storing in the output.
|
||||
//
|
||||
// The incoming and outgoing [iR,iG,iB,iA] and [oR,oG,oB,oA] are
|
||||
// considered to be non-premultiplied. When working on premultiplied
|
||||
// pixel data, the necessary pre<->non-pre conversions must be performed.
|
||||
class DlMatrixColorFilter final : public DlColorFilter {
|
||||
public:
|
||||
DlMatrixColorFilter(const float matrix[20]) {
|
||||
@ -124,30 +122,18 @@ class DlMatrixColorFilter final : public DlColorFilter {
|
||||
DlMatrixColorFilter(const DlMatrixColorFilter* filter)
|
||||
: DlMatrixColorFilter(filter->matrix_) {}
|
||||
|
||||
static std::shared_ptr<DlColorFilter> Make(const float matrix[20]);
|
||||
|
||||
DlColorFilterType type() const override { return DlColorFilterType::kMatrix; }
|
||||
size_t size() const override { return sizeof(*this); }
|
||||
bool modifies_transparent_black() const override {
|
||||
// Look at the matrix to make a faster determination?
|
||||
// Basically, are the translation components all 0?
|
||||
sk_sp<SkColorFilter> sk_filter = skia_object();
|
||||
return sk_filter &&
|
||||
sk_filter->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
|
||||
}
|
||||
|
||||
bool can_commute_with_opacity() const override {
|
||||
return matrix_[3] == 0 && matrix_[8] == 0 && matrix_[13] == 0 &&
|
||||
matrix_[15] == 0 && matrix_[16] == 0 && matrix_[17] == 0 &&
|
||||
(matrix_[18] >= 0.0 && matrix_[18] <= 1.0) && matrix_[19] == 0;
|
||||
}
|
||||
bool modifies_transparent_black() const override;
|
||||
bool can_commute_with_opacity() const override;
|
||||
|
||||
std::shared_ptr<DlColorFilter> shared() const override {
|
||||
return std::make_shared<DlMatrixColorFilter>(this);
|
||||
}
|
||||
|
||||
sk_sp<SkColorFilter> skia_object() const override {
|
||||
return SkColorFilters::Matrix(matrix_);
|
||||
}
|
||||
|
||||
const DlMatrixColorFilter* asMatrix() const override { return this; }
|
||||
|
||||
const float& operator[](int index) const { return matrix_[index]; }
|
||||
@ -186,7 +172,6 @@ class DlSrgbToLinearGammaColorFilter final : public DlColorFilter {
|
||||
bool can_commute_with_opacity() const override { return true; }
|
||||
|
||||
std::shared_ptr<DlColorFilter> shared() const override { return instance; }
|
||||
sk_sp<SkColorFilter> skia_object() const override { return sk_filter_; }
|
||||
|
||||
protected:
|
||||
bool equals_(const DlColorFilter& other) const override {
|
||||
@ -195,7 +180,6 @@ class DlSrgbToLinearGammaColorFilter final : public DlColorFilter {
|
||||
}
|
||||
|
||||
private:
|
||||
static const sk_sp<SkColorFilter> sk_filter_;
|
||||
friend class DlColorFilter;
|
||||
};
|
||||
|
||||
@ -219,7 +203,6 @@ class DlLinearToSrgbGammaColorFilter final : public DlColorFilter {
|
||||
bool can_commute_with_opacity() const override { return true; }
|
||||
|
||||
std::shared_ptr<DlColorFilter> shared() const override { return instance; }
|
||||
sk_sp<SkColorFilter> skia_object() const override { return sk_filter_; }
|
||||
|
||||
protected:
|
||||
bool equals_(const DlColorFilter& other) const override {
|
||||
@ -228,7 +211,6 @@ class DlLinearToSrgbGammaColorFilter final : public DlColorFilter {
|
||||
}
|
||||
|
||||
private:
|
||||
static const sk_sp<SkColorFilter> sk_filter_;
|
||||
friend class DlColorFilter;
|
||||
};
|
||||
|
||||
|
||||
@ -17,18 +17,6 @@ static const float kMatrix[20] = {
|
||||
16, 17, 18, 19, 20, //
|
||||
};
|
||||
|
||||
TEST(DisplayListColorFilter, BuilderSetGet) {
|
||||
DlBlendColorFilter filter(DlColor::kRed(), DlBlendMode::kDstATop);
|
||||
DisplayListBuilder builder;
|
||||
ASSERT_EQ(builder.getColorFilter(), nullptr);
|
||||
builder.setColorFilter(&filter);
|
||||
ASSERT_NE(builder.getColorFilter(), nullptr);
|
||||
ASSERT_TRUE(
|
||||
Equals(builder.getColorFilter(), static_cast<DlColorFilter*>(&filter)));
|
||||
builder.setColorFilter(nullptr);
|
||||
ASSERT_EQ(builder.getColorFilter(), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListColorFilter, BlendConstructor) {
|
||||
DlBlendColorFilter filter(DlColor::kRed(), DlBlendMode::kDstATop);
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ static void DlGradientDeleter(void* p) {
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
std::shared_ptr<DlColorSource> DlColorSource::MakeLinear(
|
||||
std::shared_ptr<DlLinearGradientColorSource> DlColorSource::MakeLinear(
|
||||
const SkPoint start_point,
|
||||
const SkPoint end_point,
|
||||
uint32_t stop_count,
|
||||
@ -37,10 +37,10 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeLinear(
|
||||
DlLinearGradientColorSource(start_point, end_point, stop_count,
|
||||
colors, stops, tile_mode, matrix),
|
||||
DlGradientDeleter);
|
||||
return std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlColorSource> DlColorSource::MakeRadial(
|
||||
std::shared_ptr<DlRadialGradientColorSource> DlColorSource::MakeRadial(
|
||||
SkPoint center,
|
||||
SkScalar radius,
|
||||
uint32_t stop_count,
|
||||
@ -57,10 +57,10 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeRadial(
|
||||
ret.reset(new (storage) DlRadialGradientColorSource(
|
||||
center, radius, stop_count, colors, stops, tile_mode, matrix),
|
||||
DlGradientDeleter);
|
||||
return std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlColorSource> DlColorSource::MakeConical(
|
||||
std::shared_ptr<DlConicalGradientColorSource> DlColorSource::MakeConical(
|
||||
SkPoint start_center,
|
||||
SkScalar start_radius,
|
||||
SkPoint end_center,
|
||||
@ -80,10 +80,10 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeConical(
|
||||
start_center, start_radius, end_center, end_radius, stop_count,
|
||||
colors, stops, tile_mode, matrix),
|
||||
DlGradientDeleter);
|
||||
return std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlColorSource> DlColorSource::MakeSweep(
|
||||
std::shared_ptr<DlSweepGradientColorSource> DlColorSource::MakeSweep(
|
||||
SkPoint center,
|
||||
SkScalar start,
|
||||
SkScalar end,
|
||||
@ -102,7 +102,7 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeSweep(
|
||||
DlSweepGradientColorSource(center, start, end, stop_count,
|
||||
colors, stops, tile_mode, matrix),
|
||||
DlGradientDeleter);
|
||||
return std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlRuntimeEffectColorSource> DlColorSource::MakeRuntimeEffect(
|
||||
|
||||
@ -63,10 +63,9 @@ enum class DlColorSourceType {
|
||||
#endif // IMPELLER_ENABLE_3D
|
||||
};
|
||||
|
||||
class DlColorSource
|
||||
: public DlAttribute<DlColorSource, SkShader, DlColorSourceType> {
|
||||
class DlColorSource : public DlAttribute<DlColorSource, DlColorSourceType> {
|
||||
public:
|
||||
static std::shared_ptr<DlColorSource> MakeLinear(
|
||||
static std::shared_ptr<DlLinearGradientColorSource> MakeLinear(
|
||||
const SkPoint start_point,
|
||||
const SkPoint end_point,
|
||||
uint32_t stop_count,
|
||||
@ -75,7 +74,7 @@ class DlColorSource
|
||||
DlTileMode tile_mode,
|
||||
const SkMatrix* matrix = nullptr);
|
||||
|
||||
static std::shared_ptr<DlColorSource> MakeRadial(
|
||||
static std::shared_ptr<DlRadialGradientColorSource> MakeRadial(
|
||||
SkPoint center,
|
||||
SkScalar radius,
|
||||
uint32_t stop_count,
|
||||
@ -84,7 +83,7 @@ class DlColorSource
|
||||
DlTileMode tile_mode,
|
||||
const SkMatrix* matrix = nullptr);
|
||||
|
||||
static std::shared_ptr<DlColorSource> MakeConical(
|
||||
static std::shared_ptr<DlConicalGradientColorSource> MakeConical(
|
||||
SkPoint start_center,
|
||||
SkScalar start_radius,
|
||||
SkPoint end_center,
|
||||
@ -95,7 +94,7 @@ class DlColorSource
|
||||
DlTileMode tile_mode,
|
||||
const SkMatrix* matrix = nullptr);
|
||||
|
||||
static std::shared_ptr<DlColorSource> MakeSweep(
|
||||
static std::shared_ptr<DlSweepGradientColorSource> MakeSweep(
|
||||
SkPoint center,
|
||||
SkScalar start,
|
||||
SkScalar end,
|
||||
@ -190,10 +189,6 @@ class DlColorColorSource final : public DlColorSource {
|
||||
|
||||
DlColor color() const { return color_; }
|
||||
|
||||
sk_sp<SkShader> skia_object() const override {
|
||||
return SkShaders::Color(color_);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(DlColorSource const& other) const override {
|
||||
FML_DCHECK(other.type() == DlColorSourceType::kColor);
|
||||
@ -263,15 +258,6 @@ class DlImageColorSource final : public SkRefCnt,
|
||||
DlTileMode vertical_tile_mode() const { return vertical_tile_mode_; }
|
||||
DlImageSampling sampling() const { return sampling_; }
|
||||
|
||||
virtual sk_sp<SkShader> skia_object() const override {
|
||||
if (!image_->skia_image()) {
|
||||
return nullptr;
|
||||
}
|
||||
return image_->skia_image()->makeShader(ToSk(horizontal_tile_mode_),
|
||||
ToSk(vertical_tile_mode_),
|
||||
ToSk(sampling_), matrix_ptr());
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(DlColorSource const& other) const override {
|
||||
FML_DCHECK(other.type() == DlColorSourceType::kImage);
|
||||
@ -386,13 +372,6 @@ class DlLinearGradientColorSource final : public DlGradientColorSourceBase {
|
||||
const SkPoint& start_point() const { return start_point_; }
|
||||
const SkPoint& end_point() const { return end_point_; }
|
||||
|
||||
sk_sp<SkShader> skia_object() const override {
|
||||
SkPoint pts[] = {start_point_, end_point_};
|
||||
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
|
||||
return SkGradientShader::MakeLinear(pts, sk_colors, stops(), stop_count(),
|
||||
ToSk(tile_mode()), 0, matrix_ptr());
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual const void* pod() const override { return this + 1; }
|
||||
|
||||
@ -454,13 +433,6 @@ class DlRadialGradientColorSource final : public DlGradientColorSourceBase {
|
||||
SkPoint center() const { return center_; }
|
||||
SkScalar radius() const { return radius_; }
|
||||
|
||||
sk_sp<SkShader> skia_object() const override {
|
||||
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
|
||||
return SkGradientShader::MakeRadial(center_, radius_, sk_colors, stops(),
|
||||
stop_count(), ToSk(tile_mode()), 0,
|
||||
matrix_ptr());
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual const void* pod() const override { return this + 1; }
|
||||
|
||||
@ -525,13 +497,6 @@ class DlConicalGradientColorSource final : public DlGradientColorSourceBase {
|
||||
SkPoint end_center() const { return end_center_; }
|
||||
SkScalar end_radius() const { return end_radius_; }
|
||||
|
||||
sk_sp<SkShader> skia_object() const override {
|
||||
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
|
||||
return SkGradientShader::MakeTwoPointConical(
|
||||
start_center_, start_radius_, end_center_, end_radius_, sk_colors,
|
||||
stops(), stop_count(), ToSk(tile_mode()), 0, matrix_ptr());
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual const void* pod() const override { return this + 1; }
|
||||
|
||||
@ -604,13 +569,6 @@ class DlSweepGradientColorSource final : public DlGradientColorSourceBase {
|
||||
SkScalar start() const { return start_; }
|
||||
SkScalar end() const { return end_; }
|
||||
|
||||
sk_sp<SkShader> skia_object() const override {
|
||||
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
|
||||
return SkGradientShader::MakeSweep(center_.x(), center_.y(), sk_colors,
|
||||
stops(), stop_count(), ToSk(tile_mode()),
|
||||
start_, end_, 0, matrix_ptr());
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual const void* pod() const override { return this + 1; }
|
||||
|
||||
@ -693,35 +651,6 @@ class DlRuntimeEffectColorSource final : public DlColorSource {
|
||||
return uniform_data_;
|
||||
}
|
||||
|
||||
sk_sp<SkShader> skia_object() const override {
|
||||
if (!runtime_effect_) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!runtime_effect_->skia_runtime_effect()) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<sk_sp<SkShader>> sk_samplers(samplers_.size());
|
||||
for (size_t i = 0; i < samplers_.size(); i++) {
|
||||
auto sampler = samplers_[i];
|
||||
if (sampler == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
sk_samplers[i] = sampler->skia_object();
|
||||
}
|
||||
|
||||
auto ref = new std::shared_ptr<std::vector<uint8_t>>(uniform_data_);
|
||||
auto uniform_data = SkData::MakeWithProc(
|
||||
uniform_data_->data(), uniform_data_->size(),
|
||||
[](const void* ptr, void* context) {
|
||||
delete reinterpret_cast<std::shared_ptr<std::vector<uint8_t>>*>(
|
||||
context);
|
||||
},
|
||||
ref);
|
||||
|
||||
return runtime_effect_->skia_runtime_effect()->makeShader(
|
||||
uniform_data, sk_samplers.data(), sk_samplers.size());
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(DlColorSource const& other) const override {
|
||||
FML_DCHECK(other.type() == DlColorSourceType::kRuntimeEffect);
|
||||
|
||||
@ -86,19 +86,6 @@ static constexpr SkPoint kTestPoints2[2] = {
|
||||
SkPoint::Make(107, 118),
|
||||
};
|
||||
|
||||
TEST(DisplayListColorSource, BuilderSetGet) {
|
||||
DlImageColorSource source(kTestImage1, DlTileMode::kClamp, DlTileMode::kClamp,
|
||||
DlImageSampling::kLinear, &kTestMatrix1);
|
||||
DisplayListBuilder builder;
|
||||
ASSERT_EQ(builder.getColorSource(), nullptr);
|
||||
builder.setColorSource(&source);
|
||||
ASSERT_NE(builder.getColorSource(), nullptr);
|
||||
ASSERT_TRUE(
|
||||
Equals(builder.getColorSource(), static_cast<DlColorSource*>(&source)));
|
||||
builder.setColorSource(nullptr);
|
||||
ASSERT_EQ(builder.getColorSource(), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListColorSource, ColorConstructor) {
|
||||
DlColorColorSource source(SK_ColorRED);
|
||||
}
|
||||
@ -763,23 +750,11 @@ TEST(DisplayListColorSource, RuntimeEffect) {
|
||||
ASSERT_EQ(source1->asConicalGradient(), nullptr);
|
||||
ASSERT_EQ(source1->asSweepGradient(), nullptr);
|
||||
|
||||
ASSERT_NE(source1->skia_object(), nullptr);
|
||||
ASSERT_EQ(source3->skia_object(), nullptr);
|
||||
|
||||
TestEquals(source1, source1);
|
||||
TestEquals(source3, source3);
|
||||
TestNotEquals(source1, source2, "SkRuntimeEffect differs");
|
||||
TestNotEquals(source2, source3, "SkRuntimeEffect differs");
|
||||
}
|
||||
|
||||
TEST(DisplayListColorSource, RuntimeEffectWithNullSampler) {
|
||||
std::shared_ptr<DlRuntimeEffectColorSource> source1 =
|
||||
DlColorSource::MakeRuntimeEffect(
|
||||
kTestRuntimeEffect1, {nullptr},
|
||||
std::make_shared<std::vector<uint8_t>>());
|
||||
|
||||
ASSERT_EQ(source1->skia_object(), nullptr);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -114,7 +114,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawRect(const SkRect& rect) {
|
||||
//
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kFill_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kFill) {
|
||||
// No real difference for AA with filled styles
|
||||
unsigned int area = rect.width() * rect.height();
|
||||
|
||||
@ -165,7 +165,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawOval(
|
||||
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kFill_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kFill) {
|
||||
// With filled styles, there is no significant AA penalty.
|
||||
// m = 1/6000
|
||||
// c = 0
|
||||
@ -199,7 +199,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawCircle(
|
||||
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kFill_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kFill) {
|
||||
// We can ignore pi here
|
||||
unsigned int area = radius * radius;
|
||||
// m = 1/525
|
||||
@ -245,7 +245,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawRRect(
|
||||
// These values were worked out by creating a straight line graph (y=mx+c)
|
||||
// approximately matching the measured data, normalising the data so that
|
||||
// 0.0005ms resulted in a score of 100 then simplifying down the formula.
|
||||
if (Style() == SkPaint::Style::kFill_Style ||
|
||||
if (DrawStyle() == DlDrawStyle::kFill ||
|
||||
((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased())) {
|
||||
unsigned int area = rrect.width() * rrect.height();
|
||||
// m = 1/3200
|
||||
@ -295,7 +295,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
|
||||
//
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kFill_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kFill) {
|
||||
unsigned int area = outer.width() * outer.height();
|
||||
if (outer.getType() == SkRRect::Type::kComplex_Type) {
|
||||
// m = 1/500
|
||||
@ -382,7 +382,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawArc(
|
||||
//
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kStroke_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kStroke) {
|
||||
if (IsAntiAliased()) {
|
||||
// m = 1/3800
|
||||
// c = 12
|
||||
@ -550,7 +550,7 @@ void DisplayListGLComplexityCalculator::GLHelper::ImageRect(
|
||||
const SkISize& size,
|
||||
bool texture_backed,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) {
|
||||
bool enforce_src_edges) {
|
||||
if (IsComplex()) {
|
||||
return;
|
||||
}
|
||||
@ -563,10 +563,8 @@ void DisplayListGLComplexityCalculator::GLHelper::ImageRect(
|
||||
// approximately matching the measured data, normalising the data so that
|
||||
// 0.0005ms resulted in a score of 100 then simplifying down the formula.
|
||||
unsigned int complexity;
|
||||
if (!texture_backed ||
|
||||
(texture_backed && render_with_attributes &&
|
||||
constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint &&
|
||||
IsAntiAliased())) {
|
||||
if (!texture_backed || (texture_backed && render_with_attributes &&
|
||||
enforce_src_edges && IsAntiAliased())) {
|
||||
unsigned int area = size.width() * size.height();
|
||||
// m = 1/4000
|
||||
// c = 5
|
||||
@ -610,11 +608,15 @@ void DisplayListGLComplexityCalculator::GLHelper::drawImageNine(
|
||||
}
|
||||
|
||||
void DisplayListGLComplexityCalculator::GLHelper::drawDisplayList(
|
||||
const sk_sp<DisplayList> display_list) {
|
||||
const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) {
|
||||
if (IsComplex()) {
|
||||
return;
|
||||
}
|
||||
GLHelper helper(Ceiling() - CurrentComplexityScore());
|
||||
if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) {
|
||||
helper.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, nullptr);
|
||||
}
|
||||
display_list->Dispatch(helper);
|
||||
AccumulateComplexity(helper.ComplexityScore());
|
||||
}
|
||||
|
||||
@ -65,7 +65,8 @@ class DisplayListGLComplexityCalculator
|
||||
const SkRect& dst,
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) override;
|
||||
void drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) override;
|
||||
@ -79,7 +80,7 @@ class DisplayListGLComplexityCalculator
|
||||
void ImageRect(const SkISize& size,
|
||||
bool texture_backed,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) override;
|
||||
bool enforce_src_edges) override;
|
||||
|
||||
unsigned int BatchedComplexity() override;
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_complexity.h"
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_utils.h"
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@ -92,7 +92,7 @@ namespace flutter {
|
||||
// y = 4x
|
||||
|
||||
class ComplexityCalculatorHelper
|
||||
: public virtual Dispatcher,
|
||||
: public virtual DlOpReceiver,
|
||||
public virtual IgnoreClipDispatchHelper,
|
||||
public virtual IgnoreTransformDispatchHelper {
|
||||
public:
|
||||
@ -121,7 +121,7 @@ class ComplexityCalculatorHelper
|
||||
void setAntiAlias(bool aa) override { current_paint_.setAntiAlias(aa); }
|
||||
|
||||
void setStyle(DlDrawStyle style) override {
|
||||
current_paint_.setStyle(ToSk(style));
|
||||
current_paint_.setDrawStyle(style);
|
||||
}
|
||||
|
||||
void setStrokeWidth(SkScalar width) override {
|
||||
@ -145,17 +145,18 @@ class ComplexityCalculatorHelper
|
||||
AccumulateComplexity(50);
|
||||
}
|
||||
|
||||
void drawImageRect(const sk_sp<DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) override {
|
||||
void drawImageRect(
|
||||
const sk_sp<DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) override {
|
||||
if (IsComplex()) {
|
||||
return;
|
||||
}
|
||||
ImageRect(image->dimensions(), image->isTextureBacked(),
|
||||
render_with_attributes, constraint);
|
||||
render_with_attributes, constraint == SrcRectConstraint::kStrict);
|
||||
}
|
||||
|
||||
void drawAtlas(const sk_sp<DlImage> atlas,
|
||||
@ -174,8 +175,7 @@ class ComplexityCalculatorHelper
|
||||
// This is equivalent to calling drawImageRect lots of times
|
||||
for (int i = 0; i < count; i++) {
|
||||
ImageRect(SkISize::Make(tex[i].width(), tex[i].height()), true,
|
||||
render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint);
|
||||
render_with_attributes, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +211,7 @@ class ComplexityCalculatorHelper
|
||||
|
||||
inline bool IsAntiAliased() { return current_paint_.isAntiAlias(); }
|
||||
inline bool IsHairline() { return current_paint_.getStrokeWidth() == 0.0f; }
|
||||
inline SkPaint::Style Style() { return current_paint_.getStyle(); }
|
||||
inline DlDrawStyle DrawStyle() { return current_paint_.getDrawStyle(); }
|
||||
inline bool IsComplex() { return is_complex_; }
|
||||
inline unsigned int Ceiling() { return ceiling_; }
|
||||
inline unsigned int CurrentComplexityScore() { return complexity_score_; }
|
||||
@ -248,7 +248,7 @@ class ComplexityCalculatorHelper
|
||||
virtual void ImageRect(const SkISize& size,
|
||||
bool texture_backed,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) = 0;
|
||||
bool enforce_src_edges) = 0;
|
||||
|
||||
// This calculates and returns the cost of draw calls which are batched and
|
||||
// thus have a time cost proportional to the number of draw calls made, such
|
||||
@ -256,7 +256,7 @@ class ComplexityCalculatorHelper
|
||||
virtual unsigned int BatchedComplexity() = 0;
|
||||
|
||||
private:
|
||||
SkPaint current_paint_;
|
||||
DlPaint current_paint_;
|
||||
|
||||
// If we exceed the ceiling (defaults to the largest number representable
|
||||
// by unsigned int), then set the is_complex_ bool and we no longer
|
||||
|
||||
@ -128,7 +128,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawRect(
|
||||
//
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kFill_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kFill) {
|
||||
// No real difference for AA with filled styles.
|
||||
unsigned int area = rect.width() * rect.height();
|
||||
|
||||
@ -170,7 +170,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawOval(
|
||||
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kFill_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kFill) {
|
||||
// With filled styles, there is no significant AA penalty.
|
||||
// m = 1/16000
|
||||
// c = 0
|
||||
@ -204,7 +204,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawCircle(
|
||||
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kFill_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kFill) {
|
||||
// We can ignore pi here.
|
||||
unsigned int area = radius * radius;
|
||||
// m = 1/1300
|
||||
@ -244,7 +244,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawRRect(
|
||||
//
|
||||
// Expensive: All filled style, symmetric w/AA.
|
||||
bool expensive =
|
||||
(Style() == SkPaint::Style::kFill_Style) ||
|
||||
(DrawStyle() == DlDrawStyle::kFill) ||
|
||||
((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased());
|
||||
|
||||
unsigned int complexity;
|
||||
@ -292,7 +292,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect(
|
||||
//
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kFill_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kFill) {
|
||||
unsigned int area = outer.width() * outer.height();
|
||||
if (outer.getType() == SkRRect::Type::kComplex_Type) {
|
||||
// m = 1/1000
|
||||
@ -374,7 +374,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawArc(
|
||||
//
|
||||
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
|
||||
// currently use it anywhere in Flutter.
|
||||
if (Style() == SkPaint::Style::kStroke_Style) {
|
||||
if (DrawStyle() == DlDrawStyle::kStroke) {
|
||||
if (IsAntiAliased()) {
|
||||
// m = 1/8500
|
||||
// c = 16
|
||||
@ -493,7 +493,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::ImageRect(
|
||||
const SkISize& size,
|
||||
bool texture_backed,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) {
|
||||
bool enforce_src_edges) {
|
||||
if (IsComplex()) {
|
||||
return;
|
||||
}
|
||||
@ -512,16 +512,12 @@ void DisplayListMetalComplexityCalculator::MetalHelper::ImageRect(
|
||||
// m = 1/23000
|
||||
// c = 2.3
|
||||
complexity = (area + 52900) * 2 / 115;
|
||||
if (render_with_attributes &&
|
||||
constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint &&
|
||||
IsAntiAliased()) {
|
||||
if (render_with_attributes && enforce_src_edges && IsAntiAliased()) {
|
||||
// There's about a 30% performance penalty from the baseline.
|
||||
complexity *= 1.3f;
|
||||
}
|
||||
} else {
|
||||
if (render_with_attributes &&
|
||||
constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint &&
|
||||
IsAntiAliased()) {
|
||||
if (render_with_attributes && enforce_src_edges && IsAntiAliased()) {
|
||||
// m = 1/12200
|
||||
// c = 2.75
|
||||
complexity = (area + 33550) * 2 / 61;
|
||||
@ -556,11 +552,15 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawImageNine(
|
||||
}
|
||||
|
||||
void DisplayListMetalComplexityCalculator::MetalHelper::drawDisplayList(
|
||||
const sk_sp<DisplayList> display_list) {
|
||||
const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) {
|
||||
if (IsComplex()) {
|
||||
return;
|
||||
}
|
||||
MetalHelper helper(Ceiling() - CurrentComplexityScore());
|
||||
if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) {
|
||||
helper.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, nullptr);
|
||||
}
|
||||
display_list->Dispatch(helper);
|
||||
AccumulateComplexity(helper.ComplexityScore());
|
||||
}
|
||||
|
||||
@ -65,7 +65,8 @@ class DisplayListMetalComplexityCalculator
|
||||
const SkRect& dst,
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) override;
|
||||
void drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) override;
|
||||
@ -79,7 +80,7 @@ class DisplayListMetalComplexityCalculator
|
||||
void ImageRect(const SkISize& size,
|
||||
bool texture_backed,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) override;
|
||||
bool enforce_src_edges) override;
|
||||
|
||||
unsigned int BatchedComplexity() override;
|
||||
|
||||
|
||||
@ -76,12 +76,13 @@ TEST(DisplayListComplexity, NestedDisplayList) {
|
||||
|
||||
TEST(DisplayListComplexity, AntiAliasing) {
|
||||
DisplayListBuilder builder_no_aa;
|
||||
builder_no_aa.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
|
||||
builder_no_aa.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
|
||||
DlPaint());
|
||||
auto display_list_no_aa = builder_no_aa.Build();
|
||||
|
||||
DisplayListBuilder builder_aa;
|
||||
builder_aa.setAntiAlias(true);
|
||||
builder_aa.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
|
||||
builder_aa.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
|
||||
DlPaint().setAntiAlias(true));
|
||||
auto display_list_aa = builder_aa.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -93,13 +94,13 @@ TEST(DisplayListComplexity, AntiAliasing) {
|
||||
|
||||
TEST(DisplayListComplexity, StrokeWidth) {
|
||||
DisplayListBuilder builder_stroke_0;
|
||||
builder_stroke_0.setStrokeWidth(0.0f);
|
||||
builder_stroke_0.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
|
||||
builder_stroke_0.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
|
||||
DlPaint().setStrokeWidth(0.0f));
|
||||
auto display_list_stroke_0 = builder_stroke_0.Build();
|
||||
|
||||
DisplayListBuilder builder_stroke_1;
|
||||
builder_stroke_1.setStrokeWidth(1.0f);
|
||||
builder_stroke_1.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
|
||||
builder_stroke_0.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
|
||||
DlPaint().setStrokeWidth(1.0f));
|
||||
auto display_list_stroke_1 = builder_stroke_1.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -111,13 +112,13 @@ TEST(DisplayListComplexity, StrokeWidth) {
|
||||
|
||||
TEST(DisplayListComplexity, Style) {
|
||||
DisplayListBuilder builder_filled;
|
||||
builder_filled.setStyle(DlDrawStyle::kFill);
|
||||
builder_filled.drawRect(SkRect::MakeXYWH(10, 10, 80, 80));
|
||||
builder_filled.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80),
|
||||
DlPaint().setDrawStyle(DlDrawStyle::kFill));
|
||||
auto display_list_filled = builder_filled.Build();
|
||||
|
||||
DisplayListBuilder builder_stroked;
|
||||
builder_stroked.setStyle(DlDrawStyle::kStroke);
|
||||
builder_stroked.drawRect(SkRect::MakeXYWH(10, 10, 80, 80));
|
||||
builder_stroked.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80),
|
||||
DlPaint().setDrawStyle(DlDrawStyle::kStroke));
|
||||
auto display_list_stroked = builder_stroked.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -129,7 +130,7 @@ TEST(DisplayListComplexity, Style) {
|
||||
|
||||
TEST(DisplayListComplexity, SaveLayers) {
|
||||
DisplayListBuilder builder;
|
||||
builder.saveLayer(nullptr, true);
|
||||
builder.SaveLayer(nullptr, nullptr);
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -144,7 +145,7 @@ TEST(DisplayListComplexity, DrawPath) {
|
||||
line_path.moveTo(SkPoint::Make(0, 0));
|
||||
line_path.lineTo(SkPoint::Make(10, 10));
|
||||
line_path.close();
|
||||
builder_line.drawPath(line_path);
|
||||
builder_line.DrawPath(line_path, DlPaint());
|
||||
auto display_list_line = builder_line.Build();
|
||||
|
||||
DisplayListBuilder builder_quad;
|
||||
@ -152,7 +153,7 @@ TEST(DisplayListComplexity, DrawPath) {
|
||||
quad_path.moveTo(SkPoint::Make(0, 0));
|
||||
quad_path.quadTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20));
|
||||
quad_path.close();
|
||||
builder_quad.drawPath(quad_path);
|
||||
builder_quad.DrawPath(quad_path, DlPaint());
|
||||
auto display_list_quad = builder_quad.Build();
|
||||
|
||||
DisplayListBuilder builder_conic;
|
||||
@ -160,7 +161,7 @@ TEST(DisplayListComplexity, DrawPath) {
|
||||
conic_path.moveTo(SkPoint::Make(0, 0));
|
||||
conic_path.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f);
|
||||
conic_path.close();
|
||||
builder_conic.drawPath(conic_path);
|
||||
builder_conic.DrawPath(conic_path, DlPaint());
|
||||
auto display_list_conic = builder_conic.Build();
|
||||
|
||||
DisplayListBuilder builder_cubic;
|
||||
@ -168,7 +169,7 @@ TEST(DisplayListComplexity, DrawPath) {
|
||||
cubic_path.moveTo(SkPoint::Make(0, 0));
|
||||
cubic_path.cubicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20),
|
||||
SkPoint::Make(20, 20));
|
||||
builder_cubic.drawPath(cubic_path);
|
||||
builder_cubic.DrawPath(cubic_path, DlPaint());
|
||||
auto display_list_cubic = builder_cubic.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -186,7 +187,7 @@ TEST(DisplayListComplexity, DrawShadow) {
|
||||
line_path.moveTo(SkPoint::Make(0, 0));
|
||||
line_path.lineTo(SkPoint::Make(10, 10));
|
||||
line_path.close();
|
||||
builder_line.drawShadow(line_path, SK_ColorRED, 10.0f, false, 1.0f);
|
||||
builder_line.DrawShadow(line_path, SK_ColorRED, 10.0f, false, 1.0f);
|
||||
auto display_list_line = builder_line.Build();
|
||||
|
||||
DisplayListBuilder builder_quad;
|
||||
@ -194,7 +195,7 @@ TEST(DisplayListComplexity, DrawShadow) {
|
||||
quad_path.moveTo(SkPoint::Make(0, 0));
|
||||
quad_path.quadTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20));
|
||||
quad_path.close();
|
||||
builder_quad.drawShadow(quad_path, SK_ColorRED, 10.0f, false, 1.0f);
|
||||
builder_quad.DrawShadow(quad_path, SK_ColorRED, 10.0f, false, 1.0f);
|
||||
auto display_list_quad = builder_quad.Build();
|
||||
|
||||
DisplayListBuilder builder_conic;
|
||||
@ -202,7 +203,7 @@ TEST(DisplayListComplexity, DrawShadow) {
|
||||
conic_path.moveTo(SkPoint::Make(0, 0));
|
||||
conic_path.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f);
|
||||
conic_path.close();
|
||||
builder_conic.drawShadow(conic_path, SK_ColorRED, 10.0f, false, 1.0f);
|
||||
builder_conic.DrawShadow(conic_path, SK_ColorRED, 10.0f, false, 1.0f);
|
||||
auto display_list_conic = builder_conic.Build();
|
||||
|
||||
DisplayListBuilder builder_cubic;
|
||||
@ -210,7 +211,7 @@ TEST(DisplayListComplexity, DrawShadow) {
|
||||
cubic_path.moveTo(SkPoint::Make(0, 0));
|
||||
cubic_path.cubicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20),
|
||||
SkPoint::Make(20, 20));
|
||||
builder_cubic.drawShadow(cubic_path, SK_ColorRED, 10.0f, false, 1.0f);
|
||||
builder_cubic.DrawShadow(cubic_path, SK_ColorRED, 10.0f, false, 1.0f);
|
||||
auto display_list_cubic = builder_cubic.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -224,7 +225,7 @@ TEST(DisplayListComplexity, DrawShadow) {
|
||||
|
||||
TEST(DisplayListComplexity, DrawOval) {
|
||||
DisplayListBuilder builder;
|
||||
builder.drawOval(SkRect::MakeXYWH(10, 10, 100, 80));
|
||||
builder.DrawOval(SkRect::MakeXYWH(10, 10, 100, 80), DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -235,7 +236,7 @@ TEST(DisplayListComplexity, DrawOval) {
|
||||
|
||||
TEST(DisplayListComplexity, DrawCircle) {
|
||||
DisplayListBuilder builder;
|
||||
builder.drawCircle(SkPoint::Make(50, 50), 10.0f);
|
||||
builder.DrawCircle(SkPoint::Make(50, 50), 10.0f, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -246,8 +247,9 @@ TEST(DisplayListComplexity, DrawCircle) {
|
||||
|
||||
TEST(DisplayListComplexity, DrawRRect) {
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f));
|
||||
builder.DrawRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f),
|
||||
DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -262,7 +264,7 @@ TEST(DisplayListComplexity, DrawDRRect) {
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f);
|
||||
SkRRect inner =
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(15, 15, 70, 70), 1.5f, 1.5f);
|
||||
builder.drawDRRect(outer, inner);
|
||||
builder.DrawDRRect(outer, inner, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -273,7 +275,8 @@ TEST(DisplayListComplexity, DrawDRRect) {
|
||||
|
||||
TEST(DisplayListComplexity, DrawArc) {
|
||||
DisplayListBuilder builder;
|
||||
builder.drawArc(SkRect::MakeXYWH(10, 10, 100, 80), 0.0f, 10.0f, true);
|
||||
builder.DrawArc(SkRect::MakeXYWH(10, 10, 100, 80), 0.0f, 10.0f, true,
|
||||
DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -287,7 +290,7 @@ TEST(DisplayListComplexity, DrawVertices) {
|
||||
auto vertices = DlVertices::Make(DlVertexMode::kTriangles, points.size(),
|
||||
points.data(), nullptr, nullptr);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawVertices(vertices, DlBlendMode::kSrc);
|
||||
builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -301,12 +304,12 @@ TEST(DisplayListComplexity, DrawTextBlob) {
|
||||
"The quick brown fox jumps over the lazy dog.", SkFont());
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.drawTextBlob(text_blob, 0.0f, 0.0f);
|
||||
builder.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
|
||||
DisplayListBuilder builder_multiple;
|
||||
builder_multiple.drawTextBlob(text_blob, 0.0f, 0.0f);
|
||||
builder_multiple.drawTextBlob(text_blob, 0.0f, 0.0f);
|
||||
builder_multiple.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
|
||||
builder_multiple.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
|
||||
auto display_list_multiple = builder_multiple.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -320,18 +323,18 @@ TEST(DisplayListComplexity, DrawTextBlob) {
|
||||
TEST(DisplayListComplexity, DrawPoints) {
|
||||
auto points = GetTestPoints();
|
||||
DisplayListBuilder builder_lines;
|
||||
builder_lines.drawPoints(DlCanvas::PointMode::kLines, points.size(),
|
||||
points.data());
|
||||
builder_lines.DrawPoints(DlCanvas::PointMode::kLines, points.size(),
|
||||
points.data(), DlPaint());
|
||||
auto display_list_lines = builder_lines.Build();
|
||||
|
||||
DisplayListBuilder builder_points;
|
||||
builder_points.drawPoints(DlCanvas::PointMode::kPoints, points.size(),
|
||||
points.data());
|
||||
builder_points.DrawPoints(DlCanvas::PointMode::kPoints, points.size(),
|
||||
points.data(), DlPaint());
|
||||
auto display_list_points = builder_points.Build();
|
||||
|
||||
DisplayListBuilder builder_polygon;
|
||||
builder_polygon.drawPoints(DlCanvas::PointMode::kPolygon, points.size(),
|
||||
points.data());
|
||||
builder_polygon.DrawPoints(DlCanvas::PointMode::kPolygon, points.size(),
|
||||
points.data(), DlPaint());
|
||||
auto display_list_polygon = builder_polygon.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -351,8 +354,8 @@ TEST(DisplayListComplexity, DrawImage) {
|
||||
auto image = SkImage::MakeFromBitmap(bitmap);
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.drawImage(DlImage::Make(image), SkPoint::Make(0, 0),
|
||||
DlImageSampling::kNearestNeighbor, false);
|
||||
builder.DrawImage(DlImage::Make(image), SkPoint::Make(0, 0),
|
||||
DlImageSampling::kNearestNeighbor, nullptr);
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -373,8 +376,8 @@ TEST(DisplayListComplexity, DrawImageNine) {
|
||||
SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50);
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.drawImageNine(DlImage::Make(image), center, dest,
|
||||
DlFilterMode::kNearest, true);
|
||||
builder.DrawImageNine(DlImage::Make(image), center, dest,
|
||||
DlFilterMode::kNearest, nullptr);
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -395,8 +398,8 @@ TEST(DisplayListComplexity, DrawImageRect) {
|
||||
SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50);
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.drawImageRect(DlImage::Make(image), src, dest,
|
||||
DlImageSampling::kNearestNeighbor, true);
|
||||
builder.DrawImageRect(DlImage::Make(image), src, dest,
|
||||
DlImageSampling::kNearestNeighbor, nullptr);
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
@ -421,9 +424,9 @@ TEST(DisplayListComplexity, DrawAtlas) {
|
||||
}
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.drawAtlas(DlImage::Make(image), xforms.data(), rects.data(), nullptr,
|
||||
builder.DrawAtlas(DlImage::Make(image), xforms.data(), rects.data(), nullptr,
|
||||
10, DlBlendMode::kSrc, DlImageSampling::kNearestNeighbor,
|
||||
nullptr, true);
|
||||
nullptr, nullptr);
|
||||
auto display_list = builder.Build();
|
||||
|
||||
auto calculators = AccumulatorCalculators();
|
||||
|
||||
@ -1,172 +0,0 @@
|
||||
// Copyright 2013 The Flutter 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 "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_paint.h"
|
||||
#include "flutter/display_list/display_list_sampling_options.h"
|
||||
#include "flutter/display_list/display_list_tile_mode.h"
|
||||
#include "flutter/display_list/display_list_vertices.h"
|
||||
#include "flutter/display_list/types.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "include/core/SkSamplingOptions.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
TEST(DisplayListEnum, ToDlTileMode) {
|
||||
ASSERT_EQ(ToDl(SkTileMode::kClamp), DlTileMode::kClamp);
|
||||
ASSERT_EQ(ToDl(SkTileMode::kRepeat), DlTileMode::kRepeat);
|
||||
ASSERT_EQ(ToDl(SkTileMode::kMirror), DlTileMode::kMirror);
|
||||
ASSERT_EQ(ToDl(SkTileMode::kDecal), DlTileMode::kDecal);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToSkTileMode) {
|
||||
ASSERT_EQ(ToSk(DlTileMode::kClamp), SkTileMode::kClamp);
|
||||
ASSERT_EQ(ToSk(DlTileMode::kRepeat), SkTileMode::kRepeat);
|
||||
ASSERT_EQ(ToSk(DlTileMode::kMirror), SkTileMode::kMirror);
|
||||
ASSERT_EQ(ToSk(DlTileMode::kDecal), SkTileMode::kDecal);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToDlDrawStyle) {
|
||||
ASSERT_EQ(ToDl(SkPaint::Style::kFill_Style), DlDrawStyle::kFill);
|
||||
ASSERT_EQ(ToDl(SkPaint::Style::kStroke_Style), DlDrawStyle::kStroke);
|
||||
ASSERT_EQ(ToDl(SkPaint::Style::kStrokeAndFill_Style),
|
||||
DlDrawStyle::kStrokeAndFill);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToSkDrawStyle) {
|
||||
ASSERT_EQ(ToSk(DlDrawStyle::kFill), SkPaint::Style::kFill_Style);
|
||||
ASSERT_EQ(ToSk(DlDrawStyle::kStroke), SkPaint::Style::kStroke_Style);
|
||||
ASSERT_EQ(ToSk(DlDrawStyle::kStrokeAndFill),
|
||||
SkPaint::Style::kStrokeAndFill_Style);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToDlStrokeCap) {
|
||||
ASSERT_EQ(ToDl(SkPaint::Cap::kButt_Cap), DlStrokeCap::kButt);
|
||||
ASSERT_EQ(ToDl(SkPaint::Cap::kRound_Cap), DlStrokeCap::kRound);
|
||||
ASSERT_EQ(ToDl(SkPaint::Cap::kSquare_Cap), DlStrokeCap::kSquare);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToSkStrokeCap) {
|
||||
ASSERT_EQ(ToSk(DlStrokeCap::kButt), SkPaint::Cap::kButt_Cap);
|
||||
ASSERT_EQ(ToSk(DlStrokeCap::kRound), SkPaint::Cap::kRound_Cap);
|
||||
ASSERT_EQ(ToSk(DlStrokeCap::kSquare), SkPaint::Cap::kSquare_Cap);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToDlStrokeJoin) {
|
||||
ASSERT_EQ(ToDl(SkPaint::Join::kMiter_Join), DlStrokeJoin::kMiter);
|
||||
ASSERT_EQ(ToDl(SkPaint::Join::kRound_Join), DlStrokeJoin::kRound);
|
||||
ASSERT_EQ(ToDl(SkPaint::Join::kBevel_Join), DlStrokeJoin::kBevel);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToSkStrokeJoin) {
|
||||
ASSERT_EQ(ToSk(DlStrokeJoin::kMiter), SkPaint::Join::kMiter_Join);
|
||||
ASSERT_EQ(ToSk(DlStrokeJoin::kRound), SkPaint::Join::kRound_Join);
|
||||
ASSERT_EQ(ToSk(DlStrokeJoin::kBevel), SkPaint::Join::kBevel_Join);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToDlVertexMode) {
|
||||
ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangles_VertexMode),
|
||||
DlVertexMode::kTriangles);
|
||||
ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangleStrip_VertexMode),
|
||||
DlVertexMode::kTriangleStrip);
|
||||
ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangleFan_VertexMode),
|
||||
DlVertexMode::kTriangleFan);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToSkVertexMode) {
|
||||
ASSERT_EQ(ToSk(DlVertexMode::kTriangles),
|
||||
SkVertices::VertexMode::kTriangles_VertexMode);
|
||||
ASSERT_EQ(ToSk(DlVertexMode::kTriangleStrip),
|
||||
SkVertices::VertexMode::kTriangleStrip_VertexMode);
|
||||
ASSERT_EQ(ToSk(DlVertexMode::kTriangleFan),
|
||||
SkVertices::VertexMode::kTriangleFan_VertexMode);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToDlFilterMode) {
|
||||
ASSERT_EQ(ToDl(SkFilterMode::kLinear), DlFilterMode::kLinear);
|
||||
ASSERT_EQ(ToDl(SkFilterMode::kNearest), DlFilterMode::kNearest);
|
||||
ASSERT_EQ(ToDl(SkFilterMode::kLast), DlFilterMode::kLast);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToSkFilterMode) {
|
||||
ASSERT_EQ(ToSk(DlFilterMode::kLinear), SkFilterMode::kLinear);
|
||||
ASSERT_EQ(ToSk(DlFilterMode::kNearest), SkFilterMode::kNearest);
|
||||
ASSERT_EQ(ToSk(DlFilterMode::kLast), SkFilterMode::kLast);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToDlImageSampling) {
|
||||
ASSERT_EQ(ToDl(SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone)),
|
||||
DlImageSampling::kLinear);
|
||||
ASSERT_EQ(
|
||||
ToDl(SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear)),
|
||||
DlImageSampling::kMipmapLinear);
|
||||
ASSERT_EQ(
|
||||
ToDl(SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone)),
|
||||
DlImageSampling::kNearestNeighbor);
|
||||
ASSERT_EQ(ToDl(SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f})),
|
||||
DlImageSampling::kCubic);
|
||||
}
|
||||
|
||||
TEST(DisplayListEnum, ToSkSamplingOptions) {
|
||||
ASSERT_EQ(ToSk(DlImageSampling::kLinear),
|
||||
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone));
|
||||
ASSERT_EQ(ToSk(DlImageSampling::kMipmapLinear),
|
||||
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
|
||||
ASSERT_EQ(ToSk(DlImageSampling::kNearestNeighbor),
|
||||
SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone));
|
||||
ASSERT_EQ(ToSk(DlImageSampling::kCubic),
|
||||
SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f}));
|
||||
}
|
||||
|
||||
#define CHECK_TO_DLENUM(V) ASSERT_EQ(ToDl(SkBlendMode::V), DlBlendMode::V);
|
||||
#define CHECK_TO_SKENUM(V) ASSERT_EQ(ToSk(DlBlendMode::V), SkBlendMode::V);
|
||||
|
||||
#define FOR_EACH_ENUM(FUNC) \
|
||||
FUNC(kSrc) \
|
||||
FUNC(kClear) \
|
||||
FUNC(kSrc) \
|
||||
FUNC(kDst) \
|
||||
FUNC(kSrcOver) \
|
||||
FUNC(kDstOver) \
|
||||
FUNC(kSrcIn) \
|
||||
FUNC(kDstIn) \
|
||||
FUNC(kSrcOut) \
|
||||
FUNC(kDstOut) \
|
||||
FUNC(kSrcATop) \
|
||||
FUNC(kDstATop) \
|
||||
FUNC(kXor) \
|
||||
FUNC(kPlus) \
|
||||
FUNC(kModulate) \
|
||||
FUNC(kScreen) \
|
||||
FUNC(kOverlay) \
|
||||
FUNC(kDarken) \
|
||||
FUNC(kLighten) \
|
||||
FUNC(kColorDodge) \
|
||||
FUNC(kColorBurn) \
|
||||
FUNC(kHardLight) \
|
||||
FUNC(kSoftLight) \
|
||||
FUNC(kDifference) \
|
||||
FUNC(kExclusion) \
|
||||
FUNC(kMultiply) \
|
||||
FUNC(kHue) \
|
||||
FUNC(kSaturation) \
|
||||
FUNC(kColor) \
|
||||
FUNC(kLuminosity) \
|
||||
FUNC(kLastCoeffMode) \
|
||||
FUNC(kLastSeparableMode) \
|
||||
FUNC(kLastMode)
|
||||
|
||||
TEST(DisplayListEnum, ToDlBlendMode){FOR_EACH_ENUM(CHECK_TO_DLENUM)}
|
||||
|
||||
TEST(DisplayListEnum, ToSkBlendMode) {
|
||||
FOR_EACH_ENUM(CHECK_TO_SKENUM)
|
||||
}
|
||||
|
||||
#undef CHECK_TO_DLENUM
|
||||
#undef CHECK_TO_SKENUM
|
||||
#undef FOR_EACH_ENUM
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
@ -29,9 +29,9 @@ enum class DlImageFilterType {
|
||||
kDilate,
|
||||
kErode,
|
||||
kMatrix,
|
||||
kComposeFilter,
|
||||
kCompose,
|
||||
kColorFilter,
|
||||
kLocalMatrixFilter,
|
||||
kLocalMatrix,
|
||||
};
|
||||
|
||||
class DlBlurImageFilter;
|
||||
@ -42,8 +42,7 @@ class DlLocalMatrixImageFilter;
|
||||
class DlComposeImageFilter;
|
||||
class DlColorFilterImageFilter;
|
||||
|
||||
class DlImageFilter
|
||||
: public DlAttribute<DlImageFilter, SkImageFilter, DlImageFilterType> {
|
||||
class DlImageFilter : public DlAttribute<DlImageFilter, DlImageFilterType> {
|
||||
public:
|
||||
enum class MatrixCapability {
|
||||
kTranslate,
|
||||
@ -227,6 +226,16 @@ class DlBlurImageFilter final : public DlImageFilter {
|
||||
explicit DlBlurImageFilter(const DlBlurImageFilter& filter)
|
||||
: DlBlurImageFilter(&filter) {}
|
||||
|
||||
static std::shared_ptr<DlImageFilter> Make(SkScalar sigma_x,
|
||||
SkScalar sigma_y,
|
||||
DlTileMode tile_mode) {
|
||||
if (SkScalarIsFinite(sigma_x) && sigma_x > SK_ScalarNearlyZero &&
|
||||
SkScalarIsFinite(sigma_y) && sigma_y > SK_ScalarNearlyZero) {
|
||||
return std::make_shared<DlBlurImageFilter>(sigma_x, sigma_y, tile_mode);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlImageFilter> shared() const override {
|
||||
return std::make_shared<DlBlurImageFilter>(this);
|
||||
}
|
||||
@ -262,10 +271,6 @@ class DlBlurImageFilter final : public DlImageFilter {
|
||||
SkScalar sigma_y() const { return sigma_y_; }
|
||||
DlTileMode tile_mode() const { return tile_mode_; }
|
||||
|
||||
sk_sp<SkImageFilter> skia_object() const override {
|
||||
return SkImageFilters::Blur(sigma_x_, sigma_y_, ToSk(tile_mode_), nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(const DlImageFilter& other) const override {
|
||||
FML_DCHECK(other.type() == DlImageFilterType::kBlur);
|
||||
@ -289,6 +294,15 @@ class DlDilateImageFilter final : public DlImageFilter {
|
||||
explicit DlDilateImageFilter(const DlDilateImageFilter& filter)
|
||||
: DlDilateImageFilter(&filter) {}
|
||||
|
||||
static std::shared_ptr<DlImageFilter> Make(SkScalar radius_x,
|
||||
SkScalar radius_y) {
|
||||
if (SkScalarIsFinite(radius_x) && radius_x > SK_ScalarNearlyZero &&
|
||||
SkScalarIsFinite(radius_y) && radius_y > SK_ScalarNearlyZero) {
|
||||
return std::make_shared<DlDilateImageFilter>(radius_x, radius_y);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlImageFilter> shared() const override {
|
||||
return std::make_shared<DlDilateImageFilter>(this);
|
||||
}
|
||||
@ -323,10 +337,6 @@ class DlDilateImageFilter final : public DlImageFilter {
|
||||
SkScalar radius_x() const { return radius_x_; }
|
||||
SkScalar radius_y() const { return radius_y_; }
|
||||
|
||||
sk_sp<SkImageFilter> skia_object() const override {
|
||||
return SkImageFilters::Dilate(radius_x_, radius_y_, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(const DlImageFilter& other) const override {
|
||||
FML_DCHECK(other.type() == DlImageFilterType::kDilate);
|
||||
@ -348,6 +358,15 @@ class DlErodeImageFilter final : public DlImageFilter {
|
||||
explicit DlErodeImageFilter(const DlErodeImageFilter& filter)
|
||||
: DlErodeImageFilter(&filter) {}
|
||||
|
||||
static std::shared_ptr<DlImageFilter> Make(SkScalar radius_x,
|
||||
SkScalar radius_y) {
|
||||
if (SkScalarIsFinite(radius_x) && radius_x > SK_ScalarNearlyZero &&
|
||||
SkScalarIsFinite(radius_y) && radius_y > SK_ScalarNearlyZero) {
|
||||
return std::make_shared<DlErodeImageFilter>(radius_x, radius_y);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlImageFilter> shared() const override {
|
||||
return std::make_shared<DlErodeImageFilter>(this);
|
||||
}
|
||||
@ -382,10 +401,6 @@ class DlErodeImageFilter final : public DlImageFilter {
|
||||
SkScalar radius_x() const { return radius_x_; }
|
||||
SkScalar radius_y() const { return radius_y_; }
|
||||
|
||||
sk_sp<SkImageFilter> skia_object() const override {
|
||||
return SkImageFilters::Erode(radius_x_, radius_y_, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(const DlImageFilter& other) const override {
|
||||
FML_DCHECK(other.type() == DlImageFilterType::kErode);
|
||||
@ -407,6 +422,14 @@ class DlMatrixImageFilter final : public DlImageFilter {
|
||||
explicit DlMatrixImageFilter(const DlMatrixImageFilter& filter)
|
||||
: DlMatrixImageFilter(&filter) {}
|
||||
|
||||
static std::shared_ptr<DlImageFilter> Make(const SkMatrix& matrix,
|
||||
DlImageSampling sampling) {
|
||||
if (matrix.isFinite() && !matrix.isIdentity()) {
|
||||
return std::make_shared<DlMatrixImageFilter>(matrix, sampling);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlImageFilter> shared() const override {
|
||||
return std::make_shared<DlMatrixImageFilter>(this);
|
||||
}
|
||||
@ -460,10 +483,6 @@ class DlMatrixImageFilter final : public DlImageFilter {
|
||||
return &input_bounds;
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> skia_object() const override {
|
||||
return SkImageFilters::MatrixTransform(matrix_, ToSk(sampling_), nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(const DlImageFilter& other) const override {
|
||||
FML_DCHECK(other.type() == DlImageFilterType::kMatrix);
|
||||
@ -478,8 +497,8 @@ class DlMatrixImageFilter final : public DlImageFilter {
|
||||
|
||||
class DlComposeImageFilter final : public DlImageFilter {
|
||||
public:
|
||||
DlComposeImageFilter(std::shared_ptr<DlImageFilter> outer,
|
||||
std::shared_ptr<DlImageFilter> inner)
|
||||
DlComposeImageFilter(std::shared_ptr<const DlImageFilter> outer,
|
||||
std::shared_ptr<const DlImageFilter> inner)
|
||||
: outer_(std::move(outer)), inner_(std::move(inner)) {}
|
||||
DlComposeImageFilter(const DlImageFilter* outer, const DlImageFilter* inner)
|
||||
: outer_(outer->shared()), inner_(inner->shared()) {}
|
||||
@ -490,17 +509,29 @@ class DlComposeImageFilter final : public DlImageFilter {
|
||||
explicit DlComposeImageFilter(const DlComposeImageFilter& filter)
|
||||
: DlComposeImageFilter(&filter) {}
|
||||
|
||||
static std::shared_ptr<const DlImageFilter> Make(
|
||||
std::shared_ptr<const DlImageFilter> outer,
|
||||
std::shared_ptr<const DlImageFilter> inner) {
|
||||
if (!outer) {
|
||||
return inner;
|
||||
}
|
||||
if (!inner) {
|
||||
return outer;
|
||||
}
|
||||
return std::make_shared<DlComposeImageFilter>(outer, inner);
|
||||
}
|
||||
|
||||
std::shared_ptr<DlImageFilter> shared() const override {
|
||||
return std::make_shared<DlComposeImageFilter>(this);
|
||||
}
|
||||
|
||||
DlImageFilterType type() const override {
|
||||
return DlImageFilterType::kComposeFilter;
|
||||
return DlImageFilterType::kCompose;
|
||||
}
|
||||
size_t size() const override { return sizeof(*this); }
|
||||
|
||||
std::shared_ptr<DlImageFilter> outer() const { return outer_; }
|
||||
std::shared_ptr<DlImageFilter> inner() const { return inner_; }
|
||||
std::shared_ptr<const DlImageFilter> outer() const { return outer_; }
|
||||
std::shared_ptr<const DlImageFilter> inner() const { return inner_; }
|
||||
|
||||
const DlComposeImageFilter* asCompose() const override { return this; }
|
||||
|
||||
@ -525,30 +556,25 @@ class DlComposeImageFilter final : public DlImageFilter {
|
||||
const SkMatrix& ctm,
|
||||
SkIRect& input_bounds) const override;
|
||||
|
||||
sk_sp<SkImageFilter> skia_object() const override {
|
||||
return SkImageFilters::Compose(outer_->skia_object(),
|
||||
inner_->skia_object());
|
||||
}
|
||||
|
||||
MatrixCapability matrix_capability() const override {
|
||||
return std::min(outer_->matrix_capability(), inner_->matrix_capability());
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(const DlImageFilter& other) const override {
|
||||
FML_DCHECK(other.type() == DlImageFilterType::kComposeFilter);
|
||||
FML_DCHECK(other.type() == DlImageFilterType::kCompose);
|
||||
auto that = static_cast<const DlComposeImageFilter*>(&other);
|
||||
return (Equals(outer_, that->outer_) && Equals(inner_, that->inner_));
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DlImageFilter> outer_;
|
||||
std::shared_ptr<DlImageFilter> inner_;
|
||||
std::shared_ptr<const DlImageFilter> outer_;
|
||||
std::shared_ptr<const DlImageFilter> inner_;
|
||||
};
|
||||
|
||||
class DlColorFilterImageFilter final : public DlImageFilter {
|
||||
public:
|
||||
explicit DlColorFilterImageFilter(std::shared_ptr<DlColorFilter> filter)
|
||||
explicit DlColorFilterImageFilter(std::shared_ptr<const DlColorFilter> filter)
|
||||
: color_filter_(std::move(filter)) {}
|
||||
explicit DlColorFilterImageFilter(const DlColorFilter* filter)
|
||||
: color_filter_(filter->shared()) {}
|
||||
@ -559,6 +585,14 @@ class DlColorFilterImageFilter final : public DlImageFilter {
|
||||
explicit DlColorFilterImageFilter(const DlColorFilterImageFilter& filter)
|
||||
: DlColorFilterImageFilter(&filter) {}
|
||||
|
||||
static std::shared_ptr<DlImageFilter> Make(
|
||||
std::shared_ptr<const DlColorFilter> filter) {
|
||||
if (filter) {
|
||||
return std::make_shared<DlColorFilterImageFilter>(filter);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<DlImageFilter> shared() const override {
|
||||
return std::make_shared<DlColorFilterImageFilter>(color_filter_);
|
||||
}
|
||||
@ -568,7 +602,7 @@ class DlColorFilterImageFilter final : public DlImageFilter {
|
||||
}
|
||||
size_t size() const override { return sizeof(*this); }
|
||||
|
||||
const std::shared_ptr<DlColorFilter> color_filter() const {
|
||||
const std::shared_ptr<const DlColorFilter> color_filter() const {
|
||||
return color_filter_;
|
||||
}
|
||||
|
||||
@ -602,10 +636,6 @@ class DlColorFilterImageFilter final : public DlImageFilter {
|
||||
return map_device_bounds(output_bounds, ctm, input_bounds);
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> skia_object() const override {
|
||||
return SkImageFilters::ColorFilter(color_filter_->skia_object(), nullptr);
|
||||
}
|
||||
|
||||
MatrixCapability matrix_capability() const override {
|
||||
return MatrixCapability::kComplex;
|
||||
}
|
||||
@ -623,7 +653,7 @@ class DlColorFilterImageFilter final : public DlImageFilter {
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DlColorFilter> color_filter_;
|
||||
std::shared_ptr<const DlColorFilter> color_filter_;
|
||||
};
|
||||
|
||||
class DlLocalMatrixImageFilter final : public DlImageFilter {
|
||||
@ -640,7 +670,7 @@ class DlLocalMatrixImageFilter final : public DlImageFilter {
|
||||
}
|
||||
|
||||
DlImageFilterType type() const override {
|
||||
return DlImageFilterType::kLocalMatrixFilter;
|
||||
return DlImageFilterType::kLocalMatrix;
|
||||
}
|
||||
size_t size() const override { return sizeof(*this); }
|
||||
|
||||
@ -689,20 +719,9 @@ class DlLocalMatrixImageFilter final : public DlImageFilter {
|
||||
output_bounds, SkMatrix::Concat(ctm, matrix_), input_bounds);
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> skia_object() const override {
|
||||
if (!image_filter_) {
|
||||
return nullptr;
|
||||
}
|
||||
sk_sp<SkImageFilter> skia_object = image_filter_->skia_object();
|
||||
if (!skia_object) {
|
||||
return nullptr;
|
||||
}
|
||||
return skia_object->makeWithLocalMatrix(matrix_);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equals_(const DlImageFilter& other) const override {
|
||||
FML_DCHECK(other.type() == DlImageFilterType::kLocalMatrixFilter);
|
||||
FML_DCHECK(other.type() == DlImageFilterType::kLocalMatrix);
|
||||
auto that = static_cast<const DlLocalMatrixImageFilter*>(&other);
|
||||
return (matrix_ == that->matrix_ &&
|
||||
Equals(image_filter_, that->image_filter_));
|
||||
|
||||
@ -17,21 +17,6 @@
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
TEST(DisplayListImageFilter, BuilderSetGet) {
|
||||
DlBlurImageFilter filter(5.0, 5.0, DlTileMode::kDecal);
|
||||
DisplayListBuilder builder;
|
||||
|
||||
ASSERT_EQ(builder.getImageFilter(), nullptr);
|
||||
|
||||
builder.setImageFilter(&filter);
|
||||
ASSERT_NE(builder.getImageFilter(), nullptr);
|
||||
ASSERT_TRUE(
|
||||
Equals(builder.getImageFilter(), static_cast<DlImageFilter*>(&filter)));
|
||||
|
||||
builder.setImageFilter(nullptr);
|
||||
ASSERT_EQ(builder.getImageFilter(), nullptr);
|
||||
}
|
||||
|
||||
// SkRect::contains treats the rect as a half-open interval which is
|
||||
// appropriate for so many operations. Unfortunately, we are using
|
||||
// it here to test containment of the corners of a transformed quad
|
||||
@ -708,8 +693,8 @@ TEST(DisplayListImageFilter, LocalImageFilterBounds) {
|
||||
SkImageFilters::ColorFilter(
|
||||
SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcOver), nullptr),
|
||||
SkImageFilters::Dilate(5.0, 10.0, nullptr),
|
||||
SkImageFilters::MatrixTransform(filter_matrix,
|
||||
ToSk(DlImageSampling::kLinear), nullptr),
|
||||
SkImageFilters::MatrixTransform(
|
||||
filter_matrix, SkSamplingOptions(SkFilterMode::kLinear), nullptr),
|
||||
SkImageFilters::Compose(
|
||||
SkImageFilters::Blur(5.0, 6.0, SkTileMode::kRepeat, nullptr),
|
||||
SkImageFilters::ColorFilter(
|
||||
@ -785,15 +770,5 @@ TEST(DisplayListImageFilter, LocalImageFilterBounds) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DisplayListImageFilter, LocalImageSkiaNull) {
|
||||
auto blur_filter =
|
||||
std::make_shared<DlBlurImageFilter>(0, 0, DlTileMode::kClamp);
|
||||
DlLocalMatrixImageFilter dl_local_matrix_filter(SkMatrix::RotateDeg(45),
|
||||
blur_filter);
|
||||
// With sigmas set to zero on the blur filter, Skia will return a null filter.
|
||||
// The local matrix filter should return nullptr instead of crashing.
|
||||
ASSERT_EQ(dl_local_matrix_filter.skia_object(), nullptr);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -20,8 +20,7 @@ class DlBlurMaskFilter;
|
||||
// An enumerated type for the supported MaskFilter operations.
|
||||
enum class DlMaskFilterType { kBlur };
|
||||
|
||||
class DlMaskFilter
|
||||
: public DlAttribute<DlMaskFilter, SkMaskFilter, DlMaskFilterType> {
|
||||
class DlMaskFilter : public DlAttribute<DlMaskFilter, DlMaskFilterType> {
|
||||
public:
|
||||
// Return a DlBlurMaskFilter pointer to this object iff it is a Blur
|
||||
// type of MaskFilter, otherwise return nullptr.
|
||||
@ -43,6 +42,15 @@ class DlBlurMaskFilter final : public DlMaskFilter {
|
||||
: DlBlurMaskFilter(filter->style_, filter->sigma_, filter->respect_ctm_) {
|
||||
}
|
||||
|
||||
static std::shared_ptr<DlMaskFilter> Make(SkBlurStyle style,
|
||||
SkScalar sigma,
|
||||
bool respect_ctm = true) {
|
||||
if (SkScalarIsFinite(sigma) && sigma > 0) {
|
||||
return std::make_shared<DlBlurMaskFilter>(style, sigma, respect_ctm);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DlMaskFilterType type() const override { return DlMaskFilterType::kBlur; }
|
||||
size_t size() const override { return sizeof(*this); }
|
||||
|
||||
@ -50,10 +58,6 @@ class DlBlurMaskFilter final : public DlMaskFilter {
|
||||
return std::make_shared<DlBlurMaskFilter>(this);
|
||||
}
|
||||
|
||||
sk_sp<SkMaskFilter> skia_object() const override {
|
||||
return SkMaskFilter::MakeBlur(style_, sigma_, respect_ctm_);
|
||||
}
|
||||
|
||||
const DlBlurMaskFilter* asBlur() const override { return this; }
|
||||
|
||||
SkBlurStyle style() const { return style_; }
|
||||
|
||||
@ -12,18 +12,6 @@
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
TEST(DisplayListMaskFilter, BuilderSetGet) {
|
||||
DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
|
||||
DisplayListBuilder builder;
|
||||
ASSERT_EQ(builder.getMaskFilter(), nullptr);
|
||||
builder.setMaskFilter(&filter);
|
||||
ASSERT_NE(builder.getMaskFilter(), nullptr);
|
||||
ASSERT_TRUE(
|
||||
Equals(builder.getMaskFilter(), static_cast<DlMaskFilter*>(&filter)));
|
||||
builder.setMaskFilter(nullptr);
|
||||
ASSERT_EQ(builder.getMaskFilter(), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListMaskFilter, BlurConstructor) {
|
||||
DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
|
||||
}
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
#include "display_list_color_source.h"
|
||||
#include "flutter/display_list/display_list.h"
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_sampling_options.h"
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
#include "flutter/display_list/types.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
|
||||
@ -37,7 +37,7 @@ namespace flutter {
|
||||
// cheap to deal with a complicated "lifetime" tracking to
|
||||
// determine if they will be used.
|
||||
struct DispatchContext {
|
||||
Dispatcher& dispatcher;
|
||||
DlOpReceiver& receiver;
|
||||
|
||||
int cur_index;
|
||||
int next_render_index;
|
||||
@ -111,7 +111,7 @@ struct DLOp {
|
||||
const bool value; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
ctx.dispatcher.set##name(value); \
|
||||
ctx.receiver.set##name(value); \
|
||||
} \
|
||||
};
|
||||
DEFINE_SET_BOOL_OP(AntiAlias)
|
||||
@ -129,7 +129,7 @@ DEFINE_SET_BOOL_OP(InvertColors)
|
||||
const DlStroke##name value; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
ctx.dispatcher.setStroke##name(value); \
|
||||
ctx.receiver.setStroke##name(value); \
|
||||
} \
|
||||
};
|
||||
DEFINE_SET_ENUM_OP(Cap)
|
||||
@ -144,7 +144,7 @@ struct SetStyleOp final : DLOp {
|
||||
|
||||
const DlDrawStyle style;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const { ctx.dispatcher.setStyle(style); }
|
||||
void dispatch(DispatchContext& ctx) const { ctx.receiver.setStyle(style); }
|
||||
};
|
||||
// 4 byte header + 4 byte payload packs into minimum 8 bytes
|
||||
struct SetStrokeWidthOp final : DLOp {
|
||||
@ -155,7 +155,7 @@ struct SetStrokeWidthOp final : DLOp {
|
||||
const float width;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
ctx.dispatcher.setStrokeWidth(width);
|
||||
ctx.receiver.setStrokeWidth(width);
|
||||
}
|
||||
};
|
||||
// 4 byte header + 4 byte payload packs into minimum 8 bytes
|
||||
@ -167,7 +167,7 @@ struct SetStrokeMiterOp final : DLOp {
|
||||
const float limit;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
ctx.dispatcher.setStrokeMiter(limit);
|
||||
ctx.receiver.setStrokeMiter(limit);
|
||||
}
|
||||
};
|
||||
|
||||
@ -179,7 +179,7 @@ struct SetColorOp final : DLOp {
|
||||
|
||||
const DlColor color;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const { ctx.dispatcher.setColor(color); }
|
||||
void dispatch(DispatchContext& ctx) const { ctx.receiver.setColor(color); }
|
||||
};
|
||||
// 4 byte header + 4 byte payload packs into minimum 8 bytes
|
||||
struct SetBlendModeOp final : DLOp {
|
||||
@ -189,8 +189,8 @@ struct SetBlendModeOp final : DLOp {
|
||||
|
||||
const DlBlendMode mode;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
ctx.dispatcher.setBlendMode(mode);
|
||||
void dispatch(DispatchContext& ctx) const { //
|
||||
ctx.receiver.setBlendMode(mode);
|
||||
}
|
||||
};
|
||||
|
||||
@ -207,7 +207,7 @@ struct SetBlendModeOp final : DLOp {
|
||||
Clear##name##Op() {} \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
ctx.dispatcher.set##name(nullptr); \
|
||||
ctx.receiver.set##name(nullptr); \
|
||||
} \
|
||||
}; \
|
||||
struct SetPod##name##Op final : DLOp { \
|
||||
@ -217,7 +217,7 @@ struct SetBlendModeOp final : DLOp {
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
const Dl##name* filter = reinterpret_cast<const Dl##name*>(this + 1); \
|
||||
ctx.dispatcher.set##name(filter); \
|
||||
ctx.receiver.set##name(filter); \
|
||||
} \
|
||||
};
|
||||
DEFINE_SET_CLEAR_DLATTR_OP(ColorFilter, ColorFilter, filter)
|
||||
@ -242,7 +242,7 @@ struct SetImageColorSourceOp : DLOp {
|
||||
const DlImageColorSource source;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
ctx.dispatcher.setColorSource(&source);
|
||||
ctx.receiver.setColorSource(&source);
|
||||
}
|
||||
};
|
||||
|
||||
@ -259,7 +259,7 @@ struct SetRuntimeEffectColorSourceOp : DLOp {
|
||||
const DlRuntimeEffectColorSource source;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
ctx.dispatcher.setColorSource(&source);
|
||||
ctx.receiver.setColorSource(&source);
|
||||
}
|
||||
|
||||
DisplayListCompare equals(const SetRuntimeEffectColorSourceOp* other) const {
|
||||
@ -278,7 +278,7 @@ struct SetSceneColorSourceOp : DLOp {
|
||||
const DlSceneColorSource source;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
ctx.dispatcher.setColorSource(&source);
|
||||
ctx.receiver.setColorSource(&source);
|
||||
}
|
||||
|
||||
DisplayListCompare equals(const SetSceneColorSourceOp* other) const {
|
||||
@ -298,7 +298,7 @@ struct SetSharedImageFilterOp : DLOp {
|
||||
const std::shared_ptr<DlImageFilter> filter;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
ctx.dispatcher.setImageFilter(filter.get());
|
||||
ctx.receiver.setImageFilter(filter.get());
|
||||
}
|
||||
|
||||
DisplayListCompare equals(const SetSharedImageFilterOp* other) const {
|
||||
@ -336,7 +336,7 @@ struct SaveOp final : SaveOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (save_needed(ctx)) {
|
||||
ctx.dispatcher.save();
|
||||
ctx.receiver.save();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -348,7 +348,7 @@ struct SaveLayerOp final : SaveOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (save_needed(ctx)) {
|
||||
ctx.dispatcher.saveLayer(nullptr, options);
|
||||
ctx.receiver.saveLayer(nullptr, options);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -363,7 +363,7 @@ struct SaveLayerBoundsOp final : SaveOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (save_needed(ctx)) {
|
||||
ctx.dispatcher.saveLayer(&rect, options);
|
||||
ctx.receiver.saveLayer(&rect, options);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -379,7 +379,7 @@ struct SaveLayerBackdropOp final : SaveOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (save_needed(ctx)) {
|
||||
ctx.dispatcher.saveLayer(nullptr, options, backdrop.get());
|
||||
ctx.receiver.saveLayer(nullptr, options, backdrop.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,7 +403,7 @@ struct SaveLayerBackdropBoundsOp final : SaveOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (save_needed(ctx)) {
|
||||
ctx.dispatcher.saveLayer(&rect, options, backdrop.get());
|
||||
ctx.receiver.saveLayer(&rect, options, backdrop.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,7 +423,7 @@ struct RestoreOp final : DLOp {
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
DispatchContext::SaveInfo& info = ctx.save_infos.back();
|
||||
if (info.save_was_needed) {
|
||||
ctx.dispatcher.restore();
|
||||
ctx.receiver.restore();
|
||||
}
|
||||
ctx.next_restore_index = info.previous_restore_index;
|
||||
ctx.save_infos.pop_back();
|
||||
@ -447,7 +447,7 @@ struct TranslateOp final : TransformClipOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.translate(tx, ty);
|
||||
ctx.receiver.translate(tx, ty);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -463,7 +463,7 @@ struct ScaleOp final : TransformClipOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.scale(sx, sy);
|
||||
ctx.receiver.scale(sx, sy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -477,7 +477,7 @@ struct RotateOp final : TransformClipOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.rotate(degrees);
|
||||
ctx.receiver.rotate(degrees);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -493,7 +493,7 @@ struct SkewOp final : TransformClipOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.skew(sx, sy);
|
||||
ctx.receiver.skew(sx, sy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -513,8 +513,8 @@ struct Transform2DAffineOp final : TransformClipOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.transform2DAffine(mxx, mxy, mxt, //
|
||||
myx, myy, myt);
|
||||
ctx.receiver.transform2DAffine(mxx, mxy, mxt, //
|
||||
myx, myy, myt);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -542,10 +542,10 @@ struct TransformFullPerspectiveOp final : TransformClipOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.transformFullPerspective(mxx, mxy, mxz, mxt, //
|
||||
myx, myy, myz, myt, //
|
||||
mzx, mzy, mzz, mzt, //
|
||||
mwx, mwy, mwz, mwt);
|
||||
ctx.receiver.transformFullPerspective(mxx, mxy, mxz, mxt, //
|
||||
myx, myy, myz, myt, //
|
||||
mzx, mzy, mzz, mzt, //
|
||||
mwx, mwy, mwz, mwt);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -558,7 +558,7 @@ struct TransformResetOp final : TransformClipOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.transformReset();
|
||||
ctx.receiver.transformReset();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -585,8 +585,8 @@ struct TransformResetOp final : TransformClipOpBase {
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.dispatcher.clip##shapetype(shape, DlCanvas::ClipOp::k##clipop, \
|
||||
is_aa); \
|
||||
ctx.receiver.clip##shapetype(shape, DlCanvas::ClipOp::k##clipop, \
|
||||
is_aa); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
@ -596,27 +596,27 @@ DEFINE_CLIP_SHAPE_OP(Rect, Difference)
|
||||
DEFINE_CLIP_SHAPE_OP(RRect, Difference)
|
||||
#undef DEFINE_CLIP_SHAPE_OP
|
||||
|
||||
#define DEFINE_CLIP_PATH_OP(clipop) \
|
||||
struct Clip##clipop##PathOp final : TransformClipOpBase { \
|
||||
static const auto kType = DisplayListOpType::kClip##clipop##Path; \
|
||||
\
|
||||
Clip##clipop##PathOp(SkPath path, bool is_aa) \
|
||||
: is_aa(is_aa), path(path) {} \
|
||||
\
|
||||
const bool is_aa; \
|
||||
const SkPath path; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.dispatcher.clipPath(path, DlCanvas::ClipOp::k##clipop, is_aa); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \
|
||||
return is_aa == other->is_aa && path == other->path \
|
||||
? DisplayListCompare::kEqual \
|
||||
: DisplayListCompare::kNotEqual; \
|
||||
} \
|
||||
#define DEFINE_CLIP_PATH_OP(clipop) \
|
||||
struct Clip##clipop##PathOp final : TransformClipOpBase { \
|
||||
static const auto kType = DisplayListOpType::kClip##clipop##Path; \
|
||||
\
|
||||
Clip##clipop##PathOp(SkPath path, bool is_aa) \
|
||||
: is_aa(is_aa), path(path) {} \
|
||||
\
|
||||
const bool is_aa; \
|
||||
const SkPath path; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.receiver.clipPath(path, DlCanvas::ClipOp::k##clipop, is_aa); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \
|
||||
return is_aa == other->is_aa && path == other->path \
|
||||
? DisplayListCompare::kEqual \
|
||||
: DisplayListCompare::kNotEqual; \
|
||||
} \
|
||||
};
|
||||
DEFINE_CLIP_PATH_OP(Intersect)
|
||||
DEFINE_CLIP_PATH_OP(Difference)
|
||||
@ -636,7 +636,7 @@ struct DrawPaintOp final : DrawOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.drawPaint();
|
||||
ctx.receiver.drawPaint();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -652,7 +652,7 @@ struct DrawColorOp final : DrawOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.drawColor(color, mode);
|
||||
ctx.receiver.drawColor(color, mode);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -672,7 +672,7 @@ struct DrawColorOp final : DrawOpBase {
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.dispatcher.draw##op_name(arg_name); \
|
||||
ctx.receiver.draw##op_name(arg_name); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
@ -692,7 +692,7 @@ struct DrawPathOp final : DrawOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.drawPath(path);
|
||||
ctx.receiver.drawPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -720,7 +720,7 @@ struct DrawPathOp final : DrawOpBase {
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.dispatcher.draw##op_name(name1, name2); \
|
||||
ctx.receiver.draw##op_name(name1, name2); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
@ -743,7 +743,7 @@ struct DrawArcOp final : DrawOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.drawArc(bounds, start, sweep, center);
|
||||
ctx.receiver.drawArc(bounds, start, sweep, center);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -754,20 +754,20 @@ struct DrawArcOp final : DrawOpBase {
|
||||
// so this op will always pack efficiently
|
||||
// The point type is packed into 3 different OpTypes to avoid expanding
|
||||
// the fixed payload beyond the 8 bytes
|
||||
#define DEFINE_DRAW_POINTS_OP(name, mode) \
|
||||
struct Draw##name##Op final : DrawOpBase { \
|
||||
static const auto kType = DisplayListOpType::kDraw##name; \
|
||||
\
|
||||
explicit Draw##name##Op(uint32_t count) : count(count) {} \
|
||||
\
|
||||
const uint32_t count; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
const SkPoint* pts = reinterpret_cast<const SkPoint*>(this + 1); \
|
||||
ctx.dispatcher.drawPoints(DlCanvas::PointMode::mode, count, pts); \
|
||||
} \
|
||||
} \
|
||||
#define DEFINE_DRAW_POINTS_OP(name, mode) \
|
||||
struct Draw##name##Op final : DrawOpBase { \
|
||||
static const auto kType = DisplayListOpType::kDraw##name; \
|
||||
\
|
||||
explicit Draw##name##Op(uint32_t count) : count(count) {} \
|
||||
\
|
||||
const uint32_t count; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
const SkPoint* pts = reinterpret_cast<const SkPoint*>(this + 1); \
|
||||
ctx.receiver.drawPoints(DlCanvas::PointMode::mode, count, pts); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
DEFINE_DRAW_POINTS_OP(Points, kPoints);
|
||||
DEFINE_DRAW_POINTS_OP(Lines, kLines);
|
||||
@ -792,38 +792,38 @@ struct DrawVerticesOp final : DrawOpBase {
|
||||
if (op_needed(ctx)) {
|
||||
const DlVertices* vertices =
|
||||
reinterpret_cast<const DlVertices*>(this + 1);
|
||||
ctx.dispatcher.drawVertices(vertices, mode);
|
||||
ctx.receiver.drawVertices(vertices, mode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 4 byte header + 40 byte payload uses 44 bytes but is rounded up to 48 bytes
|
||||
// (4 bytes unused)
|
||||
#define DEFINE_DRAW_IMAGE_OP(name, with_attributes) \
|
||||
struct name##Op final : DrawOpBase { \
|
||||
static const auto kType = DisplayListOpType::k##name; \
|
||||
\
|
||||
name##Op(const sk_sp<DlImage> image, \
|
||||
const SkPoint& point, \
|
||||
DlImageSampling sampling) \
|
||||
: point(point), sampling(sampling), image(std::move(image)) {} \
|
||||
\
|
||||
const SkPoint point; \
|
||||
const DlImageSampling sampling; \
|
||||
const sk_sp<DlImage> image; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.dispatcher.drawImage(image, point, sampling, with_attributes); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
DisplayListCompare equals(const name##Op* other) const { \
|
||||
return (point == other->point && sampling == other->sampling && \
|
||||
image->Equals(other->image)) \
|
||||
? DisplayListCompare::kEqual \
|
||||
: DisplayListCompare::kNotEqual; \
|
||||
} \
|
||||
#define DEFINE_DRAW_IMAGE_OP(name, with_attributes) \
|
||||
struct name##Op final : DrawOpBase { \
|
||||
static const auto kType = DisplayListOpType::k##name; \
|
||||
\
|
||||
name##Op(const sk_sp<DlImage> image, \
|
||||
const SkPoint& point, \
|
||||
DlImageSampling sampling) \
|
||||
: point(point), sampling(sampling), image(std::move(image)) {} \
|
||||
\
|
||||
const SkPoint point; \
|
||||
const DlImageSampling sampling; \
|
||||
const sk_sp<DlImage> image; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.receiver.drawImage(image, point, sampling, with_attributes); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
DisplayListCompare equals(const name##Op* other) const { \
|
||||
return (point == other->point && sampling == other->sampling && \
|
||||
image->Equals(other->image)) \
|
||||
? DisplayListCompare::kEqual \
|
||||
: DisplayListCompare::kNotEqual; \
|
||||
} \
|
||||
};
|
||||
DEFINE_DRAW_IMAGE_OP(DrawImage, false)
|
||||
DEFINE_DRAW_IMAGE_OP(DrawImageWithAttr, true)
|
||||
@ -839,7 +839,7 @@ struct DrawImageRectOp final : DrawOpBase {
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint)
|
||||
DlCanvas::SrcRectConstraint constraint)
|
||||
: src(src),
|
||||
dst(dst),
|
||||
sampling(sampling),
|
||||
@ -851,13 +851,13 @@ struct DrawImageRectOp final : DrawOpBase {
|
||||
const SkRect dst;
|
||||
const DlImageSampling sampling;
|
||||
const bool render_with_attributes;
|
||||
const SkCanvas::SrcRectConstraint constraint;
|
||||
const DlCanvas::SrcRectConstraint constraint;
|
||||
const sk_sp<DlImage> image;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.drawImageRect(image, src, dst, sampling,
|
||||
render_with_attributes, constraint);
|
||||
ctx.receiver.drawImageRect(image, src, dst, sampling,
|
||||
render_with_attributes, constraint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -889,8 +889,8 @@ struct DrawImageRectOp final : DrawOpBase {
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.dispatcher.drawImageNine(image, center, dst, mode, \
|
||||
render_with_attributes); \
|
||||
ctx.receiver.drawImageNine(image, center, dst, mode, \
|
||||
render_with_attributes); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@ -976,8 +976,8 @@ struct DrawAtlasOp final : DrawAtlasBaseOp {
|
||||
const DlColor* colors =
|
||||
has_colors ? reinterpret_cast<const DlColor*>(tex + count) : nullptr;
|
||||
const DlBlendMode mode = static_cast<DlBlendMode>(mode_index);
|
||||
ctx.dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
|
||||
nullptr, render_with_attributes);
|
||||
ctx.receiver.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
|
||||
nullptr, render_with_attributes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1021,8 +1021,8 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp {
|
||||
const DlColor* colors =
|
||||
has_colors ? reinterpret_cast<const DlColor*>(tex + count) : nullptr;
|
||||
const DlBlendMode mode = static_cast<DlBlendMode>(mode_index);
|
||||
ctx.dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
|
||||
&cull_rect, render_with_attributes);
|
||||
ctx.receiver.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
|
||||
&cull_rect, render_with_attributes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1041,19 +1041,22 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp {
|
||||
struct DrawDisplayListOp final : DrawOpBase {
|
||||
static const auto kType = DisplayListOpType::kDrawDisplayList;
|
||||
|
||||
explicit DrawDisplayListOp(const sk_sp<DisplayList> display_list)
|
||||
: display_list(std::move(display_list)) {}
|
||||
explicit DrawDisplayListOp(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity)
|
||||
: opacity(opacity), display_list(std::move(display_list)) {}
|
||||
|
||||
SkScalar opacity;
|
||||
const sk_sp<DisplayList> display_list;
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.drawDisplayList(display_list);
|
||||
ctx.receiver.drawDisplayList(display_list, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
DisplayListCompare equals(const DrawDisplayListOp* other) const {
|
||||
return display_list->Equals(other->display_list)
|
||||
return (opacity == other->opacity &&
|
||||
display_list->Equals(other->display_list))
|
||||
? DisplayListCompare::kEqual
|
||||
: DisplayListCompare::kNotEqual;
|
||||
}
|
||||
@ -1073,33 +1076,33 @@ struct DrawTextBlobOp final : DrawOpBase {
|
||||
|
||||
void dispatch(DispatchContext& ctx) const {
|
||||
if (op_needed(ctx)) {
|
||||
ctx.dispatcher.drawTextBlob(blob, x, y);
|
||||
ctx.receiver.drawTextBlob(blob, x, y);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 4 byte header + 28 byte payload packs evenly into 32 bytes
|
||||
#define DEFINE_DRAW_SHADOW_OP(name, transparent_occluder) \
|
||||
struct Draw##name##Op final : DrawOpBase { \
|
||||
static const auto kType = DisplayListOpType::kDraw##name; \
|
||||
\
|
||||
Draw##name##Op(const SkPath& path, \
|
||||
DlColor color, \
|
||||
SkScalar elevation, \
|
||||
SkScalar dpr) \
|
||||
: color(color), elevation(elevation), dpr(dpr), path(path) {} \
|
||||
\
|
||||
const DlColor color; \
|
||||
const SkScalar elevation; \
|
||||
const SkScalar dpr; \
|
||||
const SkPath path; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.dispatcher.drawShadow(path, color, elevation, \
|
||||
transparent_occluder, dpr); \
|
||||
} \
|
||||
} \
|
||||
#define DEFINE_DRAW_SHADOW_OP(name, transparent_occluder) \
|
||||
struct Draw##name##Op final : DrawOpBase { \
|
||||
static const auto kType = DisplayListOpType::kDraw##name; \
|
||||
\
|
||||
Draw##name##Op(const SkPath& path, \
|
||||
DlColor color, \
|
||||
SkScalar elevation, \
|
||||
SkScalar dpr) \
|
||||
: color(color), elevation(elevation), dpr(dpr), path(path) {} \
|
||||
\
|
||||
const DlColor color; \
|
||||
const SkScalar elevation; \
|
||||
const SkScalar dpr; \
|
||||
const SkPath path; \
|
||||
\
|
||||
void dispatch(DispatchContext& ctx) const { \
|
||||
if (op_needed(ctx)) { \
|
||||
ctx.receiver.drawShadow(path, color, elevation, transparent_occluder, \
|
||||
dpr); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
DEFINE_DRAW_SHADOW_OP(Shadow, false)
|
||||
DEFINE_DRAW_SHADOW_OP(ShadowTransparentOccluder, true)
|
||||
|
||||
@ -25,14 +25,6 @@ enum class DlDrawStyle {
|
||||
kDefaultStyle = kFill,
|
||||
};
|
||||
|
||||
inline DlDrawStyle ToDl(SkPaint::Style style) {
|
||||
return static_cast<DlDrawStyle>(style);
|
||||
}
|
||||
|
||||
inline SkPaint::Style ToSk(DlDrawStyle style) {
|
||||
return static_cast<SkPaint::Style>(style);
|
||||
}
|
||||
|
||||
enum class DlStrokeCap {
|
||||
kButt, //!< no stroke extension
|
||||
kRound, //!< adds circle
|
||||
@ -42,14 +34,6 @@ enum class DlStrokeCap {
|
||||
kDefaultCap = kButt,
|
||||
};
|
||||
|
||||
inline DlStrokeCap ToDl(SkPaint::Cap cap) {
|
||||
return static_cast<DlStrokeCap>(cap);
|
||||
}
|
||||
|
||||
inline SkPaint::Cap ToSk(DlStrokeCap cap) {
|
||||
return static_cast<SkPaint::Cap>(cap);
|
||||
}
|
||||
|
||||
enum class DlStrokeJoin {
|
||||
kMiter, //!< extends to miter limit
|
||||
kRound, //!< adds circle
|
||||
@ -59,14 +43,6 @@ enum class DlStrokeJoin {
|
||||
kDefaultJoin = kMiter,
|
||||
};
|
||||
|
||||
inline DlStrokeJoin ToDl(SkPaint::Join join) {
|
||||
return static_cast<DlStrokeJoin>(join);
|
||||
}
|
||||
|
||||
inline SkPaint::Join ToSk(DlStrokeJoin join) {
|
||||
return static_cast<SkPaint::Join>(join);
|
||||
}
|
||||
|
||||
class DlPaint {
|
||||
public:
|
||||
static constexpr DlColor kDefaultColor = DlColor::kBlack();
|
||||
@ -174,7 +150,7 @@ class DlPaint {
|
||||
}
|
||||
const DlColorFilter* getColorFilterPtr() const { return colorFilter_.get(); }
|
||||
DlPaint& setColorFilter(const std::shared_ptr<const DlColorFilter> filter) {
|
||||
colorFilter_ = filter ? filter->shared() : nullptr;
|
||||
colorFilter_ = filter;
|
||||
return *this;
|
||||
}
|
||||
DlPaint& setColorFilter(const DlColorFilter* filter) {
|
||||
@ -216,6 +192,10 @@ class DlPaint {
|
||||
pathEffect_ = pathEffect;
|
||||
return *this;
|
||||
}
|
||||
DlPaint& setPathEffect(const DlPathEffect* effect) {
|
||||
pathEffect_ = effect ? effect->shared() : nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isDefault() const { return *this == kDefault; }
|
||||
|
||||
|
||||
@ -25,8 +25,7 @@ enum class DlPathEffectType {
|
||||
kDash,
|
||||
};
|
||||
|
||||
class DlPathEffect
|
||||
: public DlAttribute<DlPathEffect, SkPathEffect, DlPathEffectType> {
|
||||
class DlPathEffect : public DlAttribute<DlPathEffect, DlPathEffectType> {
|
||||
public:
|
||||
virtual const DlDashPathEffect* asDash() const { return nullptr; }
|
||||
|
||||
@ -77,13 +76,11 @@ class DlDashPathEffect final : public DlPathEffect {
|
||||
|
||||
const DlDashPathEffect* asDash() const override { return this; }
|
||||
|
||||
sk_sp<SkPathEffect> skia_object() const override {
|
||||
return SkDashPathEffect::Make(intervals(), count_, phase_);
|
||||
}
|
||||
|
||||
const SkScalar* intervals() const {
|
||||
return reinterpret_cast<const SkScalar*>(this + 1);
|
||||
}
|
||||
int count() const { return count_; }
|
||||
SkScalar phase() const { return phase_; }
|
||||
|
||||
std::optional<SkRect> effect_bounds(SkRect& rect) const override;
|
||||
|
||||
|
||||
@ -13,19 +13,6 @@
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
TEST(DisplayListPathEffect, BuilderSetGet) {
|
||||
const SkScalar test_dashes[] = {4.0, 2.0};
|
||||
auto dash_path_effect = DlDashPathEffect::Make(test_dashes, 2, 0.0);
|
||||
DisplayListBuilder builder;
|
||||
ASSERT_EQ(builder.getPathEffect(), nullptr);
|
||||
builder.setPathEffect(dash_path_effect.get());
|
||||
ASSERT_NE(builder.getPathEffect(), nullptr);
|
||||
ASSERT_TRUE(Equals(builder.getPathEffect(),
|
||||
static_cast<DlPathEffect*>(dash_path_effect.get())));
|
||||
builder.setPathEffect(nullptr);
|
||||
ASSERT_EQ(builder.getPathEffect(), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListPathEffect, EffectShared) {
|
||||
const SkScalar TestDashes2[] = {1.0, 1.5};
|
||||
auto effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0);
|
||||
|
||||
@ -16,14 +16,6 @@ enum class DlFilterMode {
|
||||
kLast = kLinear,
|
||||
};
|
||||
|
||||
inline DlFilterMode ToDl(const SkFilterMode filter_mode) {
|
||||
return static_cast<DlFilterMode>(filter_mode);
|
||||
}
|
||||
|
||||
inline SkFilterMode ToSk(const DlFilterMode filter_mode) {
|
||||
return static_cast<SkFilterMode>(filter_mode);
|
||||
}
|
||||
|
||||
enum class DlImageSampling {
|
||||
kNearestNeighbor,
|
||||
kLinear,
|
||||
@ -31,34 +23,6 @@ enum class DlImageSampling {
|
||||
kCubic,
|
||||
};
|
||||
|
||||
inline DlImageSampling ToDl(const SkSamplingOptions& so) {
|
||||
if (so.useCubic) {
|
||||
return DlImageSampling::kCubic;
|
||||
}
|
||||
if (so.filter == SkFilterMode::kLinear) {
|
||||
if (so.mipmap == SkMipmapMode::kNone) {
|
||||
return DlImageSampling::kLinear;
|
||||
}
|
||||
if (so.mipmap == SkMipmapMode::kLinear) {
|
||||
return DlImageSampling::kMipmapLinear;
|
||||
}
|
||||
}
|
||||
return DlImageSampling::kNearestNeighbor;
|
||||
}
|
||||
|
||||
inline SkSamplingOptions ToSk(DlImageSampling sampling) {
|
||||
switch (sampling) {
|
||||
case DlImageSampling::kCubic:
|
||||
return SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f});
|
||||
case DlImageSampling::kLinear:
|
||||
return SkSamplingOptions(SkFilterMode::kLinear);
|
||||
case DlImageSampling::kMipmapLinear:
|
||||
return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
|
||||
case DlImageSampling::kNearestNeighbor:
|
||||
return SkSamplingOptions(SkFilterMode::kNearest);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_SAMPLING_OPTIONS_H_
|
||||
|
||||
@ -30,14 +30,6 @@ enum class DlTileMode {
|
||||
kDecal,
|
||||
};
|
||||
|
||||
inline DlTileMode ToDl(SkTileMode sk_mode) {
|
||||
return static_cast<DlTileMode>(sk_mode);
|
||||
}
|
||||
|
||||
inline SkTileMode ToSk(DlTileMode dl_mode) {
|
||||
return static_cast<SkTileMode>(dl_mode);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_TILE_MODE_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -4,106 +4,8 @@
|
||||
|
||||
#include "flutter/display_list/display_list_utils.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_canvas_dispatcher.h"
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "third_party/skia/include/core/SkMaskFilter.h"
|
||||
#include "third_party/skia/include/core/SkPath.h"
|
||||
#include "third_party/skia/include/core/SkRSXform.h"
|
||||
#include "third_party/skia/include/core/SkTextBlob.h"
|
||||
#include "third_party/skia/include/utils/SkShadowUtils.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// clang-format off
|
||||
constexpr float kInvertColorMatrix[20] = {
|
||||
-1.0, 0, 0, 1.0, 0,
|
||||
0, -1.0, 0, 1.0, 0,
|
||||
0, 0, -1.0, 1.0, 0,
|
||||
1.0, 1.0, 1.0, 1.0, 0
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void SkPaintDispatchHelper::save_opacity(SkScalar child_opacity) {
|
||||
save_stack_.emplace_back(opacity_);
|
||||
set_opacity(child_opacity);
|
||||
}
|
||||
void SkPaintDispatchHelper::restore_opacity() {
|
||||
if (save_stack_.empty()) {
|
||||
return;
|
||||
}
|
||||
set_opacity(save_stack_.back().opacity);
|
||||
save_stack_.pop_back();
|
||||
}
|
||||
|
||||
void SkPaintDispatchHelper::setAntiAlias(bool aa) {
|
||||
paint_.setAntiAlias(aa);
|
||||
}
|
||||
void SkPaintDispatchHelper::setDither(bool dither) {
|
||||
paint_.setDither(dither);
|
||||
}
|
||||
void SkPaintDispatchHelper::setInvertColors(bool invert) {
|
||||
invert_colors_ = invert;
|
||||
paint_.setColorFilter(makeColorFilter());
|
||||
}
|
||||
void SkPaintDispatchHelper::setStrokeCap(DlStrokeCap cap) {
|
||||
paint_.setStrokeCap(ToSk(cap));
|
||||
}
|
||||
void SkPaintDispatchHelper::setStrokeJoin(DlStrokeJoin join) {
|
||||
paint_.setStrokeJoin(ToSk(join));
|
||||
}
|
||||
void SkPaintDispatchHelper::setStyle(DlDrawStyle style) {
|
||||
paint_.setStyle(ToSk(style));
|
||||
}
|
||||
void SkPaintDispatchHelper::setStrokeWidth(SkScalar width) {
|
||||
paint_.setStrokeWidth(width);
|
||||
}
|
||||
void SkPaintDispatchHelper::setStrokeMiter(SkScalar limit) {
|
||||
paint_.setStrokeMiter(limit);
|
||||
}
|
||||
void SkPaintDispatchHelper::setColor(DlColor color) {
|
||||
current_color_ = color;
|
||||
paint_.setColor(color);
|
||||
if (has_opacity()) {
|
||||
paint_.setAlphaf(paint_.getAlphaf() * opacity());
|
||||
}
|
||||
}
|
||||
void SkPaintDispatchHelper::setBlendMode(DlBlendMode mode) {
|
||||
paint_.setBlendMode(ToSk(mode));
|
||||
}
|
||||
void SkPaintDispatchHelper::setColorSource(const DlColorSource* source) {
|
||||
paint_.setShader(source ? source->skia_object() : nullptr);
|
||||
}
|
||||
void SkPaintDispatchHelper::setImageFilter(const DlImageFilter* filter) {
|
||||
paint_.setImageFilter(filter ? filter->skia_object() : nullptr);
|
||||
}
|
||||
void SkPaintDispatchHelper::setColorFilter(const DlColorFilter* filter) {
|
||||
color_filter_ = filter ? filter->shared() : nullptr;
|
||||
paint_.setColorFilter(makeColorFilter());
|
||||
}
|
||||
void SkPaintDispatchHelper::setPathEffect(const DlPathEffect* effect) {
|
||||
paint_.setPathEffect(effect ? effect->skia_object() : nullptr);
|
||||
}
|
||||
void SkPaintDispatchHelper::setMaskFilter(const DlMaskFilter* filter) {
|
||||
paint_.setMaskFilter(filter ? filter->skia_object() : nullptr);
|
||||
}
|
||||
|
||||
sk_sp<SkColorFilter> SkPaintDispatchHelper::makeColorFilter() const {
|
||||
if (!invert_colors_) {
|
||||
return color_filter_ ? color_filter_->skia_object() : nullptr;
|
||||
}
|
||||
sk_sp<SkColorFilter> invert_filter =
|
||||
SkColorFilters::Matrix(kInvertColorMatrix);
|
||||
if (color_filter_) {
|
||||
invert_filter = invert_filter->makeComposed(color_filter_->skia_object());
|
||||
}
|
||||
return invert_filter;
|
||||
}
|
||||
|
||||
void RectBoundsAccumulator::accumulate(const SkRect& r, int index) {
|
||||
if (r.fLeft < r.fRight && r.fTop < r.fBottom) {
|
||||
rect_.accumulate(r.fLeft, r.fTop);
|
||||
|
||||
@ -7,33 +7,24 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "flutter/display_list/display_list.h"
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_flags.h"
|
||||
#include "flutter/display_list/display_list_rtree.h"
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "third_party/skia/include/core/SkMaskFilter.h"
|
||||
|
||||
// This file contains various utility classes to ease implementing
|
||||
// a Flutter DisplayList Dispatcher, including:
|
||||
// a Flutter DisplayList DlOpReceiver, including:
|
||||
//
|
||||
// IgnoreAttributeDispatchHelper:
|
||||
// IgnoreClipDispatchHelper:
|
||||
// IgnoreTransformDispatchHelper
|
||||
// Empty overrides of all of the associated methods of Dispatcher
|
||||
// for dispatchers that only track some of the rendering operations
|
||||
//
|
||||
// SkPaintAttributeDispatchHelper:
|
||||
// Tracks the attribute methods and maintains their state in an
|
||||
// SkPaint object.
|
||||
// Empty overrides of all of the associated methods of DlOpReceiver
|
||||
// for receivers that only track some of the rendering operations
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// A utility class that will ignore all Dispatcher methods relating
|
||||
// A utility class that will ignore all DlOpReceiver methods relating
|
||||
// to the setting of attributes.
|
||||
class IgnoreAttributeDispatchHelper : public virtual Dispatcher {
|
||||
class IgnoreAttributeDispatchHelper : public virtual DlOpReceiver {
|
||||
public:
|
||||
void setAntiAlias(bool aa) override {}
|
||||
void setDither(bool dither) override {}
|
||||
@ -52,9 +43,9 @@ class IgnoreAttributeDispatchHelper : public virtual Dispatcher {
|
||||
void setMaskFilter(const DlMaskFilter* filter) override {}
|
||||
};
|
||||
|
||||
// A utility class that will ignore all Dispatcher methods relating
|
||||
// A utility class that will ignore all DlOpReceiver methods relating
|
||||
// to setting a clip.
|
||||
class IgnoreClipDispatchHelper : public virtual Dispatcher {
|
||||
class IgnoreClipDispatchHelper : public virtual DlOpReceiver {
|
||||
void clipRect(const SkRect& rect,
|
||||
DlCanvas::ClipOp clip_op,
|
||||
bool is_aa) override {}
|
||||
@ -66,9 +57,9 @@ class IgnoreClipDispatchHelper : public virtual Dispatcher {
|
||||
bool is_aa) override {}
|
||||
};
|
||||
|
||||
// A utility class that will ignore all Dispatcher methods relating
|
||||
// A utility class that will ignore all DlOpReceiver methods relating
|
||||
// to modifying the transform.
|
||||
class IgnoreTransformDispatchHelper : public virtual Dispatcher {
|
||||
class IgnoreTransformDispatchHelper : public virtual DlOpReceiver {
|
||||
public:
|
||||
void translate(SkScalar tx, SkScalar ty) override {}
|
||||
void scale(SkScalar sx, SkScalar sy) override {}
|
||||
@ -88,7 +79,7 @@ class IgnoreTransformDispatchHelper : public virtual Dispatcher {
|
||||
void transformReset() override {}
|
||||
};
|
||||
|
||||
class IgnoreDrawDispatchHelper : public virtual Dispatcher {
|
||||
class IgnoreDrawDispatchHelper : public virtual DlOpReceiver {
|
||||
public:
|
||||
void save() override {}
|
||||
void saveLayer(const SkRect* bounds,
|
||||
@ -121,7 +112,7 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher {
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) override {}
|
||||
SrcRectConstraint constraint) override {}
|
||||
void drawImageNine(const sk_sp<DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
@ -136,7 +127,8 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher {
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cull_rect,
|
||||
bool render_with_attributes) override {}
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list) override {}
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) override {}
|
||||
void drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) override {}
|
||||
@ -147,77 +139,6 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher {
|
||||
SkScalar dpr) override {}
|
||||
};
|
||||
|
||||
// A utility class that will monitor the Dispatcher methods relating
|
||||
// to the rendering attributes and accumulate them into an SkPaint
|
||||
// which can be accessed at any time via paint().
|
||||
class SkPaintDispatchHelper : public virtual Dispatcher {
|
||||
public:
|
||||
SkPaintDispatchHelper(SkScalar opacity = SK_Scalar1)
|
||||
: current_color_(SK_ColorBLACK), opacity_(opacity) {
|
||||
if (opacity < SK_Scalar1) {
|
||||
paint_.setAlphaf(opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void setAntiAlias(bool aa) override;
|
||||
void setDither(bool dither) override;
|
||||
void setStyle(DlDrawStyle style) override;
|
||||
void setColor(DlColor color) override;
|
||||
void setStrokeWidth(SkScalar width) override;
|
||||
void setStrokeMiter(SkScalar limit) override;
|
||||
void setStrokeCap(DlStrokeCap cap) override;
|
||||
void setStrokeJoin(DlStrokeJoin join) override;
|
||||
void setColorSource(const DlColorSource* source) override;
|
||||
void setColorFilter(const DlColorFilter* filter) override;
|
||||
void setInvertColors(bool invert) override;
|
||||
void setBlendMode(DlBlendMode mode) override;
|
||||
void setPathEffect(const DlPathEffect* effect) override;
|
||||
void setMaskFilter(const DlMaskFilter* filter) override;
|
||||
void setImageFilter(const DlImageFilter* filter) override;
|
||||
|
||||
const SkPaint& paint() { return paint_; }
|
||||
|
||||
/// Returns the current opacity attribute which is used to reduce
|
||||
/// the alpha of all setColor calls encountered in the streeam
|
||||
SkScalar opacity() { return opacity_; }
|
||||
/// Returns the combined opacity that includes both the current
|
||||
/// opacity attribute and the alpha of the most recent color.
|
||||
/// The most recently set color will have combined the two and
|
||||
/// stored the combined value in the alpha of the paint.
|
||||
SkScalar combined_opacity() { return paint_.getAlphaf(); }
|
||||
/// Returns true iff the current opacity attribute is not opaque,
|
||||
/// irrespective of the alpha of the current color
|
||||
bool has_opacity() { return opacity_ < SK_Scalar1; }
|
||||
|
||||
protected:
|
||||
void save_opacity(SkScalar opacity_for_children);
|
||||
void restore_opacity();
|
||||
|
||||
private:
|
||||
SkPaint paint_;
|
||||
bool invert_colors_ = false;
|
||||
std::shared_ptr<const DlColorFilter> color_filter_;
|
||||
|
||||
sk_sp<SkColorFilter> makeColorFilter() const;
|
||||
|
||||
struct SaveInfo {
|
||||
SaveInfo(SkScalar opacity) : opacity(opacity) {}
|
||||
|
||||
SkScalar opacity;
|
||||
};
|
||||
std::vector<SaveInfo> save_stack_;
|
||||
|
||||
void set_opacity(SkScalar opacity) {
|
||||
if (opacity_ != opacity) {
|
||||
opacity_ = opacity;
|
||||
setColor(current_color_);
|
||||
}
|
||||
}
|
||||
|
||||
SkColor current_color_;
|
||||
SkScalar opacity_;
|
||||
};
|
||||
|
||||
enum class BoundsAccumulatorType {
|
||||
kRect,
|
||||
kRTree,
|
||||
|
||||
@ -176,13 +176,6 @@ DlVertices::DlVertices(DlVertexMode mode,
|
||||
FML_DCHECK((index_count_ != 0) == (indices() != nullptr));
|
||||
}
|
||||
|
||||
sk_sp<SkVertices> DlVertices::skia_object() const {
|
||||
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
|
||||
return SkVertices::MakeCopy(ToSk(mode_), vertex_count_, vertices(),
|
||||
texture_coordinates(), sk_colors, index_count_,
|
||||
indices());
|
||||
}
|
||||
|
||||
bool DlVertices::operator==(DlVertices const& other) const {
|
||||
auto lists_equal = [](auto* a, auto* b, int count) {
|
||||
if (a == nullptr || b == nullptr) {
|
||||
|
||||
@ -30,14 +30,6 @@ enum class DlVertexMode {
|
||||
kTriangleFan,
|
||||
};
|
||||
|
||||
inline SkVertices::VertexMode ToSk(DlVertexMode dl_mode) {
|
||||
return static_cast<SkVertices::VertexMode>(dl_mode);
|
||||
}
|
||||
|
||||
inline DlVertexMode ToDl(SkVertices::VertexMode sk_mode) {
|
||||
return static_cast<DlVertexMode>(sk_mode);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @brief Holds all of the data (both required and optional) for a
|
||||
/// DisplayList drawVertices call.
|
||||
@ -233,9 +225,6 @@ class DlVertices {
|
||||
return static_cast<const uint16_t*>(pod(indices_offset_));
|
||||
}
|
||||
|
||||
// Returns an equivalent sk_sp<SkVertices> analog to this object.
|
||||
sk_sp<SkVertices> skia_object() const;
|
||||
|
||||
bool operator==(DlVertices const& other) const;
|
||||
|
||||
bool operator!=(DlVertices const& other) const { return !(*this == other); }
|
||||
|
||||
@ -22,7 +22,6 @@ TEST(DisplayListVertices, MakeWithZeroAndNegativeVerticesAndIndices) {
|
||||
EXPECT_EQ(vertices1->colors(), nullptr);
|
||||
EXPECT_EQ(vertices1->index_count(), 0);
|
||||
EXPECT_EQ(vertices1->indices(), nullptr);
|
||||
EXPECT_NE(vertices1->skia_object(), nullptr);
|
||||
|
||||
std::shared_ptr<const DlVertices> vertices2 = DlVertices::Make(
|
||||
DlVertexMode::kTriangles, -1, nullptr, nullptr, nullptr, -1, nullptr);
|
||||
@ -33,7 +32,6 @@ TEST(DisplayListVertices, MakeWithZeroAndNegativeVerticesAndIndices) {
|
||||
EXPECT_EQ(vertices2->colors(), nullptr);
|
||||
EXPECT_EQ(vertices2->index_count(), 0);
|
||||
EXPECT_EQ(vertices2->indices(), nullptr);
|
||||
EXPECT_NE(vertices2->skia_object(), nullptr);
|
||||
|
||||
TestEquals(*vertices1, *vertices2);
|
||||
}
|
||||
@ -425,7 +423,6 @@ TEST(DisplayListVertices, BuildWithZeroAndNegativeVerticesAndIndices) {
|
||||
EXPECT_EQ(vertices1->colors(), nullptr);
|
||||
EXPECT_EQ(vertices1->index_count(), 0);
|
||||
EXPECT_EQ(vertices1->indices(), nullptr);
|
||||
EXPECT_NE(vertices1->skia_object(), nullptr);
|
||||
|
||||
Builder builder2(DlVertexMode::kTriangles, -1, Builder::kNone, -1);
|
||||
EXPECT_TRUE(builder2.is_valid());
|
||||
@ -437,7 +434,6 @@ TEST(DisplayListVertices, BuildWithZeroAndNegativeVerticesAndIndices) {
|
||||
EXPECT_EQ(vertices2->colors(), nullptr);
|
||||
EXPECT_EQ(vertices2->index_count(), 0);
|
||||
EXPECT_EQ(vertices2->indices(), nullptr);
|
||||
EXPECT_NE(vertices2->skia_object(), nullptr);
|
||||
|
||||
TestEquals(*vertices1, *vertices2);
|
||||
}
|
||||
|
||||
23
engine/src/flutter/display_list/dl_canvas.cc
Normal file
23
engine/src/flutter/display_list/dl_canvas.cc
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2013 The Flutter 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 "flutter/display_list/dl_canvas.h"
|
||||
|
||||
#include "third_party/skia/include/utils/SkShadowUtils.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
SkRect DlCanvas::ComputeShadowBounds(const SkPath& path,
|
||||
float elevation,
|
||||
SkScalar dpr,
|
||||
const SkMatrix& ctm) {
|
||||
SkRect shadow_bounds(path.getBounds());
|
||||
SkShadowUtils::GetLocalBounds(
|
||||
ctm, path, SkPoint3::Make(0, 0, dpr * elevation),
|
||||
SkPoint3::Make(0, -1, 1), kShadowLightRadius / kShadowLightHeight,
|
||||
SkShadowFlags::kDirectionalLight_ShadowFlag, &shadow_bounds);
|
||||
return shadow_bounds;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@ -35,6 +35,11 @@ class DlCanvas {
|
||||
kPolygon, //!< draw each pair of overlapping points as a line segment
|
||||
};
|
||||
|
||||
enum class SrcRectConstraint {
|
||||
kStrict,
|
||||
kFast,
|
||||
};
|
||||
|
||||
virtual ~DlCanvas() = default;
|
||||
|
||||
virtual SkISize GetBaseLayerSize() const = 0;
|
||||
@ -146,28 +151,29 @@ class DlCanvas {
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr) = 0;
|
||||
virtual void DrawImageRect(const sk_sp<DlImage>& image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
bool enforce_src_edges = false) = 0;
|
||||
virtual void DrawImageRect(const sk_sp<DlImage>& image,
|
||||
const SkIRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
bool enforce_src_edges = false) {
|
||||
DrawImageRect(image, SkRect::Make(src), dst, sampling, paint,
|
||||
enforce_src_edges);
|
||||
virtual void DrawImageRect(
|
||||
const sk_sp<DlImage>& image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) = 0;
|
||||
virtual void DrawImageRect(
|
||||
const sk_sp<DlImage>& image,
|
||||
const SkIRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) {
|
||||
DrawImageRect(image, SkRect::Make(src), dst, sampling, paint, constraint);
|
||||
}
|
||||
virtual void DrawImageRect(const sk_sp<DlImage>& image,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
bool enforce_src_edges = false) {
|
||||
DrawImageRect(image, image->bounds(), dst, sampling, paint,
|
||||
enforce_src_edges);
|
||||
virtual void DrawImageRect(
|
||||
const sk_sp<DlImage>& image,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) {
|
||||
DrawImageRect(image, image->bounds(), dst, sampling, paint, constraint);
|
||||
}
|
||||
virtual void DrawImageNine(const sk_sp<DlImage>& image,
|
||||
const SkIRect& center,
|
||||
@ -196,6 +202,14 @@ class DlCanvas {
|
||||
SkScalar dpr) = 0;
|
||||
|
||||
virtual void Flush() = 0;
|
||||
|
||||
static constexpr SkScalar kShadowLightHeight = 600;
|
||||
static constexpr SkScalar kShadowLightRadius = 800;
|
||||
|
||||
static SkRect ComputeShadowBounds(const SkPath& path,
|
||||
float elevation,
|
||||
SkScalar dpr,
|
||||
const SkMatrix& ctm);
|
||||
};
|
||||
|
||||
class DlAutoCanvasRestore {
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
//
|
||||
// Just exists to ensure that the header can be cleanly imported.
|
||||
|
||||
} // namespace flutter
|
||||
@ -28,10 +28,11 @@ class DisplayList;
|
||||
/// through the DisplayListBuilder and also the methods that will be
|
||||
/// invoked through the DisplayList::dispatch() method.
|
||||
///
|
||||
class Dispatcher {
|
||||
class DlOpReceiver {
|
||||
protected:
|
||||
using ClipOp = DlCanvas::ClipOp;
|
||||
using PointMode = DlCanvas::PointMode;
|
||||
using SrcRectConstraint = DlCanvas::SrcRectConstraint;
|
||||
|
||||
public:
|
||||
// MaxDrawPointsCount * sizeof(SkPoint) must be less than 1 << 32
|
||||
@ -219,12 +220,13 @@ class Dispatcher {
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes) = 0;
|
||||
virtual void drawImageRect(const sk_sp<DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) = 0;
|
||||
virtual void drawImageRect(
|
||||
const sk_sp<DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) = 0;
|
||||
virtual void drawImageNine(const sk_sp<DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
@ -239,7 +241,8 @@ class Dispatcher {
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cull_rect,
|
||||
bool render_with_attributes) = 0;
|
||||
virtual void drawDisplayList(const sk_sp<DisplayList> display_list) = 0;
|
||||
virtual void drawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity = SK_Scalar1) = 0;
|
||||
virtual void drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) = 0;
|
||||
File diff suppressed because it is too large
Load Diff
@ -4,43 +4,11 @@
|
||||
|
||||
#include "flutter/display_list/skia/dl_sk_canvas.h"
|
||||
|
||||
#include "flutter/display_list/display_list_canvas_dispatcher.h"
|
||||
#include "flutter/display_list/skia/dl_sk_conversions.h"
|
||||
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
static sk_sp<SkShader> ToSk(const DlColorSource* source) {
|
||||
return source ? source->skia_object() : nullptr;
|
||||
}
|
||||
|
||||
static sk_sp<SkImageFilter> ToSk(const DlImageFilter* filter) {
|
||||
return filter ? filter->skia_object() : nullptr;
|
||||
}
|
||||
|
||||
static sk_sp<SkColorFilter> ToSk(const DlColorFilter* filter) {
|
||||
return filter ? filter->skia_object() : nullptr;
|
||||
}
|
||||
|
||||
static sk_sp<SkMaskFilter> ToSk(const DlMaskFilter* filter) {
|
||||
return filter ? filter->skia_object() : nullptr;
|
||||
}
|
||||
|
||||
static sk_sp<SkPathEffect> ToSk(const DlPathEffect* effect) {
|
||||
return effect ? effect->skia_object() : nullptr;
|
||||
}
|
||||
|
||||
static SkCanvas::SrcRectConstraint ToSkConstraint(bool enforce_edges) {
|
||||
return enforce_edges ? SkCanvas::kStrict_SrcRectConstraint
|
||||
: SkCanvas::kFast_SrcRectConstraint;
|
||||
}
|
||||
|
||||
static SkClipOp ToSk(DlCanvas::ClipOp op) {
|
||||
return static_cast<SkClipOp>(op);
|
||||
}
|
||||
|
||||
static SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) {
|
||||
return static_cast<SkCanvas::PointMode>(mode);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
constexpr float kInvertColorMatrix[20] = {
|
||||
-1.0, 0, 0, 1.0, 0,
|
||||
@ -119,10 +87,10 @@ void DlSkCanvasAdapter::Save() {
|
||||
void DlSkCanvasAdapter::SaveLayer(const SkRect* bounds,
|
||||
const DlPaint* paint,
|
||||
const DlImageFilter* backdrop) {
|
||||
sk_sp<SkImageFilter> sk_filter = backdrop ? backdrop->skia_object() : nullptr;
|
||||
sk_sp<SkImageFilter> sk_backdrop = ToSk(backdrop);
|
||||
SkOptionalPaint sk_paint(paint);
|
||||
delegate_->saveLayer(
|
||||
SkCanvas::SaveLayerRec{bounds, sk_paint(), sk_filter.get(), 0});
|
||||
SkCanvas::SaveLayerRec{bounds, sk_paint(), sk_backdrop.get(), 0});
|
||||
}
|
||||
|
||||
void DlSkCanvasAdapter::Restore() {
|
||||
@ -309,7 +277,7 @@ void DlSkCanvasAdapter::DrawPoints(PointMode mode,
|
||||
void DlSkCanvasAdapter::DrawVertices(const DlVertices* vertices,
|
||||
DlBlendMode mode,
|
||||
const DlPaint& paint) {
|
||||
delegate_->drawVertices(vertices->skia_object(), ToSk(mode), ToSk(paint));
|
||||
delegate_->drawVertices(ToSk(vertices), ToSk(mode), ToSk(paint));
|
||||
}
|
||||
|
||||
void DlSkCanvasAdapter::DrawImage(const sk_sp<DlImage>& image,
|
||||
@ -327,11 +295,11 @@ void DlSkCanvasAdapter::DrawImageRect(const sk_sp<DlImage>& image,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint,
|
||||
bool enforce_src_edges) {
|
||||
SrcRectConstraint constraint) {
|
||||
SkOptionalPaint sk_paint(paint);
|
||||
sk_sp<SkImage> sk_image = image->skia_image();
|
||||
delegate_->drawImageRect(sk_image.get(), src, dst, ToSk(sampling), sk_paint(),
|
||||
ToSkConstraint(enforce_src_edges));
|
||||
ToSk(constraint));
|
||||
}
|
||||
|
||||
void DlSkCanvasAdapter::DrawImageNine(const sk_sp<DlImage>& image,
|
||||
@ -363,7 +331,26 @@ void DlSkCanvasAdapter::DrawAtlas(const sk_sp<DlImage>& atlas,
|
||||
|
||||
void DlSkCanvasAdapter::DrawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) {
|
||||
display_list->RenderTo(delegate_, opacity);
|
||||
int restore_count = delegate_->getSaveCount();
|
||||
|
||||
// Figure out whether we can apply the opacity during dispatch or
|
||||
// if we need a saveLayer.
|
||||
if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) {
|
||||
DlPaint save_paint = DlPaint().setOpacity(opacity);
|
||||
SaveLayer(&display_list->bounds(), &save_paint);
|
||||
opacity = SK_Scalar1;
|
||||
} else {
|
||||
Save();
|
||||
}
|
||||
|
||||
DlSkCanvasDispatcher dispatcher(delegate_, opacity);
|
||||
if (display_list->has_rtree()) {
|
||||
display_list->Dispatch(dispatcher, delegate_->getLocalClipBounds());
|
||||
} else {
|
||||
display_list->Dispatch(dispatcher);
|
||||
}
|
||||
|
||||
delegate_->restoreToCount(restore_count);
|
||||
}
|
||||
|
||||
void DlSkCanvasAdapter::DrawTextBlob(const sk_sp<SkTextBlob>& blob,
|
||||
@ -378,8 +365,8 @@ void DlSkCanvasAdapter::DrawShadow(const SkPath& path,
|
||||
const SkScalar elevation,
|
||||
bool transparent_occluder,
|
||||
SkScalar dpr) {
|
||||
DisplayListCanvasDispatcher::DrawShadow(delegate_, path, color, elevation,
|
||||
transparent_occluder, dpr);
|
||||
DlSkCanvasDispatcher::DrawShadow(delegate_, path, color, elevation,
|
||||
transparent_occluder, dpr);
|
||||
}
|
||||
|
||||
void DlSkCanvasAdapter::Flush() {
|
||||
|
||||
@ -114,12 +114,13 @@ class DlSkCanvasAdapter final : public virtual DlCanvas {
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
void DrawImageRect(const sk_sp<DlImage>& image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
bool enforce_src_edges = false) override;
|
||||
void DrawImageRect(
|
||||
const sk_sp<DlImage>& image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
|
||||
void DrawImageNine(const sk_sp<DlImage>& image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
@ -135,7 +136,7 @@ class DlSkCanvasAdapter final : public virtual DlCanvas {
|
||||
const SkRect* cullRect,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
void DrawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) override;
|
||||
SkScalar opacity = SK_Scalar1) override;
|
||||
void DrawTextBlob(const sk_sp<SkTextBlob>& blob,
|
||||
SkScalar x,
|
||||
SkScalar y,
|
||||
|
||||
235
engine/src/flutter/display_list/skia/dl_sk_conversions.cc
Normal file
235
engine/src/flutter/display_list/skia/dl_sk_conversions.cc
Normal file
@ -0,0 +1,235 @@
|
||||
// Copyright 2013 The Flutter 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 "flutter/display_list/skia/dl_sk_conversions.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
sk_sp<SkShader> ToSk(const DlColorSource* source) {
|
||||
if (!source) {
|
||||
return nullptr;
|
||||
}
|
||||
static auto ToSkColors = [](const DlGradientColorSourceBase* gradient) {
|
||||
return reinterpret_cast<const SkColor*>(gradient->colors());
|
||||
};
|
||||
switch (source->type()) {
|
||||
case DlColorSourceType::kColor: {
|
||||
const DlColorColorSource* color_source = source->asColor();
|
||||
FML_DCHECK(color_source != nullptr);
|
||||
return SkShaders::Color(color_source->color());
|
||||
}
|
||||
case DlColorSourceType::kImage: {
|
||||
const DlImageColorSource* image_source = source->asImage();
|
||||
FML_DCHECK(image_source != nullptr);
|
||||
auto image = image_source->image();
|
||||
if (!image || !image->skia_image()) {
|
||||
return nullptr;
|
||||
}
|
||||
return image->skia_image()->makeShader(
|
||||
ToSk(image_source->horizontal_tile_mode()),
|
||||
ToSk(image_source->vertical_tile_mode()),
|
||||
ToSk(image_source->sampling()), image_source->matrix_ptr());
|
||||
}
|
||||
case DlColorSourceType::kLinearGradient: {
|
||||
const DlLinearGradientColorSource* linear_source =
|
||||
source->asLinearGradient();
|
||||
FML_DCHECK(linear_source != nullptr);
|
||||
SkPoint pts[] = {linear_source->start_point(),
|
||||
linear_source->end_point()};
|
||||
return SkGradientShader::MakeLinear(
|
||||
pts, ToSkColors(linear_source), linear_source->stops(),
|
||||
linear_source->stop_count(), ToSk(linear_source->tile_mode()), 0,
|
||||
linear_source->matrix_ptr());
|
||||
}
|
||||
case DlColorSourceType::kRadialGradient: {
|
||||
const DlRadialGradientColorSource* radial_source =
|
||||
source->asRadialGradient();
|
||||
FML_DCHECK(radial_source != nullptr);
|
||||
return SkGradientShader::MakeRadial(
|
||||
radial_source->center(), radial_source->radius(),
|
||||
ToSkColors(radial_source), radial_source->stops(),
|
||||
radial_source->stop_count(), ToSk(radial_source->tile_mode()), 0,
|
||||
radial_source->matrix_ptr());
|
||||
}
|
||||
case DlColorSourceType::kConicalGradient: {
|
||||
const DlConicalGradientColorSource* conical_source =
|
||||
source->asConicalGradient();
|
||||
FML_DCHECK(conical_source != nullptr);
|
||||
return SkGradientShader::MakeTwoPointConical(
|
||||
conical_source->start_center(), conical_source->start_radius(),
|
||||
conical_source->end_center(), conical_source->end_radius(),
|
||||
ToSkColors(conical_source), conical_source->stops(),
|
||||
conical_source->stop_count(), ToSk(conical_source->tile_mode()), 0,
|
||||
conical_source->matrix_ptr());
|
||||
}
|
||||
case DlColorSourceType::kSweepGradient: {
|
||||
const DlSweepGradientColorSource* sweep_source =
|
||||
source->asSweepGradient();
|
||||
FML_DCHECK(sweep_source != nullptr);
|
||||
return SkGradientShader::MakeSweep(
|
||||
sweep_source->center().x(), sweep_source->center().y(),
|
||||
ToSkColors(sweep_source), sweep_source->stops(),
|
||||
sweep_source->stop_count(), ToSk(sweep_source->tile_mode()),
|
||||
sweep_source->start(), sweep_source->end(), 0,
|
||||
sweep_source->matrix_ptr());
|
||||
}
|
||||
case DlColorSourceType::kRuntimeEffect: {
|
||||
const DlRuntimeEffectColorSource* runtime_source =
|
||||
source->asRuntimeEffect();
|
||||
FML_DCHECK(runtime_source != nullptr);
|
||||
auto runtime_effect = runtime_source->runtime_effect();
|
||||
if (!runtime_effect || !runtime_effect->skia_runtime_effect()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto samplers = runtime_source->samplers();
|
||||
std::vector<sk_sp<SkShader>> sk_samplers(samplers.size());
|
||||
for (size_t i = 0; i < samplers.size(); i++) {
|
||||
auto sampler = samplers[i];
|
||||
if (sampler == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
sk_samplers[i] = ToSk(sampler);
|
||||
}
|
||||
|
||||
auto uniform_data = runtime_source->uniform_data();
|
||||
auto ref = new std::shared_ptr<std::vector<uint8_t>>(uniform_data);
|
||||
auto sk_uniform_data = SkData::MakeWithProc(
|
||||
uniform_data->data(), uniform_data->size(),
|
||||
[](const void* ptr, void* context) {
|
||||
delete reinterpret_cast<std::shared_ptr<std::vector<uint8_t>>*>(
|
||||
context);
|
||||
},
|
||||
ref);
|
||||
|
||||
return runtime_effect->skia_runtime_effect()->makeShader(
|
||||
sk_uniform_data, sk_samplers.data(), sk_samplers.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> ToSk(const DlImageFilter* filter) {
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (filter->type()) {
|
||||
case DlImageFilterType::kBlur: {
|
||||
const DlBlurImageFilter* blur_filter = filter->asBlur();
|
||||
FML_DCHECK(blur_filter != nullptr);
|
||||
return SkImageFilters::Blur(blur_filter->sigma_x(),
|
||||
blur_filter->sigma_y(),
|
||||
ToSk(blur_filter->tile_mode()), nullptr);
|
||||
}
|
||||
case DlImageFilterType::kDilate: {
|
||||
const DlDilateImageFilter* dilate_filter = filter->asDilate();
|
||||
FML_DCHECK(dilate_filter != nullptr);
|
||||
return SkImageFilters::Dilate(dilate_filter->radius_x(),
|
||||
dilate_filter->radius_y(), nullptr);
|
||||
}
|
||||
case DlImageFilterType::kErode: {
|
||||
const DlErodeImageFilter* erode_filter = filter->asErode();
|
||||
FML_DCHECK(erode_filter != nullptr);
|
||||
return SkImageFilters::Erode(erode_filter->radius_x(),
|
||||
erode_filter->radius_y(), nullptr);
|
||||
}
|
||||
case DlImageFilterType::kMatrix: {
|
||||
const DlMatrixImageFilter* matrix_filter = filter->asMatrix();
|
||||
FML_DCHECK(matrix_filter != nullptr);
|
||||
return SkImageFilters::MatrixTransform(
|
||||
matrix_filter->matrix(), ToSk(matrix_filter->sampling()), nullptr);
|
||||
}
|
||||
case DlImageFilterType::kCompose: {
|
||||
const DlComposeImageFilter* compose_filter = filter->asCompose();
|
||||
FML_DCHECK(compose_filter != nullptr);
|
||||
return SkImageFilters::Compose(ToSk(compose_filter->outer()),
|
||||
ToSk(compose_filter->inner()));
|
||||
}
|
||||
case DlImageFilterType::kColorFilter: {
|
||||
const DlColorFilterImageFilter* cf_filter = filter->asColorFilter();
|
||||
FML_DCHECK(cf_filter != nullptr);
|
||||
return SkImageFilters::ColorFilter(ToSk(cf_filter->color_filter()),
|
||||
nullptr);
|
||||
}
|
||||
case DlImageFilterType::kLocalMatrix: {
|
||||
const DlLocalMatrixImageFilter* lm_filter = filter->asLocalMatrix();
|
||||
FML_DCHECK(lm_filter != nullptr);
|
||||
sk_sp<SkImageFilter> skia_filter = ToSk(lm_filter->image_filter());
|
||||
// The image_filter property itself might have been null, or the
|
||||
// construction of the SkImageFilter might be optimized to null
|
||||
// for any number of reasons. In any case, if the filter is null
|
||||
// or optimizaed away, let's then optimize away this local matrix
|
||||
// case by returning null.
|
||||
if (!skia_filter) {
|
||||
return nullptr;
|
||||
}
|
||||
return skia_filter->makeWithLocalMatrix(lm_filter->matrix());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkColorFilter> ToSk(const DlColorFilter* filter) {
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (filter->type()) {
|
||||
case DlColorFilterType::kBlend: {
|
||||
const DlBlendColorFilter* blend_filter = filter->asBlend();
|
||||
FML_DCHECK(blend_filter != nullptr);
|
||||
return SkColorFilters::Blend(blend_filter->color(),
|
||||
ToSk(blend_filter->mode()));
|
||||
}
|
||||
case DlColorFilterType::kMatrix: {
|
||||
const DlMatrixColorFilter* matrix_filter = filter->asMatrix();
|
||||
FML_DCHECK(matrix_filter != nullptr);
|
||||
float matrix[20];
|
||||
matrix_filter->get_matrix(matrix);
|
||||
return SkColorFilters::Matrix(matrix);
|
||||
}
|
||||
case DlColorFilterType::kSrgbToLinearGamma: {
|
||||
return SkColorFilters::SRGBToLinearGamma();
|
||||
}
|
||||
case DlColorFilterType::kLinearToSrgbGamma: {
|
||||
return SkColorFilters::LinearToSRGBGamma();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkMaskFilter> ToSk(const DlMaskFilter* filter) {
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (filter->type()) {
|
||||
case DlMaskFilterType::kBlur: {
|
||||
const DlBlurMaskFilter* blur_filter = filter->asBlur();
|
||||
FML_DCHECK(blur_filter != nullptr);
|
||||
return SkMaskFilter::MakeBlur(blur_filter->style(), blur_filter->sigma(),
|
||||
blur_filter->respectCTM());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkPathEffect> ToSk(const DlPathEffect* effect) {
|
||||
if (!effect) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (effect->type()) {
|
||||
case DlPathEffectType::kDash: {
|
||||
const DlDashPathEffect* dash_effect = effect->asDash();
|
||||
FML_DCHECK(dash_effect != nullptr);
|
||||
return SkDashPathEffect::Make(dash_effect->intervals(),
|
||||
dash_effect->count(), dash_effect->phase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkVertices> ToSk(const DlVertices* vertices) {
|
||||
const SkColor* sk_colors =
|
||||
reinterpret_cast<const SkColor*>(vertices->colors());
|
||||
return SkVertices::MakeCopy(ToSk(vertices->mode()), vertices->vertex_count(),
|
||||
vertices->vertices(),
|
||||
vertices->texture_coordinates(), sk_colors,
|
||||
vertices->index_count(), vertices->indices());
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
116
engine/src/flutter/display_list/skia/dl_sk_conversions.h
Normal file
116
engine/src/flutter/display_list/skia/dl_sk_conversions.h
Normal file
@ -0,0 +1,116 @@
|
||||
// Copyright 2013 The Flutter 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 FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_
|
||||
#define FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_
|
||||
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
inline SkBlendMode ToSk(DlBlendMode mode) {
|
||||
return static_cast<SkBlendMode>(mode);
|
||||
}
|
||||
|
||||
inline SkPaint::Style ToSk(DlDrawStyle style) {
|
||||
return static_cast<SkPaint::Style>(style);
|
||||
}
|
||||
|
||||
inline SkPaint::Cap ToSk(DlStrokeCap cap) {
|
||||
return static_cast<SkPaint::Cap>(cap);
|
||||
}
|
||||
|
||||
inline SkPaint::Join ToSk(DlStrokeJoin join) {
|
||||
return static_cast<SkPaint::Join>(join);
|
||||
}
|
||||
|
||||
inline SkTileMode ToSk(DlTileMode dl_mode) {
|
||||
return static_cast<SkTileMode>(dl_mode);
|
||||
}
|
||||
|
||||
inline SkFilterMode ToSk(const DlFilterMode filter_mode) {
|
||||
return static_cast<SkFilterMode>(filter_mode);
|
||||
}
|
||||
|
||||
inline SkVertices::VertexMode ToSk(DlVertexMode dl_mode) {
|
||||
return static_cast<SkVertices::VertexMode>(dl_mode);
|
||||
}
|
||||
|
||||
inline SkSamplingOptions ToSk(DlImageSampling sampling) {
|
||||
switch (sampling) {
|
||||
case DlImageSampling::kCubic:
|
||||
return SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f});
|
||||
case DlImageSampling::kLinear:
|
||||
return SkSamplingOptions(SkFilterMode::kLinear);
|
||||
case DlImageSampling::kMipmapLinear:
|
||||
return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
|
||||
case DlImageSampling::kNearestNeighbor:
|
||||
return SkSamplingOptions(SkFilterMode::kNearest);
|
||||
}
|
||||
}
|
||||
|
||||
inline SkCanvas::SrcRectConstraint ToSk(
|
||||
DlCanvas::SrcRectConstraint constraint) {
|
||||
return static_cast<SkCanvas::SrcRectConstraint>(constraint);
|
||||
}
|
||||
|
||||
inline SkClipOp ToSk(DlCanvas::ClipOp op) {
|
||||
return static_cast<SkClipOp>(op);
|
||||
}
|
||||
|
||||
inline SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) {
|
||||
return static_cast<SkCanvas::PointMode>(mode);
|
||||
}
|
||||
|
||||
extern sk_sp<SkShader> ToSk(const DlColorSource* source);
|
||||
inline sk_sp<SkShader> ToSk(std::shared_ptr<const DlColorSource> source) {
|
||||
return ToSk(source.get());
|
||||
}
|
||||
inline sk_sp<SkShader> ToSk(const DlColorSource& source) {
|
||||
return ToSk(&source);
|
||||
}
|
||||
|
||||
extern sk_sp<SkImageFilter> ToSk(const DlImageFilter* filter);
|
||||
inline sk_sp<SkImageFilter> ToSk(std::shared_ptr<const DlImageFilter> filter) {
|
||||
return ToSk(filter.get());
|
||||
}
|
||||
inline sk_sp<SkImageFilter> ToSk(const DlImageFilter& filter) {
|
||||
return ToSk(&filter);
|
||||
}
|
||||
|
||||
extern sk_sp<SkColorFilter> ToSk(const DlColorFilter* filter);
|
||||
inline sk_sp<SkColorFilter> ToSk(std::shared_ptr<const DlColorFilter> filter) {
|
||||
return ToSk(filter.get());
|
||||
}
|
||||
inline sk_sp<SkColorFilter> ToSk(const DlColorFilter& filter) {
|
||||
return ToSk(&filter);
|
||||
}
|
||||
|
||||
extern sk_sp<SkMaskFilter> ToSk(const DlMaskFilter* filter);
|
||||
inline sk_sp<SkMaskFilter> ToSk(std::shared_ptr<const DlMaskFilter> filter) {
|
||||
return ToSk(filter.get());
|
||||
}
|
||||
inline sk_sp<SkMaskFilter> ToSk(const DlMaskFilter& filter) {
|
||||
return ToSk(&filter);
|
||||
}
|
||||
|
||||
extern sk_sp<SkPathEffect> ToSk(const DlPathEffect* effect);
|
||||
inline sk_sp<SkPathEffect> ToSk(std::shared_ptr<const DlPathEffect> effect) {
|
||||
return ToSk(effect.get());
|
||||
}
|
||||
inline sk_sp<SkPathEffect> ToSk(const DlPathEffect& effect) {
|
||||
return ToSk(&effect);
|
||||
}
|
||||
|
||||
extern sk_sp<SkVertices> ToSk(const DlVertices* vertices);
|
||||
inline sk_sp<SkVertices> ToSk(std::shared_ptr<const DlVertices> vertices) {
|
||||
return ToSk(vertices.get());
|
||||
}
|
||||
inline sk_sp<SkVertices> ToSk(const DlVertices& vertices) {
|
||||
return ToSk(&vertices);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_
|
||||
@ -0,0 +1,267 @@
|
||||
// Copyright 2013 The Flutter 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 "flutter/display_list/skia/dl_sk_conversions.h"
|
||||
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_paint.h"
|
||||
#include "flutter/display_list/display_list_sampling_options.h"
|
||||
#include "flutter/display_list/display_list_tile_mode.h"
|
||||
#include "flutter/display_list/display_list_vertices.h"
|
||||
#include "flutter/display_list/types.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "include/core/SkSamplingOptions.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
TEST(DisplayListImageFilter, LocalImageSkiaNull) {
|
||||
auto blur_filter =
|
||||
std::make_shared<DlBlurImageFilter>(0, 0, DlTileMode::kClamp);
|
||||
DlLocalMatrixImageFilter dl_local_matrix_filter(SkMatrix::RotateDeg(45),
|
||||
blur_filter);
|
||||
// With sigmas set to zero on the blur filter, Skia will return a null filter.
|
||||
// The local matrix filter should return nullptr instead of crashing.
|
||||
ASSERT_EQ(ToSk(dl_local_matrix_filter), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkTileMode) {
|
||||
ASSERT_EQ(ToSk(DlTileMode::kClamp), SkTileMode::kClamp);
|
||||
ASSERT_EQ(ToSk(DlTileMode::kRepeat), SkTileMode::kRepeat);
|
||||
ASSERT_EQ(ToSk(DlTileMode::kMirror), SkTileMode::kMirror);
|
||||
ASSERT_EQ(ToSk(DlTileMode::kDecal), SkTileMode::kDecal);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkDrawStyle) {
|
||||
ASSERT_EQ(ToSk(DlDrawStyle::kFill), SkPaint::Style::kFill_Style);
|
||||
ASSERT_EQ(ToSk(DlDrawStyle::kStroke), SkPaint::Style::kStroke_Style);
|
||||
ASSERT_EQ(ToSk(DlDrawStyle::kStrokeAndFill),
|
||||
SkPaint::Style::kStrokeAndFill_Style);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkStrokeCap) {
|
||||
ASSERT_EQ(ToSk(DlStrokeCap::kButt), SkPaint::Cap::kButt_Cap);
|
||||
ASSERT_EQ(ToSk(DlStrokeCap::kRound), SkPaint::Cap::kRound_Cap);
|
||||
ASSERT_EQ(ToSk(DlStrokeCap::kSquare), SkPaint::Cap::kSquare_Cap);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkStrokeJoin) {
|
||||
ASSERT_EQ(ToSk(DlStrokeJoin::kMiter), SkPaint::Join::kMiter_Join);
|
||||
ASSERT_EQ(ToSk(DlStrokeJoin::kRound), SkPaint::Join::kRound_Join);
|
||||
ASSERT_EQ(ToSk(DlStrokeJoin::kBevel), SkPaint::Join::kBevel_Join);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkVertexMode) {
|
||||
ASSERT_EQ(ToSk(DlVertexMode::kTriangles),
|
||||
SkVertices::VertexMode::kTriangles_VertexMode);
|
||||
ASSERT_EQ(ToSk(DlVertexMode::kTriangleStrip),
|
||||
SkVertices::VertexMode::kTriangleStrip_VertexMode);
|
||||
ASSERT_EQ(ToSk(DlVertexMode::kTriangleFan),
|
||||
SkVertices::VertexMode::kTriangleFan_VertexMode);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkFilterMode) {
|
||||
ASSERT_EQ(ToSk(DlFilterMode::kLinear), SkFilterMode::kLinear);
|
||||
ASSERT_EQ(ToSk(DlFilterMode::kNearest), SkFilterMode::kNearest);
|
||||
ASSERT_EQ(ToSk(DlFilterMode::kLast), SkFilterMode::kLast);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkSrcRectConstraint) {
|
||||
ASSERT_EQ(ToSk(DlCanvas::SrcRectConstraint::kFast),
|
||||
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint);
|
||||
ASSERT_EQ(ToSk(DlCanvas::SrcRectConstraint::kStrict),
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkSamplingOptions) {
|
||||
ASSERT_EQ(ToSk(DlImageSampling::kLinear),
|
||||
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone));
|
||||
ASSERT_EQ(ToSk(DlImageSampling::kMipmapLinear),
|
||||
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
|
||||
ASSERT_EQ(ToSk(DlImageSampling::kNearestNeighbor),
|
||||
SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone));
|
||||
ASSERT_EQ(ToSk(DlImageSampling::kCubic),
|
||||
SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f}));
|
||||
}
|
||||
|
||||
#define FOR_EACH_BLEND_MODE_ENUM(FUNC) \
|
||||
FUNC(kSrc) \
|
||||
FUNC(kClear) \
|
||||
FUNC(kSrc) \
|
||||
FUNC(kDst) \
|
||||
FUNC(kSrcOver) \
|
||||
FUNC(kDstOver) \
|
||||
FUNC(kSrcIn) \
|
||||
FUNC(kDstIn) \
|
||||
FUNC(kSrcOut) \
|
||||
FUNC(kDstOut) \
|
||||
FUNC(kSrcATop) \
|
||||
FUNC(kDstATop) \
|
||||
FUNC(kXor) \
|
||||
FUNC(kPlus) \
|
||||
FUNC(kModulate) \
|
||||
FUNC(kScreen) \
|
||||
FUNC(kOverlay) \
|
||||
FUNC(kDarken) \
|
||||
FUNC(kLighten) \
|
||||
FUNC(kColorDodge) \
|
||||
FUNC(kColorBurn) \
|
||||
FUNC(kHardLight) \
|
||||
FUNC(kSoftLight) \
|
||||
FUNC(kDifference) \
|
||||
FUNC(kExclusion) \
|
||||
FUNC(kMultiply) \
|
||||
FUNC(kHue) \
|
||||
FUNC(kSaturation) \
|
||||
FUNC(kColor) \
|
||||
FUNC(kLuminosity) \
|
||||
FUNC(kLastCoeffMode) \
|
||||
FUNC(kLastSeparableMode) \
|
||||
FUNC(kLastMode)
|
||||
|
||||
TEST(DisplayListSkConversions, ToSkBlendMode) {
|
||||
#define CHECK_TO_SKENUM(V) ASSERT_EQ(ToSk(DlBlendMode::V), SkBlendMode::V);
|
||||
FOR_EACH_BLEND_MODE_ENUM(CHECK_TO_SKENUM)
|
||||
#undef CHECK_TO_SKENUM
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, BlendColorFilterModifiesTransparency) {
|
||||
auto test_mode_color = [](DlBlendMode mode, DlColor color) {
|
||||
std::stringstream desc_str;
|
||||
desc_str << "blend[" << static_cast<int>(mode) << ", " << color << "]";
|
||||
std::string desc = desc_str.str();
|
||||
DlBlendColorFilter filter(color, mode);
|
||||
if (filter.modifies_transparent_black()) {
|
||||
auto dl_filter = DlBlendColorFilter::Make(color, mode);
|
||||
auto sk_filter = ToSk(filter);
|
||||
ASSERT_NE(dl_filter, nullptr) << desc;
|
||||
ASSERT_NE(sk_filter, nullptr) << desc;
|
||||
ASSERT_TRUE(sk_filter->filterColor(0) != 0) << desc;
|
||||
} else {
|
||||
auto dl_filter = DlBlendColorFilter::Make(color, mode);
|
||||
auto sk_filter = ToSk(filter);
|
||||
EXPECT_EQ(dl_filter == nullptr, sk_filter == nullptr) << desc;
|
||||
ASSERT_TRUE(sk_filter == nullptr || sk_filter->filterColor(0) == 0)
|
||||
<< desc;
|
||||
}
|
||||
};
|
||||
|
||||
auto test_mode = [&test_mode_color](DlBlendMode mode) {
|
||||
test_mode_color(mode, DlColor::kTransparent());
|
||||
test_mode_color(mode, DlColor::kWhite());
|
||||
test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5));
|
||||
test_mode_color(mode, DlColor::kBlack());
|
||||
test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5));
|
||||
};
|
||||
|
||||
#define TEST_MODE(V) test_mode(DlBlendMode::V);
|
||||
FOR_EACH_BLEND_MODE_ENUM(TEST_MODE)
|
||||
#undef TEST_MODE
|
||||
}
|
||||
|
||||
#undef FOR_EACH_BLEND_MODE_ENUM
|
||||
|
||||
TEST(DisplayListSkConversions, ConvertWithZeroAndNegativeVerticesAndIndices) {
|
||||
std::shared_ptr<const DlVertices> vertices1 = DlVertices::Make(
|
||||
DlVertexMode::kTriangles, 0, nullptr, nullptr, nullptr, 0, nullptr);
|
||||
EXPECT_NE(vertices1, nullptr);
|
||||
EXPECT_NE(ToSk(vertices1), nullptr);
|
||||
|
||||
std::shared_ptr<const DlVertices> vertices2 = DlVertices::Make(
|
||||
DlVertexMode::kTriangles, -1, nullptr, nullptr, nullptr, -1, nullptr);
|
||||
EXPECT_NE(vertices2, nullptr);
|
||||
EXPECT_NE(ToSk(vertices2), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListVertices, ConvertWithZeroAndNegativeVerticesAndIndices) {
|
||||
DlVertices::Builder builder1(DlVertexMode::kTriangles, 0,
|
||||
DlVertices::Builder::kNone, 0);
|
||||
EXPECT_TRUE(builder1.is_valid());
|
||||
std::shared_ptr<DlVertices> vertices1 = builder1.build();
|
||||
EXPECT_NE(vertices1, nullptr);
|
||||
EXPECT_NE(ToSk(vertices1), nullptr);
|
||||
|
||||
DlVertices::Builder builder2(DlVertexMode::kTriangles, -1,
|
||||
DlVertices::Builder::kNone, -1);
|
||||
EXPECT_TRUE(builder2.is_valid());
|
||||
std::shared_ptr<DlVertices> vertices2 = builder2.build();
|
||||
EXPECT_NE(vertices2, nullptr);
|
||||
EXPECT_NE(ToSk(vertices2), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListColorSource, ConvertRuntimeEffect) {
|
||||
const sk_sp<DlRuntimeEffect> kTestRuntimeEffect1 = DlRuntimeEffect::MakeSkia(
|
||||
SkRuntimeEffect::MakeForShader(
|
||||
SkString("vec4 main(vec2 p) { return vec4(0); }"))
|
||||
.effect);
|
||||
const sk_sp<DlRuntimeEffect> kTestRuntimeEffect2 = DlRuntimeEffect::MakeSkia(
|
||||
SkRuntimeEffect::MakeForShader(
|
||||
SkString("vec4 main(vec2 p) { return vec4(1); }"))
|
||||
.effect);
|
||||
std::shared_ptr<DlRuntimeEffectColorSource> source1 =
|
||||
DlColorSource::MakeRuntimeEffect(
|
||||
kTestRuntimeEffect1, {}, std::make_shared<std::vector<uint8_t>>());
|
||||
std::shared_ptr<DlRuntimeEffectColorSource> source2 =
|
||||
DlColorSource::MakeRuntimeEffect(
|
||||
kTestRuntimeEffect2, {}, std::make_shared<std::vector<uint8_t>>());
|
||||
std::shared_ptr<DlRuntimeEffectColorSource> source3 =
|
||||
DlColorSource::MakeRuntimeEffect(
|
||||
nullptr, {}, std::make_shared<std::vector<uint8_t>>());
|
||||
|
||||
ASSERT_NE(ToSk(source1), nullptr);
|
||||
ASSERT_NE(ToSk(source2), nullptr);
|
||||
ASSERT_EQ(ToSk(source3), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListColorSource, ConvertRuntimeEffectWithNullSampler) {
|
||||
const sk_sp<DlRuntimeEffect> kTestRuntimeEffect1 = DlRuntimeEffect::MakeSkia(
|
||||
SkRuntimeEffect::MakeForShader(
|
||||
SkString("vec4 main(vec2 p) { return vec4(0); }"))
|
||||
.effect);
|
||||
std::shared_ptr<DlRuntimeEffectColorSource> source1 =
|
||||
DlColorSource::MakeRuntimeEffect(
|
||||
kTestRuntimeEffect1, {nullptr},
|
||||
std::make_shared<std::vector<uint8_t>>());
|
||||
|
||||
ASSERT_EQ(ToSk(source1), nullptr);
|
||||
}
|
||||
|
||||
TEST(DisplayListSkConversions, MatrixColorFilterModifiesTransparency) {
|
||||
auto test_matrix = [](int element, SkScalar value) {
|
||||
// clang-format off
|
||||
float matrix[] = {
|
||||
1, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 0, 1, 0,
|
||||
};
|
||||
// clang-format on
|
||||
std::string desc =
|
||||
"matrix[" + std::to_string(element) + "] = " + std::to_string(value);
|
||||
matrix[element] = value;
|
||||
DlMatrixColorFilter filter(matrix);
|
||||
auto dl_filter = DlMatrixColorFilter::Make(matrix);
|
||||
auto sk_filter = ToSk(filter);
|
||||
EXPECT_EQ(dl_filter == nullptr, sk_filter == nullptr);
|
||||
EXPECT_EQ(filter.modifies_transparent_black(),
|
||||
sk_filter && sk_filter->filterColor(0) != 0);
|
||||
};
|
||||
|
||||
// Tests identity (matrix[0] already == 1 in an identity filter)
|
||||
test_matrix(0, 1);
|
||||
// test_matrix(19, 1);
|
||||
for (int i = 0; i < 20; i++) {
|
||||
test_matrix(i, -0.25);
|
||||
test_matrix(i, 0);
|
||||
test_matrix(i, 0.25);
|
||||
test_matrix(i, 1);
|
||||
test_matrix(i, 1.25);
|
||||
test_matrix(i, SK_ScalarNaN);
|
||||
test_matrix(i, SK_ScalarInfinity);
|
||||
test_matrix(i, -SK_ScalarInfinity);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
305
engine/src/flutter/display_list/skia/dl_sk_dispatcher.cc
Normal file
305
engine/src/flutter/display_list/skia/dl_sk_dispatcher.cc
Normal file
@ -0,0 +1,305 @@
|
||||
// Copyright 2013 The Flutter 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 "flutter/display_list/skia/dl_sk_dispatcher.h"
|
||||
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/skia/dl_sk_conversions.h"
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "third_party/skia/include/utils/SkShadowUtils.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
const SkPaint* DlSkCanvasDispatcher::safe_paint(bool use_attributes) {
|
||||
if (use_attributes) {
|
||||
// The accumulated SkPaint object will already have incorporated
|
||||
// any attribute overrides.
|
||||
return &paint();
|
||||
} else if (has_opacity()) {
|
||||
temp_paint_.setAlphaf(opacity());
|
||||
return &temp_paint_;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DlSkCanvasDispatcher::save() {
|
||||
canvas_->save();
|
||||
// save has no impact on attributes, but it needs to register a record
|
||||
// on the restore stack so that the eventual call to restore() will
|
||||
// know what to do at that time. We could annotate the restore record
|
||||
// with a flag that the record came from a save call, but it is simpler
|
||||
// to just pass in the current opacity value as the value to be used by
|
||||
// the children and let the utility calls notice that it didn't change.
|
||||
save_opacity(opacity());
|
||||
}
|
||||
void DlSkCanvasDispatcher::restore() {
|
||||
canvas_->restore();
|
||||
restore_opacity();
|
||||
}
|
||||
void DlSkCanvasDispatcher::saveLayer(const SkRect* bounds,
|
||||
const SaveLayerOptions options,
|
||||
const DlImageFilter* backdrop) {
|
||||
if (bounds == nullptr && options.can_distribute_opacity() &&
|
||||
backdrop == nullptr) {
|
||||
// We know that:
|
||||
// - no bounds is needed for clipping here
|
||||
// - no backdrop filter is used to initialize the layer
|
||||
// - the current attributes only have an alpha
|
||||
// - the children are compatible with individually rendering with
|
||||
// an inherited opacity
|
||||
// Therefore we can just use a save instead of a saveLayer and pass the
|
||||
// intended opacity to the children.
|
||||
canvas_->save();
|
||||
// If the saveLayer does not use attributes, the children should continue
|
||||
// to render with the inherited opacity unmodified. If attributes are to
|
||||
// be applied, the children should render with the combination of the
|
||||
// inherited opacity combined with the alpha from the current color.
|
||||
save_opacity(options.renders_with_attributes() ? combined_opacity()
|
||||
: opacity());
|
||||
} else {
|
||||
TRACE_EVENT0("flutter", "Canvas::saveLayer");
|
||||
const SkPaint* paint = safe_paint(options.renders_with_attributes());
|
||||
const sk_sp<SkImageFilter> sk_backdrop = ToSk(backdrop);
|
||||
canvas_->saveLayer(
|
||||
SkCanvas::SaveLayerRec(bounds, paint, sk_backdrop.get(), 0));
|
||||
// saveLayer will apply the current opacity on behalf of the children
|
||||
// so they will inherit an opaque opacity.
|
||||
save_opacity(SK_Scalar1);
|
||||
}
|
||||
}
|
||||
|
||||
void DlSkCanvasDispatcher::translate(SkScalar tx, SkScalar ty) {
|
||||
canvas_->translate(tx, ty);
|
||||
}
|
||||
void DlSkCanvasDispatcher::scale(SkScalar sx, SkScalar sy) {
|
||||
canvas_->scale(sx, sy);
|
||||
}
|
||||
void DlSkCanvasDispatcher::rotate(SkScalar degrees) {
|
||||
canvas_->rotate(degrees);
|
||||
}
|
||||
void DlSkCanvasDispatcher::skew(SkScalar sx, SkScalar sy) {
|
||||
canvas_->skew(sx, sy);
|
||||
}
|
||||
// clang-format off
|
||||
// 2x3 2D affine subset of a 4x4 transform in row major order
|
||||
void DlSkCanvasDispatcher::transform2DAffine(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myt) {
|
||||
// Internally concat(SkMatrix) gets redirected to concat(SkM44)
|
||||
// so we just jump directly to the SkM44 version
|
||||
canvas_->concat(SkM44(mxx, mxy, 0, mxt,
|
||||
myx, myy, 0, myt,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1));
|
||||
}
|
||||
// full 4x4 transform in row major order
|
||||
void DlSkCanvasDispatcher::transformFullPerspective(
|
||||
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
|
||||
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
|
||||
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
|
||||
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) {
|
||||
canvas_->concat(SkM44(mxx, mxy, mxz, mxt,
|
||||
myx, myy, myz, myt,
|
||||
mzx, mzy, mzz, mzt,
|
||||
mwx, mwy, mwz, mwt));
|
||||
}
|
||||
// clang-format on
|
||||
void DlSkCanvasDispatcher::transformReset() {
|
||||
canvas_->setMatrix(original_transform_);
|
||||
}
|
||||
|
||||
void DlSkCanvasDispatcher::clipRect(const SkRect& rect,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
canvas_->clipRect(rect, ToSk(clip_op), is_aa);
|
||||
}
|
||||
void DlSkCanvasDispatcher::clipRRect(const SkRRect& rrect,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
canvas_->clipRRect(rrect, ToSk(clip_op), is_aa);
|
||||
}
|
||||
void DlSkCanvasDispatcher::clipPath(const SkPath& path,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
canvas_->clipPath(path, ToSk(clip_op), is_aa);
|
||||
}
|
||||
|
||||
void DlSkCanvasDispatcher::drawPaint() {
|
||||
const SkPaint& sk_paint = paint();
|
||||
SkImageFilter* filter = sk_paint.getImageFilter();
|
||||
if (filter && !filter->asColorFilter(nullptr)) {
|
||||
// drawPaint does an implicit saveLayer if an SkImageFilter is
|
||||
// present that cannot be replaced by an SkColorFilter.
|
||||
TRACE_EVENT0("flutter", "Canvas::saveLayer");
|
||||
}
|
||||
canvas_->drawPaint(sk_paint);
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawColor(DlColor color, DlBlendMode mode) {
|
||||
// SkCanvas::drawColor(SkColor) does the following conversion anyway
|
||||
// We do it here manually to increase precision on applying opacity
|
||||
SkColor4f color4f = SkColor4f::FromColor(color);
|
||||
color4f.fA *= opacity();
|
||||
canvas_->drawColor(color4f, ToSk(mode));
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
|
||||
canvas_->drawLine(p0, p1, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawRect(const SkRect& rect) {
|
||||
canvas_->drawRect(rect, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawOval(const SkRect& bounds) {
|
||||
canvas_->drawOval(bounds, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawCircle(const SkPoint& center, SkScalar radius) {
|
||||
canvas_->drawCircle(center, radius, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawRRect(const SkRRect& rrect) {
|
||||
canvas_->drawRRect(rrect, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawDRRect(const SkRRect& outer,
|
||||
const SkRRect& inner) {
|
||||
canvas_->drawDRRect(outer, inner, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawPath(const SkPath& path) {
|
||||
canvas_->drawPath(path, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawArc(const SkRect& bounds,
|
||||
SkScalar start,
|
||||
SkScalar sweep,
|
||||
bool useCenter) {
|
||||
canvas_->drawArc(bounds, start, sweep, useCenter, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawPoints(PointMode mode,
|
||||
uint32_t count,
|
||||
const SkPoint pts[]) {
|
||||
canvas_->drawPoints(ToSk(mode), count, pts, paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawVertices(const DlVertices* vertices,
|
||||
DlBlendMode mode) {
|
||||
canvas_->drawVertices(ToSk(vertices), ToSk(mode), paint());
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawImage(const sk_sp<DlImage> image,
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes) {
|
||||
canvas_->drawImage(image ? image->skia_image() : nullptr, point.fX, point.fY,
|
||||
ToSk(sampling), safe_paint(render_with_attributes));
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawImageRect(const sk_sp<DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SrcRectConstraint constraint) {
|
||||
canvas_->drawImageRect(image ? image->skia_image() : nullptr, src, dst,
|
||||
ToSk(sampling), safe_paint(render_with_attributes),
|
||||
ToSk(constraint));
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawImageNine(const sk_sp<DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
DlFilterMode filter,
|
||||
bool render_with_attributes) {
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
auto skia_image = image->skia_image();
|
||||
if (!skia_image) {
|
||||
return;
|
||||
}
|
||||
canvas_->drawImageNine(skia_image.get(), center, dst, ToSk(filter),
|
||||
safe_paint(render_with_attributes));
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const SkRect tex[],
|
||||
const DlColor colors[],
|
||||
int count,
|
||||
DlBlendMode mode,
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cullRect,
|
||||
bool render_with_attributes) {
|
||||
if (!atlas) {
|
||||
return;
|
||||
}
|
||||
auto skia_atlas = atlas->skia_image();
|
||||
if (!skia_atlas) {
|
||||
return;
|
||||
}
|
||||
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors);
|
||||
canvas_->drawAtlas(skia_atlas.get(), xform, tex, sk_colors, count, ToSk(mode),
|
||||
ToSk(sampling), cullRect,
|
||||
safe_paint(render_with_attributes));
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawDisplayList(
|
||||
const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) {
|
||||
int restore_count;
|
||||
|
||||
// Compute combined opacity and figure out whether we can apply it
|
||||
// during dispatch or if we need a saveLayer.
|
||||
SkScalar combined_opacity = opacity * this->opacity();
|
||||
if (combined_opacity < SK_Scalar1 &&
|
||||
!display_list->can_apply_group_opacity()) {
|
||||
SkPaint save_paint;
|
||||
save_paint.setAlphaf(combined_opacity);
|
||||
restore_count = canvas_->saveLayer(display_list->bounds(), &save_paint);
|
||||
combined_opacity = SK_Scalar1;
|
||||
} else {
|
||||
restore_count = canvas_->save();
|
||||
}
|
||||
|
||||
// Create a new CanvasDispatcher to isolate the actions of the
|
||||
// display_list from the current environment.
|
||||
DlSkCanvasDispatcher dispatcher(canvas_, combined_opacity);
|
||||
if (display_list->rtree()) {
|
||||
display_list->Dispatch(dispatcher, canvas_->getLocalClipBounds());
|
||||
} else {
|
||||
display_list->Dispatch(dispatcher);
|
||||
}
|
||||
|
||||
// Restore canvas state to what it was before dispatching.
|
||||
canvas_->restoreToCount(restore_count);
|
||||
}
|
||||
void DlSkCanvasDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) {
|
||||
canvas_->drawTextBlob(blob, x, y, paint());
|
||||
}
|
||||
|
||||
void DlSkCanvasDispatcher::DrawShadow(SkCanvas* canvas,
|
||||
const SkPath& path,
|
||||
DlColor color,
|
||||
float elevation,
|
||||
bool transparentOccluder,
|
||||
SkScalar dpr) {
|
||||
const SkScalar kAmbientAlpha = 0.039f;
|
||||
const SkScalar kSpotAlpha = 0.25f;
|
||||
|
||||
uint32_t flags = transparentOccluder
|
||||
? SkShadowFlags::kTransparentOccluder_ShadowFlag
|
||||
: SkShadowFlags::kNone_ShadowFlag;
|
||||
flags |= SkShadowFlags::kDirectionalLight_ShadowFlag;
|
||||
SkColor in_ambient = SkColorSetA(color, kAmbientAlpha * SkColorGetA(color));
|
||||
SkColor in_spot = SkColorSetA(color, kSpotAlpha * SkColorGetA(color));
|
||||
SkColor ambient_color, spot_color;
|
||||
SkShadowUtils::ComputeTonalColors(in_ambient, in_spot, &ambient_color,
|
||||
&spot_color);
|
||||
SkShadowUtils::DrawShadow(
|
||||
canvas, path, SkPoint3::Make(0, 0, dpr * elevation),
|
||||
SkPoint3::Make(0, -1, 1),
|
||||
DlCanvas::kShadowLightRadius / DlCanvas::kShadowLightHeight,
|
||||
ambient_color, spot_color, flags);
|
||||
}
|
||||
|
||||
void DlSkCanvasDispatcher::drawShadow(const SkPath& path,
|
||||
const DlColor color,
|
||||
const SkScalar elevation,
|
||||
bool transparent_occluder,
|
||||
SkScalar dpr) {
|
||||
DrawShadow(canvas_, path, color, elevation, transparent_occluder, dpr);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@ -6,9 +6,8 @@
|
||||
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_CANVAS_DISPATCHER_H_
|
||||
|
||||
#include "flutter/display_list/display_list.h"
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_utils.h"
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
#include "flutter/display_list/skia/dl_sk_utils.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
|
||||
namespace flutter {
|
||||
@ -19,11 +18,10 @@ namespace flutter {
|
||||
///
|
||||
/// Receives all methods on Dispatcher and sends them to an SkCanvas
|
||||
///
|
||||
class DisplayListCanvasDispatcher : public virtual Dispatcher,
|
||||
public SkPaintDispatchHelper {
|
||||
class DlSkCanvasDispatcher : public virtual DlOpReceiver,
|
||||
public SkPaintDispatchHelper {
|
||||
public:
|
||||
explicit DisplayListCanvasDispatcher(SkCanvas* canvas,
|
||||
SkScalar opacity = SK_Scalar1)
|
||||
explicit DlSkCanvasDispatcher(SkCanvas* canvas, SkScalar opacity = SK_Scalar1)
|
||||
: SkPaintDispatchHelper(opacity),
|
||||
canvas_(canvas),
|
||||
original_transform_(canvas->getLocalToDevice()) {}
|
||||
@ -81,7 +79,7 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) override;
|
||||
SrcRectConstraint constraint) override;
|
||||
void drawImageNine(const sk_sp<DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
@ -96,7 +94,8 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cullRect,
|
||||
bool render_with_attributes) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) override;
|
||||
void drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) override;
|
||||
@ -106,11 +105,6 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
|
||||
bool transparent_occluder,
|
||||
SkScalar dpr) override;
|
||||
|
||||
static SkRect ComputeShadowBounds(const SkPath& path,
|
||||
float elevation,
|
||||
SkScalar dpr,
|
||||
const SkMatrix& ctm);
|
||||
|
||||
static void DrawShadow(SkCanvas* canvas,
|
||||
const SkPath& path,
|
||||
DlColor color,
|
||||
102
engine/src/flutter/display_list/skia/dl_sk_utils.cc
Normal file
102
engine/src/flutter/display_list/skia/dl_sk_utils.cc
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright 2013 The Flutter 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 "flutter/display_list/skia/dl_sk_utils.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/skia/dl_sk_conversions.h"
|
||||
#include "flutter/fml/logging.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// clang-format off
|
||||
constexpr float kInvertColorMatrix[20] = {
|
||||
-1.0, 0, 0, 1.0, 0,
|
||||
0, -1.0, 0, 1.0, 0,
|
||||
0, 0, -1.0, 1.0, 0,
|
||||
1.0, 1.0, 1.0, 1.0, 0
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void SkPaintDispatchHelper::save_opacity(SkScalar child_opacity) {
|
||||
save_stack_.emplace_back(opacity_);
|
||||
set_opacity(child_opacity);
|
||||
}
|
||||
void SkPaintDispatchHelper::restore_opacity() {
|
||||
if (save_stack_.empty()) {
|
||||
return;
|
||||
}
|
||||
set_opacity(save_stack_.back().opacity);
|
||||
save_stack_.pop_back();
|
||||
}
|
||||
|
||||
void SkPaintDispatchHelper::setAntiAlias(bool aa) {
|
||||
paint_.setAntiAlias(aa);
|
||||
}
|
||||
void SkPaintDispatchHelper::setDither(bool dither) {
|
||||
paint_.setDither(dither);
|
||||
}
|
||||
void SkPaintDispatchHelper::setInvertColors(bool invert) {
|
||||
invert_colors_ = invert;
|
||||
paint_.setColorFilter(makeColorFilter());
|
||||
}
|
||||
void SkPaintDispatchHelper::setStrokeCap(DlStrokeCap cap) {
|
||||
paint_.setStrokeCap(ToSk(cap));
|
||||
}
|
||||
void SkPaintDispatchHelper::setStrokeJoin(DlStrokeJoin join) {
|
||||
paint_.setStrokeJoin(ToSk(join));
|
||||
}
|
||||
void SkPaintDispatchHelper::setStyle(DlDrawStyle style) {
|
||||
paint_.setStyle(ToSk(style));
|
||||
}
|
||||
void SkPaintDispatchHelper::setStrokeWidth(SkScalar width) {
|
||||
paint_.setStrokeWidth(width);
|
||||
}
|
||||
void SkPaintDispatchHelper::setStrokeMiter(SkScalar limit) {
|
||||
paint_.setStrokeMiter(limit);
|
||||
}
|
||||
void SkPaintDispatchHelper::setColor(DlColor color) {
|
||||
current_color_ = color;
|
||||
paint_.setColor(color);
|
||||
if (has_opacity()) {
|
||||
paint_.setAlphaf(paint_.getAlphaf() * opacity());
|
||||
}
|
||||
}
|
||||
void SkPaintDispatchHelper::setBlendMode(DlBlendMode mode) {
|
||||
paint_.setBlendMode(ToSk(mode));
|
||||
}
|
||||
void SkPaintDispatchHelper::setColorSource(const DlColorSource* source) {
|
||||
paint_.setShader(ToSk(source));
|
||||
}
|
||||
void SkPaintDispatchHelper::setImageFilter(const DlImageFilter* filter) {
|
||||
paint_.setImageFilter(ToSk(filter));
|
||||
}
|
||||
void SkPaintDispatchHelper::setColorFilter(const DlColorFilter* filter) {
|
||||
sk_color_filter_ = ToSk(filter);
|
||||
paint_.setColorFilter(makeColorFilter());
|
||||
}
|
||||
void SkPaintDispatchHelper::setPathEffect(const DlPathEffect* effect) {
|
||||
paint_.setPathEffect(ToSk(effect));
|
||||
}
|
||||
void SkPaintDispatchHelper::setMaskFilter(const DlMaskFilter* filter) {
|
||||
paint_.setMaskFilter(ToSk(filter));
|
||||
}
|
||||
|
||||
sk_sp<SkColorFilter> SkPaintDispatchHelper::makeColorFilter() const {
|
||||
if (!invert_colors_) {
|
||||
return sk_color_filter_;
|
||||
}
|
||||
sk_sp<SkColorFilter> invert_filter =
|
||||
SkColorFilters::Matrix(kInvertColorMatrix);
|
||||
if (sk_color_filter_) {
|
||||
invert_filter = invert_filter->makeComposed(sk_color_filter_);
|
||||
}
|
||||
return invert_filter;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
85
engine/src/flutter/display_list/skia/dl_sk_utils.h
Normal file
85
engine/src/flutter/display_list/skia/dl_sk_utils.h
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright 2013 The Flutter 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 FLUTTER_DISPLAY_LIST_SKIA_DL_SK_UTILS_H_
|
||||
#define FLUTTER_DISPLAY_LIST_SKIA_DL_SK_UTILS_H_
|
||||
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// A utility class that will monitor the DlOpReceiver methods relating
|
||||
// to the rendering attributes and accumulate them into an SkPaint
|
||||
// which can be accessed at any time via paint().
|
||||
class SkPaintDispatchHelper : public virtual DlOpReceiver {
|
||||
public:
|
||||
SkPaintDispatchHelper(SkScalar opacity = SK_Scalar1)
|
||||
: current_color_(SK_ColorBLACK), opacity_(opacity) {
|
||||
if (opacity < SK_Scalar1) {
|
||||
paint_.setAlphaf(opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void setAntiAlias(bool aa) override;
|
||||
void setDither(bool dither) override;
|
||||
void setStyle(DlDrawStyle style) override;
|
||||
void setColor(DlColor color) override;
|
||||
void setStrokeWidth(SkScalar width) override;
|
||||
void setStrokeMiter(SkScalar limit) override;
|
||||
void setStrokeCap(DlStrokeCap cap) override;
|
||||
void setStrokeJoin(DlStrokeJoin join) override;
|
||||
void setColorSource(const DlColorSource* source) override;
|
||||
void setColorFilter(const DlColorFilter* filter) override;
|
||||
void setInvertColors(bool invert) override;
|
||||
void setBlendMode(DlBlendMode mode) override;
|
||||
void setPathEffect(const DlPathEffect* effect) override;
|
||||
void setMaskFilter(const DlMaskFilter* filter) override;
|
||||
void setImageFilter(const DlImageFilter* filter) override;
|
||||
|
||||
const SkPaint& paint() { return paint_; }
|
||||
|
||||
/// Returns the current opacity attribute which is used to reduce
|
||||
/// the alpha of all setColor calls encountered in the streeam
|
||||
SkScalar opacity() { return opacity_; }
|
||||
/// Returns the combined opacity that includes both the current
|
||||
/// opacity attribute and the alpha of the most recent color.
|
||||
/// The most recently set color will have combined the two and
|
||||
/// stored the combined value in the alpha of the paint.
|
||||
SkScalar combined_opacity() { return paint_.getAlphaf(); }
|
||||
/// Returns true iff the current opacity attribute is not opaque,
|
||||
/// irrespective of the alpha of the current color
|
||||
bool has_opacity() { return opacity_ < SK_Scalar1; }
|
||||
|
||||
protected:
|
||||
void save_opacity(SkScalar opacity_for_children);
|
||||
void restore_opacity();
|
||||
|
||||
private:
|
||||
SkPaint paint_;
|
||||
bool invert_colors_ = false;
|
||||
sk_sp<SkColorFilter> sk_color_filter_;
|
||||
|
||||
sk_sp<SkColorFilter> makeColorFilter() const;
|
||||
|
||||
struct SaveInfo {
|
||||
SaveInfo(SkScalar opacity) : opacity(opacity) {}
|
||||
|
||||
SkScalar opacity;
|
||||
};
|
||||
std::vector<SaveInfo> save_stack_;
|
||||
|
||||
void set_opacity(SkScalar opacity) {
|
||||
if (opacity_ != opacity) {
|
||||
opacity_ = opacity;
|
||||
setColor(current_color_);
|
||||
}
|
||||
}
|
||||
|
||||
SkColor current_color_;
|
||||
SkScalar opacity_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_DISPLAY_LIST_SKIA_DL_SK_UTILS_H_
|
||||
@ -3,12 +3,13 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/display_list/display_list_utils.h"
|
||||
#include "flutter/display_list/skia/dl_sk_utils.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
class MockDispatchHelper final : public virtual Dispatcher,
|
||||
class MockDispatchHelper final : public virtual DlOpReceiver,
|
||||
public SkPaintDispatchHelper,
|
||||
public IgnoreClipDispatchHelper,
|
||||
public IgnoreTransformDispatchHelper,
|
||||
File diff suppressed because it is too large
Load Diff
@ -20,7 +20,7 @@ sk_sp<DisplayList> GetSampleDisplayList();
|
||||
sk_sp<DisplayList> GetSampleDisplayList(int ops);
|
||||
sk_sp<DisplayList> GetSampleNestedDisplayList();
|
||||
|
||||
typedef const std::function<void(DisplayListBuilder&)> DlInvoker;
|
||||
typedef const std::function<void(DlOpReceiver&)> DlInvoker;
|
||||
|
||||
constexpr SkPoint kEndPoints[] = {
|
||||
{0, 0},
|
||||
@ -214,8 +214,7 @@ static std::shared_ptr<const DlVertices> TestVertices2 =
|
||||
|
||||
static sk_sp<DisplayList> MakeTestDisplayList(int w, int h, SkColor color) {
|
||||
DisplayListBuilder builder;
|
||||
builder.setColor(color);
|
||||
builder.drawRect(SkRect::MakeWH(w, h));
|
||||
builder.DrawRect(SkRect::MakeWH(w, h), DlPaint(color));
|
||||
return builder.Build();
|
||||
}
|
||||
static sk_sp<DisplayList> TestDisplayList1 =
|
||||
@ -271,13 +270,13 @@ struct DisplayListInvocation {
|
||||
// through an SkCanvas interface, comparable to |DisplayList.byte_count().
|
||||
size_t sk_byte_count() { return sizeof(DisplayList) + sk_byte_count_; }
|
||||
|
||||
void Invoke(DisplayListBuilder& builder) { invoker(builder); }
|
||||
void Invoke(DlOpReceiver& builder) { invoker(builder); }
|
||||
|
||||
sk_sp<DisplayList> Build() {
|
||||
DisplayListBuilder builder;
|
||||
invoker(builder);
|
||||
return builder.Build();
|
||||
}
|
||||
// sk_sp<DisplayList> Build() {
|
||||
// DisplayListBuilder builder;
|
||||
// invoker(builder.asReceiver());
|
||||
// return builder.Build();
|
||||
// }
|
||||
};
|
||||
|
||||
struct DisplayListInvocationGroup {
|
||||
|
||||
@ -28,5 +28,4 @@
|
||||
#include "third_party/skia/include/effects/SkDashPathEffect.h"
|
||||
#include "third_party/skia/include/effects/SkDiscretePathEffect.h"
|
||||
#include "third_party/skia/include/gpu/GrTypes.h"
|
||||
#include "third_party/skia/include/utils/SkShadowUtils.h"
|
||||
#endif // FLUTTER_DISPLAY_LIST_TYPES_H_
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/display_list/display_list_canvas_dispatcher.h"
|
||||
#include "flutter/flow/layers/clip_path_layer.h"
|
||||
#include "flutter/flow/layers/clip_rect_layer.h"
|
||||
#include "flutter/flow/layers/clip_rrect_layer.h"
|
||||
@ -235,8 +234,8 @@ TEST_F(CheckerBoardLayerTest, PhysicalSaveLayerCheckBoard) {
|
||||
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
|
||||
// their shadows , so we do not do any painting there.
|
||||
EXPECT_EQ(layer->paint_bounds(),
|
||||
DisplayListCanvasDispatcher::ComputeShadowBounds(
|
||||
layer_path, initial_elevation, 1.0f, SkMatrix()));
|
||||
DlCanvas::ComputeShadowBounds(layer_path, initial_elevation, 1.0f,
|
||||
SkMatrix()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(layer->elevation(), initial_elevation);
|
||||
|
||||
|
||||
@ -424,7 +424,7 @@ TEST_F(ClipPathLayerTest, OpacityInheritancePainting) {
|
||||
{
|
||||
expected_builder.Translate(offset.fX, offset.fY);
|
||||
/* ClipRectLayer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
expected_builder.ClipPath(layer_clip, ClipOp::kIntersect, true);
|
||||
/* child layer1 paint */ {
|
||||
expected_builder.DrawPath(path1, DlPaint().setAlpha(opacity_alpha));
|
||||
@ -472,25 +472,24 @@ TEST_F(ClipPathLayerTest, OpacityInheritanceSaveLayerPainting) {
|
||||
|
||||
DisplayListBuilder expected_builder;
|
||||
/* OpacityLayer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(offset.fX, offset.fY);
|
||||
expected_builder.Translate(offset.fX, offset.fY);
|
||||
/* ClipRectLayer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.clipPath(layer_clip, ClipOp::kIntersect, true);
|
||||
expected_builder.setColor(opacity_alpha << 24);
|
||||
expected_builder.saveLayer(&children_bounds, true);
|
||||
expected_builder.Save();
|
||||
expected_builder.ClipPath(layer_clip, ClipOp::kIntersect, true);
|
||||
expected_builder.SaveLayer(&children_bounds,
|
||||
&DlPaint().setAlpha(opacity_alpha));
|
||||
/* child layer1 paint */ {
|
||||
expected_builder.setColor(0xFF000000);
|
||||
expected_builder.drawPath(path1);
|
||||
expected_builder.DrawPath(path1, DlPaint());
|
||||
}
|
||||
/* child layer2 paint */ { //
|
||||
expected_builder.drawPath(path2);
|
||||
expected_builder.DrawPath(path2, DlPaint());
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
|
||||
opacity_layer->Paint(display_list_paint_context());
|
||||
|
||||
@ -454,25 +454,24 @@ TEST_F(ClipRectLayerTest, OpacityInheritanceSaveLayerPainting) {
|
||||
|
||||
DisplayListBuilder expected_builder;
|
||||
/* OpacityLayer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(offset.fX, offset.fY);
|
||||
expected_builder.Translate(offset.fX, offset.fY);
|
||||
/* ClipRectLayer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.clipRect(clip_rect, ClipOp::kIntersect, true);
|
||||
expected_builder.setColor(opacity_alpha << 24);
|
||||
expected_builder.saveLayer(&children_bounds, true);
|
||||
expected_builder.Save();
|
||||
expected_builder.ClipRect(clip_rect, ClipOp::kIntersect, true);
|
||||
expected_builder.SaveLayer(&children_bounds,
|
||||
&DlPaint().setAlpha(opacity_alpha));
|
||||
/* child layer1 paint */ {
|
||||
expected_builder.setColor(0xFF000000);
|
||||
expected_builder.drawPath(path1);
|
||||
expected_builder.DrawPath(path1, DlPaint());
|
||||
}
|
||||
/* child layer2 paint */ { //
|
||||
expected_builder.drawPath(path2);
|
||||
expected_builder.DrawPath(path2, DlPaint());
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
|
||||
opacity_layer->Paint(display_list_paint_context());
|
||||
|
||||
@ -467,25 +467,24 @@ TEST_F(ClipRRectLayerTest, OpacityInheritanceSaveLayerPainting) {
|
||||
|
||||
DisplayListBuilder expected_builder;
|
||||
/* OpacityLayer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(offset.fX, offset.fY);
|
||||
expected_builder.Translate(offset.fX, offset.fY);
|
||||
/* ClipRectLayer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.clipRRect(clip_rrect, ClipOp::kIntersect, true);
|
||||
expected_builder.setColor(opacity_alpha << 24);
|
||||
expected_builder.saveLayer(&children_bounds, true);
|
||||
expected_builder.Save();
|
||||
expected_builder.ClipRRect(clip_rrect, ClipOp::kIntersect, true);
|
||||
expected_builder.SaveLayer(&children_bounds,
|
||||
&DlPaint().setAlpha(opacity_alpha));
|
||||
/* child layer1 paint */ {
|
||||
expected_builder.setColor(0xFF000000);
|
||||
expected_builder.drawPath(path1);
|
||||
expected_builder.DrawPath(path1, DlPaint());
|
||||
}
|
||||
/* child layer2 paint */ { //
|
||||
expected_builder.drawPath(path2);
|
||||
expected_builder.DrawPath(path2, DlPaint());
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
|
||||
opacity_layer->Paint(display_list_paint_context());
|
||||
|
||||
@ -32,7 +32,7 @@ TEST_F(DisplayListLayerTest, PaintBeforePrerollDies) {
|
||||
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
|
||||
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture_bounds);
|
||||
builder.DrawRect(picture_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject<DisplayList>(display_list, unref_queue()),
|
||||
@ -47,7 +47,7 @@ TEST_F(DisplayListLayerTest, PaintingEmptyLayerDies) {
|
||||
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
|
||||
const SkRect picture_bounds = SkRect::MakeEmpty();
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture_bounds);
|
||||
builder.DrawRect(picture_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject<DisplayList>(display_list, unref_queue()),
|
||||
@ -77,7 +77,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayList) {
|
||||
SkMatrix::Translate(layer_offset.fX, layer_offset.fY);
|
||||
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture_bounds);
|
||||
builder.DrawRect(picture_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
|
||||
@ -102,7 +102,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayList) {
|
||||
TEST_F(DisplayListLayerTest, CachingDoesNotChangeCullRect) {
|
||||
const SkPoint layer_offset = SkPoint::Make(10, 10);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect({10, 10, 20, 20});
|
||||
builder.DrawRect({10, 10, 20, 20}, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false);
|
||||
@ -118,7 +118,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) {
|
||||
const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f);
|
||||
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture_bounds);
|
||||
builder.DrawRect(picture_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto display_list_layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
|
||||
@ -130,6 +130,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) {
|
||||
LayerStateStack::kCallerCanApplyOpacity);
|
||||
|
||||
int opacity_alpha = 0x7F;
|
||||
SkScalar opacity = opacity_alpha / 255.0;
|
||||
SkPoint opacity_offset = SkPoint::Make(10, 10);
|
||||
auto opacity_layer =
|
||||
std::make_shared<OpacityLayer>(opacity_alpha, opacity_offset);
|
||||
@ -138,30 +139,24 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) {
|
||||
EXPECT_TRUE(opacity_layer->children_can_accept_opacity());
|
||||
|
||||
DisplayListBuilder child_builder;
|
||||
child_builder.drawRect(picture_bounds);
|
||||
child_builder.DrawRect(picture_bounds, DlPaint());
|
||||
auto child_display_list = child_builder.Build();
|
||||
|
||||
DisplayListBuilder expected_builder;
|
||||
/* opacity_layer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(opacity_offset.fX, opacity_offset.fY);
|
||||
expected_builder.Translate(opacity_offset.fX, opacity_offset.fY);
|
||||
/* display_list_layer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(layer_offset.fX, layer_offset.fY);
|
||||
expected_builder.setColor(opacity_alpha << 24);
|
||||
expected_builder.saveLayer(&picture_bounds, true);
|
||||
/* display_list contents */ { //
|
||||
expected_builder.drawDisplayList(child_display_list);
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.setColor(DlColor::kBlack());
|
||||
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
|
||||
expected_builder.DrawDisplayList(child_display_list, opacity);
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
|
||||
opacity_layer->Paint(display_list_paint_context());
|
||||
@ -174,8 +169,8 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) {
|
||||
const SkRect picture1_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
const SkRect picture2_bounds = SkRect::MakeLTRB(10.0f, 15.0f, 30.0f, 35.0f);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture1_bounds);
|
||||
builder.drawRect(picture2_bounds);
|
||||
builder.DrawRect(picture1_bounds, DlPaint());
|
||||
builder.DrawRect(picture2_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto display_list_layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
|
||||
@ -194,8 +189,8 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) {
|
||||
EXPECT_FALSE(opacity_layer->children_can_accept_opacity());
|
||||
|
||||
DisplayListBuilder child_builder;
|
||||
child_builder.drawRect(picture1_bounds);
|
||||
child_builder.drawRect(picture2_bounds);
|
||||
child_builder.DrawRect(picture1_bounds, DlPaint());
|
||||
child_builder.DrawRect(picture2_bounds, DlPaint());
|
||||
auto child_display_list = child_builder.Build();
|
||||
|
||||
auto display_list_bounds = picture1_bounds;
|
||||
@ -204,24 +199,24 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) {
|
||||
display_list_bounds.makeOffset(layer_offset.fX, layer_offset.fY);
|
||||
DisplayListBuilder expected_builder;
|
||||
/* opacity_layer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(opacity_offset.fX, opacity_offset.fY);
|
||||
expected_builder.setColor(opacity_alpha << 24);
|
||||
expected_builder.saveLayer(&save_layer_bounds, true);
|
||||
expected_builder.Translate(opacity_offset.fX, opacity_offset.fY);
|
||||
expected_builder.SaveLayer(&save_layer_bounds,
|
||||
&DlPaint().setAlpha(opacity_alpha));
|
||||
{
|
||||
/* display_list_layer::Paint() */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(layer_offset.fX, layer_offset.fY);
|
||||
expected_builder.drawDisplayList(child_display_list);
|
||||
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
|
||||
expected_builder.DrawDisplayList(child_display_list);
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
|
||||
opacity_layer->Paint(display_list_paint_context());
|
||||
@ -234,8 +229,8 @@ TEST_F(DisplayListLayerTest, CachedIncompatibleDisplayListOpacityInheritance) {
|
||||
const SkRect picture1_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
const SkRect picture2_bounds = SkRect::MakeLTRB(10.0f, 15.0f, 30.0f, 35.0f);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture1_bounds);
|
||||
builder.drawRect(picture2_bounds);
|
||||
builder.DrawRect(picture1_bounds, DlPaint());
|
||||
builder.DrawRect(picture2_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto display_list_layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false);
|
||||
@ -386,7 +381,7 @@ TEST_F(DisplayListLayerTest, LayerTreeSnapshotsWhenEnabled) {
|
||||
const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f);
|
||||
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture_bounds);
|
||||
builder.DrawRect(picture_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
|
||||
@ -405,7 +400,7 @@ TEST_F(DisplayListLayerTest, NoLayerTreeSnapshotsWhenDisabledByDefault) {
|
||||
const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f);
|
||||
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture_bounds);
|
||||
builder.DrawRect(picture_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
|
||||
@ -423,7 +418,7 @@ TEST_F(DisplayListLayerTest, DisplayListAccessCountDependsOnVisibility) {
|
||||
const SkRect missed_cull_rect = SkRect::MakeLTRB(100, 100, 200, 200);
|
||||
const SkRect hit_cull_rect = SkRect::MakeLTRB(0, 0, 200, 200);
|
||||
DisplayListBuilder builder;
|
||||
builder.drawRect(picture_bounds);
|
||||
builder.DrawRect(picture_bounds, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
auto layer = std::make_shared<DisplayListLayer>(
|
||||
layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false);
|
||||
@ -524,8 +519,8 @@ TEST_F(DisplayListLayerTest, OverflowCachedDisplayListOpacityInheritance) {
|
||||
std::shared_ptr<DisplayListLayer> layers[layer_count];
|
||||
for (int i = 0; i < layer_count; i++) {
|
||||
DisplayListBuilder builder(false);
|
||||
builder.drawRect({0, 0, 100, 100});
|
||||
builder.drawRect({50, 50, 100, 100});
|
||||
builder.DrawRect({0, 0, 100, 100}, DlPaint());
|
||||
builder.DrawRect({50, 50, 100, 100}, DlPaint());
|
||||
auto display_list = builder.Build();
|
||||
ASSERT_FALSE(display_list->can_apply_group_opacity());
|
||||
SkPoint offset = {i * 200.0f, 0};
|
||||
|
||||
@ -248,7 +248,7 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) {
|
||||
}
|
||||
}
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
auto expected_display_list = expected_builder.Build();
|
||||
|
||||
layer->Paint(display_list_paint_context());
|
||||
|
||||
@ -606,24 +606,23 @@ TEST_F(OpacityLayerTest, OpacityInheritanceNestedWithIncompatibleChild) {
|
||||
|
||||
DisplayListBuilder expected_builder;
|
||||
/* opacity_layer_1::Paint */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(offset1.fX, offset1.fY);
|
||||
expected_builder.Translate(offset1.fX, offset1.fY);
|
||||
/* opacity_layer_2::Paint */ {
|
||||
expected_builder.save();
|
||||
expected_builder.Save();
|
||||
{
|
||||
expected_builder.translate(offset2.fX, offset2.fY);
|
||||
expected_builder.setColor(savelayer_paint.getAlpha() << 24);
|
||||
expected_builder.saveLayer(&mock_layer->paint_bounds(), true);
|
||||
expected_builder.Translate(offset2.fX, offset2.fY);
|
||||
expected_builder.SaveLayer(&mock_layer->paint_bounds(),
|
||||
&savelayer_paint);
|
||||
/* mock_layer::Paint */ {
|
||||
expected_builder.setColor(0xFF000000);
|
||||
expected_builder.drawPath(mock_path);
|
||||
expected_builder.DrawPath(mock_path, DlPaint());
|
||||
}
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
}
|
||||
expected_builder.restore();
|
||||
expected_builder.Restore();
|
||||
}
|
||||
|
||||
opacity_layer_1->Paint(display_list_paint_context());
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
#include "flutter/flow/layers/physical_shape_layer.h"
|
||||
|
||||
#include "flutter/display_list/display_list_canvas_dispatcher.h"
|
||||
#include "flutter/flow/paint_utils.h"
|
||||
|
||||
namespace flutter {
|
||||
@ -36,9 +35,9 @@ void PhysicalShapeLayer::Diff(DiffContext* context, const Layer* old_layer) {
|
||||
if (elevation_ == 0) {
|
||||
bounds = path_.getBounds();
|
||||
} else {
|
||||
bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
|
||||
path_, elevation_, context->frame_device_pixel_ratio(),
|
||||
context->GetTransform3x3());
|
||||
bounds = DlCanvas::ComputeShadowBounds(path_, elevation_,
|
||||
context->frame_device_pixel_ratio(),
|
||||
context->GetTransform3x3());
|
||||
}
|
||||
|
||||
context->AddLayerBounds(bounds);
|
||||
@ -65,7 +64,7 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context) {
|
||||
} else {
|
||||
// We will draw the shadow in Paint(), so add some margin to the paint
|
||||
// bounds to leave space for the shadow.
|
||||
paint_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
|
||||
paint_bounds = DlCanvas::ComputeShadowBounds(
|
||||
path_, elevation_, context->frame_device_pixel_ratio,
|
||||
context->state_stack.transform_3x3());
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
#include "flutter/flow/layers/physical_shape_layer.h"
|
||||
|
||||
#include "flutter/display_list/display_list_canvas_dispatcher.h"
|
||||
#include "flutter/flow/testing/diff_context_test.h"
|
||||
#include "flutter/flow/testing/layer_test.h"
|
||||
#include "flutter/flow/testing/mock_layer.h"
|
||||
@ -214,8 +213,8 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) {
|
||||
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
|
||||
// their shadows , so we do not do any painting there.
|
||||
EXPECT_EQ(layer->paint_bounds(),
|
||||
DisplayListCanvasDispatcher::ComputeShadowBounds(
|
||||
layer_path, initial_elevation, 1.0f, SkMatrix()));
|
||||
DlCanvas::ComputeShadowBounds(layer_path, initial_elevation, 1.0f,
|
||||
SkMatrix()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(layer->elevation(), initial_elevation);
|
||||
|
||||
@ -264,7 +263,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
|
||||
// On Fuchsia, the system compositor handles all elevated
|
||||
// PhysicalShapeLayers and their shadows , so we do not do any painting
|
||||
// there.
|
||||
SkRect paint_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
|
||||
SkRect paint_bounds = DlCanvas::ComputeShadowBounds(
|
||||
layer_path, initial_elevations[i], 1.0f /* pixel_ratio */, SkMatrix());
|
||||
|
||||
// Without clipping the children will be painted as well
|
||||
@ -313,15 +312,15 @@ TEST_F(PhysicalShapeLayerTest, ShadowNotDependsCtm) {
|
||||
path.addRect(0, 0, 8, 8).close();
|
||||
|
||||
for (SkScalar elevation : elevations) {
|
||||
SkRect baseline_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
|
||||
path, elevation, 1.0f, SkMatrix());
|
||||
SkRect baseline_bounds =
|
||||
DlCanvas::ComputeShadowBounds(path, elevation, 1.0f, SkMatrix());
|
||||
for (SkScalar scale : scales) {
|
||||
for (SkScalar translate_x : translates) {
|
||||
for (SkScalar translate_y : translates) {
|
||||
SkMatrix ctm;
|
||||
ctm.setScaleTranslate(scale, scale, translate_x, translate_y);
|
||||
SkRect bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
|
||||
path, elevation, scale, ctm);
|
||||
SkRect bounds =
|
||||
DlCanvas::ComputeShadowBounds(path, elevation, scale, ctm);
|
||||
EXPECT_FLOAT_EQ(bounds.fLeft, baseline_bounds.fLeft);
|
||||
EXPECT_FLOAT_EQ(bounds.fTop, baseline_bounds.fTop);
|
||||
EXPECT_FLOAT_EQ(bounds.fRight, baseline_bounds.fRight);
|
||||
@ -377,14 +376,14 @@ TEST_F(PhysicalShapeLayerTest, ShadowNotDependsPathSize) {
|
||||
[=](SkCanvas* canvas) {
|
||||
SkPath path;
|
||||
path.addRect(test_case[0]).close();
|
||||
DisplayListCanvasDispatcher::DrawShadow(
|
||||
canvas, path, DlColor::kBlack(), 1.0f, false, 1.0f);
|
||||
DlSkCanvasAdapter(canvas).DrawShadow(
|
||||
path, DlColor::kBlack(), 1.0f, false, 1.0f);
|
||||
},
|
||||
[=](SkCanvas* canvas) {
|
||||
SkPath path;
|
||||
path.addRect(test_case[1]).close();
|
||||
DisplayListCanvasDispatcher::DrawShadow(
|
||||
canvas, path, DlColor::kBlack(), 1.0f, false, 1.0f);
|
||||
DlSkCanvasAdapter(canvas).DrawShadow(
|
||||
path, DlColor::kBlack(), 1.0f, false, 1.0f);
|
||||
},
|
||||
SkSize::Make(100, 100)),
|
||||
0);
|
||||
|
||||
@ -383,7 +383,7 @@ TEST_F(ShaderMaskLayerTest, OpacityInheritance) {
|
||||
/* child layer paint */ {
|
||||
expected_builder.DrawPath(child_path, DlPaint());
|
||||
}
|
||||
expected_builder.translate(mask_rect.fLeft, mask_rect.fTop);
|
||||
expected_builder.Translate(mask_rect.fLeft, mask_rect.fTop);
|
||||
expected_builder.DrawRect(
|
||||
SkRect::MakeWH(mask_rect.width(), mask_rect.height()),
|
||||
DlPaint().setBlendMode(DlBlendMode::kSrc));
|
||||
|
||||
@ -449,8 +449,7 @@ TEST(RasterCache, DeviceRectRoundOutForDisplayList) {
|
||||
|
||||
SkRect logical_rect = SkRect::MakeLTRB(28, 0, 354.56731, 310.288);
|
||||
DisplayListBuilder builder(logical_rect);
|
||||
builder.setColor(SK_ColorRED);
|
||||
builder.drawRect(logical_rect);
|
||||
builder.DrawRect(logical_rect, DlPaint(DlColor::kRed()));
|
||||
sk_sp<DisplayList> display_list = builder.Build();
|
||||
|
||||
SkMatrix ctm = SkMatrix::MakeAll(1.3312, 0, 233, 0, 1.3312, 206, 0, 0, 1);
|
||||
|
||||
@ -35,8 +35,7 @@ Damage DiffContextTest::DiffLayerTree(MockLayerTree& layer_tree,
|
||||
sk_sp<DisplayList> DiffContextTest::CreateDisplayList(const SkRect& bounds,
|
||||
SkColor color) {
|
||||
DisplayListBuilder builder;
|
||||
builder.setColor(color);
|
||||
builder.drawRect(bounds);
|
||||
builder.DrawRect(bounds, DlPaint().setColor(color));
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
|
||||
@ -180,12 +180,12 @@ static Matrix ToMatrix(const SkMatrix& m) {
|
||||
};
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setAntiAlias(bool aa) {
|
||||
// Nothing to do because AA is implicit.
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setDither(bool dither) {}
|
||||
|
||||
static Paint::Style ToStyle(flutter::DlDrawStyle style) {
|
||||
@ -201,12 +201,12 @@ static Paint::Style ToStyle(flutter::DlDrawStyle style) {
|
||||
return Paint::Style::kFill;
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setStyle(flutter::DlDrawStyle style) {
|
||||
paint_.style = ToStyle(style);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setColor(flutter::DlColor color) {
|
||||
paint_.color = {
|
||||
color.getRedF(),
|
||||
@ -216,17 +216,17 @@ void DisplayListDispatcher::setColor(flutter::DlColor color) {
|
||||
};
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setStrokeWidth(SkScalar width) {
|
||||
paint_.stroke_width = width;
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setStrokeMiter(SkScalar limit) {
|
||||
paint_.stroke_miter = limit;
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setStrokeCap(flutter::DlStrokeCap cap) {
|
||||
switch (cap) {
|
||||
case flutter::DlStrokeCap::kButt:
|
||||
@ -241,7 +241,7 @@ void DisplayListDispatcher::setStrokeCap(flutter::DlStrokeCap cap) {
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setStrokeJoin(flutter::DlStrokeJoin join) {
|
||||
switch (join) {
|
||||
case flutter::DlStrokeJoin::kMiter:
|
||||
@ -345,7 +345,7 @@ static std::optional<Paint::ColorSourceType> ToColorSourceType(
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setColorSource(
|
||||
const flutter::DlColorSource* source) {
|
||||
if (!source) {
|
||||
@ -583,24 +583,24 @@ static std::optional<Paint::ColorFilterProc> ToColorFilterProc(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setColorFilter(
|
||||
const flutter::DlColorFilter* filter) {
|
||||
// Needs https://github.com/flutter/flutter/issues/95434
|
||||
paint_.color_filter = ToColorFilterProc(filter);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setInvertColors(bool invert) {
|
||||
paint_.invert_colors = invert;
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setBlendMode(flutter::DlBlendMode dl_mode) {
|
||||
paint_.blend_mode = ToBlendMode(dl_mode);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setPathEffect(const flutter::DlPathEffect* effect) {
|
||||
// Needs https://github.com/flutter/flutter/issues/95434
|
||||
UNIMPLEMENTED;
|
||||
@ -619,7 +619,7 @@ static FilterContents::BlurStyle ToBlurStyle(SkBlurStyle blur_style) {
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
|
||||
// Needs https://github.com/flutter/flutter/issues/95434
|
||||
if (filter == nullptr) {
|
||||
@ -704,7 +704,7 @@ static std::optional<Paint::ImageFilterProc> ToImageFilterProc(
|
||||
};
|
||||
break;
|
||||
}
|
||||
case flutter::DlImageFilterType::kComposeFilter: {
|
||||
case flutter::DlImageFilterType::kCompose: {
|
||||
auto compose = filter->asCompose();
|
||||
FML_DCHECK(compose);
|
||||
auto outer = compose->outer();
|
||||
@ -741,7 +741,7 @@ static std::optional<Paint::ImageFilterProc> ToImageFilterProc(
|
||||
};
|
||||
break;
|
||||
}
|
||||
case flutter::DlImageFilterType::kLocalMatrixFilter: {
|
||||
case flutter::DlImageFilterType::kLocalMatrix: {
|
||||
auto local_matrix_filter = filter->asLocalMatrix();
|
||||
FML_DCHECK(local_matrix_filter);
|
||||
auto internal_filter = local_matrix_filter->image_filter();
|
||||
@ -766,13 +766,13 @@ static std::optional<Paint::ImageFilterProc> ToImageFilterProc(
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::setImageFilter(
|
||||
const flutter::DlImageFilter* filter) {
|
||||
paint_.image_filter = ToImageFilterProc(filter);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::save() {
|
||||
canvas_.Save();
|
||||
}
|
||||
@ -792,7 +792,7 @@ static std::vector<Rect> ToRects(const SkRect tex[], int count) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::saveLayer(const SkRect* bounds,
|
||||
const flutter::SaveLayerOptions options,
|
||||
const flutter::DlImageFilter* backdrop) {
|
||||
@ -800,32 +800,32 @@ void DisplayListDispatcher::saveLayer(const SkRect* bounds,
|
||||
canvas_.SaveLayer(paint, ToRect(bounds), ToImageFilterProc(backdrop));
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::restore() {
|
||||
canvas_.Restore();
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::translate(SkScalar tx, SkScalar ty) {
|
||||
canvas_.Translate({tx, ty, 0.0});
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::scale(SkScalar sx, SkScalar sy) {
|
||||
canvas_.Scale({sx, sy, 1.0});
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::rotate(SkScalar degrees) {
|
||||
canvas_.Rotate(Degrees{degrees});
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::skew(SkScalar sx, SkScalar sy) {
|
||||
canvas_.Skew(sx, sy);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::transform2DAffine(SkScalar mxx,
|
||||
SkScalar mxy,
|
||||
SkScalar mxt,
|
||||
@ -842,7 +842,7 @@ void DisplayListDispatcher::transform2DAffine(SkScalar mxx,
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::transformFullPerspective(SkScalar mxx,
|
||||
SkScalar mxy,
|
||||
SkScalar mxz,
|
||||
@ -872,7 +872,7 @@ void DisplayListDispatcher::transformFullPerspective(SkScalar mxx,
|
||||
canvas_.Transform(xformation);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::transformReset() {
|
||||
canvas_.ResetTransform();
|
||||
canvas_.Transform(initial_matrix_);
|
||||
@ -892,7 +892,7 @@ static Entity::ClipOperation ToClipOperation(
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::clipRect(const SkRect& rect,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
@ -979,7 +979,7 @@ static Path ToPath(const SkPath& path) {
|
||||
case SkPathFillType::kInverseWinding:
|
||||
case SkPathFillType::kInverseEvenOdd:
|
||||
// Flutter doesn't expose these path fill types. These are only visible
|
||||
// via the dispatcher interface. We should never get here.
|
||||
// via the receiver interface. We should never get here.
|
||||
fill_type = FillType::kNonZero;
|
||||
break;
|
||||
}
|
||||
@ -992,21 +992,21 @@ static Path ToPath(const SkRRect& rrect) {
|
||||
.TakePath();
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::clipRRect(const SkRRect& rrect,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
canvas_.ClipPath(ToPath(rrect), ToClipOperation(clip_op));
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::clipPath(const SkPath& path,
|
||||
ClipOp clip_op,
|
||||
bool is_aa) {
|
||||
canvas_.ClipPath(ToPath(path), ToClipOperation(clip_op));
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawColor(flutter::DlColor color,
|
||||
flutter::DlBlendMode dl_mode) {
|
||||
Paint paint;
|
||||
@ -1015,12 +1015,12 @@ void DisplayListDispatcher::drawColor(flutter::DlColor color,
|
||||
canvas_.DrawPaint(paint);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawPaint() {
|
||||
canvas_.DrawPaint(paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
|
||||
auto path = PathBuilder{}.AddLine(ToPoint(p0), ToPoint(p1)).TakePath();
|
||||
Paint paint = paint_;
|
||||
@ -1028,12 +1028,12 @@ void DisplayListDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
|
||||
canvas_.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawRect(const SkRect& rect) {
|
||||
canvas_.DrawRect(ToRect(rect), paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawOval(const SkRect& bounds) {
|
||||
if (bounds.width() == bounds.height()) {
|
||||
canvas_.DrawCircle(ToPoint(bounds.center()), bounds.width() * 0.5, paint_);
|
||||
@ -1043,12 +1043,12 @@ void DisplayListDispatcher::drawOval(const SkRect& bounds) {
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawCircle(const SkPoint& center, SkScalar radius) {
|
||||
canvas_.DrawCircle(ToPoint(center), radius, paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawRRect(const SkRRect& rrect) {
|
||||
if (rrect.isSimple()) {
|
||||
canvas_.DrawRRect(ToRect(rrect.rect()), rrect.getSimpleRadii().fX, paint_);
|
||||
@ -1057,7 +1057,7 @@ void DisplayListDispatcher::drawRRect(const SkRRect& rrect) {
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawDRRect(const SkRRect& outer,
|
||||
const SkRRect& inner) {
|
||||
PathBuilder builder;
|
||||
@ -1066,12 +1066,12 @@ void DisplayListDispatcher::drawDRRect(const SkRRect& outer,
|
||||
canvas_.DrawPath(builder.TakePath(FillType::kOdd), paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawPath(const SkPath& path) {
|
||||
canvas_.DrawPath(ToPath(path), paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawArc(const SkRect& oval_bounds,
|
||||
SkScalar start_degrees,
|
||||
SkScalar sweep_degrees,
|
||||
@ -1082,7 +1082,7 @@ void DisplayListDispatcher::drawArc(const SkRect& oval_bounds,
|
||||
canvas_.DrawPath(builder.TakePath(), paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawPoints(PointMode mode,
|
||||
uint32_t count,
|
||||
const SkPoint points[]) {
|
||||
@ -1121,14 +1121,14 @@ void DisplayListDispatcher::drawPoints(PointMode mode,
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawVertices(const flutter::DlVertices* vertices,
|
||||
flutter::DlBlendMode dl_mode) {
|
||||
canvas_.DrawVertices(DLVerticesGeometry::MakeVertices(vertices),
|
||||
ToBlendMode(dl_mode), paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawImage(const sk_sp<flutter::DlImage> image,
|
||||
const SkPoint point,
|
||||
flutter::DlImageSampling sampling,
|
||||
@ -1147,24 +1147,23 @@ void DisplayListDispatcher::drawImage(const sk_sp<flutter::DlImage> image,
|
||||
const auto dest =
|
||||
SkRect::MakeXYWH(point.fX, point.fY, size.width, size.height);
|
||||
|
||||
drawImageRect(
|
||||
image, // image
|
||||
src, // source rect
|
||||
dest, // destination rect
|
||||
sampling, // sampling options
|
||||
render_with_attributes, // render with attributes
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint // constraint
|
||||
drawImageRect(image, // image
|
||||
src, // source rect
|
||||
dest, // destination rect
|
||||
sampling, // sampling options
|
||||
render_with_attributes, // render with attributes
|
||||
SrcRectConstraint::kStrict // constraint
|
||||
);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawImageRect(
|
||||
const sk_sp<flutter::DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
flutter::DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) {
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) {
|
||||
canvas_.DrawImageRect(
|
||||
std::make_shared<Image>(image->impeller_texture()), // image
|
||||
ToRect(src), // source rect
|
||||
@ -1174,7 +1173,7 @@ void DisplayListDispatcher::drawImageRect(
|
||||
);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawImageNine(const sk_sp<flutter::DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
@ -1187,7 +1186,7 @@ void DisplayListDispatcher::drawImageNine(const sk_sp<flutter::DlImage> image,
|
||||
ToRect(dst), ToSamplerDescriptor(filter), &canvas_, &paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawAtlas(const sk_sp<flutter::DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const SkRect tex[],
|
||||
@ -1203,21 +1202,43 @@ void DisplayListDispatcher::drawAtlas(const sk_sp<flutter::DlImage> atlas,
|
||||
ToSamplerDescriptor(sampling), ToRect(cull_rect), paint_);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawDisplayList(
|
||||
const sk_sp<flutter::DisplayList> display_list) {
|
||||
int saveCount = canvas_.GetSaveCount();
|
||||
Paint savePaint = paint_;
|
||||
Matrix saveMatrix = initial_matrix_;
|
||||
paint_ = Paint();
|
||||
const sk_sp<flutter::DisplayList> display_list,
|
||||
SkScalar opacity) {
|
||||
// Save all values that must remain untouched after the operation.
|
||||
Paint saved_paint = paint_;
|
||||
Matrix saved_initial_matrix = initial_matrix_;
|
||||
int restore_count = canvas_.GetSaveCount();
|
||||
|
||||
// Establish a new baseline for interpreting the new DL.
|
||||
// Matrix and clip are left untouched, the current
|
||||
// transform is saved as the new base matrix, and paint
|
||||
// values are reset to defaults.
|
||||
initial_matrix_ = canvas_.GetCurrentTransformation();
|
||||
paint_ = Paint();
|
||||
|
||||
// Handle passed opacity in the most brute-force way by using
|
||||
// a SaveLayer. If the display_list is able to inherit the
|
||||
// opacity, this could also be handled by modulating all of its
|
||||
// attribute settings (for example, color), by the indicated
|
||||
// opacity.
|
||||
if (opacity < SK_Scalar1) {
|
||||
Paint save_paint;
|
||||
save_paint.color = Color(0, 0, 0, opacity);
|
||||
canvas_.SaveLayer(save_paint);
|
||||
}
|
||||
|
||||
display_list->Dispatch(*this);
|
||||
paint_ = savePaint;
|
||||
initial_matrix_ = saveMatrix;
|
||||
canvas_.RestoreToCount(saveCount);
|
||||
|
||||
// Restore all saved state back to what it was before we interpreted
|
||||
// the display_list
|
||||
canvas_.RestoreToCount(restore_count);
|
||||
initial_matrix_ = saved_initial_matrix;
|
||||
paint_ = saved_paint;
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) {
|
||||
@ -1228,7 +1249,7 @@ void DisplayListDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
);
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void DisplayListDispatcher::drawShadow(const SkPath& path,
|
||||
const flutter::DlColor color,
|
||||
const SkScalar elevation,
|
||||
|
||||
@ -7,14 +7,14 @@
|
||||
#include "display_list/display_list_path_effect.h"
|
||||
#include "flutter/display_list/display_list.h"
|
||||
#include "flutter/display_list/display_list_blend_mode.h"
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/aiks/canvas.h"
|
||||
#include "impeller/aiks/paint.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
class DisplayListDispatcher final : public flutter::Dispatcher {
|
||||
class DisplayListDispatcher final : public flutter::DlOpReceiver {
|
||||
public:
|
||||
DisplayListDispatcher();
|
||||
|
||||
@ -22,75 +22,75 @@ class DisplayListDispatcher final : public flutter::Dispatcher {
|
||||
|
||||
Picture EndRecordingAsPicture();
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setAntiAlias(bool aa) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setDither(bool dither) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setStyle(flutter::DlDrawStyle style) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setColor(flutter::DlColor color) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setStrokeWidth(SkScalar width) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setStrokeMiter(SkScalar limit) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setStrokeCap(flutter::DlStrokeCap cap) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setStrokeJoin(flutter::DlStrokeJoin join) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setColorSource(const flutter::DlColorSource* source) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setColorFilter(const flutter::DlColorFilter* filter) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setInvertColors(bool invert) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setBlendMode(flutter::DlBlendMode mode) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setPathEffect(const flutter::DlPathEffect* effect) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setMaskFilter(const flutter::DlMaskFilter* filter) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void setImageFilter(const flutter::DlImageFilter* filter) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void save() override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void saveLayer(const SkRect* bounds,
|
||||
const flutter::SaveLayerOptions options,
|
||||
const flutter::DlImageFilter* backdrop) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void restore() override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void translate(SkScalar tx, SkScalar ty) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void scale(SkScalar sx, SkScalar sy) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void rotate(SkScalar degrees) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void skew(SkScalar sx, SkScalar sy) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void transform2DAffine(SkScalar mxx,
|
||||
SkScalar mxy,
|
||||
SkScalar mxt,
|
||||
@ -98,7 +98,7 @@ class DisplayListDispatcher final : public flutter::Dispatcher {
|
||||
SkScalar myy,
|
||||
SkScalar myt) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void transformFullPerspective(SkScalar mxx,
|
||||
SkScalar mxy,
|
||||
SkScalar mxz,
|
||||
@ -116,82 +116,82 @@ class DisplayListDispatcher final : public flutter::Dispatcher {
|
||||
SkScalar mwz,
|
||||
SkScalar mwt) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void transformReset() override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawPaint() override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawLine(const SkPoint& p0, const SkPoint& p1) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawRect(const SkRect& rect) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawOval(const SkRect& bounds) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawCircle(const SkPoint& center, SkScalar radius) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawRRect(const SkRRect& rrect) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawPath(const SkPath& path) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawArc(const SkRect& oval_bounds,
|
||||
SkScalar start_degrees,
|
||||
SkScalar sweep_degrees,
|
||||
bool use_center) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawPoints(PointMode mode,
|
||||
uint32_t count,
|
||||
const SkPoint points[]) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawVertices(const flutter::DlVertices* vertices,
|
||||
flutter::DlBlendMode dl_mode) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawImage(const sk_sp<flutter::DlImage> image,
|
||||
const SkPoint point,
|
||||
flutter::DlImageSampling sampling,
|
||||
bool render_with_attributes) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawImageRect(const sk_sp<flutter::DlImage> image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
flutter::DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) override;
|
||||
SrcRectConstraint constraint) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawImageNine(const sk_sp<flutter::DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
flutter::DlFilterMode filter,
|
||||
bool render_with_attributes) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawAtlas(const sk_sp<flutter::DlImage> atlas,
|
||||
const SkRSXform xform[],
|
||||
const SkRect tex[],
|
||||
@ -202,15 +202,16 @@ class DisplayListDispatcher final : public flutter::Dispatcher {
|
||||
const SkRect* cull_rect,
|
||||
bool render_with_attributes) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
void drawDisplayList(const sk_sp<flutter::DisplayList> display_list) override;
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawDisplayList(const sk_sp<flutter::DisplayList> display_list,
|
||||
SkScalar opacity) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) override;
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
// |flutter::DlOpReceiver|
|
||||
void drawShadow(const SkPath& path,
|
||||
const flutter::DlColor color,
|
||||
const SkScalar elevation,
|
||||
|
||||
@ -44,85 +44,83 @@ INSTANTIATE_PLAYGROUND_SUITE(DisplayListTest);
|
||||
|
||||
TEST_P(DisplayListTest, CanDrawRect) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
builder.setColor(SK_ColorBLUE);
|
||||
builder.drawRect(SkRect::MakeXYWH(10, 10, 100, 100));
|
||||
builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100),
|
||||
flutter::DlPaint(flutter::DlColor::kBlue()));
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(DisplayListTest, CanDrawTextBlob) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
builder.setColor(SK_ColorBLUE);
|
||||
builder.drawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
|
||||
100, 100);
|
||||
builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
|
||||
100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(DisplayListTest, CanDrawTextWithSaveLayer) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
builder.setColor(SK_ColorRED);
|
||||
builder.drawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
|
||||
100, 100);
|
||||
builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
|
||||
100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
|
||||
|
||||
flutter::DlPaint save_paint;
|
||||
float alpha = 0.5;
|
||||
save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
|
||||
builder.SaveLayer(nullptr, &save_paint);
|
||||
builder.setColor(SK_ColorRED);
|
||||
builder.drawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
|
||||
builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
|
||||
CreateTestFontOfSize(100)),
|
||||
100, 300);
|
||||
builder.restore();
|
||||
100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
|
||||
builder.Restore();
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(DisplayListTest, CanDrawImage) {
|
||||
auto texture = CreateTextureForFixture("embarcadero.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, nullptr);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(DisplayListTest, CanDrawCapsAndJoins) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
builder.setStyle(flutter::DlDrawStyle::kStroke);
|
||||
builder.setStrokeWidth(30);
|
||||
builder.setColor(SK_ColorRED);
|
||||
paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
|
||||
paint.setStrokeWidth(30);
|
||||
paint.setColor(SK_ColorRED);
|
||||
|
||||
auto path =
|
||||
SkPathBuilder{}.moveTo(-50, 0).lineTo(0, -50).lineTo(50, 0).snapshot();
|
||||
|
||||
builder.translate(100, 100);
|
||||
builder.Translate(100, 100);
|
||||
{
|
||||
builder.setStrokeCap(flutter::DlStrokeCap::kButt);
|
||||
builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
|
||||
builder.setStrokeMiter(4);
|
||||
builder.drawPath(path);
|
||||
paint.setStrokeCap(flutter::DlStrokeCap::kButt);
|
||||
paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
|
||||
paint.setStrokeMiter(4);
|
||||
builder.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
{
|
||||
builder.save();
|
||||
builder.translate(0, 100);
|
||||
builder.Save();
|
||||
builder.Translate(0, 100);
|
||||
// The joint in the path is 45 degrees. A miter length of 1 convert to a
|
||||
// bevel in this case.
|
||||
builder.setStrokeMiter(1);
|
||||
builder.drawPath(path);
|
||||
builder.restore();
|
||||
paint.setStrokeMiter(1);
|
||||
builder.DrawPath(path, paint);
|
||||
builder.Restore();
|
||||
}
|
||||
|
||||
builder.translate(150, 0);
|
||||
builder.Translate(150, 0);
|
||||
{
|
||||
builder.setStrokeCap(flutter::DlStrokeCap::kSquare);
|
||||
builder.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
|
||||
builder.drawPath(path);
|
||||
paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
|
||||
paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
|
||||
builder.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
builder.translate(150, 0);
|
||||
builder.Translate(150, 0);
|
||||
{
|
||||
builder.setStrokeCap(flutter::DlStrokeCap::kRound);
|
||||
builder.setStrokeJoin(flutter::DlStrokeJoin::kRound);
|
||||
builder.drawPath(path);
|
||||
paint.setStrokeCap(flutter::DlStrokeCap::kRound);
|
||||
paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
|
||||
builder.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
@ -167,20 +165,21 @@ TEST_P(DisplayListTest, CanDrawArc) {
|
||||
Point(200, 200), Point(400, 400), 20, Color::White(), Color::White());
|
||||
|
||||
flutter::DisplayListBuilder builder;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
Vector2 scale = GetContentScale();
|
||||
builder.scale(scale.x, scale.y);
|
||||
builder.setStyle(flutter::DlDrawStyle::kStroke);
|
||||
builder.setStrokeCap(cap);
|
||||
builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
|
||||
builder.setStrokeMiter(10);
|
||||
builder.Scale(scale.x, scale.y);
|
||||
paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
|
||||
paint.setStrokeCap(cap);
|
||||
paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
|
||||
paint.setStrokeMiter(10);
|
||||
auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
|
||||
builder.setColor(SK_ColorGREEN);
|
||||
builder.setStrokeWidth(2);
|
||||
builder.drawRect(rect);
|
||||
builder.setColor(SK_ColorRED);
|
||||
builder.setStrokeWidth(stroke_width);
|
||||
builder.drawArc(rect, start_angle, sweep_angle, use_center);
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
paint.setStrokeWidth(2);
|
||||
builder.DrawRect(rect, paint);
|
||||
paint.setColor(SK_ColorRED);
|
||||
paint.setStrokeWidth(stroke_width);
|
||||
builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
|
||||
|
||||
return builder.Build();
|
||||
};
|
||||
@ -189,45 +188,48 @@ TEST_P(DisplayListTest, CanDrawArc) {
|
||||
|
||||
TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
builder.setColor(SK_ColorRED);
|
||||
builder.setStyle(flutter::DlDrawStyle::kStroke);
|
||||
builder.setStrokeWidth(10);
|
||||
flutter::DlPaint paint;
|
||||
|
||||
paint.setColor(SK_ColorRED);
|
||||
paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
|
||||
paint.setStrokeWidth(10);
|
||||
|
||||
// Rectangle
|
||||
builder.translate(100, 100);
|
||||
builder.drawRect(SkRect::MakeSize({100, 100}));
|
||||
builder.Translate(100, 100);
|
||||
builder.DrawRect(SkRect::MakeSize({100, 100}), paint);
|
||||
|
||||
// Rounded rectangle
|
||||
builder.translate(150, 0);
|
||||
builder.drawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10));
|
||||
builder.Translate(150, 0);
|
||||
builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
|
||||
paint);
|
||||
|
||||
// Double rounded rectangle
|
||||
builder.translate(150, 0);
|
||||
builder.drawDRRect(
|
||||
builder.Translate(150, 0);
|
||||
builder.DrawDRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10));
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10), paint);
|
||||
|
||||
// Contour with duplicate join points
|
||||
{
|
||||
builder.translate(150, 0);
|
||||
builder.Translate(150, 0);
|
||||
SkPath path;
|
||||
path.lineTo({100, 0});
|
||||
path.lineTo({100, 0});
|
||||
path.lineTo({100, 100});
|
||||
builder.drawPath(path);
|
||||
builder.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
// Contour with duplicate end points
|
||||
{
|
||||
builder.setStrokeCap(flutter::DlStrokeCap::kRound);
|
||||
builder.translate(150, 0);
|
||||
paint.setStrokeCap(flutter::DlStrokeCap::kRound);
|
||||
builder.Translate(150, 0);
|
||||
SkPath path;
|
||||
path.moveTo(0, 0);
|
||||
path.lineTo({0, 0});
|
||||
path.lineTo({50, 50});
|
||||
path.lineTo({100, 0});
|
||||
path.lineTo({100, 0});
|
||||
builder.drawPath(path);
|
||||
builder.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
@ -235,15 +237,17 @@ TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) {
|
||||
|
||||
TEST_P(DisplayListTest, CanDrawWithOddPathWinding) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
builder.setColor(SK_ColorRED);
|
||||
builder.setStyle(flutter::DlDrawStyle::kFill);
|
||||
flutter::DlPaint paint;
|
||||
|
||||
builder.translate(300, 300);
|
||||
paint.setColor(SK_ColorRED);
|
||||
paint.setDrawStyle(flutter::DlDrawStyle::kFill);
|
||||
|
||||
builder.Translate(300, 300);
|
||||
SkPath path;
|
||||
path.setFillType(SkPathFillType::kEvenOdd);
|
||||
path.addCircle(0, 0, 100);
|
||||
path.addCircle(0, 0, 50);
|
||||
builder.drawPath(path);
|
||||
builder.DrawPath(path, paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
@ -251,29 +255,31 @@ TEST_P(DisplayListTest, CanDrawWithOddPathWinding) {
|
||||
TEST_P(DisplayListTest, CanDrawWithMaskBlur) {
|
||||
auto texture = CreateTextureForFixture("embarcadero.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
// Mask blurred image.
|
||||
{
|
||||
auto filter = flutter::DlBlurMaskFilter(kNormal_SkBlurStyle, 10.0f);
|
||||
builder.setMaskFilter(&filter);
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
paint.setMaskFilter(&filter);
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
}
|
||||
|
||||
// Mask blurred filled path.
|
||||
{
|
||||
builder.setColor(SK_ColorYELLOW);
|
||||
paint.setColor(SK_ColorYELLOW);
|
||||
auto filter = flutter::DlBlurMaskFilter(kOuter_SkBlurStyle, 10.0f);
|
||||
builder.setMaskFilter(&filter);
|
||||
builder.drawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true);
|
||||
paint.setMaskFilter(&filter);
|
||||
builder.DrawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
|
||||
}
|
||||
|
||||
// Mask blurred text.
|
||||
{
|
||||
auto filter = flutter::DlBlurMaskFilter(kSolid_SkBlurStyle, 10.0f);
|
||||
builder.setMaskFilter(&filter);
|
||||
builder.drawTextBlob(
|
||||
SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170);
|
||||
paint.setMaskFilter(&filter);
|
||||
builder.DrawTextBlob(
|
||||
SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
|
||||
paint);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
@ -295,23 +301,24 @@ TEST_P(DisplayListTest, IgnoreMaskFilterWhenSavingLayer) {
|
||||
TEST_P(DisplayListTest, CanDrawWithBlendColorFilter) {
|
||||
auto texture = CreateTextureForFixture("embarcadero.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
// Pipeline blended image.
|
||||
{
|
||||
auto filter = flutter::DlBlendColorFilter(SK_ColorYELLOW,
|
||||
flutter::DlBlendMode::kModulate);
|
||||
builder.setColorFilter(&filter);
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
paint.setColorFilter(&filter);
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
}
|
||||
|
||||
// Advanced blended image.
|
||||
{
|
||||
auto filter =
|
||||
flutter::DlBlendColorFilter(SK_ColorRED, flutter::DlBlendMode::kScreen);
|
||||
builder.setColorFilter(&filter);
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
paint.setColorFilter(&filter);
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
@ -326,18 +333,21 @@ TEST_P(DisplayListTest, CanDrawWithColorFilterImageFilter) {
|
||||
};
|
||||
auto texture = CreateTextureForFixture("boston.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
auto color_filter =
|
||||
std::make_shared<flutter::DlMatrixColorFilter>(invert_color_matrix);
|
||||
auto image_filter =
|
||||
std::make_shared<flutter::DlColorFilterImageFilter>(color_filter);
|
||||
builder.setImageFilter(image_filter.get());
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
|
||||
builder.translate(0, 700);
|
||||
builder.setColorFilter(color_filter.get());
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
paint.setImageFilter(image_filter.get());
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
|
||||
builder.Translate(0, 700);
|
||||
paint.setColorFilter(color_filter.get());
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
@ -352,12 +362,13 @@ TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) {
|
||||
ImGui::End();
|
||||
|
||||
flutter::DisplayListBuilder builder;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
|
||||
flutter::DlTileMode::kClamp);
|
||||
builder.setImageFilter(&filter);
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
paint.setImageFilter(&filter);
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
|
||||
return builder.Build();
|
||||
};
|
||||
@ -368,17 +379,20 @@ TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) {
|
||||
TEST_P(DisplayListTest, CanDrawWithComposeImageFilter) {
|
||||
auto texture = CreateTextureForFixture("boston.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
|
||||
auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
|
||||
auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
|
||||
auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
|
||||
builder.setImageFilter(open.get());
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
builder.translate(0, 700);
|
||||
builder.setImageFilter(close.get());
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
|
||||
paint.setImageFilter(open.get());
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
builder.Translate(0, 700);
|
||||
paint.setImageFilter(close.get());
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
@ -407,9 +421,10 @@ TEST_P(DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter) {
|
||||
auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
|
||||
|
||||
flutter::DisplayListBuilder builder;
|
||||
builder.setImageFilter(compose.get());
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
flutter::DlPaint paint;
|
||||
paint.setImageFilter(compose.get());
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
|
||||
flutter::DlImageSampling::kNearestNeighbor, &paint);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
@ -543,7 +558,7 @@ TEST_P(DisplayListTest, CanDrawBackdropFilter) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
|
||||
Vector2 scale = ctm_scale * GetContentScale();
|
||||
builder.scale(scale.x, scale.y);
|
||||
builder.Scale(scale.x, scale.y);
|
||||
|
||||
auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
|
||||
flutter::DlTileMode::kClamp);
|
||||
@ -558,12 +573,12 @@ TEST_P(DisplayListTest, CanDrawBackdropFilter) {
|
||||
// Insert a clip to test that the backdrop filter handles stencil depths > 0
|
||||
// correctly.
|
||||
if (add_clip) {
|
||||
builder.clipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
|
||||
builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
|
||||
flutter::DlCanvas::ClipOp::kIntersect, true);
|
||||
}
|
||||
|
||||
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
|
||||
flutter::DlImageSampling::kNearestNeighbor, true);
|
||||
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
|
||||
flutter::DlImageSampling::kNearestNeighbor, nullptr);
|
||||
builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
|
||||
&filter);
|
||||
|
||||
@ -571,12 +586,13 @@ TEST_P(DisplayListTest, CanDrawBackdropFilter) {
|
||||
auto circle_center =
|
||||
IMPELLER_PLAYGROUND_POINT(Point(500, 400), 20, Color::Red());
|
||||
|
||||
builder.setStyle(flutter::DlDrawStyle::kStroke);
|
||||
builder.setStrokeCap(flutter::DlStrokeCap::kButt);
|
||||
builder.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
|
||||
builder.setStrokeWidth(10);
|
||||
builder.setColor(flutter::DlColor::kRed().withAlpha(100));
|
||||
builder.drawCircle({circle_center.x, circle_center.y}, 100);
|
||||
flutter::DlPaint paint;
|
||||
paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
|
||||
paint.setStrokeCap(flutter::DlStrokeCap::kButt);
|
||||
paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
|
||||
paint.setStrokeWidth(10);
|
||||
paint.setColor(flutter::DlColor::kRed().withAlpha(100));
|
||||
builder.DrawCircle({circle_center.x, circle_center.y}, 100, paint);
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
@ -590,12 +606,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImage) {
|
||||
auto texture = CreateTextureForFixture("embarcadero.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
auto size = texture->GetSize();
|
||||
builder.drawImageNine(
|
||||
builder.DrawImageNine(
|
||||
DlImageImpeller::Make(texture),
|
||||
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
|
||||
size.height * 3 / 4),
|
||||
SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
|
||||
flutter::DlFilterMode::kNearest, true);
|
||||
flutter::DlFilterMode::kNearest, nullptr);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
@ -606,12 +622,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest) {
|
||||
auto texture = CreateTextureForFixture("embarcadero.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
auto size = texture->GetSize();
|
||||
builder.drawImageNine(
|
||||
builder.DrawImageNine(
|
||||
DlImageImpeller::Make(texture),
|
||||
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
|
||||
size.height * 3 / 4),
|
||||
SkRect::MakeLTRB(0, 0, size.width / 2, size.height),
|
||||
flutter::DlFilterMode::kNearest, true);
|
||||
flutter::DlFilterMode::kNearest, nullptr);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
@ -622,12 +638,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest) {
|
||||
auto texture = CreateTextureForFixture("embarcadero.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
auto size = texture->GetSize();
|
||||
builder.drawImageNine(
|
||||
builder.DrawImageNine(
|
||||
DlImageImpeller::Make(texture),
|
||||
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
|
||||
size.height * 3 / 4),
|
||||
SkRect::MakeLTRB(0, 0, size.width, size.height / 2),
|
||||
flutter::DlFilterMode::kNearest, true);
|
||||
flutter::DlFilterMode::kNearest, nullptr);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
@ -637,12 +653,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest) {
|
||||
auto texture = CreateTextureForFixture("embarcadero.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
auto size = texture->GetSize();
|
||||
builder.drawImageNine(
|
||||
builder.DrawImageNine(
|
||||
DlImageImpeller::Make(texture),
|
||||
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
|
||||
size.height * 3 / 4),
|
||||
SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
|
||||
flutter::DlFilterMode::kNearest, true);
|
||||
flutter::DlFilterMode::kNearest, nullptr);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
@ -652,12 +668,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCornersScaledDown) {
|
||||
auto texture = CreateTextureForFixture("embarcadero.jpg");
|
||||
flutter::DisplayListBuilder builder;
|
||||
auto size = texture->GetSize();
|
||||
builder.drawImageNine(
|
||||
builder.DrawImageNine(
|
||||
DlImageImpeller::Make(texture),
|
||||
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
|
||||
size.height * 3 / 4),
|
||||
SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
|
||||
flutter::DlFilterMode::kNearest, true);
|
||||
flutter::DlFilterMode::kNearest, nullptr);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
@ -722,9 +738,10 @@ TEST_P(DisplayListTest, CanDrawZeroLengthLine) {
|
||||
|
||||
TEST_P(DisplayListTest, CanDrawShadow) {
|
||||
flutter::DisplayListBuilder builder;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
auto content_scale = GetContentScale() * 0.8;
|
||||
builder.scale(content_scale.x, content_scale.y);
|
||||
builder.Scale(content_scale.x, content_scale.y);
|
||||
|
||||
constexpr size_t star_spikes = 5;
|
||||
constexpr SkScalar half_spike_rotation = kPi / star_spikes;
|
||||
@ -749,20 +766,20 @@ TEST_P(DisplayListTest, CanDrawShadow) {
|
||||
SkPath{}.addCircle(100, 50, 50),
|
||||
SkPath{}.addPoly(star.data(), star.size(), true),
|
||||
};
|
||||
builder.setColor(flutter::DlColor::kWhite());
|
||||
builder.drawPaint();
|
||||
builder.setColor(flutter::DlColor::kCyan());
|
||||
builder.translate(100, 50);
|
||||
paint.setColor(flutter::DlColor::kWhite());
|
||||
builder.DrawPaint(paint);
|
||||
paint.setColor(flutter::DlColor::kCyan());
|
||||
builder.Translate(100, 50);
|
||||
for (size_t x = 0; x < paths.size(); x++) {
|
||||
builder.save();
|
||||
builder.Save();
|
||||
for (size_t y = 0; y < 6; y++) {
|
||||
builder.drawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
|
||||
builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
|
||||
1);
|
||||
builder.drawPath(paths[x]);
|
||||
builder.translate(0, 150);
|
||||
builder.DrawPath(paths[x], paint);
|
||||
builder.Translate(0, 150);
|
||||
}
|
||||
builder.restore();
|
||||
builder.translate(250, 0);
|
||||
builder.Restore();
|
||||
builder.Translate(250, 0);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
@ -878,20 +895,21 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) {
|
||||
ImGui::End();
|
||||
|
||||
flutter::DisplayListBuilder builder;
|
||||
SkPaint paint;
|
||||
flutter::DlPaint paint;
|
||||
|
||||
if (enable_savelayer) {
|
||||
builder.SaveLayer(nullptr, nullptr);
|
||||
}
|
||||
{
|
||||
auto content_scale = GetContentScale();
|
||||
builder.scale(content_scale.x, content_scale.y);
|
||||
builder.Scale(content_scale.x, content_scale.y);
|
||||
|
||||
// Set the current transform
|
||||
auto ctm_matrix =
|
||||
SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
|
||||
ctm_skew[1], ctm_scale[1], ctm_translation[1], //
|
||||
0, 0, 1);
|
||||
builder.transform(ctm_matrix);
|
||||
builder.Transform(ctm_matrix);
|
||||
|
||||
// Set the matrix filter
|
||||
auto filter_matrix =
|
||||
@ -904,7 +922,7 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) {
|
||||
case 0: {
|
||||
auto filter = flutter::DlMatrixImageFilter(
|
||||
filter_matrix, flutter::DlImageSampling::kLinear);
|
||||
builder.setImageFilter(&filter);
|
||||
paint.setImageFilter(&filter);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
@ -913,17 +931,17 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) {
|
||||
.shared();
|
||||
auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
|
||||
internal_filter);
|
||||
builder.setImageFilter(&filter);
|
||||
paint.setImageFilter(&filter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.drawImage(DlImageImpeller::Make(boston), {},
|
||||
flutter::DlImageSampling::kLinear, true);
|
||||
builder.DrawImage(DlImageImpeller::Make(boston), {},
|
||||
flutter::DlImageSampling::kLinear, &paint);
|
||||
}
|
||||
if (enable_savelayer) {
|
||||
builder.restore();
|
||||
builder.Restore();
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
|
||||
@ -47,7 +47,7 @@ Canvas::~Canvas() {}
|
||||
|
||||
void Canvas::save() {
|
||||
if (display_list_builder_) {
|
||||
builder()->save();
|
||||
builder()->Save();
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,11 +57,11 @@ void Canvas::saveLayerWithoutBounds(Dart_Handle paint_objects,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
bool restore_with_paint =
|
||||
paint.sync_to(builder(), kSaveLayerWithPaintFlags);
|
||||
FML_DCHECK(restore_with_paint);
|
||||
DlPaint dl_paint;
|
||||
const DlPaint* save_paint = paint.paint(dl_paint, kSaveLayerWithPaintFlags);
|
||||
FML_DCHECK(save_paint);
|
||||
TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)");
|
||||
builder()->saveLayer(nullptr, restore_with_paint);
|
||||
builder()->SaveLayer(nullptr, save_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,17 +76,17 @@ void Canvas::saveLayer(double left,
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
if (display_list_builder_) {
|
||||
bool restore_with_paint =
|
||||
paint.sync_to(builder(), kSaveLayerWithPaintFlags);
|
||||
FML_DCHECK(restore_with_paint);
|
||||
DlPaint dl_paint;
|
||||
const DlPaint* save_paint = paint.paint(dl_paint, kSaveLayerWithPaintFlags);
|
||||
FML_DCHECK(save_paint);
|
||||
TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)");
|
||||
builder()->saveLayer(&bounds, restore_with_paint);
|
||||
builder()->SaveLayer(&bounds, save_paint);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::restore() {
|
||||
if (display_list_builder_) {
|
||||
builder()->restore();
|
||||
builder()->Restore();
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,31 +100,31 @@ int Canvas::getSaveCount() {
|
||||
|
||||
void Canvas::restoreToCount(int count) {
|
||||
if (display_list_builder_ && count < getSaveCount()) {
|
||||
builder()->restoreToCount(count);
|
||||
builder()->RestoreToCount(count);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::translate(double dx, double dy) {
|
||||
if (display_list_builder_) {
|
||||
builder()->translate(dx, dy);
|
||||
builder()->Translate(dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::scale(double sx, double sy) {
|
||||
if (display_list_builder_) {
|
||||
builder()->scale(sx, sy);
|
||||
builder()->Scale(sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::rotate(double radians) {
|
||||
if (display_list_builder_) {
|
||||
builder()->rotate(radians * 180.0 / M_PI);
|
||||
builder()->Rotate(radians * 180.0 / M_PI);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::skew(double sx, double sy) {
|
||||
if (display_list_builder_) {
|
||||
builder()->skew(sx, sy);
|
||||
builder()->Skew(sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ void Canvas::transform(const tonic::Float64List& matrix4) {
|
||||
// Both DisplayList and SkM44 constructor take row-major matrix order
|
||||
if (display_list_builder_) {
|
||||
// clang-format off
|
||||
builder()->transformFullPerspective(
|
||||
builder()->TransformFullPerspective(
|
||||
matrix4[ 0], matrix4[ 4], matrix4[ 8], matrix4[12],
|
||||
matrix4[ 1], matrix4[ 5], matrix4[ 9], matrix4[13],
|
||||
matrix4[ 2], matrix4[ 6], matrix4[10], matrix4[14],
|
||||
@ -162,14 +162,14 @@ void Canvas::clipRect(double left,
|
||||
DlCanvas::ClipOp clipOp,
|
||||
bool doAntiAlias) {
|
||||
if (display_list_builder_) {
|
||||
builder()->clipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp,
|
||||
builder()->ClipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp,
|
||||
doAntiAlias);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::clipRRect(const RRect& rrect, bool doAntiAlias) {
|
||||
if (display_list_builder_) {
|
||||
builder()->clipRRect(rrect.sk_rrect, DlCanvas::ClipOp::kIntersect,
|
||||
builder()->ClipRRect(rrect.sk_rrect, DlCanvas::ClipOp::kIntersect,
|
||||
doAntiAlias);
|
||||
}
|
||||
}
|
||||
@ -181,7 +181,7 @@ void Canvas::clipPath(const CanvasPath* path, bool doAntiAlias) {
|
||||
return;
|
||||
}
|
||||
if (display_list_builder_) {
|
||||
builder()->clipPath(path->path(), DlCanvas::ClipOp::kIntersect,
|
||||
builder()->ClipPath(path->path(), DlCanvas::ClipOp::kIntersect,
|
||||
doAntiAlias);
|
||||
}
|
||||
}
|
||||
@ -210,7 +210,7 @@ void Canvas::getLocalClipBounds(Dart_Handle rect_handle) {
|
||||
|
||||
void Canvas::drawColor(SkColor color, DlBlendMode blend_mode) {
|
||||
if (display_list_builder_) {
|
||||
builder()->drawColor(color, blend_mode);
|
||||
builder()->DrawColor(color, blend_mode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,8 +224,9 @@ void Canvas::drawLine(double x1,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawLineFlags);
|
||||
builder()->drawLine(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawLineFlags);
|
||||
builder()->DrawLine(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,14 +235,15 @@ void Canvas::drawPaint(Dart_Handle paint_objects, Dart_Handle paint_data) {
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawPaintFlags);
|
||||
std::shared_ptr<const DlImageFilter> filter = builder()->getImageFilter();
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawPaintFlags);
|
||||
std::shared_ptr<const DlImageFilter> filter = dl_paint.getImageFilter();
|
||||
if (filter && !filter->asColorFilter()) {
|
||||
// drawPaint does an implicit saveLayer if an SkImageFilter is
|
||||
// present that cannot be replaced by an SkColorFilter.
|
||||
TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)");
|
||||
}
|
||||
builder()->drawPaint();
|
||||
builder()->DrawPaint(dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,8 +257,9 @@ void Canvas::drawRect(double left,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawRectFlags);
|
||||
builder()->drawRect(SkRect::MakeLTRB(left, top, right, bottom));
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawRectFlags);
|
||||
builder()->DrawRect(SkRect::MakeLTRB(left, top, right, bottom), dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,8 +270,9 @@ void Canvas::drawRRect(const RRect& rrect,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawRRectFlags);
|
||||
builder()->drawRRect(rrect.sk_rrect);
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawRRectFlags);
|
||||
builder()->DrawRRect(rrect.sk_rrect, dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,8 +284,9 @@ void Canvas::drawDRRect(const RRect& outer,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawDRRectFlags);
|
||||
builder()->drawDRRect(outer.sk_rrect, inner.sk_rrect);
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawDRRectFlags);
|
||||
builder()->DrawDRRect(outer.sk_rrect, inner.sk_rrect, dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,8 +300,9 @@ void Canvas::drawOval(double left,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawOvalFlags);
|
||||
builder()->drawOval(SkRect::MakeLTRB(left, top, right, bottom));
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawOvalFlags);
|
||||
builder()->DrawOval(SkRect::MakeLTRB(left, top, right, bottom), dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,8 +315,9 @@ void Canvas::drawCircle(double x,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawCircleFlags);
|
||||
builder()->drawCircle(SkPoint::Make(x, y), radius);
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawCircleFlags);
|
||||
builder()->DrawCircle(SkPoint::Make(x, y), radius, dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,13 +334,13 @@ void Canvas::drawArc(double left,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(),
|
||||
useCenter //
|
||||
? kDrawArcWithCenterFlags
|
||||
: kDrawArcNoCenterFlags);
|
||||
builder()->drawArc(SkRect::MakeLTRB(left, top, right, bottom),
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, useCenter //
|
||||
? kDrawArcWithCenterFlags
|
||||
: kDrawArcNoCenterFlags);
|
||||
builder()->DrawArc(SkRect::MakeLTRB(left, top, right, bottom),
|
||||
startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
|
||||
useCenter);
|
||||
useCenter, dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,8 +356,9 @@ void Canvas::drawPath(const CanvasPath* path,
|
||||
return;
|
||||
}
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawPathFlags);
|
||||
builder()->drawPath(path->path());
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawPathFlags);
|
||||
builder()->DrawPath(path->path(), dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,9 +386,9 @@ Dart_Handle Canvas::drawImage(const CanvasImage* image,
|
||||
|
||||
auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
|
||||
if (display_list_builder_) {
|
||||
bool with_attributes = paint.sync_to(builder(), kDrawImageWithPaintFlags);
|
||||
builder()->drawImage(dl_image, SkPoint::Make(x, y), sampling,
|
||||
with_attributes);
|
||||
DlPaint dl_paint;
|
||||
const DlPaint* opt_paint = paint.paint(dl_paint, kDrawImageWithPaintFlags);
|
||||
builder()->DrawImage(dl_image, SkPoint::Make(x, y), sampling, opt_paint);
|
||||
}
|
||||
return Dart_Null();
|
||||
}
|
||||
@ -417,10 +425,11 @@ Dart_Handle Canvas::drawImageRect(const CanvasImage* image,
|
||||
SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
|
||||
auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
|
||||
if (display_list_builder_) {
|
||||
bool with_attributes =
|
||||
paint.sync_to(builder(), kDrawImageRectWithPaintFlags);
|
||||
builder()->drawImageRect(dl_image, src, dst, sampling, with_attributes,
|
||||
SkCanvas::kFast_SrcRectConstraint);
|
||||
DlPaint dl_paint;
|
||||
const DlPaint* opt_paint =
|
||||
paint.paint(dl_paint, kDrawImageRectWithPaintFlags);
|
||||
builder()->DrawImageRect(dl_image, src, dst, sampling, opt_paint,
|
||||
DlCanvas::SrcRectConstraint::kFast);
|
||||
}
|
||||
return Dart_Null();
|
||||
}
|
||||
@ -459,9 +468,10 @@ Dart_Handle Canvas::drawImageNine(const CanvasImage* image,
|
||||
SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
|
||||
auto filter = ImageFilter::FilterModeFromIndex(bitmapSamplingIndex);
|
||||
if (display_list_builder_) {
|
||||
bool with_attributes =
|
||||
paint.sync_to(builder(), kDrawImageNineWithPaintFlags);
|
||||
builder()->drawImageNine(dl_image, icenter, dst, filter, with_attributes);
|
||||
DlPaint dl_paint;
|
||||
const DlPaint* opt_paint =
|
||||
paint.paint(dl_paint, kDrawImageNineWithPaintFlags);
|
||||
builder()->DrawImageNine(dl_image, icenter, dst, filter, opt_paint);
|
||||
}
|
||||
return Dart_Null();
|
||||
}
|
||||
@ -474,7 +484,7 @@ void Canvas::drawPicture(Picture* picture) {
|
||||
}
|
||||
if (picture->display_list()) {
|
||||
if (display_list_builder_) {
|
||||
builder()->drawDisplayList(picture->display_list());
|
||||
builder()->DrawDisplayList(picture->display_list());
|
||||
}
|
||||
} else {
|
||||
FML_DCHECK(false);
|
||||
@ -492,20 +502,22 @@ void Canvas::drawPoints(Dart_Handle paint_objects,
|
||||
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
DlPaint dl_paint;
|
||||
switch (point_mode) {
|
||||
case DlCanvas::PointMode::kPoints:
|
||||
paint.sync_to(builder(), kDrawPointsAsPointsFlags);
|
||||
paint.paint(dl_paint, kDrawPointsAsPointsFlags);
|
||||
break;
|
||||
case DlCanvas::PointMode::kLines:
|
||||
paint.sync_to(builder(), kDrawPointsAsLinesFlags);
|
||||
paint.paint(dl_paint, kDrawPointsAsLinesFlags);
|
||||
break;
|
||||
case DlCanvas::PointMode::kPolygon:
|
||||
paint.sync_to(builder(), kDrawPointsAsPolygonFlags);
|
||||
paint.paint(dl_paint, kDrawPointsAsPolygonFlags);
|
||||
break;
|
||||
}
|
||||
builder()->drawPoints(point_mode,
|
||||
builder()->DrawPoints(point_mode,
|
||||
points.num_elements() / 2, // SkPoints have 2 floats
|
||||
reinterpret_cast<const SkPoint*>(points.data()));
|
||||
reinterpret_cast<const SkPoint*>(points.data()),
|
||||
dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,8 +534,9 @@ void Canvas::drawVertices(const Vertices* vertices,
|
||||
}
|
||||
FML_DCHECK(paint.isNotNull());
|
||||
if (display_list_builder_) {
|
||||
paint.sync_to(builder(), kDrawVerticesFlags);
|
||||
builder()->drawVertices(vertices->vertices(), blend_mode);
|
||||
DlPaint dl_paint;
|
||||
paint.paint(dl_paint, kDrawVerticesFlags);
|
||||
builder()->DrawVertices(vertices->vertices(), blend_mode, dl_paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,14 +577,15 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects,
|
||||
tonic::Int32List colors(colors_handle);
|
||||
tonic::Float32List cull_rect(cull_rect_handle);
|
||||
|
||||
bool with_attributes = paint.sync_to(builder(), kDrawAtlasWithPaintFlags);
|
||||
builder()->drawAtlas(
|
||||
DlPaint dl_paint;
|
||||
const DlPaint* opt_paint = paint.paint(dl_paint, kDrawAtlasWithPaintFlags);
|
||||
builder()->DrawAtlas(
|
||||
dl_image, reinterpret_cast<const SkRSXform*>(transforms.data()),
|
||||
reinterpret_cast<const SkRect*>(rects.data()),
|
||||
reinterpret_cast<const DlColor*>(colors.data()),
|
||||
rects.num_elements() / 4, // SkRect have four floats.
|
||||
blend_mode, sampling, reinterpret_cast<const SkRect*>(cull_rect.data()),
|
||||
with_attributes);
|
||||
opt_paint);
|
||||
}
|
||||
return Dart_Null();
|
||||
}
|
||||
@ -598,7 +612,7 @@ void Canvas::drawShadow(const CanvasPath* path,
|
||||
// that situation we bypass the canvas interface and inject the
|
||||
// shadow parameters directly into the underlying DisplayList.
|
||||
// See: https://bugs.chromium.org/p/skia/issues/detail?id=12125
|
||||
builder()->drawShadow(path->path(), color, elevation, transparentOccluder,
|
||||
builder()->DrawShadow(path->path(), color, elevation, transparentOccluder,
|
||||
dpr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,8 +23,8 @@ void ColorFilter::Create(Dart_Handle wrapper) {
|
||||
}
|
||||
|
||||
void ColorFilter::initMode(int color, int blend_mode) {
|
||||
filter_ = std::make_shared<DlBlendColorFilter>(
|
||||
static_cast<DlColor>(color), static_cast<DlBlendMode>(blend_mode));
|
||||
filter_ = DlBlendColorFilter::Make(static_cast<DlColor>(color),
|
||||
static_cast<DlBlendMode>(blend_mode));
|
||||
}
|
||||
|
||||
void ColorFilter::initMatrix(const tonic::Float32List& color_matrix) {
|
||||
@ -39,7 +39,7 @@ void ColorFilter::initMatrix(const tonic::Float32List& color_matrix) {
|
||||
matrix[9] *= 1.0f / 255;
|
||||
matrix[14] *= 1.0f / 255;
|
||||
matrix[19] *= 1.0f / 255;
|
||||
filter_ = std::make_shared<DlMatrixColorFilter>(matrix);
|
||||
filter_ = DlMatrixColorFilter::Make(matrix);
|
||||
}
|
||||
|
||||
void ColorFilter::initLinearToSrgbGamma() {
|
||||
|
||||
@ -31,9 +31,6 @@ class ColorFilter : public RefCountedDartWrappable<ColorFilter> {
|
||||
~ColorFilter() override;
|
||||
|
||||
const std::shared_ptr<const DlColorFilter> filter() const { return filter_; }
|
||||
const DlColorFilter* dl_filter() const {
|
||||
return (filter_ && filter_->skia_object()) ? filter_.get() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<const DlColorFilter> filter_;
|
||||
|
||||
@ -25,7 +25,7 @@ void CanvasGradient::Create(Dart_Handle wrapper) {
|
||||
void CanvasGradient::initLinear(const tonic::Float32List& end_points,
|
||||
const tonic::Int32List& colors,
|
||||
const tonic::Float32List& color_stops,
|
||||
SkTileMode tile_mode,
|
||||
DlTileMode tile_mode,
|
||||
const tonic::Float64List& matrix4) {
|
||||
FML_DCHECK(end_points.num_elements() == 4);
|
||||
FML_DCHECK(colors.num_elements() == color_stops.num_elements() ||
|
||||
@ -48,7 +48,7 @@ void CanvasGradient::initLinear(const tonic::Float32List& end_points,
|
||||
|
||||
dl_shader_ = DlColorSource::MakeLinear(
|
||||
p0, p1, colors.num_elements(), colors_array, color_stops.data(),
|
||||
ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr);
|
||||
tile_mode, has_matrix ? &sk_matrix : nullptr);
|
||||
}
|
||||
|
||||
void CanvasGradient::initRadial(double center_x,
|
||||
@ -56,7 +56,7 @@ void CanvasGradient::initRadial(double center_x,
|
||||
double radius,
|
||||
const tonic::Int32List& colors,
|
||||
const tonic::Float32List& color_stops,
|
||||
SkTileMode tile_mode,
|
||||
DlTileMode tile_mode,
|
||||
const tonic::Float64List& matrix4) {
|
||||
FML_DCHECK(colors.num_elements() == color_stops.num_elements() ||
|
||||
color_stops.data() == nullptr);
|
||||
@ -74,7 +74,7 @@ void CanvasGradient::initRadial(double center_x,
|
||||
|
||||
dl_shader_ = DlColorSource::MakeRadial(
|
||||
SkPoint::Make(center_x, center_y), radius, colors.num_elements(),
|
||||
colors_array, color_stops.data(), ToDl(tile_mode),
|
||||
colors_array, color_stops.data(), tile_mode,
|
||||
has_matrix ? &sk_matrix : nullptr);
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ void CanvasGradient::initSweep(double center_x,
|
||||
double center_y,
|
||||
const tonic::Int32List& colors,
|
||||
const tonic::Float32List& color_stops,
|
||||
SkTileMode tile_mode,
|
||||
DlTileMode tile_mode,
|
||||
double start_angle,
|
||||
double end_angle,
|
||||
const tonic::Float64List& matrix4) {
|
||||
@ -103,7 +103,7 @@ void CanvasGradient::initSweep(double center_x,
|
||||
dl_shader_ = DlColorSource::MakeSweep(
|
||||
SkPoint::Make(center_x, center_y), start_angle * 180.0 / M_PI,
|
||||
end_angle * 180.0 / M_PI, colors.num_elements(), colors_array,
|
||||
color_stops.data(), ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr);
|
||||
color_stops.data(), tile_mode, has_matrix ? &sk_matrix : nullptr);
|
||||
}
|
||||
|
||||
void CanvasGradient::initTwoPointConical(double start_x,
|
||||
@ -114,7 +114,7 @@ void CanvasGradient::initTwoPointConical(double start_x,
|
||||
double end_radius,
|
||||
const tonic::Int32List& colors,
|
||||
const tonic::Float32List& color_stops,
|
||||
SkTileMode tile_mode,
|
||||
DlTileMode tile_mode,
|
||||
const tonic::Float64List& matrix4) {
|
||||
FML_DCHECK(colors.num_elements() == color_stops.num_elements() ||
|
||||
color_stops.data() == nullptr);
|
||||
@ -134,7 +134,7 @@ void CanvasGradient::initTwoPointConical(double start_x,
|
||||
SkPoint::Make(start_x, start_y), start_radius, //
|
||||
SkPoint::Make(end_x, end_y), end_radius, //
|
||||
colors.num_elements(), colors_array, color_stops.data(), //
|
||||
ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr);
|
||||
tile_mode, has_matrix ? &sk_matrix : nullptr);
|
||||
}
|
||||
|
||||
CanvasGradient::CanvasGradient() = default;
|
||||
|
||||
@ -12,9 +12,6 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// TODO: update this if/when Skia adds Decal mode skbug.com/7638
|
||||
static_assert(kSkTileModeCount >= 3, "Need to update tile mode enum");
|
||||
|
||||
class CanvasGradient : public Shader {
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
FML_FRIEND_MAKE_REF_COUNTED(CanvasGradient);
|
||||
@ -26,7 +23,7 @@ class CanvasGradient : public Shader {
|
||||
void initLinear(const tonic::Float32List& end_points,
|
||||
const tonic::Int32List& colors,
|
||||
const tonic::Float32List& color_stops,
|
||||
SkTileMode tile_mode,
|
||||
DlTileMode tile_mode,
|
||||
const tonic::Float64List& matrix4);
|
||||
|
||||
void initRadial(double center_x,
|
||||
@ -34,14 +31,14 @@ class CanvasGradient : public Shader {
|
||||
double radius,
|
||||
const tonic::Int32List& colors,
|
||||
const tonic::Float32List& color_stops,
|
||||
SkTileMode tile_mode,
|
||||
DlTileMode tile_mode,
|
||||
const tonic::Float64List& matrix4);
|
||||
|
||||
void initSweep(double center_x,
|
||||
double center_y,
|
||||
const tonic::Int32List& colors,
|
||||
const tonic::Float32List& color_stops,
|
||||
SkTileMode tile_mode,
|
||||
DlTileMode tile_mode,
|
||||
double start_angle,
|
||||
double end_angle,
|
||||
const tonic::Float64List& matrix4);
|
||||
@ -54,7 +51,7 @@ class CanvasGradient : public Shader {
|
||||
double end_radius,
|
||||
const tonic::Int32List& colors,
|
||||
const tonic::Float32List& color_stops,
|
||||
SkTileMode tile_mode,
|
||||
DlTileMode tile_mode,
|
||||
const tonic::Float64List& matrix4);
|
||||
|
||||
std::shared_ptr<DlColorSource> shader(DlImageSampling sampling) override {
|
||||
|
||||
@ -52,45 +52,32 @@ ImageFilter::~ImageFilter() {}
|
||||
|
||||
void ImageFilter::initBlur(double sigma_x,
|
||||
double sigma_y,
|
||||
SkTileMode tile_mode) {
|
||||
filter_ =
|
||||
std::make_shared<DlBlurImageFilter>(sigma_x, sigma_y, ToDl(tile_mode));
|
||||
DlTileMode tile_mode) {
|
||||
filter_ = DlBlurImageFilter::Make(sigma_x, sigma_y, tile_mode);
|
||||
}
|
||||
|
||||
void ImageFilter::initDilate(double radius_x, double radius_y) {
|
||||
filter_ = std::make_shared<DlDilateImageFilter>(radius_x, radius_y);
|
||||
filter_ = DlDilateImageFilter::Make(radius_x, radius_y);
|
||||
}
|
||||
|
||||
void ImageFilter::initErode(double radius_x, double radius_y) {
|
||||
filter_ = std::make_shared<DlErodeImageFilter>(radius_x, radius_y);
|
||||
filter_ = DlErodeImageFilter::Make(radius_x, radius_y);
|
||||
}
|
||||
|
||||
void ImageFilter::initMatrix(const tonic::Float64List& matrix4,
|
||||
int filterQualityIndex) {
|
||||
auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
|
||||
filter_ =
|
||||
std::make_shared<DlMatrixImageFilter>(ToSkMatrix(matrix4), sampling);
|
||||
filter_ = DlMatrixImageFilter::Make(ToSkMatrix(matrix4), sampling);
|
||||
}
|
||||
|
||||
void ImageFilter::initColorFilter(ColorFilter* colorFilter) {
|
||||
FML_DCHECK(colorFilter);
|
||||
auto dl_filter = colorFilter->dl_filter();
|
||||
// Skia may return nullptr if the colorfilter is a no-op.
|
||||
if (dl_filter) {
|
||||
filter_ = std::make_shared<DlColorFilterImageFilter>(dl_filter);
|
||||
}
|
||||
filter_ = DlColorFilterImageFilter::Make(colorFilter->filter());
|
||||
}
|
||||
|
||||
void ImageFilter::initComposeFilter(ImageFilter* outer, ImageFilter* inner) {
|
||||
FML_DCHECK(outer && inner);
|
||||
if (!outer->dl_filter()) {
|
||||
filter_ = inner->filter();
|
||||
} else if (!inner->dl_filter()) {
|
||||
filter_ = outer->filter();
|
||||
} else {
|
||||
filter_ = std::make_shared<DlComposeImageFilter>(outer->dl_filter(),
|
||||
inner->dl_filter());
|
||||
}
|
||||
filter_ = DlComposeImageFilter::Make(outer->filter(), inner->filter());
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -30,7 +30,7 @@ class ImageFilter : public RefCountedDartWrappable<ImageFilter> {
|
||||
static DlImageSampling SamplingFromIndex(int filterQualityIndex);
|
||||
static DlFilterMode FilterModeFromIndex(int index);
|
||||
|
||||
void initBlur(double sigma_x, double sigma_y, SkTileMode tile_mode);
|
||||
void initBlur(double sigma_x, double sigma_y, DlTileMode tile_mode);
|
||||
void initDilate(double radius_x, double radius_y);
|
||||
void initErode(double radius_x, double radius_y);
|
||||
void initMatrix(const tonic::Float64List& matrix4, int filter_quality_index);
|
||||
@ -38,9 +38,6 @@ class ImageFilter : public RefCountedDartWrappable<ImageFilter> {
|
||||
void initComposeFilter(ImageFilter* outer, ImageFilter* inner);
|
||||
|
||||
const std::shared_ptr<const DlImageFilter> filter() const { return filter_; }
|
||||
const DlImageFilter* dl_filter() const {
|
||||
return (filter_ && filter_->skia_object()) ? filter_.get() : nullptr;
|
||||
}
|
||||
|
||||
static void RegisterNatives(tonic::DartLibraryNatives* natives);
|
||||
|
||||
|
||||
@ -24,8 +24,8 @@ void ImageShader::Create(Dart_Handle wrapper) {
|
||||
}
|
||||
|
||||
Dart_Handle ImageShader::initWithImage(CanvasImage* image,
|
||||
SkTileMode tmx,
|
||||
SkTileMode tmy,
|
||||
DlTileMode tmx,
|
||||
DlTileMode tmy,
|
||||
int filter_quality_index,
|
||||
Dart_Handle matrix_handle) {
|
||||
if (!image) {
|
||||
@ -41,7 +41,7 @@ Dart_Handle ImageShader::initWithImage(CanvasImage* image,
|
||||
sampling_is_locked_ ? ImageFilter::SamplingFromIndex(filter_quality_index)
|
||||
: DlImageSampling::kLinear;
|
||||
cached_shader_ = UIDartState::CreateGPUObject(sk_make_sp<DlImageColorSource>(
|
||||
image_, ToDl(tmx), ToDl(tmy), sampling, &local_matrix));
|
||||
image_, tmx, tmy, sampling, &local_matrix));
|
||||
return Dart_Null();
|
||||
}
|
||||
|
||||
|
||||
@ -25,8 +25,8 @@ class ImageShader : public Shader {
|
||||
static void Create(Dart_Handle wrapper);
|
||||
|
||||
Dart_Handle initWithImage(CanvasImage* image,
|
||||
SkTileMode tmx,
|
||||
SkTileMode tmy,
|
||||
DlTileMode tmx,
|
||||
DlTileMode tmy,
|
||||
int filter_quality_index,
|
||||
Dart_Handle matrix_handle);
|
||||
|
||||
|
||||
@ -53,148 +53,17 @@ constexpr uint32_t kBlendModeDefault =
|
||||
// default SkPaintDefaults_MiterLimit in Skia (which is not in a public header).
|
||||
constexpr double kStrokeMiterLimitDefault = 4.0;
|
||||
|
||||
// A color matrix which inverts colors.
|
||||
// clang-format off
|
||||
constexpr float kInvertColors[20] = {
|
||||
-1.0, 0, 0, 1.0, 0,
|
||||
0, -1.0, 0, 1.0, 0,
|
||||
0, 0, -1.0, 1.0, 0,
|
||||
1.0, 1.0, 1.0, 1.0, 0
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// Must be kept in sync with the MaskFilter private constants in painting.dart.
|
||||
enum MaskFilterType { kNull, kBlur };
|
||||
|
||||
Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data)
|
||||
: paint_objects_(paint_objects), paint_data_(paint_data) {}
|
||||
|
||||
const SkPaint* Paint::paint(SkPaint& paint) const {
|
||||
const DlPaint* Paint::paint(DlPaint& paint,
|
||||
const DisplayListAttributeFlags& flags) const {
|
||||
if (isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
FML_DCHECK(paint == SkPaint());
|
||||
|
||||
tonic::DartByteData byte_data(paint_data_);
|
||||
FML_CHECK(byte_data.length_in_bytes() == kDataByteCount);
|
||||
|
||||
const uint32_t* uint_data = static_cast<const uint32_t*>(byte_data.data());
|
||||
const float* float_data = static_cast<const float*>(byte_data.data());
|
||||
|
||||
Dart_Handle values[kObjectCount];
|
||||
if (!Dart_IsNull(paint_objects_)) {
|
||||
FML_DCHECK(Dart_IsList(paint_objects_));
|
||||
intptr_t length = 0;
|
||||
Dart_ListLength(paint_objects_, &length);
|
||||
|
||||
FML_CHECK(length == kObjectCount);
|
||||
if (Dart_IsError(
|
||||
Dart_ListGetRange(paint_objects_, 0, kObjectCount, values))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Dart_Handle shader = values[kShaderIndex];
|
||||
if (!Dart_IsNull(shader)) {
|
||||
if (Shader* decoded = tonic::DartConverter<Shader*>::FromDart(shader)) {
|
||||
auto sampling =
|
||||
ImageFilter::SamplingFromIndex(uint_data[kFilterQualityIndex]);
|
||||
auto color_source = decoded->shader(sampling);
|
||||
// TODO(dnfield): Remove this restriction.
|
||||
// This currently is only used by paragraph code. Once SkParagraph does
|
||||
// not need to take an SkPaint, we won't be restricted in this way
|
||||
// because we will not need to access the shader on the UI task runner.
|
||||
if (color_source->owning_context() != DlImage::OwningContext::kRaster) {
|
||||
paint.setShader(color_source->skia_object());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dart_Handle color_filter = values[kColorFilterIndex];
|
||||
if (!Dart_IsNull(color_filter)) {
|
||||
ColorFilter* decoded =
|
||||
tonic::DartConverter<ColorFilter*>::FromDart(color_filter);
|
||||
paint.setColorFilter(decoded->filter()->skia_object());
|
||||
}
|
||||
|
||||
Dart_Handle image_filter = values[kImageFilterIndex];
|
||||
if (!Dart_IsNull(image_filter)) {
|
||||
ImageFilter* decoded =
|
||||
tonic::DartConverter<ImageFilter*>::FromDart(image_filter);
|
||||
paint.setImageFilter(decoded->filter()->skia_object());
|
||||
}
|
||||
}
|
||||
|
||||
paint.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0);
|
||||
|
||||
uint32_t encoded_color = uint_data[kColorIndex];
|
||||
if (encoded_color) {
|
||||
SkColor color = encoded_color ^ kColorDefault;
|
||||
paint.setColor(color);
|
||||
}
|
||||
|
||||
uint32_t encoded_blend_mode = uint_data[kBlendModeIndex];
|
||||
if (encoded_blend_mode) {
|
||||
uint32_t blend_mode = encoded_blend_mode ^ kBlendModeDefault;
|
||||
paint.setBlendMode(static_cast<SkBlendMode>(blend_mode));
|
||||
}
|
||||
|
||||
uint32_t style = uint_data[kStyleIndex];
|
||||
if (style) {
|
||||
paint.setStyle(static_cast<SkPaint::Style>(style));
|
||||
}
|
||||
|
||||
float stroke_width = float_data[kStrokeWidthIndex];
|
||||
if (stroke_width != 0.0) {
|
||||
paint.setStrokeWidth(stroke_width);
|
||||
}
|
||||
|
||||
uint32_t stroke_cap = uint_data[kStrokeCapIndex];
|
||||
if (stroke_cap) {
|
||||
paint.setStrokeCap(static_cast<SkPaint::Cap>(stroke_cap));
|
||||
}
|
||||
|
||||
uint32_t stroke_join = uint_data[kStrokeJoinIndex];
|
||||
if (stroke_join) {
|
||||
paint.setStrokeJoin(static_cast<SkPaint::Join>(stroke_join));
|
||||
}
|
||||
|
||||
float stroke_miter_limit = float_data[kStrokeMiterLimitIndex];
|
||||
if (stroke_miter_limit != 0.0) {
|
||||
paint.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault);
|
||||
}
|
||||
|
||||
if (uint_data[kInvertColorIndex]) {
|
||||
sk_sp<SkColorFilter> invert_filter = SkColorFilters::Matrix(kInvertColors);
|
||||
sk_sp<SkColorFilter> current_filter = paint.refColorFilter();
|
||||
if (current_filter) {
|
||||
invert_filter = invert_filter->makeComposed(current_filter);
|
||||
}
|
||||
paint.setColorFilter(invert_filter);
|
||||
}
|
||||
|
||||
if (uint_data[kDitherIndex]) {
|
||||
paint.setDither(true);
|
||||
}
|
||||
|
||||
switch (uint_data[kMaskFilterIndex]) {
|
||||
case kNull:
|
||||
break;
|
||||
case kBlur:
|
||||
SkBlurStyle blur_style =
|
||||
static_cast<SkBlurStyle>(uint_data[kMaskFilterBlurStyleIndex]);
|
||||
double sigma = float_data[kMaskFilterSigmaIndex];
|
||||
paint.setMaskFilter(SkMaskFilter::MakeBlur(blur_style, sigma));
|
||||
break;
|
||||
}
|
||||
|
||||
return &paint;
|
||||
}
|
||||
|
||||
bool Paint::sync_to(DisplayListBuilder* builder,
|
||||
const DisplayListAttributeFlags& flags) const {
|
||||
if (isNull()) {
|
||||
return false;
|
||||
}
|
||||
tonic::DartByteData byte_data(paint_data_);
|
||||
FML_CHECK(byte_data.length_in_bytes() == kDataByteCount);
|
||||
|
||||
@ -204,13 +73,13 @@ bool Paint::sync_to(DisplayListBuilder* builder,
|
||||
Dart_Handle values[kObjectCount];
|
||||
if (Dart_IsNull(paint_objects_)) {
|
||||
if (flags.applies_shader()) {
|
||||
builder->setColorSource(nullptr);
|
||||
paint.setColorSource(nullptr);
|
||||
}
|
||||
if (flags.applies_color_filter()) {
|
||||
builder->setColorFilter(nullptr);
|
||||
paint.setColorFilter(nullptr);
|
||||
}
|
||||
if (flags.applies_image_filter()) {
|
||||
builder->setImageFilter(nullptr);
|
||||
paint.setImageFilter(nullptr);
|
||||
}
|
||||
} else {
|
||||
FML_DCHECK(Dart_IsList(paint_objects_));
|
||||
@ -220,20 +89,20 @@ bool Paint::sync_to(DisplayListBuilder* builder,
|
||||
FML_CHECK(length == kObjectCount);
|
||||
if (Dart_IsError(
|
||||
Dart_ListGetRange(paint_objects_, 0, kObjectCount, values))) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (flags.applies_shader()) {
|
||||
Dart_Handle shader = values[kShaderIndex];
|
||||
if (Dart_IsNull(shader)) {
|
||||
builder->setColorSource(nullptr);
|
||||
paint.setColorSource(nullptr);
|
||||
} else {
|
||||
if (Shader* decoded = tonic::DartConverter<Shader*>::FromDart(shader)) {
|
||||
auto sampling =
|
||||
ImageFilter::SamplingFromIndex(uint_data[kFilterQualityIndex]);
|
||||
builder->setColorSource(decoded->shader(sampling).get());
|
||||
paint.setColorSource(decoded->shader(sampling).get());
|
||||
} else {
|
||||
builder->setColorSource(nullptr);
|
||||
paint.setColorSource(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -241,94 +110,89 @@ bool Paint::sync_to(DisplayListBuilder* builder,
|
||||
if (flags.applies_color_filter()) {
|
||||
Dart_Handle color_filter = values[kColorFilterIndex];
|
||||
if (Dart_IsNull(color_filter)) {
|
||||
builder->setColorFilter(nullptr);
|
||||
paint.setColorFilter(nullptr);
|
||||
} else {
|
||||
ColorFilter* decoded =
|
||||
tonic::DartConverter<ColorFilter*>::FromDart(color_filter);
|
||||
builder->setColorFilter(decoded->dl_filter());
|
||||
paint.setColorFilter(decoded->filter());
|
||||
}
|
||||
}
|
||||
|
||||
if (flags.applies_image_filter()) {
|
||||
Dart_Handle image_filter = values[kImageFilterIndex];
|
||||
if (Dart_IsNull(image_filter)) {
|
||||
builder->setImageFilter(nullptr);
|
||||
paint.setImageFilter(nullptr);
|
||||
} else {
|
||||
ImageFilter* decoded =
|
||||
tonic::DartConverter<ImageFilter*>::FromDart(image_filter);
|
||||
builder->setImageFilter(decoded->dl_filter());
|
||||
paint.setImageFilter(decoded->filter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags.applies_anti_alias()) {
|
||||
builder->setAntiAlias(uint_data[kIsAntiAliasIndex] == 0);
|
||||
paint.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0);
|
||||
}
|
||||
|
||||
if (flags.applies_alpha_or_color()) {
|
||||
uint32_t encoded_color = uint_data[kColorIndex];
|
||||
builder->setColor(encoded_color ^ kColorDefault);
|
||||
paint.setColor(encoded_color ^ kColorDefault);
|
||||
}
|
||||
|
||||
if (flags.applies_blend()) {
|
||||
uint32_t encoded_blend_mode = uint_data[kBlendModeIndex];
|
||||
uint32_t blend_mode = encoded_blend_mode ^ kBlendModeDefault;
|
||||
builder->setBlendMode(static_cast<DlBlendMode>(blend_mode));
|
||||
paint.setBlendMode(static_cast<DlBlendMode>(blend_mode));
|
||||
}
|
||||
|
||||
if (flags.applies_style()) {
|
||||
uint32_t style = uint_data[kStyleIndex];
|
||||
builder->setStyle(static_cast<DlDrawStyle>(style));
|
||||
paint.setDrawStyle(static_cast<DlDrawStyle>(style));
|
||||
}
|
||||
|
||||
if (flags.is_stroked(builder->getStyle())) {
|
||||
if (flags.is_stroked(paint.getDrawStyle())) {
|
||||
float stroke_width = float_data[kStrokeWidthIndex];
|
||||
builder->setStrokeWidth(stroke_width);
|
||||
paint.setStrokeWidth(stroke_width);
|
||||
|
||||
float stroke_miter_limit = float_data[kStrokeMiterLimitIndex];
|
||||
builder->setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault);
|
||||
paint.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault);
|
||||
|
||||
uint32_t stroke_cap = uint_data[kStrokeCapIndex];
|
||||
builder->setStrokeCap(static_cast<DlStrokeCap>(stroke_cap));
|
||||
paint.setStrokeCap(static_cast<DlStrokeCap>(stroke_cap));
|
||||
|
||||
uint32_t stroke_join = uint_data[kStrokeJoinIndex];
|
||||
builder->setStrokeJoin(static_cast<DlStrokeJoin>(stroke_join));
|
||||
paint.setStrokeJoin(static_cast<DlStrokeJoin>(stroke_join));
|
||||
}
|
||||
|
||||
if (flags.applies_color_filter()) {
|
||||
builder->setInvertColors(uint_data[kInvertColorIndex] != 0);
|
||||
paint.setInvertColors(uint_data[kInvertColorIndex] != 0);
|
||||
}
|
||||
|
||||
if (flags.applies_dither()) {
|
||||
builder->setDither(uint_data[kDitherIndex] != 0);
|
||||
paint.setDither(uint_data[kDitherIndex] != 0);
|
||||
}
|
||||
|
||||
if (flags.applies_path_effect()) {
|
||||
// The paint API exposed to Dart does not support path effects. But other
|
||||
// operations such as text may set a path effect, which must be cleared.
|
||||
builder->setPathEffect(nullptr);
|
||||
paint.setPathEffect(nullptr);
|
||||
}
|
||||
|
||||
if (flags.applies_mask_filter()) {
|
||||
switch (uint_data[kMaskFilterIndex]) {
|
||||
case kNull:
|
||||
builder->setMaskFilter(nullptr);
|
||||
paint.setMaskFilter(nullptr);
|
||||
break;
|
||||
case kBlur:
|
||||
SkBlurStyle blur_style =
|
||||
static_cast<SkBlurStyle>(uint_data[kMaskFilterBlurStyleIndex]);
|
||||
double sigma = float_data[kMaskFilterSigmaIndex];
|
||||
DlBlurMaskFilter dl_filter(blur_style, sigma);
|
||||
if (dl_filter.skia_object()) {
|
||||
builder->setMaskFilter(&dl_filter);
|
||||
} else {
|
||||
builder->setMaskFilter(nullptr);
|
||||
}
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(blur_style, sigma));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return &paint;
|
||||
}
|
||||
|
||||
void Paint::toDlPaint(DlPaint& paint) const {
|
||||
@ -414,11 +278,14 @@ void Paint::toDlPaint(DlPaint& paint) const {
|
||||
SkBlurStyle blur_style =
|
||||
static_cast<SkBlurStyle>(uint_data[kMaskFilterBlurStyleIndex]);
|
||||
double sigma = float_data[kMaskFilterSigmaIndex];
|
||||
std::shared_ptr<DlBlurMaskFilter> dl_filter =
|
||||
std::make_shared<DlBlurMaskFilter>(blur_style, sigma);
|
||||
if (dl_filter->skia_object()) {
|
||||
paint.setMaskFilter(dl_filter);
|
||||
}
|
||||
// Make could return a nullptr here if the values are NOP or
|
||||
// do not make sense. We could interpret that as if there was
|
||||
// no value passed from Dart at all (i.e. don't change the
|
||||
// setting in the paint object as in the kNull branch right
|
||||
// above here), but the maskfilter flag was actually set
|
||||
// indicating that the developer "tried" to set a mask, so we
|
||||
// should set the null value rather than do nothing.
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(blur_style, sigma));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,19 +17,11 @@ class Paint {
|
||||
Paint() = default;
|
||||
Paint(Dart_Handle paint_objects, Dart_Handle paint_data);
|
||||
|
||||
const SkPaint* paint(SkPaint& paint) const;
|
||||
const DlPaint* paint(DlPaint& paint,
|
||||
const DisplayListAttributeFlags& flags) const;
|
||||
|
||||
void toDlPaint(DlPaint& paint) const;
|
||||
|
||||
/// Synchronize the Dart properties to the display list according
|
||||
/// to the attribute flags that indicate which properties are needed.
|
||||
/// The return value indicates if the paint was non-null and can
|
||||
/// either be DCHECKed or used to indicate to the DisplayList
|
||||
/// draw operation whether or not to use the synchronized attributes
|
||||
/// (mainly the drawImage and saveLayer methods).
|
||||
bool sync_to(DisplayListBuilder* builder,
|
||||
const DisplayListAttributeFlags& flags) const;
|
||||
|
||||
bool isNull() const { return Dart_IsNull(paint_data_); }
|
||||
bool isNotNull() const { return !Dart_IsNull(paint_data_); }
|
||||
|
||||
|
||||
@ -270,9 +270,9 @@ std::unique_ptr<SnapshotDelegate::GpuImageResult> MakeBitmapImage(
|
||||
};
|
||||
|
||||
sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
|
||||
SkCanvas* canvas = surface->getCanvas();
|
||||
canvas->clear(SK_ColorTRANSPARENT);
|
||||
display_list->RenderTo(canvas);
|
||||
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
|
||||
canvas.Clear(DlColor::kTransparent());
|
||||
canvas.DrawDisplayList(display_list);
|
||||
|
||||
sk_sp<SkImage> image = surface->makeImageSnapshot();
|
||||
return std::make_unique<SnapshotDelegate::GpuImageResult>(
|
||||
@ -335,9 +335,9 @@ std::unique_ptr<Rasterizer::GpuImageResult> Rasterizer::MakeSkiaGpuImage(
|
||||
return;
|
||||
}
|
||||
|
||||
SkCanvas* canvas = sk_surface->getCanvas();
|
||||
canvas->clear(SK_ColorTRANSPARENT);
|
||||
display_list->RenderTo(canvas);
|
||||
auto canvas = DlSkCanvasAdapter(sk_surface->getCanvas());
|
||||
canvas.Clear(DlColor::kTransparent());
|
||||
canvas.DrawDisplayList(display_list);
|
||||
|
||||
result = std::make_unique<SnapshotDelegate::GpuImageResult>(
|
||||
texture, sk_ref_sp(context), nullptr, "");
|
||||
|
||||
@ -126,7 +126,7 @@ sk_sp<DlImage> SnapshotControllerSkia::MakeRasterSnapshot(
|
||||
sk_sp<DisplayList> display_list,
|
||||
SkISize size) {
|
||||
return DoMakeRasterSnapshot(size, [display_list](SkCanvas* canvas) {
|
||||
display_list->RenderTo(canvas);
|
||||
DlSkCanvasAdapter(canvas).DrawDisplayList(display_list);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -61,12 +61,12 @@ FLUTTER_ASSERT_ARC
|
||||
}
|
||||
|
||||
if (_externalImage) {
|
||||
context.canvas->DrawImageRect(_externalImage, // image
|
||||
SkRect::Make(_externalImage->bounds()), // source rect
|
||||
bounds, // destination rect
|
||||
sampling, // sampling
|
||||
context.paint, // paint
|
||||
false // enforce edges
|
||||
context.canvas->DrawImageRect(_externalImage, // image
|
||||
SkRect::Make(_externalImage->bounds()), // source rect
|
||||
bounds, // destination rect
|
||||
sampling, // sampling
|
||||
context.paint, // paint
|
||||
flutter::DlCanvas::SrcRectConstraint::kStrict // enforce edges
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,8 +197,15 @@ std::ostream& operator<<(std::ostream& os, const DlCanvas::ClipOp& op) {
|
||||
switch (op) {
|
||||
case DlCanvas::ClipOp::kDifference: return os << "ClipOp::kDifference";
|
||||
case DlCanvas::ClipOp::kIntersect: return os << "ClipOp::kIntersect";
|
||||
}
|
||||
}
|
||||
|
||||
default: return os << "ClipOp::????";
|
||||
std::ostream& operator<<(std::ostream& os, const DlCanvas::SrcRectConstraint& constraint) {
|
||||
switch (constraint) {
|
||||
case DlCanvas::SrcRectConstraint::kFast:
|
||||
return os << "SrcRectConstraint::kFast";
|
||||
case DlCanvas::SrcRectConstraint::kStrict:
|
||||
return os << "SrcRectConstraint::kStrict";
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,8 +214,6 @@ std::ostream& operator<<(std::ostream& os, const DlStrokeCap& cap) {
|
||||
case DlStrokeCap::kButt: return os << "Cap::kButt";
|
||||
case DlStrokeCap::kRound: return os << "Cap::kRound";
|
||||
case DlStrokeCap::kSquare: return os << "Cap::kSquare";
|
||||
|
||||
default: return os << "Cap::????";
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,8 +222,6 @@ std::ostream& operator<<(std::ostream& os, const DlStrokeJoin& join) {
|
||||
case DlStrokeJoin::kMiter: return os << "Join::kMiter";
|
||||
case DlStrokeJoin::kRound: return os << "Join::kRound";
|
||||
case DlStrokeJoin::kBevel: return os << "Join::kBevel";
|
||||
|
||||
default: return os << "Join::????";
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,8 +230,6 @@ std::ostream& operator<<(std::ostream& os, const DlDrawStyle& style) {
|
||||
case DlDrawStyle::kFill: return os << "Style::kFill";
|
||||
case DlDrawStyle::kStroke: return os << "Style::kStroke";
|
||||
case DlDrawStyle::kStrokeAndFill: return os << "Style::kStrokeAnFill";
|
||||
|
||||
default: return os << "Style::????";
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,19 +239,14 @@ std::ostream& operator<<(std::ostream& os, const SkBlurStyle& style) {
|
||||
case kSolid_SkBlurStyle: return os << "BlurStyle::kSolid";
|
||||
case kOuter_SkBlurStyle: return os << "BlurStyle::kOuter";
|
||||
case kInner_SkBlurStyle: return os << "BlurStyle::kInner";
|
||||
|
||||
default: return os << "Style::????";
|
||||
}
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& os,
|
||||
const DlCanvas::PointMode& mode) {
|
||||
std::ostream& operator<<(std::ostream& os, const DlCanvas::PointMode& mode) {
|
||||
switch (mode) {
|
||||
case DlCanvas::PointMode::kPoints: return os << "PointMode::kPoints";
|
||||
case DlCanvas::PointMode::kLines: return os << "PointMode::kLines";
|
||||
case DlCanvas::PointMode::kPolygon: return os << "PointMode::kPolygon";
|
||||
|
||||
default: return os << "PointMode::????";
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,7 +444,7 @@ void DisplayListStreamDispatcher::setColorSource(const DlColorSource* source) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
os_ << "DlUnknownColorSource(" << source->skia_object().get() << ")";
|
||||
os_ << "?DlUnknownColorSource?()";
|
||||
break;
|
||||
}
|
||||
os_ << ");" << std::endl;
|
||||
@ -490,7 +486,7 @@ void DisplayListStreamDispatcher::out(const DlColorFilter& filter) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
os_ << "DlUnknownColorFilter(" << filter.skia_object().get() << ")";
|
||||
os_ << "?DlUnknownColorFilter?()";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -530,7 +526,7 @@ void DisplayListStreamDispatcher::setMaskFilter(const DlMaskFilter* filter) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
os_ << "DlUnknownMaskFilter(" << filter->skia_object().get() << ")";
|
||||
os_ << "?DlUnknownMaskFilter?()";
|
||||
break;
|
||||
}
|
||||
os_ << ");" << std::endl;
|
||||
@ -563,7 +559,7 @@ void DisplayListStreamDispatcher::out(const DlImageFilter& filter) {
|
||||
os_ << "DlMatrixImageFilter(" << matrix->matrix() << ", " << matrix->sampling() << ")";
|
||||
break;
|
||||
}
|
||||
case DlImageFilterType::kComposeFilter: {
|
||||
case DlImageFilterType::kCompose: {
|
||||
const DlComposeImageFilter* compose = filter.asCompose();
|
||||
FML_DCHECK(compose);
|
||||
os_ << "DlComposeImageFilter(" << std::endl;
|
||||
@ -590,7 +586,7 @@ void DisplayListStreamDispatcher::out(const DlImageFilter& filter) {
|
||||
os_ << ")";
|
||||
break;
|
||||
}
|
||||
case DlImageFilterType::kLocalMatrixFilter: {
|
||||
case DlImageFilterType::kLocalMatrix: {
|
||||
const DlLocalMatrixImageFilter* local_matrix = filter.asLocalMatrix();
|
||||
FML_DCHECK(local_matrix);
|
||||
os_ << "DlLocalMatrixImageFilter(" << local_matrix->matrix();
|
||||
@ -810,7 +806,7 @@ void DisplayListStreamDispatcher::drawImageRect(const sk_sp<DlImage> image,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) {
|
||||
SrcRectConstraint constraint) {
|
||||
startl() << "drawImageRect(" << image.get() << "," << std::endl;
|
||||
startl() << " src: " << src << "," << std::endl;
|
||||
startl() << " dst: " << dst << "," << std::endl;
|
||||
@ -849,8 +845,12 @@ void DisplayListStreamDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
|
||||
<< ");" << std::endl;
|
||||
}
|
||||
void DisplayListStreamDispatcher::drawDisplayList(
|
||||
const sk_sp<DisplayList> display_list) {
|
||||
startl() << "drawDisplayList(ID: " << display_list->unique_id() << ", bounds: " << display_list->bounds() << ");" << std::endl;
|
||||
const sk_sp<DisplayList> display_list, SkScalar opacity) {
|
||||
startl() << "drawDisplayList("
|
||||
<< "ID: " << display_list->unique_id() << ", "
|
||||
<< "bounds: " << display_list->bounds() << ", "
|
||||
<< "opacity: " << opacity
|
||||
<< ");" << std::endl;
|
||||
}
|
||||
void DisplayListStreamDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
#include <ostream>
|
||||
|
||||
#include "flutter/display_list/display_list.h"
|
||||
#include "flutter/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/display_list/display_list_path_effect.h"
|
||||
#include "flutter/display_list/dl_op_receiver.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
@ -36,6 +36,10 @@ extern std::ostream& operator<<(std::ostream& os,
|
||||
extern std::ostream& operator<<(std::ostream& os, const DlPaint& paint);
|
||||
extern std::ostream& operator<<(std::ostream& os, const DlBlendMode& mode);
|
||||
extern std::ostream& operator<<(std::ostream& os, const DlCanvas::ClipOp& op);
|
||||
extern std::ostream& operator<<(std::ostream& os,
|
||||
const DlCanvas::PointMode& op);
|
||||
extern std::ostream& operator<<(std::ostream& os,
|
||||
const DlCanvas::SrcRectConstraint& op);
|
||||
extern std::ostream& operator<<(std::ostream& os, const DlStrokeCap& cap);
|
||||
extern std::ostream& operator<<(std::ostream& os, const DlStrokeJoin& join);
|
||||
extern std::ostream& operator<<(std::ostream& os, const DlDrawStyle& style);
|
||||
@ -47,7 +51,7 @@ extern std::ostream& operator<<(std::ostream& os, const DlVertexMode& mode);
|
||||
extern std::ostream& operator<<(std::ostream& os, const DlTileMode& mode);
|
||||
extern std::ostream& operator<<(std::ostream& os, const DlImage* image);
|
||||
|
||||
class DisplayListStreamDispatcher final : public Dispatcher {
|
||||
class DisplayListStreamDispatcher final : public DlOpReceiver {
|
||||
public:
|
||||
DisplayListStreamDispatcher(std::ostream& os,
|
||||
int cur_indent = 2,
|
||||
@ -121,7 +125,7 @@ class DisplayListStreamDispatcher final : public Dispatcher {
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
bool render_with_attributes,
|
||||
SkCanvas::SrcRectConstraint constraint) override;
|
||||
SrcRectConstraint constraint) override;
|
||||
void drawImageNine(const sk_sp<DlImage> image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
@ -136,7 +140,8 @@ class DisplayListStreamDispatcher final : public Dispatcher {
|
||||
DlImageSampling sampling,
|
||||
const SkRect* cull_rect,
|
||||
bool render_with_attributes) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
|
||||
void drawDisplayList(const sk_sp<DisplayList> display_list,
|
||||
SkScalar opacity) override;
|
||||
void drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) override;
|
||||
|
||||
@ -285,7 +285,7 @@ void MockCanvas::DrawImageRect(const sk_sp<DlImage>&,
|
||||
const SkRect&,
|
||||
const DlImageSampling,
|
||||
const DlPaint*,
|
||||
bool enforce_src_edges) {
|
||||
SrcRectConstraint constraint) {
|
||||
FML_DCHECK(false);
|
||||
}
|
||||
|
||||
|
||||
@ -247,12 +247,13 @@ class MockCanvas final : public DlCanvas {
|
||||
const SkPoint point,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr) override;
|
||||
void DrawImageRect(const sk_sp<DlImage>& image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
bool enforce_src_edges = false) override;
|
||||
void DrawImageRect(
|
||||
const sk_sp<DlImage>& image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
DlImageSampling sampling,
|
||||
const DlPaint* paint = nullptr,
|
||||
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
|
||||
void DrawImageNine(const sk_sp<DlImage>& image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user