支持轻量图文混排

Signed-off-by: limeng <limeng208@huawei.com>
This commit is contained in:
limeng 2023-04-10 22:10:46 +08:00
parent 3a9b2c4237
commit 4e2c172686
36 changed files with 715 additions and 105 deletions

View File

@ -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",

View File

@ -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 = {}));

View File

@ -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<std::string, std::function<void(BindingTarget)>>
{ "RelativeContainer", JSRelativeContainer::JSBind },
{ "__Common__", JSCommonView::JSBind },
{ "LinearGradient", JSLinearGradient::JSBind },
{ "ImageSpan", JSImageSpan::JSBind },
#ifdef PREVIEW
{ "FormComponent", JSForm::JSBind },
{ "XComponent", JSXComponent::JSBind },

View File

@ -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

View File

@ -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 <dlfcn.h>
#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<PixelMap> 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<ImageFit>(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>(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<JSImageSpan>::Declare("ImageSpan");
MethodOptions opt = MethodOptions::NONE;
JSClass<JSImageSpan>::StaticMethod("create", &JSImageSpan::Create, opt);
JSClass<JSImageSpan>::StaticMethod("objectFit", &JSImageSpan::SetObjectFit, opt);
JSClass<JSImageSpan>::StaticMethod("verticalAlign", &JSImageSpan::SetVerticalAlign);
JSClass<JSImageSpan>::Inherit<JSViewAbstract>();
JSClass<JSImageSpan>::Bind<>(globalObj);
}
} // namespace OHOS::Ace::Framework

View File

@ -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<JSVal>& 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

View File

@ -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<int32_t>(FONT_STYLES.size())) {
@ -551,6 +564,7 @@ void JSText::JSBind(BindingTarget globalObj)
JSClass<JSText>::StaticMethod("fontSize", &JSText::SetFontSize, opt);
JSClass<JSText>::StaticMethod("fontWeight", &JSText::SetFontWeight, opt);
JSClass<JSText>::StaticMethod("maxLines", &JSText::SetMaxLines, opt);
JSClass<JSText>::StaticMethod("textIndent", &JSText::SetTextIndent);
JSClass<JSText>::StaticMethod("textOverflow", &JSText::SetTextOverflow, opt);
JSClass<JSText>::StaticMethod("fontStyle", &JSText::SetFontStyle, opt);
JSClass<JSText>::StaticMethod("align", &JSText::SetAlign, opt);

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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<PipelineBase>& co
Rect ConvertSkRect(SkRect skRect);
txt::PlaceholderAlignment ConvertPlaceholderAlignment(PlaceholderAlignment textDecoration);
void ConvertPlaceholderRun(const PlaceholderRun& span, txt::PlaceholderRun& txtSpan);
} // namespace Constants
} // namespace OHOS::Ace

View File

@ -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",

View File

