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_property.h" 24 #include "render_service_client/core/modifier_ng/overlay/rs_overlay_style_modifier.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/common/font_manager.h" 30 #include "core/components/common/properties/alignment.h" 31 #include "core/components_ng/property/overlay_property.h" 32 #include "core/components_ng/render/drawing.h" 33 #include "core/components_ng/render/drawing_prop_convertor.h" 34 #include "core/components_ng/render/font_collection.h" 35 #include "core/pipeline/pipeline_base.h" 36 37 namespace OHOS::Ace::NG { 38 39 class OverlayTextData : public Rosen::RSArithmetic<OverlayTextData> { 40 public: 41 OverlayTextData() = default; OverlayTextData(const OverlayOptions & overlay)42 explicit OverlayTextData(const OverlayOptions& overlay) : overlay_(overlay) {} 43 ~OverlayTextData() override = default; 44 IsEqual(const OverlayTextData & other)45 bool IsEqual(const OverlayTextData& other) const override 46 { 47 return overlay_ == other.overlay_; 48 } 49 GetOverlayOptions()50 OverlayOptions GetOverlayOptions() 51 { 52 return overlay_; 53 } 54 55 private: 56 OverlayOptions overlay_; 57 }; 58 59 using RSOverlayStyleModifier = Rosen::ModifierNG::RSOverlayStyleModifier; 60 using RSDrawingContext = Rosen::ModifierNG::RSDrawingContext; 61 62 class OverlayTextModifier : public RSOverlayStyleModifier { 63 public: 64 OverlayTextModifier() = default; 65 ~OverlayTextModifier() override = default; 66 Draw(RSDrawingContext & context)67 void Draw(RSDrawingContext& context) const override 68 { 69 CHECK_NULL_VOID(property_); 70 auto overlayOptions = property_->Get().GetOverlayOptions(); 71 auto paragraph = GetParagraph(context.width); 72 CHECK_NULL_VOID(paragraph); 73 OffsetF offset = OverlayTextModifier::GetTextPosition(SizeF(context.width, context.height), 74 SizeF(static_cast<float>(paragraph->GetActualWidth()), static_cast<float>(paragraph->GetHeight())), 75 overlayOptions); 76 #ifndef USE_ROSEN_DRAWING 77 std::shared_ptr<SkCanvas> skCanvas { context.canvas, [](SkCanvas*) {} }; 78 RSCanvas canvas(&skCanvas); 79 CHECK_NULL_VOID(&canvas); 80 paragraph->Paint(&canvas, offset.GetX(), offset.GetY()); 81 #else 82 CHECK_NULL_VOID(context.canvas); 83 paragraph->Paint(context.canvas, offset.GetX(), offset.GetY()); 84 #endif 85 } 86 GetParagraph(double contextWidth)87 std::unique_ptr<Rosen::Typography> GetParagraph(double contextWidth) const 88 { 89 CHECK_NULL_RETURN(property_, nullptr); 90 const Dimension fontSize = Dimension(40); 91 auto overlayOptions = property_->Get().GetOverlayOptions(); 92 // create paragraph 93 TextStyle textStyle; 94 textStyle.SetFontSize(fontSize); 95 RSParagraphStyle paraStyle; 96 paraStyle.textAlign = ToRSTextAlign(textStyle.GetTextAlign()); 97 paraStyle.maxLines = textStyle.GetMaxLines(); 98 paraStyle.locale = Localization::GetInstance()->GetFontLocale(); 99 paraStyle.wordBreakType = ToRSWordBreakType(textStyle.GetWordBreak()); 100 paraStyle.fontSize = fontSize.Value(); 101 auto builder = RSParagraphBuilder::Create(paraStyle, RSFontCollection::Create()); 102 CHECK_NULL_RETURN(builder, nullptr); 103 auto pipelineContext = PipelineBase::GetCurrentContext(); 104 CHECK_NULL_RETURN(pipelineContext, nullptr); 105 builder->PushStyle(ToRSTextStyle(pipelineContext, textStyle)); 106 builder->AppendText(StringUtils::Str8ToStr16(overlayOptions.content)); 107 builder->PopStyle(); 108 auto paragraph = builder->CreateTypography(); 109 CHECK_NULL_RETURN(paragraph, nullptr); 110 paragraph->Layout(contextWidth); 111 return paragraph; 112 } 113 GetParagraphSize(double contextWidth)114 SizeF GetParagraphSize(double contextWidth) const 115 { 116 auto paragraph = GetParagraph(contextWidth); 117 CHECK_NULL_RETURN(paragraph, SizeF()); 118 return SizeF(static_cast<float>(paragraph->GetActualWidth()), static_cast<float>(paragraph->GetHeight())); 119 } 120 SetCustomData(const OverlayTextData & data)121 void SetCustomData(const OverlayTextData& data) 122 { 123 if (!property_) { 124 property_ = std::make_shared<Rosen::RSProperty<OverlayTextData>>(data); 125 AttachProperty(property_); 126 } else { 127 property_->Set(data); 128 } 129 } 130 GetOverlayOffset()131 OffsetF GetOverlayOffset() 132 { 133 OffsetF overlayOffset; 134 if (property_) { 135 auto overlayOptions = property_->Get().GetOverlayOptions(); 136 auto dx = overlayOptions.x.ConvertToPx(); 137 auto dy = overlayOptions.y.ConvertToPx(); 138 overlayOffset = OffsetF(dx, dy); 139 } 140 return overlayOffset; 141 } 142 IsCustomFont()143 bool IsCustomFont() 144 { 145 auto pipelineContext = PipelineBase::GetCurrentContext(); 146 CHECK_NULL_RETURN(pipelineContext, false); 147 auto fontManager = pipelineContext->GetFontManager(); 148 CHECK_NULL_RETURN(fontManager, false); 149 return fontManager->IsDefaultFontChanged(); 150 } 151 152 private: GetTextPosition(const SizeF & parentSize,const SizeF & childSize,OverlayOptions & overlay)153 static OffsetF GetTextPosition(const SizeF& parentSize, const SizeF& childSize, OverlayOptions& overlay) 154 { 155 const double dx = overlay.x.ConvertToPx(); 156 const double dy = overlay.y.ConvertToPx(); 157 const Alignment align = overlay.align; 158 OffsetF const offset = Alignment::GetAlignPosition(parentSize, childSize, align); 159 const float fx = static_cast<float>(dx) + offset.GetX(); 160 const float fy = static_cast<float>(dy) + offset.GetY(); 161 return { fx, fy }; 162 } 163 164 std::shared_ptr<Rosen::RSProperty<OverlayTextData>> property_; 165 }; 166 } // namespace OHOS::Ace::NG 167 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_OVERLAY_MODIFIER_H 168