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_RENDER_OVERLAY_MODIFIER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_OVERLAY_MODIFIER_H 18 19 #include <memory> 20 #include <string> 21 22 #include "modifier/rs_animatable_arithmetic.h" 23 #include "render_service_client/core/modifier/rs_extended_modifier.h" 24 #include "render_service_client/core/modifier/rs_property.h" 25 26 #include "base/geometry/ng/offset_t.h" 27 #include "base/i18n/localization.h" 28 #include "base/memory/referenced.h" 29 #include "core/components/common/properties/alignment.h" 30 #include "core/components_ng/property/overlay_property.h" 31 #include "core/components_ng/render/drawing.h" 32 #include "core/components_ng/render/drawing_prop_convertor.h" 33 #include "core/components_ng/render/font_collection.h" 34 #include "core/pipeline/pipeline_base.h" 35 36 namespace OHOS::Ace::NG { 37 38 class OverlayTextData : public Rosen::RSArithmetic<OverlayTextData> { 39 public: 40 OverlayTextData() = default; OverlayTextData(const OverlayOptions & overlay)41 explicit OverlayTextData(const OverlayOptions& overlay) : overlay_(overlay) {} 42 ~OverlayTextData() override = default; 43 IsEqual(const OverlayTextData & other)44 bool IsEqual(const OverlayTextData& other) const override 45 { 46 return overlay_ == other.overlay_; 47 } 48 GetOverlayOptions()49 OverlayOptions GetOverlayOptions() 50 { 51 return overlay_; 52 } 53 54 private: 55 OverlayOptions overlay_; 56 }; 57 58 class OverlayTextModifier : public Rosen::RSOverlayStyleModifier { 59 public: 60 OverlayTextModifier() = default; 61 ~OverlayTextModifier() override = default; 62 Draw(Rosen::RSDrawingContext & context)63 void Draw(Rosen::RSDrawingContext& context) const override 64 { 65 if (property_) { 66 const Dimension fontSize = Dimension(40); 67 auto overlayOptions = property_->Get().GetOverlayOptions(); 68 // create paragraph 69 TextStyle textStyle; 70 textStyle.SetFontSize(fontSize); 71 RSParagraphStyle paraStyle; 72 paraStyle.textAlign_ = ToRSTextAlign(textStyle.GetTextAlign()); 73 paraStyle.maxLines_ = textStyle.GetMaxLines(); 74 paraStyle.locale_ = Localization::GetInstance()->GetFontLocale(); 75 paraStyle.wordBreakType_ = ToRSWordBreakType(textStyle.GetWordBreak()); 76 paraStyle.fontSize_ = fontSize.Value(); 77 auto builder = RSParagraphBuilder::CreateRosenBuilder(paraStyle, RSFontCollection::GetInstance(false)); 78 CHECK_NULL_VOID(builder); 79 auto pipelineContext = PipelineBase::GetCurrentContext(); 80 CHECK_NULL_VOID(pipelineContext); 81 builder->PushStyle(ToRSTextStyle(pipelineContext, textStyle)); 82 builder->AddText(StringUtils::Str8ToStr16(overlayOptions.content)); 83 builder->Pop(); 84 auto paragraph = builder->Build(); 85 CHECK_NULL_VOID(paragraph); 86 paragraph->Layout(context.width); 87 OffsetF offset = OverlayTextModifier::GetTextPosition(SizeF(context.width, context.height), 88 SizeF(paragraph->GetLongestLine(), paragraph->GetHeight()), overlayOptions); 89 #ifndef USE_ROSEN_DRAWING 90 std::shared_ptr<SkCanvas> skCanvas { context.canvas, [](SkCanvas*) {} }; 91 RSCanvas canvas(&skCanvas); 92 CHECK_NULL_VOID(&canvas); 93 paragraph->Paint(&canvas, offset.GetX(), offset.GetY()); 94 #else 95 CHECK_NULL_VOID(context.canvas); 96 paragraph->Paint(context.canvas, offset.GetX(), offset.GetY()); 97 #endif 98 } else { 99 LOGE("property is null"); 100 } 101 } 102 SetCustomData(const OverlayTextData & data)103 void SetCustomData(const OverlayTextData& data) 104 { 105 if (!property_) { 106 property_ = std::make_shared<Rosen::RSProperty<OverlayTextData>>(data); 107 AttachProperty(property_); 108 } else { 109 property_->Set(data); 110 } 111 } 112 GetOverlayOffset()113 OffsetF GetOverlayOffset() 114 { 115 OffsetF overlayOffset; 116 if (property_) { 117 auto overlayOptions = property_->Get().GetOverlayOptions(); 118 auto dx = overlayOptions.x.ConvertToPx(); 119 auto dy = overlayOptions.y.ConvertToPx(); 120 overlayOffset = OffsetF(dx, dy); 121 } 122 return overlayOffset; 123 } 124 125 private: GetTextPosition(const SizeF & parentSize,const SizeF & childSize,OverlayOptions & overlay)126 static OffsetF GetTextPosition(const SizeF& parentSize, const SizeF& childSize, OverlayOptions& overlay) 127 { 128 const double dx = overlay.x.ConvertToPx(); 129 const double dy = overlay.y.ConvertToPx(); 130 const Alignment align = overlay.align; 131 OffsetF const offset = Alignment::GetAlignPosition(parentSize, childSize, align); 132 const float fx = static_cast<float>(dx) + offset.GetX(); 133 const float fy = static_cast<float>(dy) + offset.GetY(); 134 return { fx, fy }; 135 } 136 137 std::shared_ptr<Rosen::RSProperty<OverlayTextData>> property_; 138 }; 139 140 } // namespace OHOS::Ace::NG 141 142 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_OVERLAY_MODIFIER_H