• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "property/rs_property_drawable.h"
17 
18 #include "pipeline/rs_render_node.h"
19 #include "platform/common/rs_log.h"
20 #include "property/rs_properties.h"
21 #include "property/rs_property_drawable_bounds_geometry.h"
22 #include "property/rs_property_drawable_frame_geometry.h"
23 #include "property/rs_property_drawable_utilities.h"
24 
25 namespace OHOS::Rosen {
26 namespace {
27 template<RSModifierType T>
CustomModifierAdapter(const RSRenderContent &)28 inline RSModifierDrawable::DrawablePtr CustomModifierAdapter(const RSRenderContent&)
29 {
30     return std::make_unique<RSModifierDrawable>(T);
31 }
32 
GenerateAlias(RSPropertyDrawableSlot slot)33 inline RSPropertyDrawable::DrawablePtr GenerateAlias(RSPropertyDrawableSlot slot)
34 {
35     return std::make_unique<RSAliasDrawable>(slot);
36 }
37 
GenerateSaveRestore(RSPaintFilterCanvas::SaveType type=RSPaintFilterCanvas::kCanvas)38 inline std::pair<RSPropertyDrawable::DrawablePtr, RSPropertyDrawable::DrawablePtr> GenerateSaveRestore(
39     RSPaintFilterCanvas::SaveType type = RSPaintFilterCanvas::kCanvas)
40 {
41     if (type == RSPaintFilterCanvas::kNone) {
42         return {};
43     } else if (type == RSPaintFilterCanvas::kCanvas) {
44         auto count = std::make_shared<uint32_t>(0);
45         return { std::make_unique<RSSaveDrawable>(count), std::make_unique<RSRestoreDrawable>(count) };
46     } else {
47         auto status = std::make_shared<RSPaintFilterCanvas::SaveStatus>();
48         return { std::make_unique<RSCustomSaveDrawable>(status, type),
49             std::make_unique<RSCustomRestoreDrawable>(status) };
50     }
51 }
52 
SaveRestoreHelper(RSPropertyDrawable::DrawableVec & drawableVec,RSPropertyDrawableSlot slot1,RSPropertyDrawableSlot slot2,RSPaintFilterCanvas::SaveType saveType)53 inline void SaveRestoreHelper(RSPropertyDrawable::DrawableVec& drawableVec, RSPropertyDrawableSlot slot1,
54     RSPropertyDrawableSlot slot2, RSPaintFilterCanvas::SaveType saveType)
55 {
56     std::tie(drawableVec[static_cast<size_t>(slot1)], drawableVec[static_cast<size_t>(slot2)]) =
57         GenerateSaveRestore(saveType);
58 }
59 
60 // key = RSModifierType, value = RSPropertyDrawableType
61 static const std::unordered_map<RSModifierType, RSPropertyDrawableSlot> g_propertyToDrawableLut = {
62     { RSModifierType::INVALID, RSPropertyDrawableSlot::INVALID },
63     { RSModifierType::BOUNDS, RSPropertyDrawableSlot::BOUNDS_MATRIX },
64     { RSModifierType::FRAME, RSPropertyDrawableSlot::FRAME_OFFSET },
65     { RSModifierType::POSITION_Z, RSPropertyDrawableSlot::BOUNDS_MATRIX },
66     { RSModifierType::POSITION_Z_APPLICABLE_CAMERA3D, RSPropertyDrawableSlot::BOUNDS_MATRIX },
67     { RSModifierType::PIVOT, RSPropertyDrawableSlot::BOUNDS_MATRIX },
68     { RSModifierType::PIVOT_Z, RSPropertyDrawableSlot::BOUNDS_MATRIX },
69     { RSModifierType::QUATERNION, RSPropertyDrawableSlot::BOUNDS_MATRIX },
70     { RSModifierType::ROTATION, RSPropertyDrawableSlot::BOUNDS_MATRIX },
71     { RSModifierType::ROTATION_X, RSPropertyDrawableSlot::BOUNDS_MATRIX },
72     { RSModifierType::ROTATION_Y, RSPropertyDrawableSlot::BOUNDS_MATRIX },
73     { RSModifierType::CAMERA_DISTANCE, RSPropertyDrawableSlot::BOUNDS_MATRIX },
74     { RSModifierType::SCALE, RSPropertyDrawableSlot::BOUNDS_MATRIX },
75     { RSModifierType::SCALE_Z, RSPropertyDrawableSlot::BOUNDS_MATRIX },
76     { RSModifierType::SKEW, RSPropertyDrawableSlot::BOUNDS_MATRIX },
77     { RSModifierType::PERSP, RSPropertyDrawableSlot::BOUNDS_MATRIX },
78     { RSModifierType::TRANSLATE, RSPropertyDrawableSlot::BOUNDS_MATRIX },
79     { RSModifierType::TRANSLATE_Z, RSPropertyDrawableSlot::BOUNDS_MATRIX },
80     { RSModifierType::SUBLAYER_TRANSFORM, RSPropertyDrawableSlot::INVALID },
81     { RSModifierType::CORNER_RADIUS, RSPropertyDrawableSlot::INVALID },
82     { RSModifierType::ALPHA, RSPropertyDrawableSlot::ALPHA },
83     { RSModifierType::ALPHA_OFFSCREEN, RSPropertyDrawableSlot::ALPHA },
84     { RSModifierType::FOREGROUND_COLOR, RSPropertyDrawableSlot::FOREGROUND_COLOR },
85     { RSModifierType::BACKGROUND_COLOR, RSPropertyDrawableSlot::BACKGROUND_COLOR },
86     { RSModifierType::BG_BRIGHTNESS_RATES, RSPropertyDrawableSlot::BACKGROUND_COLOR },
87     { RSModifierType::BG_BRIGHTNESS_SATURATION, RSPropertyDrawableSlot::BACKGROUND_COLOR },
88     { RSModifierType::BG_BRIGHTNESS_POSCOEFF, RSPropertyDrawableSlot::BACKGROUND_COLOR },
89     { RSModifierType::BG_BRIGHTNESS_NEGCOEFF, RSPropertyDrawableSlot::BACKGROUND_COLOR },
90     { RSModifierType::BG_BRIGHTNESS_FRACTION, RSPropertyDrawableSlot::BACKGROUND_COLOR },
91     { RSModifierType::BACKGROUND_SHADER, RSPropertyDrawableSlot::BACKGROUND_SHADER },
92     { RSModifierType::BG_IMAGE, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
93     { RSModifierType::BG_IMAGE_WIDTH, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
94     { RSModifierType::BG_IMAGE_HEIGHT, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
95     { RSModifierType::BG_IMAGE_POSITION_X, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
96     { RSModifierType::BG_IMAGE_POSITION_Y, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
97     { RSModifierType::SURFACE_BG_COLOR, RSPropertyDrawableSlot::INVALID },
98     { RSModifierType::BORDER_COLOR, RSPropertyDrawableSlot::BORDER },
99     { RSModifierType::BORDER_WIDTH, RSPropertyDrawableSlot::BORDER },
100     { RSModifierType::BORDER_STYLE, RSPropertyDrawableSlot::BORDER },
101     { RSModifierType::BORDER_DASH_WIDTH, RSPropertyDrawableSlot::BORDER },
102     { RSModifierType::BORDER_DASH_GAP, RSPropertyDrawableSlot::BORDER },
103     { RSModifierType::FILTER, RSPropertyDrawableSlot::COMPOSITING_FILTER },
104     { RSModifierType::BACKGROUND_FILTER, RSPropertyDrawableSlot::BACKGROUND_FILTER },
105     { RSModifierType::LINEAR_GRADIENT_BLUR_PARA, RSPropertyDrawableSlot::COMPOSITING_FILTER },
106     { RSModifierType::FOREGROUND_EFFECT_RADIUS, RSPropertyDrawableSlot::FOREGROUND_FILTER },
107     { RSModifierType::MOTION_BLUR_PARA, RSPropertyDrawableSlot::FOREGROUND_FILTER },
108     { RSModifierType::FLY_OUT_DEGREE, RSPropertyDrawableSlot::FOREGROUND_FILTER },
109     { RSModifierType::FLY_OUT_PARAMS, RSPropertyDrawableSlot::FOREGROUND_FILTER },
110     { RSModifierType::DISTORTION_K, RSPropertyDrawableSlot::FOREGROUND_FILTER },
111     { RSModifierType::MAGNIFIER_PARA, RSPropertyDrawableSlot::BACKGROUND_FILTER },
112     { RSModifierType::DYNAMIC_LIGHT_UP_RATE, RSPropertyDrawableSlot::DYNAMIC_LIGHT_UP },
113     { RSModifierType::DYNAMIC_LIGHT_UP_DEGREE, RSPropertyDrawableSlot::DYNAMIC_LIGHT_UP },
114     { RSModifierType::FRAME_GRAVITY, RSPropertyDrawableSlot::FRAME_OFFSET },
115     { RSModifierType::CLIP_RRECT, RSPropertyDrawableSlot::CLIP_TO_BOUNDS },
116     { RSModifierType::CLIP_BOUNDS, RSPropertyDrawableSlot::CLIP_TO_BOUNDS },
117     { RSModifierType::CLIP_TO_BOUNDS, RSPropertyDrawableSlot::CLIP_TO_BOUNDS },
118     { RSModifierType::CLIP_TO_FRAME, RSPropertyDrawableSlot::CLIP_TO_FRAME },
119     { RSModifierType::VISIBLE, RSPropertyDrawableSlot::INVALID },
120     { RSModifierType::SHADOW_COLOR, RSPropertyDrawableSlot::SHADOW },
121     { RSModifierType::SHADOW_OFFSET_X, RSPropertyDrawableSlot::SHADOW },
122     { RSModifierType::SHADOW_OFFSET_Y, RSPropertyDrawableSlot::SHADOW },
123     { RSModifierType::SHADOW_ALPHA, RSPropertyDrawableSlot::SHADOW },
124     { RSModifierType::SHADOW_ELEVATION, RSPropertyDrawableSlot::SHADOW },
125     { RSModifierType::SHADOW_RADIUS, RSPropertyDrawableSlot::SHADOW },
126     { RSModifierType::SHADOW_PATH, RSPropertyDrawableSlot::SHADOW },
127     { RSModifierType::SHADOW_MASK, RSPropertyDrawableSlot::SHADOW },
128     { RSModifierType::MASK, RSPropertyDrawableSlot::MASK },
129     { RSModifierType::SPHERIZE, RSPropertyDrawableSlot::INVALID },
130     { RSModifierType::LIGHT_UP_EFFECT, RSPropertyDrawableSlot::LIGHT_UP_EFFECT },
131     { RSModifierType::AIINVERT, RSPropertyDrawableSlot::BINARIZATION },
132     { RSModifierType::SYSTEMBAREFFECT, RSPropertyDrawableSlot::BACKGROUND_FILTER },
133     { RSModifierType::WATER_RIPPLE_PROGRESS, RSPropertyDrawableSlot::BACKGROUND_FILTER },
134     { RSModifierType::WATER_RIPPLE_PARAMS, RSPropertyDrawableSlot::BACKGROUND_FILTER },
135     { RSModifierType::PIXEL_STRETCH, RSPropertyDrawableSlot::PIXEL_STRETCH },
136     { RSModifierType::PIXEL_STRETCH_PERCENT, RSPropertyDrawableSlot::PIXEL_STRETCH },
137     { RSModifierType::PIXEL_STRETCH_TILE_MODE, RSPropertyDrawableSlot::PIXEL_STRETCH },
138     { RSModifierType::USE_EFFECT, RSPropertyDrawableSlot::USE_EFFECT },
139     { RSModifierType::SANDBOX, RSPropertyDrawableSlot::BOUNDS_MATRIX },
140     { RSModifierType::GRAY_SCALE, RSPropertyDrawableSlot::COLOR_FILTER },
141     { RSModifierType::BRIGHTNESS, RSPropertyDrawableSlot::COLOR_FILTER },
142     { RSModifierType::CONTRAST, RSPropertyDrawableSlot::COLOR_FILTER },
143     { RSModifierType::SATURATE, RSPropertyDrawableSlot::COLOR_FILTER },
144     { RSModifierType::SEPIA, RSPropertyDrawableSlot::COLOR_FILTER },
145     { RSModifierType::INVERT, RSPropertyDrawableSlot::COLOR_FILTER },
146     { RSModifierType::HUE_ROTATE, RSPropertyDrawableSlot::COLOR_FILTER },
147     { RSModifierType::COLOR_BLEND, RSPropertyDrawableSlot::COLOR_FILTER },
148     { RSModifierType::PARTICLE, RSPropertyDrawableSlot::PARTICLE_EFFECT },
149     { RSModifierType::SHADOW_IS_FILLED, RSPropertyDrawableSlot::INVALID },
150     { RSModifierType::OUTLINE_COLOR, RSPropertyDrawableSlot::OUTLINE },
151     { RSModifierType::OUTLINE_WIDTH, RSPropertyDrawableSlot::OUTLINE },
152     { RSModifierType::OUTLINE_STYLE, RSPropertyDrawableSlot::OUTLINE },
153     { RSModifierType::OUTLINE_DASH_WIDTH, RSPropertyDrawableSlot::OUTLINE },
154     { RSModifierType::OUTLINE_DASH_GAP, RSPropertyDrawableSlot::OUTLINE },
155     { RSModifierType::OUTLINE_RADIUS, RSPropertyDrawableSlot::OUTLINE },
156     { RSModifierType::USE_SHADOW_BATCHING, RSPropertyDrawableSlot::INVALID },
157     { RSModifierType::FG_BRIGHTNESS_RATES, RSPropertyDrawableSlot::BLEND_MODE },
158     { RSModifierType::FG_BRIGHTNESS_SATURATION, RSPropertyDrawableSlot::BLEND_MODE },
159     { RSModifierType::FG_BRIGHTNESS_POSCOEFF, RSPropertyDrawableSlot::BLEND_MODE },
160     { RSModifierType::FG_BRIGHTNESS_NEGCOEFF, RSPropertyDrawableSlot::BLEND_MODE },
161     { RSModifierType::FG_BRIGHTNESS_FRACTION, RSPropertyDrawableSlot::BLEND_MODE },
162     { RSModifierType::COLOR_BLEND_MODE, RSPropertyDrawableSlot::BLEND_MODE },
163     { RSModifierType::COLOR_BLEND_APPLY_TYPE, RSPropertyDrawableSlot::BLEND_MODE },
164     { RSModifierType::LIGHT_INTENSITY, RSPropertyDrawableSlot::POINT_LIGHT },
165     { RSModifierType::LIGHT_COLOR, RSPropertyDrawableSlot::POINT_LIGHT },
166     { RSModifierType::LIGHT_POSITION, RSPropertyDrawableSlot::POINT_LIGHT },
167     { RSModifierType::ILLUMINATED_TYPE, RSPropertyDrawableSlot::POINT_LIGHT },
168     { RSModifierType::BLOOM, RSPropertyDrawableSlot::POINT_LIGHT },
169     { RSModifierType::BACKGROUND_BLUR_RADIUS, RSPropertyDrawableSlot::BACKGROUND_FILTER },
170     { RSModifierType::BACKGROUND_BLUR_SATURATION, RSPropertyDrawableSlot::BACKGROUND_FILTER },
171     { RSModifierType::BACKGROUND_BLUR_BRIGHTNESS, RSPropertyDrawableSlot::BACKGROUND_FILTER },
172     { RSModifierType::BACKGROUND_BLUR_MASK_COLOR, RSPropertyDrawableSlot::BACKGROUND_FILTER },
173     { RSModifierType::BACKGROUND_BLUR_COLOR_MODE, RSPropertyDrawableSlot::BACKGROUND_FILTER },
174     { RSModifierType::BACKGROUND_BLUR_RADIUS_X, RSPropertyDrawableSlot::BACKGROUND_FILTER },
175     { RSModifierType::BACKGROUND_BLUR_RADIUS_Y, RSPropertyDrawableSlot::BACKGROUND_FILTER },
176     { RSModifierType::FOREGROUND_BLUR_RADIUS, RSPropertyDrawableSlot::COMPOSITING_FILTER },
177     { RSModifierType::FOREGROUND_BLUR_SATURATION, RSPropertyDrawableSlot::COMPOSITING_FILTER },
178     { RSModifierType::FOREGROUND_BLUR_BRIGHTNESS, RSPropertyDrawableSlot::COMPOSITING_FILTER },
179     { RSModifierType::FOREGROUND_BLUR_MASK_COLOR, RSPropertyDrawableSlot::COMPOSITING_FILTER },
180     { RSModifierType::FOREGROUND_BLUR_COLOR_MODE, RSPropertyDrawableSlot::COMPOSITING_FILTER },
181     { RSModifierType::FOREGROUND_BLUR_RADIUS_X, RSPropertyDrawableSlot::COMPOSITING_FILTER },
182     { RSModifierType::FOREGROUND_BLUR_RADIUS_Y, RSPropertyDrawableSlot::COMPOSITING_FILTER },
183     { RSModifierType::ATTRACTION_FRACTION, RSPropertyDrawableSlot::INVALID },
184     { RSModifierType::ATTRACTION_DSTPOINT, RSPropertyDrawableSlot::INVALID },
185     { RSModifierType::CUSTOM, RSPropertyDrawableSlot::INVALID },
186     { RSModifierType::EXTENDED, RSPropertyDrawableSlot::INVALID },
187     { RSModifierType::TRANSITION, RSPropertyDrawableSlot::TRANSITION },
188     { RSModifierType::BACKGROUND_STYLE, RSPropertyDrawableSlot::BACKGROUND_STYLE },
189     { RSModifierType::CONTENT_STYLE, RSPropertyDrawableSlot::CONTENT_STYLE },
190     { RSModifierType::FOREGROUND_STYLE, RSPropertyDrawableSlot::FOREGROUND_STYLE },
191     { RSModifierType::OVERLAY_STYLE, RSPropertyDrawableSlot::OVERLAY },
192     { RSModifierType::NODE_MODIFIER, RSPropertyDrawableSlot::INVALID },
193     { RSModifierType::ENV_FOREGROUND_COLOR, RSPropertyDrawableSlot::ENV_FOREGROUND_COLOR },
194     { RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY, RSPropertyDrawableSlot::ENV_FOREGROUND_COLOR_STRATEGY },
195     { RSModifierType::CUSTOM_CLIP_TO_FRAME, RSPropertyDrawableSlot::CUSTOM_CLIP_TO_FRAME },
196     { RSModifierType::HDR_BRIGHTNESS, RSPropertyDrawableSlot::INVALID },
197     { RSModifierType::PARTICLE_EMITTER_UPDATER, RSPropertyDrawableSlot::PARTICLE_EFFECT },
198     { RSModifierType::PARTICLE_NOISE_FIELD, RSPropertyDrawableSlot::PARTICLE_EFFECT },
199     { RSModifierType::DYNAMIC_DIM_DEGREE, RSPropertyDrawableSlot::DYNAMIC_DIM },
200     { RSModifierType::GEOMETRYTRANS, RSPropertyDrawableSlot::INVALID },
201 };
202 
203 // NOTE: This LUT should always the same size as RSPropertyDrawableSlot
204 // index = RSPropertyDrawableType, value = DrawableGenerator
205 constexpr int LUT_SIZE = static_cast<int>(RSPropertyDrawableSlot::MAX);
206 static const std::array<RSPropertyDrawable::DrawableGenerator, LUT_SIZE> g_drawableGeneratorLut = {
207     nullptr, // INVALID = 0
208     nullptr, // SAVE_ALL
209 
210     // Bounds Geometry
211     nullptr,                                                     // BOUNDS_MATRIX
212     RSAlphaDrawable::Generate,                                   // ALPHA
213     RSMaskDrawable::Generate,                                    // MASK
214     CustomModifierAdapter<RSModifierType::TRANSITION>,           // TRANSITION
215     CustomModifierAdapter<RSModifierType::ENV_FOREGROUND_COLOR>, // ENV_FOREGROUND_COLOR
216     RSShadowDrawable::Generate,                                  // SHADOW
217     RSForegroundFilterDrawable::Generate,                        // FOREGROUND_FILTER
218     RSOutlineDrawable::Generate,                                 // OUTLINE
219 
220     // BG properties in Bounds Clip
221     nullptr,                                                              // BG_SAVE_BOUNDS
222     nullptr,                                                              // CLIP_TO_BOUNDS
223     BlendSaveDrawableGenerate,                                            // BLEND_MODE
224     RSBackgroundColorDrawable::Generate,                                  // BACKGROUND_COLOR
225     RSBackgroundShaderDrawable::Generate,                                 // BACKGROUND_SHADER
226     RSBackgroundImageDrawable::Generate,                                  // BACKGROUND_IMAGE
227     RSBackgroundFilterDrawable::Generate,                                 // BACKGROUND_FILTER
228     RSEffectDataApplyDrawable::Generate,                                  // USE_EFFECT
229     CustomModifierAdapter<RSModifierType::BACKGROUND_STYLE>,              // BACKGROUND_STYLE
230     RSDynamicLightUpDrawable::Generate,                                   // DYNAMIC_LIGHT_UP
231     CustomModifierAdapter<RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY>, // ENV_FOREGROUND_COLOR_STRATEGY
232     nullptr,                                                              // BG_RESTORE_BOUNDS
233 
234     // Frame Geometry
235     nullptr,                                                 // SAVE_FRAME
236     nullptr,                                                 // FRAME_OFFSET
237     RSClipFrameDrawable::Generate,                           // CLIP_TO_FRAME
238     CustomModifierAdapter<RSModifierType::CUSTOM_CLIP_TO_FRAME>,    // CUSTOM_CLIP_TO_FRAME
239     CustomModifierAdapter<RSModifierType::CONTENT_STYLE>,    // CONTENT_STYLE
240     nullptr,                                                 // CHILDREN
241     CustomModifierAdapter<RSModifierType::FOREGROUND_STYLE>, // FOREGROUND_STYLE
242     nullptr,                                                 // RESTORE_FRAME
243 
244     // FG properties in Bounds clip
245     nullptr,                                      // FG_SAVE_BOUNDS
246     nullptr,                                      // EXTRA_CLIP_TO_BOUNDS
247     RSBinarizationDrawable::Generate,             // BINARIZATION,
248     RSColorFilterDrawable::Generate,              // COLOR_FILTER
249     RSDynamicDimDrawable::Generate,               // DYNAMIC_DIM
250     RSLightUpEffectDrawable::Generate,            // LIGHT_UP_EFFECT
251     RSCompositingFilterDrawable::Generate,        // COMPOSITING_FILTER
252     RSForegroundColorDrawable::Generate,          // FOREGROUND_COLOR
253     nullptr,                                      // FG_RESTORE_BOUNDS
254 
255     // No clip (unless ClipToBounds is set)
256     RSPointLightDrawable::Generate,                       // POINT_LIGHT
257     RSBorderDrawable::Generate,                           // BORDER
258     CustomModifierAdapter<RSModifierType::OVERLAY_STYLE>, // OVERLAY
259     RSParticleDrawable::Generate,                         // PARTICLE_EFFECT
260     RSPixelStretchDrawable::Generate,                     // PIXEL_STRETCH
261 
262     BlendRestoreDrawableGenerate,                   // RESTORE_BLEND
263     RSForegroundFilterRestoreDrawable::Generate,    // RESTORE_FOREGROUND_FILTER
264     nullptr,                                        // RESTORE_ALL
265 };
266 
267 enum DrawableVecStatus : uint8_t {
268     CLIP_TO_BOUNDS          = 1 << 0,
269     BG_BOUNDS_PROPERTY      = 1 << 1,
270     FG_BOUNDS_PROPERTY      = 1 << 2,
271     CLIP_TO_FRAME           = 1 << 3,
272     FRAME_PROPERTY          = 1 << 4,
273     HAS_CHILDREN            = 1 << 5,
274     BOUNDS_MASK             = CLIP_TO_BOUNDS | BG_BOUNDS_PROPERTY | FG_BOUNDS_PROPERTY,
275     FRAME_MASK              = CLIP_TO_FRAME | FRAME_PROPERTY | HAS_CHILDREN,
276 };
277 } // namespace
278 
GenerateDirtySlots(const RSProperties & properties,const ModifierDirtyTypes & dirtyTypes)279 std::unordered_set<RSPropertyDrawableSlot> RSPropertyDrawable::GenerateDirtySlots(
280     const RSProperties& properties, const ModifierDirtyTypes& dirtyTypes)
281 {
282     // Step 1.1: collect dirty slots
283     std::unordered_set<RSPropertyDrawableSlot> dirtySlots;
284     for (uint8_t type = 0; type < static_cast<size_t>(RSModifierType::MAX_RS_MODIFIER_TYPE); type++) {
285         if (dirtyTypes[type]) {
286             auto it = g_propertyToDrawableLut.find(static_cast<RSModifierType>(type));
287             if (it == g_propertyToDrawableLut.end() || it->second == RSPropertyDrawableSlot::INVALID) {
288                 continue;
289             }
290             dirtySlots.emplace(it->second);
291         }
292     }
293 
294     // Step 1.2: expand dirty slots if needed
295     if (dirtyTypes.test(static_cast<size_t>(RSModifierType::BOUNDS))) {
296         if (properties.GetPixelStretch().has_value()) {
297             dirtySlots.emplace(RSPropertyDrawableSlot::PIXEL_STRETCH);
298         }
299         if (properties.GetBorder() != nullptr) {
300             dirtySlots.emplace(RSPropertyDrawableSlot::BORDER);
301         }
302         if (properties.GetOutline() != nullptr) {
303             dirtySlots.emplace(RSPropertyDrawableSlot::OUTLINE);
304         }
305         // PLANNING: add other slots: ClipToFrame, ColorFilter
306     }
307     if (dirtyTypes.test(static_cast<size_t>(RSModifierType::CORNER_RADIUS))) {
308         // border may should be updated with corner radius
309         if (properties.GetBorder() != nullptr) {
310             dirtySlots.emplace(RSPropertyDrawableSlot::BORDER);
311         }
312 
313         if (properties.GetOutline() != nullptr) {
314             dirtySlots.emplace(RSPropertyDrawableSlot::OUTLINE);
315         }
316     }
317     if (dirtySlots.count(RSPropertyDrawableSlot::BLEND_MODE)) {
318         // BlendMode Restore should be regenerated with BlendMode
319         dirtySlots.emplace(RSPropertyDrawableSlot::RESTORE_BLEND_MODE);
320     }
321     if (dirtySlots.count(RSPropertyDrawableSlot::FOREGROUND_FILTER)) {
322         // ForegroundFilter Restore should be regenerated with ForegroundFilter
323         dirtySlots.emplace(RSPropertyDrawableSlot::RESTORE_FOREGROUND_FILTER);
324     }
325 
326     return dirtySlots;
327 }
328 
UpdateDrawableVec(const RSRenderContent & content,DrawableVec & drawableVec,std::unordered_set<RSPropertyDrawableSlot> & dirtySlots)329 bool RSPropertyDrawable::UpdateDrawableVec(
330     const RSRenderContent& content, DrawableVec& drawableVec, std::unordered_set<RSPropertyDrawableSlot>& dirtySlots)
331 {
332     if (dirtySlots.empty()) {
333         return false;
334     }
335     // ====================================================================
336     // Step 2.1: re-generate drawables for all dirty slots
337     auto drawableSlotChanged = false;
338     for (const auto& slot : dirtySlots) {
339         auto& origDrawable = drawableVec[static_cast<size_t>(slot)];
340         if (origDrawable != nullptr && origDrawable->Update(content)) {
341             continue;
342         }
343         auto& generator = g_drawableGeneratorLut[static_cast<int>(slot)];
344         if (!generator) {
345             continue;
346         }
347         auto drawable = generator(content);
348         if (bool(origDrawable) != bool(drawable)) {
349             // drawable slot changed (nullptr to non-nullptr or vice versa)
350             drawableSlotChanged = true;
351         }
352         origDrawable = std::move(drawable);
353     }
354 
355     // Step 2.2: post-generate hooks (PLANNING: refactor this into a separate function)
356 
357     // Temporary fix, change of clipToBounds should trigger UpdateSaveRestore
358     if (!drawableSlotChanged && dirtySlots.count(RSPropertyDrawableSlot::CLIP_TO_BOUNDS)) {
359         drawableSlotChanged = true;
360     }
361 
362     return drawableSlotChanged;
363 }
364 
365 namespace {
HasPropertyDrawableInRange(const RSPropertyDrawable::DrawableVec & drawableVec,RSPropertyDrawableSlot begin,RSPropertyDrawableSlot end)366 inline bool HasPropertyDrawableInRange(
367     const RSPropertyDrawable::DrawableVec& drawableVec, RSPropertyDrawableSlot begin, RSPropertyDrawableSlot end)
368 {
369     return std::any_of(drawableVec.begin() + static_cast<size_t>(begin), drawableVec.begin() + static_cast<size_t>(end),
370         [](const auto& drawablePtr) { return drawablePtr != nullptr; });
371 }
372 
CalculateDrawableVecStatus(RSRenderContent & content,const RSPropertyDrawable::DrawableVec & drawableVec)373 uint8_t CalculateDrawableVecStatus(RSRenderContent& content, const RSPropertyDrawable::DrawableVec& drawableVec)
374 {
375     uint8_t result = 0;
376     auto& properties = content.GetRenderProperties();
377 
378     // color blend mode has implicit dependency on clipToBounds
379     if (properties.GetClipToBounds() || properties.GetClipToRRect() || properties.GetClipBounds() != nullptr ||
380         properties.GetColorBlendMode()) {
381         result |= DrawableVecStatus::CLIP_TO_BOUNDS;
382     }
383     if (properties.GetClipToFrame()) {
384         result |= DrawableVecStatus::CLIP_TO_FRAME;
385     }
386 
387     if (HasPropertyDrawableInRange(
388         drawableVec, RSPropertyDrawableSlot::BG_PROPERTIES_BEGIN, RSPropertyDrawableSlot::BG_PROPERTIES_END)) {
389         result |= DrawableVecStatus::BG_BOUNDS_PROPERTY;
390     }
391     if (HasPropertyDrawableInRange(
392         drawableVec, RSPropertyDrawableSlot::FG_PROPERTIES_BEGIN, RSPropertyDrawableSlot::FG_PROPERTIES_END)) {
393         result |= DrawableVecStatus::FG_BOUNDS_PROPERTY;
394     }
395     if (HasPropertyDrawableInRange(drawableVec, RSPropertyDrawableSlot::CONTENT_PROPERTIES_BEGIN,
396         RSPropertyDrawableSlot::CONTENT_PROPERTIES_END)) {
397         result |= DrawableVecStatus::FRAME_PROPERTY;
398     }
399 
400     return result;
401 }
402 
403 constexpr std::array boundsSlotsToErase = {
404     RSPropertyDrawableSlot::BG_SAVE_BOUNDS,
405     RSPropertyDrawableSlot::CLIP_TO_BOUNDS,
406     RSPropertyDrawableSlot::BG_RESTORE_BOUNDS,
407     RSPropertyDrawableSlot::FG_SAVE_BOUNDS,
408     RSPropertyDrawableSlot::FG_CLIP_TO_BOUNDS,
409     RSPropertyDrawableSlot::FG_RESTORE_BOUNDS,
410 };
411 
412 constexpr std::array frameSlotsToErase = {
413     RSPropertyDrawableSlot::SAVE_FRAME,
414     RSPropertyDrawableSlot::RESTORE_FRAME,
415 };
416 
OptimizeBoundsSaveRestore(RSRenderContent & content,RSPropertyDrawable::DrawableVec & drawableVec,uint8_t flags)417 void OptimizeBoundsSaveRestore(RSRenderContent& content, RSPropertyDrawable::DrawableVec& drawableVec, uint8_t flags)
418 {
419     // Erase existing save/clip/restore before re-generating
420     for (auto& slot : boundsSlotsToErase) {
421         drawableVec[static_cast<size_t>(slot)] = nullptr;
422     }
423 
424     if (flags & DrawableVecStatus::CLIP_TO_BOUNDS) {
425         // case 1: ClipToBounds set.
426         // add one clip, and reuse SAVE_ALL and RESTORE_ALL.
427         drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::CLIP_TO_BOUNDS)] =
428             RSClipBoundsDrawable::Generate(content);
429         return;
430     }
431 
432     if ((flags & DrawableVecStatus::BG_BOUNDS_PROPERTY) && (flags & DrawableVecStatus::FG_BOUNDS_PROPERTY)) {
433         // case 2: ClipToBounds not set and we have bounds properties both BG and FG.
434         // add two sets of save/clip/restore before & after content.
435 
436         // part 1: before children
437         SaveRestoreHelper(drawableVec, RSPropertyDrawableSlot::BG_SAVE_BOUNDS,
438             RSPropertyDrawableSlot::BG_RESTORE_BOUNDS, RSPaintFilterCanvas::kCanvas);
439         drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::CLIP_TO_BOUNDS)] =
440             RSClipBoundsDrawable::Generate(content);
441 
442         // part 2: after children, add aliases
443         drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FG_SAVE_BOUNDS)] =
444             GenerateAlias(RSPropertyDrawableSlot::BG_SAVE_BOUNDS);
445         drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FG_CLIP_TO_BOUNDS)] =
446             GenerateAlias(RSPropertyDrawableSlot::CLIP_TO_BOUNDS);
447         drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FG_RESTORE_BOUNDS)] =
448             GenerateAlias(RSPropertyDrawableSlot::BG_RESTORE_BOUNDS);
449         return;
450     }
451 
452     if (flags & DrawableVecStatus::BG_BOUNDS_PROPERTY) {
453         // case 3: ClipToBounds not set and we have background bounds properties.
454         SaveRestoreHelper(drawableVec, RSPropertyDrawableSlot::BG_SAVE_BOUNDS,
455             RSPropertyDrawableSlot::BG_RESTORE_BOUNDS, RSPaintFilterCanvas::kCanvas);
456 
457         drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::CLIP_TO_BOUNDS)] =
458             RSClipBoundsDrawable::Generate(content);
459         return;
460     }
461 
462     if (flags & DrawableVecStatus::FG_BOUNDS_PROPERTY) {
463         // case 4: ClipToBounds not set and we have foreground bounds properties.
464         SaveRestoreHelper(drawableVec, RSPropertyDrawableSlot::FG_SAVE_BOUNDS,
465             RSPropertyDrawableSlot::FG_RESTORE_BOUNDS, RSPaintFilterCanvas::kCanvas);
466 
467         drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FG_CLIP_TO_BOUNDS)] =
468             RSClipBoundsDrawable::Generate(content);
469         return;
470     }
471     // case 5: ClipToBounds not set and no bounds properties, no need to save/clip/restore.
472     // nothing to do
473 }
474 
OptimizeFrameSaveRestore(RSRenderContent & content,RSPropertyDrawable::DrawableVec & drawableVec,uint8_t flags)475 void OptimizeFrameSaveRestore(RSRenderContent& content, RSPropertyDrawable::DrawableVec& drawableVec, uint8_t flags)
476 {
477     // Erase existing save/clip/restore before re-generating
478     for (auto& slot : frameSlotsToErase) {
479         drawableVec[static_cast<size_t>(slot)] = nullptr;
480     }
481 
482     // PLANNING: if both clipToFrame and clipToBounds are set, and frame == bounds, we don't need an extra clip
483     if (flags & DrawableVecStatus::FRAME_PROPERTY) {
484         // save/restore
485         SaveRestoreHelper(drawableVec, RSPropertyDrawableSlot::SAVE_FRAME,
486             RSPropertyDrawableSlot::RESTORE_FRAME, RSPaintFilterCanvas::kCanvas);
487     } else {
488         // no need to save/clip/restore
489     }
490 }
491 } // namespace
492 
InitializeSaveRestore(const RSRenderContent & content,DrawableVec & drawableVec)493 void RSPropertyDrawable::InitializeSaveRestore(const RSRenderContent& content, DrawableVec& drawableVec)
494 {
495     SaveRestoreHelper(
496         drawableVec, RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::RESTORE_ALL, RSPaintFilterCanvas::kAll);
497     drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::BOUNDS_MATRIX)] =
498         RSBoundsGeometryDrawable::Generate(content);
499     drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FRAME_OFFSET)] = RSFrameGeometryDrawable::Generate(content);
500 }
501 
UpdateSaveRestore(RSRenderContent & content,DrawableVec & drawableVec,uint8_t & drawableVecStatus)502 void RSPropertyDrawable::UpdateSaveRestore(
503     RSRenderContent& content, DrawableVec& drawableVec, uint8_t& drawableVecStatus)
504 {
505     // ====================================================================
506     // Step 3: Universal save/clip/restore optimization
507 
508     // calculate new drawable map status
509     auto drawableVecStatusNew = CalculateDrawableVecStatus(content, drawableVec);
510 
511     // calculate changed bits
512     uint8_t changedBits = drawableVecStatus ^ drawableVecStatusNew;
513     if (changedBits & BOUNDS_MASK) {
514         // update bounds save/clip if need
515         OptimizeBoundsSaveRestore(content, drawableVec, drawableVecStatusNew);
516     }
517     if (changedBits & FRAME_MASK) {
518         // update frame save/clip if need
519         OptimizeFrameSaveRestore(content, drawableVec, drawableVecStatusNew);
520     }
521     drawableVecStatus = drawableVecStatusNew;
522 }
523 
524 } // namespace OHOS::Rosen
525