@ -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<JsonValue>& 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<int32_t>(propImageFit_.value_or(ImageFit::COVER))]);
json->Put("syncLoad", propSyncMode_.value_or(false) ? "true" : "false");
json->Put("copyOption", COPYOPTIONSVALUE[static_cast<int32_t>(propCopyOptions_.value_or(CopyOptions::None))]);
json->Put("verticalAlign",
VERTICALALIGNVALUE[static_cast<int32_t>(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);

View File

@ -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

View File

@ -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 <string>
#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

View File

@ -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<Paragraph>& builder)
int32_t SpanItem::UpdateParagraph(
const RefPtr<Paragraph>& 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<TextTheme>());
builder->PushStyle(textStyle);
}
@ -142,5 +143,36 @@ void SpanItem::UpdateParagraph(const RefPtr<Paragraph>& builder)
if (fontStyle) {
builder->PopStyle();
}
return -1;
}
int32_t ImageSpanItem::UpdateParagraph(
const RefPtr<Paragraph>& 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

View File

@ -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> fontStyle;
GestureEventFunc onClick;
std::list<RefPtr<SpanItem>> children;
int32_t placeHolderIndex = -1;
void UpdateParagraph(const RefPtr<Paragraph>& builder);
virtual int32_t UpdateParagraph(const RefPtr<Paragraph>& builder, double width = 0.0f, double height = 0.0f,
VerticalAlign verticalAlign = VerticalAlign::BASELINE);
void ToJsonValue(std::unique_ptr<JsonValue>& json) const;
virtual void ToJsonValue(std::unique_ptr<JsonValue>& json) const;
};
struct ImageSpanItem : public SpanItem {
DECLARE_ACE_TYPE(ImageSpanItem, SpanItem);
public:
ImageSpanItem() = default;
~ImageSpanItem() override = default;
int32_t UpdateParagraph(
const RefPtr<Paragraph>& builder, double width, double height, VerticalAlign verticalAlign) override;
void ToJsonValue(std::unique_ptr<JsonValue>& json) const override {};
ACE_DISALLOW_COPY_AND_MOVE(ImageSpanItem);
};
class ACE_EXPORT SpanNode : public UINode {

View File

@ -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<SizeF> 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<ImageSpanItem>(child);
if (imageSpanItem) {
if (iterItems == children.end() || !(*iterItems)) {
continue;
}
(*iterItems)->Measure(layoutConstrain);
auto verticalAlign = VerticalAlign::BOTTOM;
auto imageLayoutProperty = DynamicCast<ImageLayoutProperty>((*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<int32_t>(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<int32_t> placeHolderIndex;
for (const auto& child : spanItemChildren_) {
if (!child) {
continue;
}
auto imageSpanItem = AceType::DynamicCast<ImageSpanItem>(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<Rect> 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<PipelineContext>& pipeline)
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& 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<RefPtr<SpanItem>>&& TextLayoutAlgorithm::GetSpanItemChildren()
}
bool TextLayoutAlgorithm::BuildParagraph(TextStyle& textStyle, const RefPtr<TextLayoutProperty>& layoutProperty,
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline)
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& 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<Text
bool TextLayoutAlgorithm::BuildParagraphAdaptUseMinFontSize(TextStyle& textStyle,
const RefPtr<TextLayoutProperty>& layoutProperty, const LayoutConstraintF& contentConstraint,
const RefPtr<PipelineContext>& pipeline)
const RefPtr<PipelineContext>& 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<TextLayoutProperty>& layoutProperty, const LayoutConstraintF& contentConstraint,
const RefPtr<PipelineContext>& pipeline)
const RefPtr<PipelineContext>& 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<float>(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<float>(paragraph_->GetHeight());
@ -371,13 +490,13 @@ bool TextLayoutAlgorithm::BuildParagraphAdaptUseLayoutConstraint(TextStyle& text
std::optional<SizeF> TextLayoutAlgorithm::BuildTextRaceParagraph(TextStyle& textStyle,
const RefPtr<TextLayoutProperty>& layoutProperty, const LayoutConstraintF& contentConstraint,
const RefPtr<PipelineContext>& pipeline)
const RefPtr<PipelineContext>& 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<PipelineContext>& pipeline)
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& 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<FrameNode>& 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<float> 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<float>(indent));
indents.emplace_back(0.0);
paragraph_->SetIndents(indents);
}
}
} // namespace OHOS::Ace::NG

View File

@ -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<SizeF> MeasureContent(
const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) override;
void Layout(LayoutWrapper* layoutWrapper) override;
const RefPtr<Paragraph>& GetParagraph();
std::list<RefPtr<SpanItem>>&& GetSpanItemChildren();
@ -57,29 +59,36 @@ public:
float GetBaselineOffset() const;
std::optional<TextStyle> 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<PipelineContext>& pipeline);
const RefPtr<PipelineContext>& 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<TextLayoutProperty>& layoutProperty,
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline);
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline,
LayoutWrapper* layoutWrapper);
bool BuildParagraphAdaptUseMinFontSize(TextStyle& textStyle, const RefPtr<TextLayoutProperty>& layoutProperty,
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline);
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline,
LayoutWrapper* layoutWrapper);
bool BuildParagraphAdaptUseLayoutConstraint(TextStyle& textStyle, const RefPtr<TextLayoutProperty>& layoutProperty,
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline);
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline,
LayoutWrapper* layoutWrapper);
std::optional<SizeF> BuildTextRaceParagraph(TextStyle& textStyle, const RefPtr<TextLayoutProperty>& layoutProperty,
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline);
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline,
LayoutWrapper* layoutWrapper);
void SetPropertyToModifier(const RefPtr<TextLayoutProperty>& layoutProperty, RefPtr<TextContentModifier> modifier);
bool AdaptMaxTextSize(TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint,
const RefPtr<PipelineContext>& pipeline);
const RefPtr<PipelineContext>& pipeline, LayoutWrapper* layoutWrapper);
void UpdateTextColorIfForeground(const RefPtr<FrameNode>& frameNode, TextStyle& textStyle);
void UpdateParagraph(LayoutWrapper* layoutWrapper);
OffsetF GetContentOffset(LayoutWrapper* layoutWrapper) const;
std::list<RefPtr<SpanItem>> spanItemChildren_;
RefPtr<Paragraph> paragraph_;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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<UINode>& child)
{
CHECK_NULL_VOID(child);
if (child->GetTag() == V2::SPAN_ETS_TAG) {
auto spanNode = DynamicCast<SpanNode>(child);
if (spanNode) {
spanItemChildren_.emplace_back(spanNode->GetSpanItem());
}
} else if (child->GetTag() == V2::IMAGE_ETS_TAG) {
auto imageNode = DynamicCast<FrameNode>(child);
if (imageNode) {
spanItemChildren_.emplace_back(MakeRefPtr<ImageSpanItem>());
}
}
}
void TextPattern::DumpInfo()
{
auto textLayoutProp = GetLayoutProperty<TextLayoutProperty>();

View File

@ -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<SpanNode>& child)
{
spanItemChildren_.emplace_back(child->GetSpanItem());
}
void AddChildSpanItem(const RefPtr<UINode>& child);
FocusPattern GetFocusPattern() const override
{

View File

@ -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>& 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;
}

