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/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 class OverlayTextModifier : public Rosen::RSOverlayStyleModifier { 60 public: 61 OverlayTextModifier() = default; 62 ~OverlayTextModifier() override = default; 63 Draw(Rosen::RSDrawingContext & context)64 void Draw(Rosen::RSDrawingContext& context) const override 65 { 66 CHECK_NULL_VOID(property_); 67 auto overlayOptions = property_->Get().GetOverlayOptions(); 68 auto paragraph = GetParagraph(context.width); 69 CHECK_NULL_VOID(paragraph); 70 #ifndef USE_GRAPHIC_TEXT_GINE 71 OffsetF offset = OverlayTextModifier::GetTextPosition(SizeF(context.width, context.height), 72 SizeF(paragraph->GetLongestLine(), paragraph->GetHeight()), overlayOptions); 73 #else 74 OffsetF offset = OverlayTextModifier::GetTextPosition(SizeF(context.width, context.height), 75 SizeF(static_cast<float>(paragraph->GetActualWidth()), static_cast<float>(paragraph->GetHeight())), 76 overlayOptions); 77 #endif 78 #ifndef USE_ROSEN_DRAWING 79 std::shared_ptr<SkCanvas> skCanvas { context.canvas, [](SkCanvas*) {} }; 80 RSCanvas canvas(&skCanvas); 81 CHECK_NULL_VOID(&canvas); 82 paragraph->Paint(&canvas, offset.GetX(), offset.GetY()); 83 #else 84 CHECK_NULL_VOID(context.canvas); 85 paragraph->Paint(context.canvas, offset.GetX(), offset.GetY()); 86 #endif 87 } 88 GetParagraph(double contextWidth)89 std::unique_ptr<Rosen::Typography> GetParagraph(double contextWidth) const 90 { 91 CHECK_NULL_RETURN(property_, nullptr); 92 const Dimension fontSize = Dimension(40); 93 auto overlayOptions = property_->Get().GetOverlayOptions(); 94 // create paragraph 95 TextStyle textStyle; 96 textStyle.SetFontSize(fontSize); 97 RSParagraphStyle paraStyle; 98 #ifndef USE_GRAPHIC_TEXT_GINE 99 paraStyle.textAlign_ = ToRSTextAlign(textStyle.GetTextAlign()); 100 paraStyle.maxLines_ = textStyle.GetMaxLines(); 101 paraStyle.locale_ = Localization::GetInstance()->GetFontLocale(); 102 paraStyle.wordBreakType_ = ToRSWordBreakType(textStyle.GetWordBreak()); 103 paraStyle.fontSize_ = fontSize.Value(); 104 auto builder = RSParagraphBuilder::CreateRosenBuilder(paraStyle, RSFontCollection::GetInstance(false)); 105 #else 106 paraStyle.textAlign = ToRSTextAlign(textStyle.GetTextAlign()); 107 paraStyle.maxLines = textStyle.GetMaxLines(); 108 paraStyle.locale = Localization::GetInstance()->GetFontLocale(); 109 paraStyle.wordBreakType = ToRSWordBreakType(textStyle.GetWordBreak()); 110 paraStyle.fontSize = fontSize.Value(); 111 auto builder = RSParagraphBuilder::Create(paraStyle, RSFontCollection::Create()); 112 #endif 113 CHECK_NULL_RETURN(builder, nullptr); 114 auto pipelineContext = PipelineBase::GetCurrentContext(); 115 CHECK_NULL_RETURN(pipelineContext, nullptr); 116 builder->PushStyle(ToRSTextStyle(pipelineContext, textStyle)); 117 #ifndef USE_GRAPHIC_TEXT_GINE 118 builder->AddText(StringUtils::Str8ToStr16(overlayOptions.content)); 119 builder->Pop(); 120 auto paragraph = builder->Build(); 121 #else 122 builder->AppendText(StringUtils::Str8ToStr16(overlayOptions.content)); 123 builder->PopStyle(); 124 auto paragraph = builder->CreateTypography(); 125 #endif 126 CHECK_NULL_RETURN(paragraph, nullptr); 127 paragraph->Layout(contextWidth); 128 return paragraph; 129 } 130 GetParagraphSize(double contextWidth)131 SizeF GetParagraphSize(double contextWidth) const 132 { 133 auto paragraph = GetParagraph(contextWidth); 134 CHECK_NULL_RETURN(paragraph, SizeF()); 135 return SizeF(static_cast<float>(paragraph->GetActualWidth()), static_cast<float>(paragraph->GetHeight())); 136 } 137 SetCustomData(const OverlayTextData & data)138 void SetCustomData(const OverlayTextData& data) 139 { 140 if (!property_) { 141 property_ = std::make_shared<Rosen::RSProperty<OverlayTextData>>(data); 142 AttachProperty(property_); 143 } else { 144 property_->Set(data); 145 } 146 } 147 GetOverlayOffset()148 OffsetF GetOverlayOffset() 149 { 150 OffsetF overlayOffset; 151 if (property_) { 152 auto overlayOptions = property_->Get().GetOverlayOptions(); 153 auto dx = overlayOptions.x.ConvertToPx(); 154 auto dy = overlayOptions.y.ConvertToPx(); 155 overlayOffset = OffsetF(dx, dy); 156 } 157 return overlayOffset; 158 } 159 IsCustomFont()160 bool IsCustomFont() 161 { 162 auto pipelineContext = PipelineBase::GetCurrentContext(); 163 CHECK_NULL_RETURN(pipelineContext, false); 164 auto fontManager = pipelineContext->GetFontManager(); 165 CHECK_NULL_RETURN(fontManager, false); 166 return fontManager->IsDefaultFontChanged(); 167 } 168 169 private: GetTextPosition(const SizeF & parentSize,const SizeF & childSize,OverlayOptions & overlay)170 static OffsetF GetTextPosition(const SizeF& parentSize, const SizeF& childSize, OverlayOptions& overlay) 171 { 172 const double dx = overlay.x.ConvertToPx(); 173 const double dy = overlay.y.ConvertToPx(); 174 const Alignment align = overlay.align; 175 OffsetF const offset = Alignment::GetAlignPosition(parentSize, childSize, align); 176 const float fx = static_cast<float>(dx) + offset.GetX(); 177 const float fy = static_cast<float>(dy) + offset.GetY(); 178 return { fx, fy }; 179 } 180 181 std::shared_ptr<Rosen::RSProperty<OverlayTextData>> property_; 182 }; 183 184 } // namespace OHOS::Ace::NG 185 186 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_OVERLAY_MODIFIER_H 187