1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_DISPATCHER_H_
6#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_DISPATCHER_H_
7
8#include "flutter/display_list/display_list.h"
9#include "flutter/display_list/dl_blend_mode.h"
10#include "flutter/display_list/dl_canvas.h"
11#include "flutter/display_list/dl_paint.h"
12#include "flutter/display_list/dl_sampling_options.h"
13#include "flutter/display_list/dl_vertices.h"
14#include "flutter/display_list/effects/dl_color_filter.h"
15#include "flutter/display_list/effects/dl_color_source.h"
16#include "flutter/display_list/effects/dl_image_filter.h"
17#include "flutter/display_list/effects/dl_mask_filter.h"
18#include "flutter/display_list/effects/dl_path_effect.h"
19#include "flutter/display_list/image/dl_image.h"
20
21namespace flutter {
22
23class DisplayList;
24
25//------------------------------------------------------------------------------
26/// @brief The pure virtual interface for interacting with a display list.
27/// This interface represents the methods used to build a list
28/// through the DisplayListBuilder and also the methods that will be
29/// invoked through the DisplayList::dispatch() method.
30///
31class DlOpReceiver {
32 protected:
33 using ClipOp = DlCanvas::ClipOp;
34 using PointMode = DlCanvas::PointMode;
35 using SrcRectConstraint = DlCanvas::SrcRectConstraint;
36
37 public:
38 // MaxDrawPointsCount * sizeof(SkPoint) must be less than 1 << 32
39 static constexpr int kMaxDrawPointsCount = ((1 << 29) - 1);
40
41 // The following methods are nearly 1:1 with the methods on DlPaint and
42 // carry the same meanings. Each method sets a persistent value for the
43 // attribute for the rest of the display list or until it is reset by
44 // another method that changes the same attribute. The current set of
45 // attributes is not affected by |save| and |restore|.
46 virtual void setAntiAlias(bool aa) = 0;
47 virtual void setDither(bool dither) = 0;
48 virtual void setDrawStyle(DlDrawStyle style) = 0;
49 virtual void setColor(DlColor color) = 0;
50 virtual void setStrokeWidth(float width) = 0;
51 virtual void setStrokeMiter(float limit) = 0;
52 virtual void setStrokeCap(DlStrokeCap cap) = 0;
53 virtual void setStrokeJoin(DlStrokeJoin join) = 0;
54 virtual void setColorSource(const DlColorSource* source) = 0;
55 virtual void setColorFilter(const DlColorFilter* filter) = 0;
56 // setInvertColors is a quick way to set a ColorFilter that inverts the
57 // rgb values of all rendered colors.
58 // It is not reset by |setColorFilter|, but instead composed with that
59 // filter so that the color inversion happens after the ColorFilter.
60 virtual void setInvertColors(bool invert) = 0;
61 virtual void setBlendMode(DlBlendMode mode) = 0;
62 virtual void setPathEffect(const DlPathEffect* effect) = 0;
63 virtual void setMaskFilter(const DlMaskFilter* filter) = 0;
64 virtual void setImageFilter(const DlImageFilter* filter) = 0;
65
66 // All of the following methods are nearly 1:1 with their counterparts
67 // in |SkCanvas| and have the same behavior and output.
68 virtual void save() = 0;
69 // The |options| parameter can specify whether the existing rendering
70 // attributes will be applied to the save layer surface while rendering
71 // it back to the current surface. If the flag is false then this method
72 // is equivalent to |SkCanvas::saveLayer| with a null paint object.
73 // The |options| parameter may contain other options that indicate some
74 // specific optimizations may be made by the underlying implementation
75 // to avoid creating a temporary layer, these optimization options will
76 // be determined as the |DisplayList| is constructed and should not be
77 // specified in calling a |DisplayListBuilder| as they will be ignored.
78 // The |backdrop| filter, if not null, is used to initialize the new
79 // layer before further rendering happens.
80 virtual void saveLayer(const SkRect* bounds,
81 const SaveLayerOptions options,
82 const DlImageFilter* backdrop = nullptr) = 0;
83 virtual void restore() = 0;
84
85 virtual void translate(SkScalar tx, SkScalar ty) = 0;
86 virtual void scale(SkScalar sx, SkScalar sy) = 0;
87 virtual void rotate(SkScalar degrees) = 0;
88 virtual void skew(SkScalar sx, SkScalar sy) = 0;
89
90 // The transform methods all assume the following math for transforming
91 // an arbitrary 3D homogenous point (x, y, z, w).
92 // All coordinates in the rendering methods (and SkPoint and SkRect objects)
93 // represent a simplified coordinate (x, y, 0, 1).
94 // x' = x * mxx + y * mxy + z * mxz + w * mxt
95 // y' = x * myx + y * myy + z * myz + w * myt
96 // z' = x * mzx + y * mzy + z * mzz + w * mzt
97 // w' = x * mwx + y * mwy + z * mwz + w * mwt
98 // Note that for non-homogenous 2D coordinates, the last column in those
99 // equations is multiplied by 1 and is simply adding a translation and
100 // so is referred to with the final letter "t" here instead of "w".
101 //
102 // In 2D coordinates, z=0 and so the 3rd column always evaluates to 0.
103 //
104 // In non-perspective transforms, the 4th row has identity values
105 // and so w` = w. (i.e. w'=1 for 2d points transformed by a matrix
106 // with identity values in the last row).
107 //
108 // In affine 2D transforms, the 3rd and 4th row and 3rd column are all
109 // identity values and so z` = z (which is 0 for 2D coordinates) and
110 // the x` and y` equations don't see a contribution from a z coordinate
111 // and the w' ends up being the same as the w from the source coordinate
112 // (which is 1 for a 2D coordinate).
113 //
114 // Here is the math for transforming a 2D source coordinate and
115 // looking for the destination 2D coordinate (for a surface that
116 // does not have a Z buffer or track the Z coordinates in any way)
117 // Source coordinate = (x, y, 0, 1)
118 // x' = x * mxx + y * mxy + 0 * mxz + 1 * mxt
119 // y' = x * myx + y * myy + 0 * myz + 1 * myt
120 // z' = x * mzx + y * mzy + 0 * mzz + 1 * mzt
121 // w' = x * mwx + y * mwy + 0 * mwz + 1 * mwt
122 // Destination coordinate does not need z', so this reduces to:
123 // x' = x * mxx + y * mxy + mxt
124 // y' = x * myx + y * myy + myt
125 // w' = x * mwx + y * mwy + mwt
126 // Destination coordinate is (x' / w', y' / w', 0, 1)
127 // Note that these are the matrix values in SkMatrix which means that
128 // an SkMatrix contains enough data to transform a 2D source coordinate
129 // and place it on a 2D surface, but is otherwise not enough to continue
130 // concatenating with further matrices as its missing elements will not
131 // be able to model the interplay between the rows and columns that
132 // happens during a full 4x4 by 4x4 matrix multiplication.
133 //
134 // If the transform doesn't have any perspective parts (the last
135 // row is identity - 0, 0, 0, 1), then this further simplifies to:
136 // x' = x * mxx + y * mxy + mxt
137 // y' = x * myx + y * myy + myt
138 // w' = x * 0 + y * 0 + 1 = 1
139 //
140 // In short, while the full 4x4 set of matrix entries needs to be
141 // maintained for accumulating transform mutations accurately, the
142 // actual end work of transforming a single 2D coordinate (or, in
143 // the case of bounds transformations, 4 of them) can be accomplished
144 // with the 9 values from transform3x3 or SkMatrix.
145 //
146 // The only need for the w value here is for homogenous coordinates
147 // which only come up if the perspective elements (the 4th row) of
148 // a transform are non-identity. Otherwise the w always ends up
149 // being 1 in all calculations. If the matrix has perspecitve elements
150 // then the final transformed coordinates will have a w that is not 1
151 // and the actual coordinates are determined by dividing out that w
152 // factor resulting in a real-world point expressed as (x, y, z, 1).
153 //
154 // Because of the predominance of 2D affine transforms the
155 // 2x3 subset of the 4x4 transform matrix is special cased with
156 // its own dispatch method that omits the last 2 rows and the 3rd
157 // column. Even though a 3x3 subset is enough for transforming
158 // leaf coordinates as shown above, no method is provided for
159 // representing a 3x3 transform in the DisplayList since if there
160 // is perspective involved then a full 4x4 matrix should be provided
161 // for accurate concatenations. Providing a 3x3 method or record
162 // in the stream would encourage developers to prematurely subset
163 // a full perspective matrix.
164
165 // clang-format off
166
167 // |transform2DAffine| is equivalent to concatenating the internal
168 // 4x4 transform with the following row major transform matrix:
169 // [ mxx mxy 0 mxt ]
170 // [ myx myy 0 myt ]
171 // [ 0 0 1 0 ]
172 // [ 0 0 0 1 ]
173 virtual void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt,
174 SkScalar myx, SkScalar myy, SkScalar myt) = 0;
175 // |transformFullPerspective| is equivalent to concatenating the internal
176 // 4x4 transform with the following row major transform matrix:
177 // [ mxx mxy mxz mxt ]
178 // [ myx myy myz myt ]
179 // [ mzx mzy mzz mzt ]
180 // [ mwx mwy mwz mwt ]
181 virtual void transformFullPerspective(
182 SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
183 SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
184 SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
185 SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) = 0;
186 // clang-format on
187
188 // Clears the transformation stack.
189 virtual void transformReset() = 0;
190
191 virtual void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) = 0;
192 virtual void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) = 0;
193 virtual void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) = 0;
194
195 // The following rendering methods all take their rendering attributes
196 // from the last value set by the attribute methods above (regardless
197 // of any |save| or |restore| operations which do not affect attributes).
198 // In cases where a paint object may have been optional in the SkCanvas
199 // method, the methods here will generally offer a boolean parameter
200 // which specifies whether to honor the attributes of the display list
201 // stream, or assume default attributes.
202 virtual void drawColor(DlColor color, DlBlendMode mode) = 0;
203 virtual void drawPaint() = 0;
204 virtual void drawLine(const SkPoint& p0, const SkPoint& p1) = 0;
205 virtual void drawRect(const SkRect& rect) = 0;
206 virtual void drawOval(const SkRect& bounds) = 0;
207 virtual void drawCircle(const SkPoint& center, SkScalar radius) = 0;
208 virtual void drawRRect(const SkRRect& rrect) = 0;
209 virtual void drawDRRect(const SkRRect& outer, const SkRRect& inner) = 0;
210 virtual void drawPath(const SkPath& path) = 0;
211 virtual void drawArc(const SkRect& oval_bounds,
212 SkScalar start_degrees,
213 SkScalar sweep_degrees,
214 bool use_center) = 0;
215 virtual void drawPoints(PointMode mode,
216 uint32_t count,
217 const SkPoint points[]) = 0;
218 virtual void drawVertices(const DlVertices* vertices, DlBlendMode mode) = 0;
219 virtual void drawImage(const sk_sp<DlImage> image,
220 const SkPoint point,
221 DlImageSampling sampling,
222 bool render_with_attributes) = 0;
223 virtual void drawImageRect(
224 const sk_sp<DlImage> image,
225 const SkRect& src,
226 const SkRect& dst,
227 DlImageSampling sampling,
228 bool render_with_attributes,
229 SrcRectConstraint constraint = SrcRectConstraint::kFast) = 0;
230 virtual void drawImageNine(const sk_sp<DlImage> image,
231 const SkIRect& center,
232 const SkRect& dst,
233 DlFilterMode filter,
234 bool render_with_attributes) = 0;
235 virtual void drawAtlas(const sk_sp<DlImage> atlas,
236 const SkRSXform xform[],
237 const SkRect tex[],
238 const DlColor colors[],
239 int count,
240 DlBlendMode mode,
241 DlImageSampling sampling,
242 const SkRect* cull_rect,
243 bool render_with_attributes) = 0;
244 virtual void drawDisplayList(const sk_sp<DisplayList> display_list,
245 SkScalar opacity = SK_Scalar1) = 0;
246 virtual void drawTextBlob(const sk_sp<SkTextBlob> blob,
247 SkScalar x,
248 SkScalar y) = 0;
249 virtual void drawShadow(const SkPath& path,
250 const DlColor color,
251 const SkScalar elevation,
252 bool transparent_occluder,
253 SkScalar dpr) = 0;
254};
255
256} // namespace flutter
257
258#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_DISPATCHER_H_
259

source code of flutter_engine/flutter/display_list/dl_op_receiver.h