diff --git a/frameworks/bridge/declarative_frontend/BUILD.gn b/frameworks/bridge/declarative_frontend/BUILD.gn index c0725cbbf9cf606f59d5ea0e5c7505847cf78c82..0460bbf0339959c08275a321bd54ddb1dbbf9a82 100644 --- a/frameworks/bridge/declarative_frontend/BUILD.gn +++ b/frameworks/bridge/declarative_frontend/BUILD.gn @@ -183,6 +183,7 @@ template("declarative_js_engine") { "jsview/js_if_else.cpp", "jsview/js_image.cpp", "jsview/js_image_animator.cpp", + "jsview/js_image_span.cpp", "jsview/js_indexer.cpp", "jsview/js_interactable_view.cpp", "jsview/js_lazy_foreach.cpp", diff --git a/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js b/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js index 3eaa7405d6d57674d1f720cf64ec5422c8b446bb..0ce9f7a4bd2baf46ac49e887f8c0502ed8c0fa75 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js +++ b/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js @@ -1329,3 +1329,12 @@ var ContentTextStyle; ContentTextStyle[ContentTextStyle["DoubleLine"] = 1] = "DoubleLine"; ContentTextStyle[ContentTextStyle["ThreeLines"] = 2] = "ThreeLines"; })(ContentTextStyle || (ContentTextStyle = {})); + +var ImageSpanAlignment; +(function (ImageSpanAlignment) { + ImageSpanAlignment[ImageSpanAlignment["NONE"] = 0] = "NONE"; + ImageSpanAlignment[ImageSpanAlignment["TOP"] = 1] = "TOP"; + ImageSpanAlignment[ImageSpanAlignment["CENTER"] = 2] = "CENTER"; + ImageSpanAlignment[ImageSpanAlignment["BOTTOM"] = 3] = "BOTTOM"; + ImageSpanAlignment[ImageSpanAlignment["BASELINE"] = 4] = "BASELINE"; +})(ImageSpanAlignment || (ImageSpanAlignment = {})); diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl.cpp index 19c925e139a4cd0e397382d7ca489acff6857f60..7e25351ade2345b16d9c14fadbded6f96dfafd96 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl.cpp @@ -66,6 +66,7 @@ #include "bridge/declarative_frontend/jsview/js_if_else.h" #include "bridge/declarative_frontend/jsview/js_image.h" #include "bridge/declarative_frontend/jsview/js_image_animator.h" +#include "bridge/declarative_frontend/jsview/js_image_span.h" #include "bridge/declarative_frontend/jsview/js_indexer.h" #include "bridge/declarative_frontend/jsview/js_lazy_foreach.h" #include "bridge/declarative_frontend/jsview/js_line.h" @@ -593,6 +594,7 @@ static const std::unordered_map> { "RelativeContainer", JSRelativeContainer::JSBind }, { "__Common__", JSCommonView::JSBind }, { "LinearGradient", JSLinearGradient::JSBind }, + { "ImageSpan", JSImageSpan::JSBind }, #ifdef PREVIEW { "FormComponent", JSForm::JSBind }, { "XComponent", JSXComponent::JSBind }, diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cpp index f456e1400dc7cf69ac6cedbe9937cecc26c1135f..2890b4582934e991d0ba04e52c44e0f982a52e6e 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -40,6 +40,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/js_grid_item.h" #include "frameworks/bridge/declarative_frontend/jsview/js_if_else.h" #include "frameworks/bridge/declarative_frontend/jsview/js_image.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_image_span.h" #include "frameworks/bridge/declarative_frontend/jsview/js_lazy_foreach.h" #include "frameworks/bridge/declarative_frontend/jsview/js_list.h" #include "frameworks/bridge/declarative_frontend/jsview/js_list_item.h" @@ -182,6 +183,7 @@ void JsBindViews(BindingTarget globalObj) JSGrid::JSBind(globalObj); JSGridItem::JSBind(globalObj); JSSwiper::JSBind(globalObj); + JSImageSpan::JSBind(globalObj); } } // namespace OHOS::Ace::Framework diff --git a/frameworks/bridge/declarative_frontend/jsview/js_image_span.cpp b/frameworks/bridge/declarative_frontend/jsview/js_image_span.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5daa7afd35aa51156dbeb0bcec6130b36c21806 --- /dev/null +++ b/frameworks/bridge/declarative_frontend/jsview/js_image_span.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "frameworks/bridge/declarative_frontend/jsview/js_image_span.h" + +#if !defined(PREVIEW) +#include +#endif + +#include "base/image/pixel_map.h" +#include "base/log/ace_scoring_log.h" +#include "base/log/ace_trace.h" +#include "bridge/declarative_frontend/engine/js_ref_ptr.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/pattern/image/image_model.h" +#include "core/components_ng/pattern/text/image_span_view.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_image.h" + +namespace OHOS::Ace::Framework { +void JSImageSpan::Create(const JSCallbackInfo& info) +{ + if (!Container::IsCurrentUseNewPipeline()) { + return; + } + if (info.Length() != 1) { + LOGE("The arg is wrong, it is supposed to have 1 argument"); + return; + } + std::string bundleName; + std::string moduleName; + std::string src; + auto noPixmap = ParseJsMedia(info[0], src); + JSImage::GetJsMediaBundleInfo(info[0], bundleName, moduleName); + LOGI("JSImageSpan::Create src = %{public}s bundleName = %{public}s moduleName = %{public}s noPixmap = " + "%{public}d", + src.c_str(), bundleName.c_str(), moduleName.c_str(), noPixmap); + RefPtr pixmap = nullptr; +#if defined(PIXEL_MAP_SUPPORTED) + if (!noPixmap) { + pixmap = CreatePixelMapFromNapiValue(info[0]); + } +#endif + ImageModel::GetInstance()->Create(src, noPixmap, pixmap, bundleName, moduleName); +} + +void JSImageSpan::SetObjectFit(int32_t value) +{ + auto fit = static_cast(value); + if (fit < ImageFit::FILL || fit > ImageFit::SCALE_DOWN) { + LOGW("The value of objectFit is out of range %{public}d", value); + fit = ImageFit::COVER; + } + ImageModel::GetInstance()->SetImageFit(fit); +} + +void JSImageSpan::SetVerticalAlign(int32_t verticalAlign) +{ + auto align = static_cast(verticalAlign); + if (align < VerticalAlign::TOP || align > VerticalAlign::NONE) { + LOGW("The value of verticalAlign is out of range %{public}d", verticalAlign); + align = VerticalAlign::BOTTOM; + } + NG::ImageSpanView::SetVerticalAlign(align); +} + +void JSImageSpan::JSBind(BindingTarget globalObj) +{ + JSClass::Declare("ImageSpan"); + MethodOptions opt = MethodOptions::NONE; + JSClass::StaticMethod("create", &JSImageSpan::Create, opt); + JSClass::StaticMethod("objectFit", &JSImageSpan::SetObjectFit, opt); + JSClass::StaticMethod("verticalAlign", &JSImageSpan::SetVerticalAlign); + JSClass::Inherit(); + JSClass::Bind<>(globalObj); +} +} // namespace OHOS::Ace::Framework diff --git a/frameworks/bridge/declarative_frontend/jsview/js_image_span.h b/frameworks/bridge/declarative_frontend/jsview/js_image_span.h new file mode 100644 index 0000000000000000000000000000000000000000..9a0bda6d636b549a74f1afa7bd0e37ebc2e7e408 --- /dev/null +++ b/frameworks/bridge/declarative_frontend/jsview/js_image_span.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_IMAGE_SPAN_H +#define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_IMAGE_SPAN_H + +#include "frameworks/bridge/declarative_frontend/jsview/js_interactable_view.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_utils.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h" + +namespace OHOS::Ace::Framework { +class JSImageSpan : public JSViewAbstract { +public: + static void Create(const JSCallbackInfo& info); + static void SetObjectFit(int32_t value); + static void SetVerticalAlign(int32_t verticalAlign); + static void GetJsMediaBundleInfo(const JSRef& jsValue, std::string& bundleName, std::string& moduleName); + static void JSBind(BindingTarget globalObj); +}; +} // namespace OHOS::Ace::Framework +#endif // FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_IMAGE_SPAN_H diff --git a/frameworks/bridge/declarative_frontend/jsview/js_text.cpp b/frameworks/bridge/declarative_frontend/jsview/js_text.cpp index 4c4be87eb1c47c18b2079188997a8e50cc9192b5..6fd1a4c3d3da937da7fefb76120ee191e1f4930d 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_text.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_text.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -206,6 +206,19 @@ void JSText::SetMaxLines(const JSCallbackInfo& info) TextModel::GetInstance()->SetMaxLines(value); } +void JSText::SetTextIndent(const JSCallbackInfo& info) +{ + if (info.Length() < 1) { + LOGE("The argv is wrong, it is supposed to have at least 1 argument"); + return; + } + Dimension value; + if (!ParseJsDimensionFp(info[0], value)) { + return; + } + TextModel::GetInstance()->SetTextIndent(value); +} + void JSText::SetFontStyle(int32_t value) { if (value < 0 || value >= static_cast(FONT_STYLES.size())) { @@ -551,6 +564,7 @@ void JSText::JSBind(BindingTarget globalObj) JSClass::StaticMethod("fontSize", &JSText::SetFontSize, opt); JSClass::StaticMethod("fontWeight", &JSText::SetFontWeight, opt); JSClass::StaticMethod("maxLines", &JSText::SetMaxLines, opt); + JSClass::StaticMethod("textIndent", &JSText::SetTextIndent); JSClass::StaticMethod("textOverflow", &JSText::SetTextOverflow, opt); JSClass::StaticMethod("fontStyle", &JSText::SetFontStyle, opt); JSClass::StaticMethod("align", &JSText::SetAlign, opt); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_text.h b/frameworks/bridge/declarative_frontend/jsview/js_text.h index a962a69eff22c23973bd6edd73aa8b5b8a3a62a0..6498a6f41b3a4979ddc7bb4e7f78a738645ac224 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_text.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_text.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -37,6 +37,7 @@ public: static void SetTextShadow(const JSCallbackInfo& info); static void SetTextOverflow(const JSCallbackInfo& info); static void SetMaxLines(const JSCallbackInfo& info); + static void SetTextIndent(const JSCallbackInfo& info); static void SetFontStyle(int32_t value); static void SetAlign(const JSCallbackInfo& info); static void SetTextAlign(int32_t value); diff --git a/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.cpp b/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.cpp index 2beb07f79a261fe268ef4ff1c87eb398e83ff731..1ab001ca756f1ce87f3605cfbe15a5c1a073884a 100644 --- a/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -127,6 +127,16 @@ void TextModelImpl::SetMaxLines(uint32_t value) component->SetTextStyle(textStyle); } +void TextModelImpl::SetTextIndent(const Dimension& value) +{ + auto component = GetComponent(); + CHECK_NULL_VOID(component); + + auto textStyle = component->GetTextStyle(); + textStyle.SetTextIndent(value); + component->SetTextStyle(textStyle); +} + void TextModelImpl::SetLineHeight(const Dimension& value) { auto component = GetComponent(); diff --git a/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.h b/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.h index 44402a122d300146c9c80ae84fc56255dc13d945..d85ddb62ac1315fb260bc257155862e4f5f62faa 100644 --- a/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.h +++ b/frameworks/bridge/declarative_frontend/jsview/models/text_model_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -35,6 +35,7 @@ public: void SetTextAlign(TextAlign value) override; void SetTextOverflow(TextOverflow value) override; void SetMaxLines(uint32_t value) override; + void SetTextIndent(const Dimension& value) override; void SetLineHeight(const Dimension& value) override; void SetTextDecoration(TextDecoration value) override; void SetTextDecorationColor(const Color& value) override; diff --git a/frameworks/core/components/common/properties/text_style.h b/frameworks/core/components/common/properties/text_style.h index 174460bf299f291499344ebdc44da39b56c90719..ff5e7de4a8ad100b7ea835d9361856277b9fdafd 100644 --- a/frameworks/core/components/common/properties/text_style.h +++ b/frameworks/core/components/common/properties/text_style.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -71,12 +71,59 @@ enum class TextCase { enum class WordBreak { NORMAL = 0, BREAK_ALL, BREAK_WORD }; +/// Where to vertically align the placeholder relative to the surrounding text. +enum class PlaceholderAlignment { + /// Match the baseline of the placeholder with the baseline. + BASELINE, + + /// Align the bottom edge of the placeholder with the baseline such that the + /// placeholder sits on top of the baseline. + ABOVEBASELINE, + + /// Align the top edge of the placeholder with the baseline specified in + /// such that the placeholder hangs below the baseline. + BELOWBASELINE, + + /// Align the top edge of the placeholder with the top edge of the font. + /// When the placeholder is very tall, the extra space will hang from + /// the top and extend through the bottom of the line. + TOP, + + /// Align the bottom edge of the placeholder with the top edge of the font. + /// When the placeholder is very tall, the extra space will rise from + /// the bottom and extend through the top of the line. + BOTTOM, + + /// Align the middle of the placeholder with the middle of the text. When the + /// placeholder is very tall, the extra space will grow equally from + /// the top and bottom of the line. + MIDDLE, +}; + struct TextSizeGroup { Dimension fontSize = 14.0_px; uint32_t maxLines = INT32_MAX; TextOverflow textOverflow = TextOverflow::CLIP; }; +/// Placeholder properties +struct PlaceholderRun { + /// Placeholder's width + float width = 0.0f; + + /// Placeholder's height + float height = 0.0f; + + /// Vertically alignment the placeholder relative to the surrounding text. + PlaceholderAlignment alignment = PlaceholderAlignment::BOTTOM; + + /// The placeholder with the baseline styles + TextBaseline baseline = TextBaseline::ALPHABETIC; + + /// The baseline offset + float baseline_offset = 0.0f; +}; + class ACE_EXPORT TextStyle final { public: TextStyle() = default; diff --git a/frameworks/core/components/font/constants_converter.cpp b/frameworks/core/components/font/constants_converter.cpp index 8cd8218b231bb2b9ec5b161d7c675926041c858b..cf7c9eb356dffad347a322cb5c54ac72742fef44 100644 --- a/frameworks/core/components/font/constants_converter.cpp +++ b/frameworks/core/components/font/constants_converter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -275,4 +275,42 @@ Rect ConvertSkRect(SkRect skRect) return result; } +txt::PlaceholderAlignment ConvertPlaceholderAlignment(PlaceholderAlignment textDecoration) +{ + txt::PlaceholderAlignment convertValue = txt::PlaceholderAlignment::kBaseline; + switch (textDecoration) { + case PlaceholderAlignment::BASELINE: + convertValue = txt::PlaceholderAlignment::kBaseline; + break; + case PlaceholderAlignment::ABOVEBASELINE: + convertValue = txt::PlaceholderAlignment::kAboveBaseline; + break; + case PlaceholderAlignment::BELOWBASELINE: + convertValue = txt::PlaceholderAlignment::kBelowBaseline; + break; + case PlaceholderAlignment::TOP: + convertValue = txt::PlaceholderAlignment::kTop; + break; + case PlaceholderAlignment::BOTTOM: + convertValue = txt::PlaceholderAlignment::kBottom; + break; + case PlaceholderAlignment::MIDDLE: + convertValue = txt::PlaceholderAlignment::kMiddle; + break; + default: + LOGW("PlaceholderAlignment setting error! Now using default PlaceholderAlignment"); + break; + } + return convertValue; +} + +void ConvertPlaceholderRun(const PlaceholderRun& span, txt::PlaceholderRun& txtSpan) +{ + txtSpan.width = span.width; + txtSpan.height = span.height; + txtSpan.alignment = ConvertPlaceholderAlignment(span.alignment); + txtSpan.baseline = ConvertTxtTextBaseline(span.baseline); + txtSpan.baseline_offset = span.baseline_offset; +} + } // namespace OHOS::Ace::Constants diff --git a/frameworks/core/components/font/constants_converter.h b/frameworks/core/components/font/constants_converter.h index 37dc06c5ab70d1053b39d56022c0d748e57f7e17..8dd6293033e35719464bcabf8d7d40c2ba7ffaac 100644 --- a/frameworks/core/components/font/constants_converter.h +++ b/frameworks/core/components/font/constants_converter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,6 +16,7 @@ #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_FONT_CONSTANTS_CONVERTER_H #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_FONT_CONSTANTS_CONVERTER_H +#include "flutter/third_party/txt/src/txt/placeholder_run.h" #include "flutter/third_party/txt/src/txt/text_baseline.h" #include "flutter/third_party/txt/src/txt/text_decoration.h" #include "flutter/third_party/txt/src/txt/text_style.h" @@ -62,6 +63,10 @@ void ConvertTxtStyle(const TextStyle& textStyle, const WeakPtr& co Rect ConvertSkRect(SkRect skRect); +txt::PlaceholderAlignment ConvertPlaceholderAlignment(PlaceholderAlignment textDecoration); + +void ConvertPlaceholderRun(const PlaceholderRun& span, txt::PlaceholderRun& txtSpan); + } // namespace Constants } // namespace OHOS::Ace diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index f9a1d28d67e9c6e4c1769fd48459729b0005d3be..35ec36fde588f3db63004bd6d1f6b3bfe1b953f8 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -352,6 +352,7 @@ build_component_ng("pattern_ng") { "tabs/tabs_model_ng.cpp", "tabs/tabs_node.cpp", "tabs/tabs_pattern.cpp", + "text/image_span_view.cpp", "text/span_model_ng.cpp", "text/span_node.cpp", "text/text_accessibility_property.cpp", diff --git a/frameworks/core/components_ng/pattern/image/image_layout_property.h b/frameworks/core/components_ng/pattern/image/image_layout_property.h index 79c81c3a1185582a6a2f1e78bdf04596f8d6933b..46a59d3d1d1d1f0205fa3eda9bd5ccd40b2b38cc 100644 --- a/frameworks/core/components_ng/pattern/image/image_layout_property.h +++ b/frameworks/core/components_ng/pattern/image/image_layout_property.h @@ -52,6 +52,7 @@ public: value->propSyncMode_ = CloneSyncMode(); value->propCopyOptions_ = CloneCopyOptions(); value->propImageSizeStyle_ = CloneImageSizeStyle(); + value->propVerticalAlign_ = CloneVerticalAlign(); return value; } @@ -64,6 +65,7 @@ public: ResetSyncMode(); ResetCopyOptions(); ResetImageSizeStyle(); + ResetVerticalAlign(); } void ToJsonValue(std::unique_ptr& json) const override @@ -73,10 +75,14 @@ public: "ImageFit.Auto", "ImageFit.FitHeight", "ImageFit.None", "ImageFit.ScaleDown" }; static const char* COPYOPTIONSVALUE[] = { "CopyOptions.None", "CopyOptions.InApp", "CopyOptions.Local", "CopyOptions.Distributed" }; + static const char* VERTICALALIGNVALUE[] = { "VerticalAlign.NONE", "VerticalAlign.TOP", "VerticalAlign.CENTER", + "VerticalAlign.BOTTOM", "CopyOptions.BASELINE", "VerticalAlign.NONE" }; json->Put("alt", propAlt_.value_or(ImageSourceInfo("")).GetSrc().c_str()); json->Put("objectFit", OBJECTFITVALUE[static_cast(propImageFit_.value_or(ImageFit::COVER))]); json->Put("syncLoad", propSyncMode_.value_or(false) ? "true" : "false"); json->Put("copyOption", COPYOPTIONSVALUE[static_cast(propCopyOptions_.value_or(CopyOptions::None))]); + json->Put("verticalAlign", + VERTICALALIGNVALUE[static_cast(propVerticalAlign_.value_or(VerticalAlign::BOTTOM))]); std::string src; if (propImageSourceInfo_.has_value()) { src = propImageSourceInfo_->GetSrc(); @@ -101,6 +107,7 @@ public: ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(ImageSizeStyle, AutoResize, bool, PROPERTY_UPDATE_LAYOUT); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(ImageSizeStyle, SourceSize, SizeF, PROPERTY_UPDATE_LAYOUT); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(ImageSizeStyle, FitOriginalSize, bool, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(VerticalAlign, VerticalAlign, PROPERTY_UPDATE_MEASURE); private: ACE_DISALLOW_COPY_AND_MOVE(ImageLayoutProperty); diff --git a/frameworks/core/components_ng/pattern/text/image_span_view.cpp b/frameworks/core/components_ng/pattern/text/image_span_view.cpp new file mode 100644 index 0000000000000000000000000000000000000000..378df0bb8e8bb97d021a9a704b86ff09633b078f --- /dev/null +++ b/frameworks/core/components_ng/pattern/text/image_span_view.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/pattern/text/image_span_view.h" + +#include "base/memory/referenced.h" +#include "base/utils/utils.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/image/image_pattern.h" + +namespace OHOS::Ace::NG { +void ImageSpanView::SetObjectFit(ImageFit value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageFit, value); +} + +void ImageSpanView::SetVerticalAlign(VerticalAlign verticalAlign) +{ + ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, VerticalAlign, verticalAlign); +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/text/image_span_view.h b/frameworks/core/components_ng/pattern/text/image_span_view.h new file mode 100644 index 0000000000000000000000000000000000000000..b7b5564e4cd92635b50232c1292fcf11f0898fb1 --- /dev/null +++ b/frameworks/core/components_ng/pattern/text/image_span_view.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_IMAGE_SPAN_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_IMAGE_SPAN_VIEW_H + +#include + +#include "base/image/pixel_map.h" +#include "base/utils/macros.h" +#include "core/components/common/layout/constants.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT ImageSpanView { +public: + static void SetObjectFit(ImageFit value); + static void SetVerticalAlign(VerticalAlign verticalAlign); +}; +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_IMAGE_SPAN_VIEW_H diff --git a/frameworks/core/components_ng/pattern/text/span_node.cpp b/frameworks/core/components_ng/pattern/text/span_node.cpp index 6f019d55fb05f6bbf34acba487a38ea6f4bbed96..1d506eda77ff4829f200742710372dbb47263707 100644 --- a/frameworks/core/components_ng/pattern/text/span_node.cpp +++ b/frameworks/core/components_ng/pattern/text/span_node.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -121,12 +121,13 @@ void SpanNode::RequestTextFlushDirty() LOGE("fail to find Text or Parent Span"); } -void SpanItem::UpdateParagraph(const RefPtr& builder) +int32_t SpanItem::UpdateParagraph( + const RefPtr& builder, double /* width */, double /* height */, VerticalAlign /* verticalAlign */) { - CHECK_NULL_VOID(builder); + CHECK_NULL_RETURN(builder, -1); if (fontStyle) { auto pipelineContext = PipelineContext::GetCurrentContext(); - CHECK_NULL_VOID(pipelineContext); + CHECK_NULL_RETURN(pipelineContext, -1); TextStyle textStyle = CreateTextStyleUsingTheme(fontStyle, nullptr, pipelineContext->GetTheme()); builder->PushStyle(textStyle); } @@ -142,5 +143,36 @@ void SpanItem::UpdateParagraph(const RefPtr& builder) if (fontStyle) { builder->PopStyle(); } + return -1; +} + +int32_t ImageSpanItem::UpdateParagraph( + const RefPtr& builder, double width, double height, VerticalAlign verticalAlign) +{ + LOGI("ImageSpanItem::UpdateParagraph imageWidth = %{public}f, imageHeight = %{public}f verticalAlign = " + "%{public}d", + width, height, verticalAlign); + CHECK_NULL_RETURN(builder, -1); + PlaceholderRun run; + run.width = width; + run.height = height; + switch (verticalAlign) { + case VerticalAlign::TOP: + run.alignment = PlaceholderAlignment::TOP; + break; + case VerticalAlign::CENTER: + run.alignment = PlaceholderAlignment::MIDDLE; + break; + case VerticalAlign::BOTTOM: + case VerticalAlign::NONE: + run.alignment = PlaceholderAlignment::BOTTOM; + break; + case VerticalAlign::BASELINE: + run.alignment = PlaceholderAlignment::ABOVEBASELINE; + break; + default: + run.alignment = PlaceholderAlignment::BOTTOM; + } + return builder->AddPlaceholder(run); } } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/text/span_node.h b/frameworks/core/components_ng/pattern/text/span_node.h index 85bcadc95d3c5665d55c12e540d1f7e58597fb0e..cec0b04015b1f486869bbce8f3dbd1be464d71cb 100644 --- a/frameworks/core/components_ng/pattern/text/span_node.h +++ b/frameworks/core/components_ng/pattern/text/span_node.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -66,16 +66,39 @@ namespace OHOS::Ace::NG { class Paragraph; -struct SpanItem : public Referenced { +struct SpanItem : public AceType { + DECLARE_ACE_TYPE(SpanItem, AceType); + +public: + SpanItem() = default; + virtual ~SpanItem() + { + children.clear(); + } int32_t positon; std::string content; std::unique_ptr fontStyle; GestureEventFunc onClick; std::list> children; + int32_t placeHolderIndex = -1; + + virtual int32_t UpdateParagraph(const RefPtr& builder, double width = 0.0f, double height = 0.0f, + VerticalAlign verticalAlign = VerticalAlign::BASELINE); - void UpdateParagraph(const RefPtr& builder); + virtual void ToJsonValue(std::unique_ptr& json) const; +}; + +struct ImageSpanItem : public SpanItem { + DECLARE_ACE_TYPE(ImageSpanItem, SpanItem); + +public: + ImageSpanItem() = default; + ~ImageSpanItem() override = default; + int32_t UpdateParagraph( + const RefPtr& builder, double width, double height, VerticalAlign verticalAlign) override; + void ToJsonValue(std::unique_ptr& json) const override {}; - void ToJsonValue(std::unique_ptr& json) const; + ACE_DISALLOW_COPY_AND_MOVE(ImageSpanItem); }; class ACE_EXPORT SpanNode : public UINode { diff --git a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp index 93c00f5c1d074ab6345be171239dbe6afd0ed73b..b8aefa86e2fb885bb44a3f66c50ce821142746bc 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp @@ -24,6 +24,7 @@ #include "base/utils/utils.h" #include "core/components/text/text_theme.h" #include "core/components_ng/base/frame_node.h" +#include "core/components_ng/pattern/image/image_layout_property.h" #include "core/components_ng/pattern/text/text_layout_property.h" #include "core/components_ng/pattern/text/text_pattern.h" #include "core/components_ng/render/drawing_prop_convertor.h" @@ -84,19 +85,21 @@ std::optional TextLayoutAlgorithm::MeasureContent( UpdateTextColorIfForeground(frameNode, textStyle); if (textStyle.GetTextOverflow() == TextOverflow::MARQUEE) { - return BuildTextRaceParagraph(textStyle, textLayoutProperty, contentConstraint, pipeline); + return BuildTextRaceParagraph(textStyle, textLayoutProperty, contentConstraint, pipeline, layoutWrapper); } bool result = false; switch (textLayoutProperty->GetHeightAdaptivePolicyValue(TextHeightAdaptivePolicy::MAX_LINES_FIRST)) { case TextHeightAdaptivePolicy::MAX_LINES_FIRST: - result = BuildParagraph(textStyle, textLayoutProperty, contentConstraint, pipeline); + result = BuildParagraph(textStyle, textLayoutProperty, contentConstraint, pipeline, layoutWrapper); break; case TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST: - result = BuildParagraphAdaptUseMinFontSize(textStyle, textLayoutProperty, contentConstraint, pipeline); + result = BuildParagraphAdaptUseMinFontSize( + textStyle, textLayoutProperty, contentConstraint, pipeline, layoutWrapper); break; case TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST: - result = BuildParagraphAdaptUseLayoutConstraint(textStyle, textLayoutProperty, contentConstraint, pipeline); + result = BuildParagraphAdaptUseLayoutConstraint( + textStyle, textLayoutProperty, contentConstraint, pipeline, layoutWrapper); break; default: break; @@ -132,7 +135,49 @@ void TextLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) layoutWrapper->GetGeometryNode()->SetBaselineDistance(baselineDistance); } -bool TextLayoutAlgorithm::CreateParagraph(const TextStyle& textStyle, std::string content) +void TextLayoutAlgorithm::UpdateParagraph(LayoutWrapper* layoutWrapper) +{ + int32_t spanTextLength = 0; + CHECK_NULL_VOID(layoutWrapper); + auto layoutProperty = layoutWrapper->GetLayoutProperty(); + CHECK_NULL_VOID(layoutProperty); + const auto& layoutConstrain = layoutProperty->CreateChildConstraint(); + const auto& children = layoutWrapper->GetAllChildrenWithBuild(); + auto iterItems = children.begin(); + for (const auto& child : spanItemChildren_) { + if (!child) { + continue; + } + auto imageSpanItem = AceType::DynamicCast(child); + if (imageSpanItem) { + if (iterItems == children.end() || !(*iterItems)) { + continue; + } + (*iterItems)->Measure(layoutConstrain); + auto verticalAlign = VerticalAlign::BOTTOM; + auto imageLayoutProperty = DynamicCast((*iterItems)->GetLayoutProperty()); + if (imageLayoutProperty) { + verticalAlign = imageLayoutProperty->GetVerticalAlign().value_or(VerticalAlign::BOTTOM); + } + auto geometryNode = (*iterItems)->GetGeometryNode(); + if (!geometryNode) { + iterItems++; + continue; + } + auto width = geometryNode->GetMarginFrameSize().Width(); + auto height = geometryNode->GetMarginFrameSize().Height(); + child->placeHolderIndex = child->UpdateParagraph(paragraph_, width, height, verticalAlign); + child->positon += 1; + iterItems++; + } else { + child->UpdateParagraph(paragraph_); + child->positon = spanTextLength + StringUtils::ToWstring(child->content).length(); + spanTextLength += StringUtils::ToWstring(child->content).length(); + } + } +} + +bool TextLayoutAlgorithm::CreateParagraph(const TextStyle& textStyle, std::string content, LayoutWrapper* layoutWrapper) { ParagraphStyle paraStyle = { .direction = GetTextDirection(content), .align = textStyle.GetTextAlign(), @@ -148,33 +193,104 @@ bool TextLayoutAlgorithm::CreateParagraph(const TextStyle& textStyle, std::strin StringUtils::TransformStrCase(content, static_cast(textStyle.GetTextCase())); paragraph_->AddText(StringUtils::Str8ToStr16(content)); } else { - int32_t spanTextLength = 0; - for (const auto& child : spanItemChildren_) { - if (child) { - child->UpdateParagraph(paragraph_); - child->positon = spanTextLength + StringUtils::ToWstring(child->content).length(); - spanTextLength += StringUtils::ToWstring(child->content).length(); - } - } + UpdateParagraph(layoutWrapper); } paragraph_->Build(); return true; } -bool TextLayoutAlgorithm::CreateParagraphAndLayout( - const TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint) +bool TextLayoutAlgorithm::CreateParagraphAndLayout(const TextStyle& textStyle, const std::string& content, + const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) { - if (!CreateParagraph(textStyle, content)) { + if (!CreateParagraph(textStyle, content, layoutWrapper)) { return false; } CHECK_NULL_RETURN(paragraph_, false); auto maxSize = GetMaxMeasureSize(contentConstraint); + if (GreatNotEqual(textStyle.GetTextIndent().Value(), 0.0)) { + ApplyIndents(textStyle, maxSize.Width()); + } paragraph_->Layout(maxSize.Width()); return true; } +OffsetF TextLayoutAlgorithm::GetContentOffset(LayoutWrapper* layoutWrapper) const +{ + OffsetF contentOffset(0.0, 0.0); + CHECK_NULL_RETURN(layoutWrapper, contentOffset); + + auto size = layoutWrapper->GetGeometryNode()->GetFrameSize(); + const auto& padding = layoutWrapper->GetLayoutProperty()->CreatePaddingAndBorder(); + MinusPaddingToSize(padding, size); + auto left = padding.left.value_or(0); + auto top = padding.top.value_or(0); + auto paddingOffset = OffsetF(left, top); + auto align = Alignment::CENTER; + if (layoutWrapper->GetLayoutProperty()->GetPositionProperty()) { + align = layoutWrapper->GetLayoutProperty()->GetPositionProperty()->GetAlignment().value_or(align); + } + + const auto& content = layoutWrapper->GetGeometryNode()->GetContent(); + if (content) { + contentOffset = Alignment::GetAlignPosition(size, content->GetRect().GetSize(), align) + paddingOffset; + content->SetOffset(contentOffset); + } + return contentOffset; +} + +void TextLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) +{ + CHECK_NULL_VOID(layoutWrapper); + auto contentOffset = GetContentOffset(layoutWrapper); + CHECK_NULL_VOID(paragraph_); + std::vector placeHolderIndex; + for (const auto& child : spanItemChildren_) { + if (!child) { + continue; + } + auto imageSpanItem = AceType::DynamicCast(child); + if (imageSpanItem) { + placeHolderIndex.emplace_back(child->placeHolderIndex); + } + } + if (spanItemChildren_.empty() || placeHolderIndex.size() == 0) { + return; + } + + size_t index = 0; + size_t imageSpanIndex = 0; + std::vector rectsForPlaceholders; + paragraph_->GetRectsForPlaceholders(rectsForPlaceholders); + const auto& children = layoutWrapper->GetAllChildrenWithBuild(); + for (const auto& child : children) { + if (!child) { + ++index; + continue; + } + if (index >= placeHolderIndex.size()) { + return; + } + imageSpanIndex = placeHolderIndex.at(index); + if (imageSpanIndex >= rectsForPlaceholders.size() || imageSpanIndex < 0) { + ++index; + continue; + } + auto rect = rectsForPlaceholders.at(imageSpanIndex); + LOGI("ImageSpan Left= %{public}f, Top = %{public}f, width = %{public}f, height = %{public}f", rect.Left(), + rect.Top(), rect.Width(), rect.Height()); + auto geometryNode = child->GetGeometryNode(); + if (!geometryNode) { + ++index; + continue; + } + geometryNode->SetMarginFrameOffset(contentOffset + OffsetF(rect.Left(), rect.Top())); + child->Layout(); + ++index; + } +} + bool TextLayoutAlgorithm::AdaptMinTextSize(TextStyle& textStyle, const std::string& content, - const LayoutConstraintF& contentConstraint, const RefPtr& pipeline) + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline, LayoutWrapper* layoutWrapper) { double maxFontSize = 0.0; double minFontSize = 0.0; @@ -187,7 +303,7 @@ bool TextLayoutAlgorithm::AdaptMinTextSize(TextStyle& textStyle, const std::stri return false; } if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(minFontSize, 0.0)) { - if (!CreateParagraphAndLayout(textStyle, content, contentConstraint)) { + if (!CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper)) { LOGE("fail to initialize text paragraph when adapt min text size."); return false; } @@ -206,7 +322,7 @@ bool TextLayoutAlgorithm::AdaptMinTextSize(TextStyle& textStyle, const std::stri auto maxSize = GetMaxMeasureSize(contentConstraint); while (GreatOrEqual(maxFontSize, minFontSize)) { textStyle.SetFontSize(Dimension(maxFontSize)); - if (!CreateParagraphAndLayout(textStyle, content, contentConstraint)) { + if (!CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper)) { return false; } if (!DidExceedMaxLines(maxSize)) { @@ -271,14 +387,16 @@ std::list>&& TextLayoutAlgorithm::GetSpanItemChildren() } bool TextLayoutAlgorithm::BuildParagraph(TextStyle& textStyle, const RefPtr& layoutProperty, - const LayoutConstraintF& contentConstraint, const RefPtr& pipeline) + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline, LayoutWrapper* layoutWrapper) { if (!textStyle.GetAdaptTextSize()) { - if (!CreateParagraphAndLayout(textStyle, layoutProperty->GetContent().value_or(""), contentConstraint)) { + if (!CreateParagraphAndLayout( + textStyle, layoutProperty->GetContent().value_or(""), contentConstraint, layoutWrapper)) { return false; } } else { - if (!AdaptMinTextSize(textStyle, layoutProperty->GetContent().value_or(""), contentConstraint, pipeline)) { + if (!AdaptMinTextSize( + textStyle, layoutProperty->GetContent().value_or(""), contentConstraint, pipeline, layoutWrapper)) { return false; } } @@ -298,9 +416,10 @@ bool TextLayoutAlgorithm::BuildParagraph(TextStyle& textStyle, const RefPtr& layoutProperty, const LayoutConstraintF& contentConstraint, - const RefPtr& pipeline) + const RefPtr& pipeline, LayoutWrapper* layoutWrapper) { - if (!AdaptMaxTextSize(textStyle, layoutProperty->GetContent().value_or(""), contentConstraint, pipeline)) { + if (!AdaptMaxTextSize( + textStyle, layoutProperty->GetContent().value_or(""), contentConstraint, pipeline, layoutWrapper)) { return false; } @@ -320,10 +439,10 @@ bool TextLayoutAlgorithm::BuildParagraphAdaptUseMinFontSize(TextStyle& textStyle bool TextLayoutAlgorithm::BuildParagraphAdaptUseLayoutConstraint(TextStyle& textStyle, const RefPtr& layoutProperty, const LayoutConstraintF& contentConstraint, - const RefPtr& pipeline) + const RefPtr& pipeline, LayoutWrapper* layoutWrapper) { // Create the paragraph and obtain the height. - if (!BuildParagraph(textStyle, layoutProperty, contentConstraint, pipeline)) { + if (!BuildParagraph(textStyle, layoutProperty, contentConstraint, pipeline, layoutWrapper)) { return false; } auto height = static_cast(paragraph_->GetHeight()); @@ -347,7 +466,7 @@ bool TextLayoutAlgorithm::BuildParagraphAdaptUseLayoutConstraint(TextStyle& text textStyle.SetMaxLines(maxLines); textStyle.DisableAdaptTextSize(); - if (!BuildParagraph(textStyle, layoutProperty, contentConstraint, pipeline)) { + if (!BuildParagraph(textStyle, layoutProperty, contentConstraint, pipeline, layoutWrapper)) { return false; } } @@ -361,7 +480,7 @@ bool TextLayoutAlgorithm::BuildParagraphAdaptUseLayoutConstraint(TextStyle& text maxLines = textStyle.GetMaxLines() - 1; textStyle.SetMaxLines(maxLines); } - if (!BuildParagraph(textStyle, layoutProperty, contentConstraint, pipeline)) { + if (!BuildParagraph(textStyle, layoutProperty, contentConstraint, pipeline, layoutWrapper)) { return false; } height = static_cast(paragraph_->GetHeight()); @@ -371,13 +490,13 @@ bool TextLayoutAlgorithm::BuildParagraphAdaptUseLayoutConstraint(TextStyle& text std::optional TextLayoutAlgorithm::BuildTextRaceParagraph(TextStyle& textStyle, const RefPtr& layoutProperty, const LayoutConstraintF& contentConstraint, - const RefPtr& pipeline) + const RefPtr& pipeline, LayoutWrapper* layoutWrapper) { // create a paragraph with all text in 1 line textStyle.SetTextOverflow(TextOverflow::CLIP); textStyle.SetMaxLines(1); textStyle.SetTextAlign(TextAlign::START); - if (!CreateParagraph(textStyle, layoutProperty->GetContent().value_or(""))) { + if (!CreateParagraph(textStyle, layoutProperty->GetContent().value_or(""), layoutWrapper)) { return std::nullopt; } if (!paragraph_) { @@ -447,23 +566,21 @@ void TextLayoutAlgorithm::SetPropertyToModifier( } bool TextLayoutAlgorithm::AdaptMaxTextSize(TextStyle& textStyle, const std::string& content, - const LayoutConstraintF& contentConstraint, const RefPtr& pipeline) + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline, LayoutWrapper* layoutWrapper) { double maxFontSize = 0.0; double minFontSize = 0.0; - if (!textStyle.GetAdaptMaxFontSize().NormalizeToPx( - pipeline->GetDipScale(), pipeline->GetFontScale(), pipeline->GetLogicScale(), - contentConstraint.maxSize.Height(), maxFontSize)) { + if (!textStyle.GetAdaptMaxFontSize().NormalizeToPx(pipeline->GetDipScale(), pipeline->GetFontScale(), + pipeline->GetLogicScale(), contentConstraint.maxSize.Height(), maxFontSize)) { return false; } - if (!textStyle.GetAdaptMinFontSize().NormalizeToPx( - pipeline->GetDipScale(), pipeline->GetFontScale(), pipeline->GetLogicScale(), - contentConstraint.maxSize.Height(), minFontSize)) { + if (!textStyle.GetAdaptMinFontSize().NormalizeToPx(pipeline->GetDipScale(), pipeline->GetFontScale(), + pipeline->GetLogicScale(), contentConstraint.maxSize.Height(), minFontSize)) { return false; } if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(minFontSize, 0.0)) { // minFontSize or maxFontSize is invalid - if (!CreateParagraphAndLayout(textStyle, content, contentConstraint)) { + if (!CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper)) { LOGE("fail to initialize text paragraph when adapt min text size."); return false; } @@ -485,7 +602,7 @@ bool TextLayoutAlgorithm::AdaptMaxTextSize(TextStyle& textStyle, const std::stri // line, then increase the font size and try to layout using the maximum available fontsize. while (LessOrEqual(minFontSize, maxFontSize)) { textStyle.SetFontSize(Dimension(minFontSize)); - if (!CreateParagraphAndLayout(textStyle, content, contentConstraint)) { + if (!CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper)) { return false; } if (paragraph_->GetLineCount() > 1 || paragraph_->DidExceedMaxLines() || @@ -517,4 +634,26 @@ void TextLayoutAlgorithm::UpdateTextColorIfForeground(const RefPtr& f textStyle.SetTextColor(Color::FOREGROUND); } } + +void TextLayoutAlgorithm::ApplyIndents(const TextStyle& textStyle, double width) +{ + CHECK_NULL_VOID(paragraph_); + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + std::vector indents; + double indent = 0.0; + if (textStyle.GetTextIndent().Unit() != DimensionUnit::PERCENT) { + if (!textStyle.GetTextIndent().NormalizeToPx( + pipeline->GetDipScale(), pipeline->GetFontScale(), pipeline->GetLogicScale(), width, indent)) { + return; + } + } else { + indent = width * textStyle.GetTextIndent().Value(); + } + if (indent > 0.0) { + indents.emplace_back(static_cast(indent)); + indents.emplace_back(0.0); + paragraph_->SetIndents(indents); + } +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h index 1cb0b7e8ab193424ce8dd94c8862d152731cb496..bb21e633b8a632e1c548733cf5c6c2b5e816aee2 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -50,6 +50,8 @@ public: std::optional MeasureContent( const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) override; + void Layout(LayoutWrapper* layoutWrapper) override; + const RefPtr& GetParagraph(); std::list>&& GetSpanItemChildren(); @@ -57,29 +59,36 @@ public: float GetBaselineOffset() const; std::optional GetTextStyle() const; + void ApplyIndents(const TextStyle& textStyle, double width); private: - bool CreateParagraph(const TextStyle& textStyle, std::string content); - bool CreateParagraphAndLayout( - const TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint); + bool CreateParagraph(const TextStyle& textStyle, std::string content, LayoutWrapper* layoutWrapper); + bool CreateParagraphAndLayout(const TextStyle& textStyle, const std::string& content, + const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper); bool AdaptMinTextSize(TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint, - const RefPtr& pipeline); + const RefPtr& pipeline, LayoutWrapper* layoutWrapper); bool DidExceedMaxLines(const SizeF& maxSize); static TextDirection GetTextDirection(const std::string& content); float GetTextWidth() const; SizeF GetMaxMeasureSize(const LayoutConstraintF& contentConstraint) const; bool BuildParagraph(TextStyle& textStyle, const RefPtr& layoutProperty, - const LayoutConstraintF& contentConstraint, const RefPtr& pipeline); + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline, + LayoutWrapper* layoutWrapper); bool BuildParagraphAdaptUseMinFontSize(TextStyle& textStyle, const RefPtr& layoutProperty, - const LayoutConstraintF& contentConstraint, const RefPtr& pipeline); + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline, + LayoutWrapper* layoutWrapper); bool BuildParagraphAdaptUseLayoutConstraint(TextStyle& textStyle, const RefPtr& layoutProperty, - const LayoutConstraintF& contentConstraint, const RefPtr& pipeline); + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline, + LayoutWrapper* layoutWrapper); std::optional BuildTextRaceParagraph(TextStyle& textStyle, const RefPtr& layoutProperty, - const LayoutConstraintF& contentConstraint, const RefPtr& pipeline); + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline, + LayoutWrapper* layoutWrapper); void SetPropertyToModifier(const RefPtr& layoutProperty, RefPtr modifier); bool AdaptMaxTextSize(TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint, - const RefPtr& pipeline); + const RefPtr& pipeline, LayoutWrapper* layoutWrapper); void UpdateTextColorIfForeground(const RefPtr& frameNode, TextStyle& textStyle); + void UpdateParagraph(LayoutWrapper* layoutWrapper); + OffsetF GetContentOffset(LayoutWrapper* layoutWrapper) const; std::list> spanItemChildren_; RefPtr paragraph_; diff --git a/frameworks/core/components_ng/pattern/text/text_layout_property.h b/frameworks/core/components_ng/pattern/text/text_layout_property.h index a2b4426991a810a2989cc529cb9fe4249717cb12..d2006b6706eb52d6f4fa99854c02fdc101ac4f3c 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_property.h +++ b/frameworks/core/components_ng/pattern/text/text_layout_property.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -73,6 +73,7 @@ public: ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(TextLineStyle, MaxLines, uint32_t, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP( TextLineStyle, HeightAdaptivePolicy, TextHeightAdaptivePolicy, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(TextLineStyle, TextIndent, Dimension, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Content, std::string, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(CopyOption, CopyOptions, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Draggable, bool, PROPERTY_UPDATE_MEASURE); diff --git a/frameworks/core/components_ng/pattern/text/text_model.h b/frameworks/core/components_ng/pattern/text/text_model.h index 4255f12bb64c9c496929f651c9d94c19a019716d..486c5d8bf94b0653941fd5c795f642c089d0c4f3 100644 --- a/frameworks/core/components_ng/pattern/text/text_model.h +++ b/frameworks/core/components_ng/pattern/text/text_model.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -45,6 +45,7 @@ public: virtual void SetTextAlign(TextAlign value) = 0; virtual void SetTextOverflow(TextOverflow value) = 0; virtual void SetMaxLines(uint32_t value) = 0; + virtual void SetTextIndent(const Dimension& value) = 0; virtual void SetLineHeight(const Dimension& value) = 0; virtual void SetTextDecoration(TextDecoration value) = 0; virtual void SetTextDecorationColor(const Color& value) = 0; diff --git a/frameworks/core/components_ng/pattern/text/text_model_ng.cpp b/frameworks/core/components_ng/pattern/text/text_model_ng.cpp index 5eb4664766167477ef600462e9bb1d4c20d7bd4d..e1bb26b72a2adfb141c2643b6430f5e3e9be6013 100644 --- a/frameworks/core/components_ng/pattern/text/text_model_ng.cpp +++ b/frameworks/core/components_ng/pattern/text/text_model_ng.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -90,6 +90,11 @@ void TextModelNG::SetMaxLines(uint32_t value) ACE_UPDATE_LAYOUT_PROPERTY(TextLayoutProperty, MaxLines, value); } +void TextModelNG::SetTextIndent(const Dimension& value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(TextLayoutProperty, TextIndent, value); +} + void TextModelNG::SetLineHeight(const Dimension& value) { ACE_UPDATE_LAYOUT_PROPERTY(TextLayoutProperty, LineHeight, value); diff --git a/frameworks/core/components_ng/pattern/text/text_model_ng.h b/frameworks/core/components_ng/pattern/text/text_model_ng.h index 2c7c1ab31d1a4ecc659e4067727c8d8639074b27..f64ae2a91103c0ee32b52643ddc5584d4ca3a1aa 100644 --- a/frameworks/core/components_ng/pattern/text/text_model_ng.h +++ b/frameworks/core/components_ng/pattern/text/text_model_ng.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -35,6 +35,7 @@ public: void SetTextAlign(TextAlign value) override; void SetTextOverflow(TextOverflow value) override; void SetMaxLines(uint32_t value) override; + void SetTextIndent(const Dimension& value) override; void SetLineHeight(const Dimension& value) override; void SetTextDecoration(TextDecoration value) override; void SetTextDecorationColor(const Color& value) override; diff --git a/frameworks/core/components_ng/pattern/text/text_pattern.cpp b/frameworks/core/components_ng/pattern/text/text_pattern.cpp index 34e842f860340982321c391bfaae3ad63883fedb..d8432234c1788ea08f4a0212655845d8a89149c7 100644 --- a/frameworks/core/components_ng/pattern/text/text_pattern.cpp +++ b/frameworks/core/components_ng/pattern/text/text_pattern.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -589,12 +589,10 @@ void TextPattern::BeforeCreateLayoutWrapper() CHECK_NULL_VOID(host); const auto& layoutProperty = host->GetLayoutProperty(); auto flag = layoutProperty ? layoutProperty->GetPropertyChangeFlag() : PROPERTY_UPDATE_NORMAL; - if (paragraph_) { - // When updating the scenario, needs to determine whether the SpanNode node is refreshed. - if ((flag & PROPERTY_UPDATE_BY_CHILD_REQUEST) != PROPERTY_UPDATE_BY_CHILD_REQUEST) { - LOGD("no need to refresh span node"); - return; - } + // When updating the scenario, needs to determine whether the SpanNode node is refreshed. + if (paragraph_ && (flag & PROPERTY_UPDATE_BY_CHILD_REQUEST) != PROPERTY_UPDATE_BY_CHILD_REQUEST) { + LOGD("no need to refresh span node"); + return; } // When dirty areas are marked because of child node changes, the text rendering node tree is reset. @@ -635,6 +633,8 @@ void TextPattern::BeforeCreateLayoutWrapper() if (spanNode->GetSpanItem()->onClick) { isSpanHasClick = true; } + } else if (current->GetTag() == V2::IMAGE_ETS_TAG) { + AddChildSpanItem(current); } const auto& nextChildren = current->GetChildren(); for (auto iter = nextChildren.rbegin(); iter != nextChildren.rend(); ++iter) { @@ -673,6 +673,22 @@ void TextPattern::OnVisibleChange(bool isVisible) } } +void TextPattern::AddChildSpanItem(const RefPtr& child) +{ + CHECK_NULL_VOID(child); + if (child->GetTag() == V2::SPAN_ETS_TAG) { + auto spanNode = DynamicCast(child); + if (spanNode) { + spanItemChildren_.emplace_back(spanNode->GetSpanItem()); + } + } else if (child->GetTag() == V2::IMAGE_ETS_TAG) { + auto imageNode = DynamicCast(child); + if (imageNode) { + spanItemChildren_.emplace_back(MakeRefPtr()); + } + } +} + void TextPattern::DumpInfo() { auto textLayoutProp = GetLayoutProperty(); diff --git a/frameworks/core/components_ng/pattern/text/text_pattern.h b/frameworks/core/components_ng/pattern/text/text_pattern.h index fece78d2f0d086c4d36ea89d68fa9e48d3729779..3536c7338a148956c4f164c03f7221a85fc67f34 100644 --- a/frameworks/core/components_ng/pattern/text/text_pattern.h +++ b/frameworks/core/components_ng/pattern/text/text_pattern.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -82,10 +82,7 @@ public: void BeforeCreateLayoutWrapper() override; - void AddChildSpanItem(const RefPtr& child) - { - spanItemChildren_.emplace_back(child->GetSpanItem()); - } + void AddChildSpanItem(const RefPtr& child); FocusPattern GetFocusPattern() const override { diff --git a/frameworks/core/components_ng/pattern/text/text_styles.cpp b/frameworks/core/components_ng/pattern/text/text_styles.cpp index 893ef63808b288282ba1fee23f5d70e326839cb5..e057616a663db893651129af393a7f5cea639d39 100644 --- a/frameworks/core/components_ng/pattern/text/text_styles.cpp +++ b/frameworks/core/components_ng/pattern/text/text_styles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -50,6 +50,7 @@ TextStyle CreateTextStyleUsingTheme(const std::unique_ptr& fontStyle, UPDATE_TEXT_STYLE(textLineStyle, TextOverflow, SetTextOverflow); UPDATE_TEXT_STYLE(textLineStyle, TextAlign, SetTextAlign); UPDATE_TEXT_STYLE(textLineStyle, MaxLines, SetMaxLines); + UPDATE_TEXT_STYLE(textLineStyle, TextIndent, SetTextIndent); } return textStyle; } diff --git a/frameworks/core/components_ng/pattern/text/text_styles.h b/frameworks/core/components_ng/pattern/text/text_styles.h index 29b0cff34d159f11f4f563c17d75f8a8e028364d..c09cfff90c232bf3d42e209d8431de03e34ea0b9 100644 --- a/frameworks/core/components_ng/pattern/text/text_styles.h +++ b/frameworks/core/components_ng/pattern/text/text_styles.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -47,6 +47,7 @@ struct TextLineStyle { ACE_DEFINE_PROPERTY_GROUP_ITEM(MaxLength, uint32_t); ACE_DEFINE_PROPERTY_GROUP_ITEM(MaxLines, uint32_t); ACE_DEFINE_PROPERTY_GROUP_ITEM(HeightAdaptivePolicy, TextHeightAdaptivePolicy); + ACE_DEFINE_PROPERTY_GROUP_ITEM(TextIndent, Dimension); }; TextStyle CreateTextStyleUsingTheme(const std::unique_ptr& fontStyle, diff --git a/frameworks/core/components_ng/render/adapter/txt_paragraph.cpp b/frameworks/core/components_ng/render/adapter/txt_paragraph.cpp index 9a64dffad9710d44bba4aa2c17474a99ff638e58..55574320383c0d7ecd33faec9398027dc05215cd 100644 --- a/frameworks/core/components_ng/render/adapter/txt_paragraph.cpp +++ b/frameworks/core/components_ng/render/adapter/txt_paragraph.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -82,6 +82,17 @@ void TxtParagraph::AddText(const std::u16string& text) builder_->AddText(text); } +int32_t TxtParagraph::AddPlaceholder(const PlaceholderRun& span) +{ + if (!builder_) { + CreateBuilder(); + } + txt::PlaceholderRun txtSpan; + Constants::ConvertPlaceholderRun(span, txtSpan); + builder_->AddPlaceholder(txtSpan); + return ++placeHolderIndex_; +} + void TxtParagraph::Build() { CHECK_NULL_VOID_NOLOG(builder_); @@ -255,6 +266,7 @@ bool TxtParagraph::ComputeOffsetForCaretDownstream(int32_t extent, CaretMetrics& void TxtParagraph::GetRectsForRange(int32_t start, int32_t end, std::vector& selectedRects) { + CHECK_NULL_VOID(paragraph_); const auto& boxes = paragraph_->GetRectsForRange( start, end, txt::Paragraph::RectHeightStyle::kMax, txt::Paragraph::RectWidthStyle::kTight); if (boxes.empty()) { @@ -266,4 +278,24 @@ void TxtParagraph::GetRectsForRange(int32_t start, int32_t end, std::vector& selectedRects) +{ + CHECK_NULL_VOID(paragraph_); + const auto& boxes = paragraph_->GetRectsForPlaceholders(); + if (boxes.empty()) { + return; + } + for (const auto& box : boxes) { + auto selectionRect = Constants::ConvertSkRect(box.rect); + selectedRects.emplace_back(selectionRect); + } +} + +void TxtParagraph::SetIndents(const std::vector& indents) +{ + auto* paragraphTxt = static_cast(paragraph_.get()); + CHECK_NULL_VOID(paragraphTxt); + paragraphTxt->SetIndents(indents); +} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/render/adapter/txt_paragraph.h b/frameworks/core/components_ng/render/adapter/txt_paragraph.h index 8bd39be54d85712cd51cdab7c53ece249668d881..24786fe73b8e5bfb7567955b378b6c377954c063 100644 --- a/frameworks/core/components_ng/render/adapter/txt_paragraph.h +++ b/frameworks/core/components_ng/render/adapter/txt_paragraph.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -43,6 +43,7 @@ public: void PopStyle() override; void AddText(const std::u16string& text) override; + int32_t AddPlaceholder(const PlaceholderRun& span) override; void Build() override; void Reset() override; @@ -64,8 +65,10 @@ public: // interfaces for calculate the the specified paragraph position int32_t GetHandlePositionForClick(const Offset& offset) override; void GetRectsForRange(int32_t start, int32_t end, std::vector& selectedRects) override; + void GetRectsForPlaceholders(std::vector& selectedRects) override; bool ComputeOffsetForCaretDownstream(int32_t extent, CaretMetrics& result) override; bool ComputeOffsetForCaretUpstream(int32_t extent, CaretMetrics& result) override; + void SetIndents(const std::vector& indents) override; private: void CreateBuilder(); @@ -74,6 +77,7 @@ private: std::unique_ptr builder_; std::shared_ptr fontCollection_; std::u16string text_; + int32_t placeHolderIndex_ = -1; ACE_DISALLOW_COPY_AND_MOVE(TxtParagraph); }; diff --git a/frameworks/core/components_ng/render/paragraph.h b/frameworks/core/components_ng/render/paragraph.h index 166c1fbe5c52fac087b42fc44c56c4f2ae2f38fc..6a14628ad73fff8c7e347238c86b5fb484d7f690 100644 --- a/frameworks/core/components_ng/render/paragraph.h +++ b/frameworks/core/components_ng/render/paragraph.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -48,6 +48,7 @@ public: virtual void PushStyle(const TextStyle& style) = 0; virtual void PopStyle() = 0; virtual void AddText(const std::u16string& text) = 0; + virtual int32_t AddPlaceholder(const PlaceholderRun& span) = 0; virtual void Build() = 0; virtual void Reset() = 0; @@ -63,8 +64,10 @@ public: virtual float GetAlphabeticBaseline() = 0; virtual int32_t GetHandlePositionForClick(const Offset& offset) = 0; virtual void GetRectsForRange(int32_t start, int32_t end, std::vector& selectedRects) = 0; + virtual void GetRectsForPlaceholders(std::vector& selectedRects) = 0; virtual bool ComputeOffsetForCaretDownstream(int32_t extent, CaretMetrics& result) = 0; virtual bool ComputeOffsetForCaretUpstream(int32_t extent, CaretMetrics& result) = 0; + virtual void SetIndents(const std::vector& indents) = 0; // interfaces for painting virtual void Paint(const RSCanvas& canvas, float x, float y) = 0; diff --git a/frameworks/core/components_ng/test/mock/pattern/text/mock_text_layout_algorithm.cpp b/frameworks/core/components_ng/test/mock/pattern/text/mock_text_layout_algorithm.cpp index e840c4ff608a974b47696fcc484be8dc271adbbc..406c6c566e0c3a2450c59b6c9fc4dae58382052a 100644 --- a/frameworks/core/components_ng/test/mock/pattern/text/mock_text_layout_algorithm.cpp +++ b/frameworks/core/components_ng/test/mock/pattern/text/mock_text_layout_algorithm.cpp @@ -30,19 +30,19 @@ std::optional TextLayoutAlgorithm::MeasureContent( return SizeF(1.0f, 1.0f); } -bool TextLayoutAlgorithm::CreateParagraph(const TextStyle& textStyle, std::string content) +bool TextLayoutAlgorithm::CreateParagraph(const TextStyle& textStyle, std::string content, LayoutWrapper* layoutWrapper) { return true; } -bool TextLayoutAlgorithm::CreateParagraphAndLayout( - const TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint) +bool TextLayoutAlgorithm::CreateParagraphAndLayout(const TextStyle& textStyle, const std::string& content, + const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) { return true; } bool TextLayoutAlgorithm::AdaptMinTextSize(TextStyle& textStyle, const std::string& content, - const LayoutConstraintF& contentConstraint, const RefPtr& pipeline) + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline, LayoutWrapper* layoutWrapper) { return true; } @@ -86,4 +86,6 @@ std::optional TextLayoutAlgorithm::GetTextStyle() const { return std::optional(TextStyle()); } + +void TextLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) {} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/test/pattern/text/mock/mock_txt_paragraph.cpp b/frameworks/core/components_ng/test/pattern/text/mock/mock_txt_paragraph.cpp index 10c86028460cf7932e06ec6b9d6bc9da328d2f2e..25107d0a07cae1d0b07c43626e2db926cdc1c994 100644 --- a/frameworks/core/components_ng/test/pattern/text/mock/mock_txt_paragraph.cpp +++ b/frameworks/core/components_ng/test/pattern/text/mock/mock_txt_paragraph.cpp @@ -134,4 +134,14 @@ bool TxtParagraph::ComputeOffsetForCaretUpstream(int32_t extent, CaretMetrics& r { return true; } + +int32_t TxtParagraph::AddPlaceholder(const PlaceholderRun& span) +{ + placeHolderIndex_ = -1; + return -1; +} + +void TxtParagraph::GetRectsForPlaceholders(std::vector& selectedRects) {} + +void TxtParagraph::SetIndents(const std::vector& indents) {} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/test/pattern/text/text_test_ng.cpp b/frameworks/core/components_ng/test/pattern/text/text_test_ng.cpp index c403ed1d11ee577511d72c8624a921cfa35a1f64..f00aaea7ca0ce4a49fc089deb5cc187dbd36f8c1 100644 --- a/frameworks/core/components_ng/test/pattern/text/text_test_ng.cpp +++ b/frameworks/core/components_ng/test/pattern/text/text_test_ng.cpp @@ -703,7 +703,7 @@ HWTEST_F(TextTestNg, OnDirtyLayoutWrapperSwap003, TestSize.Level1) auto rowLayoutAlgorithm = AceType::DynamicCast(pattern->CreateLayoutAlgorithm()); TextStyle textStyle; LayoutConstraintF contentConstraint; - auto ret = rowLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint); + auto ret = rowLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint, nullptr); EXPECT_TRUE(ret); layoutWrapper->SetLayoutAlgorithm(AceType::MakeRefPtr(rowLayoutAlgorithm)); ret = pattern->OnDirtyLayoutWrapperSwap(layoutWrapper, config); @@ -730,7 +730,7 @@ HWTEST_F(TextTestNg, BeforeCreateLayoutWrapper001, TestSize.Level1) auto rowLayoutAlgorithm = AceType::DynamicCast(pattern->CreateLayoutAlgorithm()); TextStyle textStyle; LayoutConstraintF contentConstraint; - auto ret = rowLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint); + auto ret = rowLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint, nullptr); EXPECT_TRUE(ret); auto layoutWrapper = AceType::MakeRefPtr( frameNode, AceType::MakeRefPtr(), frameNode->GetLayoutProperty()); @@ -785,7 +785,7 @@ HWTEST_F(TextTestNg, BeforeCreateLayoutWrapper003, TestSize.Level1) auto rowLayoutAlgorithm = AceType::DynamicCast(pattern->CreateLayoutAlgorithm()); TextStyle textStyle; LayoutConstraintF contentConstraint; - auto ret = rowLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint); + auto ret = rowLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint, nullptr); EXPECT_TRUE(ret); DirtySwapConfig config; @@ -1069,7 +1069,8 @@ HWTEST_F(TextTestNg, TextLayoutTest003, TestSize.Level1) */ auto textLayoutAlgorithm = AceType::MakeRefPtr(); - auto result = textLayoutAlgorithm->AdaptMinTextSize(textStyle, CREATE_VALUE, parentLayoutConstraint, pipeline); + auto result = + textLayoutAlgorithm->AdaptMinTextSize(textStyle, CREATE_VALUE, parentLayoutConstraint, pipeline, nullptr); /** * @tc.steps: step4. check the fontSize. @@ -1122,7 +1123,8 @@ HWTEST_F(TextTestNg, TextLayoutTest004, TestSize.Level1) */ auto textLayoutAlgorithm = AceType::MakeRefPtr(); - auto result = textLayoutAlgorithm->AdaptMinTextSize(textStyle, CREATE_VALUE, parentLayoutConstraint, pipeline); + auto result = + textLayoutAlgorithm->AdaptMinTextSize(textStyle, CREATE_VALUE, parentLayoutConstraint, pipeline, nullptr); /** * @tc.steps: step4. check the fontSize. @@ -1175,7 +1177,8 @@ HWTEST_F(TextTestNg, TextLayoutTest005, TestSize.Level1) */ auto textLayoutAlgorithm = AceType::MakeRefPtr(); - auto result = textLayoutAlgorithm->AdaptMinTextSize(textStyle, CREATE_VALUE, parentLayoutConstraint, pipeline); + auto result = + textLayoutAlgorithm->AdaptMinTextSize(textStyle, CREATE_VALUE, parentLayoutConstraint, pipeline, nullptr); /** * @tc.steps: step4. check the fontSize. @@ -1223,7 +1226,7 @@ HWTEST_F(TextTestNg, TextLayoutTest006, TestSize.Level1) auto textLayoutAlgorithm = AceType::MakeRefPtr(); TextStyle textStyle; LayoutConstraintF contentConstraint; - auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint); + auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint, nullptr); EXPECT_TRUE(ret); auto sizeX = textLayoutAlgorithm->MeasureContent(parentLayoutConstraint, AccessibilityManager::RawPtr(layoutWrapper)); @@ -1276,7 +1279,7 @@ HWTEST_F(TextTestNg, TextLayoutTest007, TestSize.Level1) TextStyle textStyle; Dimension adaptMinFontSize(DIMENSION, DimensionUnit::PERCENT); textStyle.SetAdaptMinFontSize(adaptMinFontSize); - auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", parentLayoutConstraint); + auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", parentLayoutConstraint, nullptr); EXPECT_TRUE(ret); auto sizeX = textLayoutAlgorithm->MeasureContent(parentLayoutConstraint, AccessibilityManager::RawPtr(layoutWrapper)); @@ -1330,7 +1333,7 @@ HWTEST_F(TextTestNg, TextLayoutTest008, TestSize.Level1) TextStyle textStyle; Dimension adaptMinFontSize(DIMENSION, DimensionUnit::PERCENT); textStyle.SetAdaptMinFontSize(adaptMinFontSize); - auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", parentLayoutConstraint); + auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", parentLayoutConstraint, nullptr); EXPECT_TRUE(ret); auto sizeX = textLayoutAlgorithm->MeasureContent(parentLayoutConstraint, AccessibilityManager::RawPtr(layoutWrapper)); @@ -1574,7 +1577,7 @@ HWTEST_F(TextTestNg, DidExceedMaxLines001, TestSize.Level1) auto textLayoutAlgorithm = AceType::MakeRefPtr(); TextStyle textStyle; LayoutConstraintF contentConstraint; - auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint); + auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint, nullptr); EXPECT_TRUE(ret); SizeF maxSize; ret = textLayoutAlgorithm->DidExceedMaxLines(maxSize); @@ -1626,7 +1629,7 @@ HWTEST_F(TextTestNg, DidExceedMaxLines002, TestSize.Level1) TextStyle textStyle; textStyle.SetMaxLines(MAX_LINES); LayoutConstraintF contentConstraint; - auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint); + auto ret = textLayoutAlgorithm->CreateParagraphAndLayout(textStyle, "", contentConstraint, nullptr); EXPECT_TRUE(ret); SizeF maxSize; ret = textLayoutAlgorithm->DidExceedMaxLines(maxSize); @@ -2193,25 +2196,28 @@ HWTEST_F(TextTestNg, TextLayoutAlgorithmTest008, TestSize.Level1) // maxFontSize < minFontSize textStyle.SetAdaptMaxFontSize(ADAPT_MIN_FONT_SIZE_VALUE); textStyle.SetAdaptMinFontSize(ADAPT_MAX_FONT_SIZE_VALUE); - EXPECT_EQ(textLayoutAlgorithm->AdaptMaxTextSize(textStyle, "abc", parentLayoutConstraint, pipeline), false); + EXPECT_EQ( + textLayoutAlgorithm->AdaptMaxTextSize(textStyle, "abc", parentLayoutConstraint, pipeline, nullptr), false); // create paragraph failed textStyle.SetAdaptMaxFontSize(ADAPT_MAX_FONT_SIZE_VALUE); textStyle.SetAdaptMinFontSize(ADAPT_MIN_FONT_SIZE_VALUE); - EXPECT_EQ(textLayoutAlgorithm->AdaptMaxTextSize(textStyle, "abc", parentLayoutConstraint, pipeline), false); + EXPECT_EQ( + textLayoutAlgorithm->AdaptMaxTextSize(textStyle, "abc", parentLayoutConstraint, pipeline, nullptr), false); MockTxtParagraph::SetCanConstruct(true); // increase font size std::vector didExceedMaxLines = { false, true }; MockTxtParagraph::SetDidExceedMaxLines(didExceedMaxLines); - EXPECT_EQ(textLayoutAlgorithm->AdaptMaxTextSize(textStyle, "abc", parentLayoutConstraint, pipeline), true); + EXPECT_EQ(textLayoutAlgorithm->AdaptMaxTextSize(textStyle, "abc", parentLayoutConstraint, pipeline, nullptr), true); didExceedMaxLines.clear(); MockTxtParagraph::SetDidExceedMaxLines(didExceedMaxLines); // set NormalizeToPx false textStyle.adaptFontSizeStep_.SetUnit(DimensionUnit::CALC); - EXPECT_EQ(textLayoutAlgorithm->AdaptMaxTextSize(textStyle, "abc", parentLayoutConstraint, pipeline), false); + EXPECT_EQ( + textLayoutAlgorithm->AdaptMaxTextSize(textStyle, "abc", parentLayoutConstraint, pipeline, nullptr), false); } /** diff --git a/test/mock/core/render/mock_paragraph.h b/test/mock/core/render/mock_paragraph.h index 24834982d44618c538af8ff224314793ac54892f..f5622d1c81b197d45c3ba170a279fda4123f4d9d 100644 --- a/test/mock/core/render/mock_paragraph.h +++ b/test/mock/core/render/mock_paragraph.h @@ -44,6 +44,9 @@ public: MOCK_METHOD1(AddText, void(const std::u16string& text)); MOCK_METHOD1(Layout, void(float width)); MOCK_METHOD1(GetHandlePositionForClick, int32_t(const Offset& offset)); + MOCK_METHOD1(AddPlaceholder, int32_t(const PlaceholderRun& span)); + MOCK_METHOD1(GetRectsForPlaceholders, void(std::vector& selectedRects)); + MOCK_METHOD1(SetIndents, void(const std::vector& indents)); MOCK_METHOD2(ComputeOffsetForCaretDownstream, bool(int32_t extent, CaretMetrics& result)); MOCK_METHOD2(ComputeOffsetForCaretUpstream, bool(int32_t extent, CaretMetrics& result)); MOCK_METHOD3(GetRectsForRange, void(int32_t start, int32_t end, std::vector& selectedRects));