View File

@ -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>& fontStyle,

View File

@ -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<Rect>& 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<Rect
}
}
void TxtParagraph::GetRectsForPlaceholders(std::vector<Rect>& 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<float>& indents)
{
auto* paragraphTxt = static_cast<txt::ParagraphTxt*>(paragraph_.get());
CHECK_NULL_VOID(paragraphTxt);
paragraphTxt->SetIndents(indents);
}
} // namespace OHOS::Ace::NG

View File

@ -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<Rect>& selectedRects) override;
void GetRectsForPlaceholders(std::vector<Rect>& selectedRects) override;
bool ComputeOffsetForCaretDownstream(int32_t extent, CaretMetrics& result) override;
bool ComputeOffsetForCaretUpstream(int32_t extent, CaretMetrics& result) override;
void SetIndents(const std::vector<float>& indents) override;
private:
void CreateBuilder();
@ -74,6 +77,7 @@ private:
std::unique_ptr<txt::ParagraphBuilder> builder_;
std::shared_ptr<txt::FontCollection> fontCollection_;
std::u16string text_;
int32_t placeHolderIndex_ = -1;
ACE_DISALLOW_COPY_AND_MOVE(TxtParagraph);
};

View File

@ -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<Rect>& selectedRects) = 0;
virtual void GetRectsForPlaceholders(std::vector<Rect>& 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<float>& indents) = 0;
// interfaces for painting
virtual void Paint(const RSCanvas& canvas, float x, float y) = 0;

View File

@ -30,19 +30,19 @@ std::optional<SizeF> 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<PipelineContext>& pipeline)
const LayoutConstraintF& contentConstraint, const RefPtr<PipelineContext>& pipeline, LayoutWrapper* layoutWrapper)
{
return true;
}
@ -86,4 +86,6 @@ std::optional<TextStyle> TextLayoutAlgorithm::GetTextStyle() const
{
return std::optional<TextStyle>(TextStyle());
}
void TextLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) {}
} // namespace OHOS::Ace::NG

View File

@ -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<Rect>& selectedRects) {}
void TxtParagraph::SetIndents(const std::vector<float>& indents) {}
} // namespace OHOS::Ace::NG

View File

@ -703,7 +703,7 @@ HWTEST_F(TextTestNg, OnDirtyLayoutWrapperSwap003, TestSize.Level1)
auto rowLayoutAlgorithm = AceType::DynamicCast<TextLayoutAlgorithm>(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<LayoutAlgorithmWrapper>(rowLayoutAlgorithm));
ret = pattern->OnDirtyLayoutWrapperSwap(layoutWrapper, config);
@ -730,7 +730,7 @@ HWTEST_F(TextTestNg, BeforeCreateLayoutWrapper001, TestSize.Level1)
auto rowLayoutAlgorithm = AceType::DynamicCast<TextLayoutAlgorithm>(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<LayoutWrapper>(
frameNode, AceType::MakeRefPtr<GeometryNode>(), frameNode->GetLayoutProperty());
@ -785,7 +785,7 @@ HWTEST_F(TextTestNg, BeforeCreateLayoutWrapper003, TestSize.Level1)
auto rowLayoutAlgorithm = AceType::DynamicCast<TextLayoutAlgorithm>(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<TextLayoutAlgorithm>();
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<TextLayoutAlgorithm>();
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<TextLayoutAlgorithm>();
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<TextLayoutAlgorithm>();
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<TextLayoutAlgorithm>();
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<bool> 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);
}
/**

View File

@ -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<Rect>& selectedRects));
MOCK_METHOD1(SetIndents, void(const std::vector<float>& 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<Rect>& selectedRects));