1 /* 2 * Copyright (c) 2022 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SHAPE_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SHAPE_PATTERN_H 18 19 #include <cstddef> 20 #include <optional> 21 22 #include "base/geometry/ng/rect_t.h" 23 #include "base/log/log_wrapper.h" 24 #include "base/memory/referenced.h" 25 #include "base/utils/noncopyable.h" 26 #include "core/components_ng/pattern/pattern.h" 27 #include "core/components_ng/pattern/shape/shape_container_pattern.h" 28 #include "core/components_ng/pattern/shape/shape_layout_algorithm.h" 29 #include "core/components_ng/pattern/shape/shape_overlay_modifier.h" 30 #include "core/components_ng/pattern/shape/shape_paint_property.h" 31 #include "core/components_ng/pattern/shape/shape_view_box.h" 32 33 namespace OHOS::Ace::NG { 34 class ShapePattern : public Pattern { 35 DECLARE_ACE_TYPE(ShapePattern, Pattern); 36 37 public: 38 ShapePattern() = default; 39 ~ShapePattern() override = default; 40 IsEnableMatchParent()41 bool IsEnableMatchParent() override 42 { 43 return true; 44 } 45 IsEnableFix()46 bool IsEnableFix() override 47 { 48 return true; 49 } 50 CreateLayoutAlgorithm()51 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override 52 { 53 return MakeRefPtr<ShapeLayoutAlgorithm>(); 54 } 55 CreatePaintProperty()56 RefPtr<PaintProperty> CreatePaintProperty() override 57 { 58 return MakeRefPtr<ShapePaintProperty>(); 59 } 60 OnModifyDone()61 void OnModifyDone() override 62 { 63 Pattern::CheckLocalized(); 64 auto host = GetHost(); 65 CHECK_NULL_VOID(host); 66 auto paintProperty = host->GetPaintProperty<ShapePaintProperty>(); 67 CHECK_NULL_VOID(paintProperty); 68 if (paintProperty->HasStrokeMiterLimit()) { 69 auto miterLimit = paintProperty->GetStrokeMiterLimitValue(); 70 if (Negative(miterLimit)) { 71 paintProperty->UpdateStrokeMiterLimit(ShapePaintProperty::STROKE_MITERLIMIT_DEFAULT); 72 } else if (NonNegative(miterLimit) && 73 LessNotEqual(miterLimit, ShapePaintProperty::STROKE_MITERLIMIT_MIN)) { 74 paintProperty->UpdateStrokeMiterLimit(ShapePaintProperty::STROKE_MITERLIMIT_MIN); 75 } 76 } 77 } 78 79 protected: GetAncestorPaintProperty()80 RefPtr<ShapePaintProperty> GetAncestorPaintProperty() 81 { 82 auto curFrameNode = GetHost(); 83 CHECK_NULL_RETURN(curFrameNode, nullptr); 84 auto childNode = curFrameNode; 85 ShapePaintProperty propertiesFromAncestor; 86 auto parentFrameNode = AceType::DynamicCast<FrameNode>(curFrameNode->GetAncestorNodeOfFrame(false)); 87 while (parentFrameNode) { 88 auto parentPaintProperty = parentFrameNode->GetPaintProperty<ShapePaintProperty>(); 89 if (parentPaintProperty) { 90 propertiesFromAncestor.UpdateShapeProperty(parentPaintProperty); 91 UpdateForeground(parentFrameNode, childNode); 92 auto pattern = AceType::DynamicCast<ShapeContainerPattern>(parentFrameNode->GetPattern()); 93 if (pattern) { 94 pattern->AddChildShapeNode(WeakPtr<FrameNode>(childNode)); 95 } 96 } 97 curFrameNode = parentFrameNode; 98 parentFrameNode = AceType::DynamicCast<FrameNode>(curFrameNode->GetAncestorNodeOfFrame(false)); 99 } 100 return DynamicCast<ShapePaintProperty>(propertiesFromAncestor.Clone()); 101 } 102 OnForegroundColorUpdate()103 void OnForegroundColorUpdate() override 104 { 105 auto host = GetHost(); 106 CHECK_NULL_VOID(host); 107 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER); 108 } 109 UpdateForeground(RefPtr<FrameNode> parentFrameNode,RefPtr<FrameNode> childFrameNode)110 void UpdateForeground(RefPtr<FrameNode> parentFrameNode, RefPtr<FrameNode> childFrameNode) 111 { 112 auto renderContext = parentFrameNode->GetRenderContext(); 113 CHECK_NULL_VOID(renderContext); 114 auto childRenderContext = childFrameNode->GetRenderContext(); 115 CHECK_NULL_VOID(childRenderContext); 116 if (!childRenderContext->HasForegroundColor() && !childRenderContext->HasForegroundColorStrategy()) { 117 if (renderContext->HasForegroundColor()) { 118 childRenderContext->UpdateForegroundColor(renderContext->GetForegroundColorValue()); 119 childRenderContext->ResetForegroundColorStrategy(); 120 childRenderContext->UpdateForegroundColorFlag(false); 121 } else if (renderContext->HasForegroundColorStrategy()) { 122 childRenderContext->UpdateForegroundColorStrategy(renderContext->GetForegroundColorStrategyValue()); 123 childRenderContext->ResetForegroundColor(); 124 childRenderContext->UpdateForegroundColorFlag(false); 125 } 126 } else { 127 if (!childRenderContext->GetForegroundColorFlag().value_or(false)) { 128 if (renderContext->HasForegroundColor()) { 129 childRenderContext->UpdateForegroundColor(renderContext->GetForegroundColorValue()); 130 childRenderContext->ResetForegroundColorStrategy(); 131 childRenderContext->UpdateForegroundColorFlag(false); 132 } else if (renderContext->HasForegroundColorStrategy()) { 133 childRenderContext->UpdateForegroundColorStrategy(renderContext->GetForegroundColorStrategyValue()); 134 childRenderContext->ResetForegroundColor(); 135 childRenderContext->UpdateForegroundColorFlag(false); 136 } 137 } 138 } 139 } 140 UpdatePropertyImpl(const std::string & key,RefPtr<PropertyValueBase> value)141 void UpdatePropertyImpl(const std::string& key, RefPtr<PropertyValueBase> value) override 142 { 143 auto frameNode = GetHost(); 144 CHECK_NULL_VOID(frameNode); 145 using Handler = std::function<void(RefPtr<PropertyValueBase>, RefPtr<FrameNode>)>; 146 static const std::unordered_map<std::string, Handler> handlers = { 147 { "ShapeAbstractStroke", 148 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) { 149 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) { 150 ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, Stroke, *realValue, frameNode); 151 } 152 } }, 153 { "ShapeAbstractFill", 154 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) { 155 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) { 156 ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, Fill, *realValue, frameNode); 157 ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, *realValue, frameNode); 158 ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, frameNode); 159 } 160 } }, 161 { "ShapeAbstractStrokeOpacity", 162 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) { 163 if (auto realValue = std::get_if<double>(&(value->GetValue()))) { 164 ACE_UPDATE_NODE_PAINT_PROPERTY( 165 ShapePaintProperty, StrokeOpacity, std::clamp(*realValue, 0.0, 1.0), frameNode); 166 } 167 } }, 168 { "ShapeAbstractFillOpacity", 169 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) { 170 if (auto realValue = std::get_if<double>(&(value->GetValue()))) { 171 ACE_UPDATE_NODE_PAINT_PROPERTY( 172 ShapePaintProperty, FillOpacity, std::clamp(*realValue, 0.0, 1.0), frameNode); 173 } 174 } }, 175 { "ShapeAbstractStrokeWidth", 176 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) { 177 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) { 178 auto strokeWidth = realValue->IsNegative() ? 1.0_vp : *realValue; 179 ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, StrokeWidth, strokeWidth, frameNode); 180 } 181 } }, 182 { "ShapeAbstractWidth", 183 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) { 184 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) { 185 auto width = *realValue; 186 if (LessNotEqual(width.Value(), 0.0)) { 187 width.SetValue(0.0); 188 } 189 CHECK_NULL_VOID(frameNode); 190 auto layoutProperty = frameNode->GetLayoutProperty(); 191 CHECK_NULL_VOID(layoutProperty); 192 // get previously user defined ideal height 193 std::optional<CalcLength> height = std::nullopt; 194 auto&& layoutConstraint = layoutProperty->GetCalcLayoutConstraint(); 195 if (layoutConstraint && layoutConstraint->selfIdealSize) { 196 height = layoutConstraint->selfIdealSize->Height(); 197 } 198 layoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(width), height)); 199 } 200 } }, 201 { "ShapeAbstractHeight", 202 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) { 203 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) { 204 auto height = *realValue; 205 if (LessNotEqual(height.Value(), 0.0)) { 206 height.SetValue(0.0); 207 } 208 CHECK_NULL_VOID(frameNode); 209 auto layoutProperty = frameNode->GetLayoutProperty(); 210 CHECK_NULL_VOID(layoutProperty); 211 std::optional<CalcLength> width = std::nullopt; 212 auto&& layoutConstraint = layoutProperty->GetCalcLayoutConstraint(); 213 if (layoutConstraint && layoutConstraint->selfIdealSize) { 214 width = layoutConstraint->selfIdealSize->Width(); 215 } 216 layoutProperty->UpdateUserDefinedIdealSize(CalcSize(width, CalcLength(height))); 217 } 218 } }, 219 { "ShapeAbstractForegroundColor", 220 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) { 221 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) { 222 if (!ViewStackProcessor::GetInstance()->IsCurrentVisualStateProcess()) { 223 return; 224 } 225 ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, Fill, *realValue, frameNode); 226 ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, *realValue, frameNode); 227 ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, frameNode); 228 } 229 } }, 230 }; 231 auto it = handlers.find(key); 232 if (it != handlers.end()) { 233 it->second(value, frameNode); 234 } 235 if (frameNode->GetRerenderable()) { 236 frameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER); 237 } 238 } 239 240 RefPtr<ShapeOverlayModifier> shapeOverlayModifier_; 241 242 private: OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,bool skipMeasure,bool skipLayout)243 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, bool skipMeasure, bool skipLayout) override 244 { 245 return !(skipMeasure || dirty->SkipMeasureContent()); 246 } 247 ACE_DISALLOW_COPY_AND_MOVE(ShapePattern); 248 }; 249 } // namespace OHOS::Ace::NG 250 251 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SHAPE_PATTERN_H 252