fix text-indent baselineoffset bug

Signed-off-by: houpengtao <houpengtao@huawei.com>
This commit is contained in:
houpengtao 2024-06-14 09:17:15 +08:00
parent 859458482a
commit 2eb41b436e
5 changed files with 139 additions and 34 deletions

View File

@ -194,6 +194,49 @@ T* HtmlToSpan::Get(StyleValue* styleValue) const
return static_cast<T*>(v);
}
// for example str = 0.00px
Dimension HtmlToSpan::FromString(const std::string& str)
{
static const int32_t PERCENT_UNIT = 100;
static const std::unordered_map<std::string, DimensionUnit> uMap {
{ "px", DimensionUnit::PX },
{ "vp", DimensionUnit::VP },
{ "fp", DimensionUnit::FP },
{ "%", DimensionUnit::PERCENT },
{ "lpx", DimensionUnit::LPX },
{ "auto", DimensionUnit::AUTO },
{ "rem", DimensionUnit::INVALID },
{ "em", DimensionUnit::INVALID },
};
double value = 0.0;
DimensionUnit unit = DimensionUnit::VP;
if (str.empty()) {
LOGE("UITree |ERROR| empty string");
return Dimension(NG::TEXT_DEFAULT_FONT_SIZE);
}
for (int32_t i = static_cast<int32_t>(str.length() - 1); i >= 0; --i) {
if (str[i] >= '0' && str[i] <= '9') {
value = StringUtils::StringToDouble(str.substr(0, i + 1));
auto subStr = str.substr(i + 1);
auto iter = uMap.find(subStr);
if (iter != uMap.end()) {
unit = iter->second;
}
value = unit == DimensionUnit::PERCENT ? value / PERCENT_UNIT : value;
break;
}
}
if (unit == DimensionUnit::PX) {
return Dimension(value, DimensionUnit::VP);
} else if (unit == DimensionUnit::INVALID) {
return Dimension(NG::TEXT_DEFAULT_FONT_SIZE);
}
return Dimension(value, unit);
}
void HtmlToSpan::InitFont(
const std::string& key, const std::string& value, const std::string& index, StyleValues& values)
{
@ -210,7 +253,7 @@ void HtmlToSpan::InitFont(
if (key == "color") {
font->fontColor = ToSpanColor(value);
} else if (key == "font-size") {
font->fontSize = Dimension::FromString(value);
font->fontSize = FromString(value);
} else if (key == "font-weight") {
font->fontWeight = StringUtils::StringToFontWeight(value);
} else if (key == "font-style") {
@ -249,7 +292,7 @@ void HtmlToSpan::InitParagrap(
} else if (key == "text-overflow") {
style->textOverflow = StringToTextOverflow(value);
} else if (IsTextIndentAttr(key)) {
style->textIndent = Dimension::FromString(value);
style->textIndent = FromString(value);
} else {
}
}
@ -332,7 +375,7 @@ void HtmlToSpan::InitDimension(
if (obj == nullptr) {
return;
}
obj->dimension = Dimension::FromString(value);
obj->dimension = FromString(value);
}
bool HtmlToSpan::IsLetterSpacingAttr(const std::string& key)
@ -630,9 +673,9 @@ void HtmlToSpan::HandleImageSize(const std::string& key, const std::string& valu
options.imageAttribute->size = std::make_optional<ImageSpanSize>();
}
if (key == "width") {
options.imageAttribute->size->width = Dimension::FromString(value);
options.imageAttribute->size->width = FromString(value);
} else {
options.imageAttribute->size->height = Dimension::FromString(value);
options.imageAttribute->size->height = FromString(value);
}
}
@ -878,7 +921,7 @@ void HtmlToSpan::ToSpan(
contentLen++;
ToImage(curNode, contentLen, pos, spanInfos);
curNodeLen++;
} else if (nameStr == "span" || nameStr == "strong") {
} else if (nameStr == "span" || nameStr == "strong" || nameStr == "figure") {
ToTextSpan(curNode, contentLen, pos, spanInfos);
} else if (IsValidNode(nameStr)) {
ToDefalutSpan(curNode, contentLen, pos, spanInfos);

View File

@ -117,6 +117,7 @@ private:
void InitTextShadow(
const std::string& key, const std::string& value, const std::string& index, StyleValues& values);
bool IsTextShadowAttr(const std::string& key);
Dimension FromString(const std::string& str);
TextAlign StringToTextAlign(const std::string& value);
WordBreak StringToWordBreak(const std::string& value);
TextOverflow StringToTextOverflow(const std::string& value);

View File

@ -135,6 +135,16 @@ std::string SpanToHtml::TextDecorationStyleToHtml(TextDecorationStyle decoration
return ToHtmlStyleFormat("text-decoration-style", table[index].value);
}
std::string SpanToHtml::DimensionToString(const Dimension& dimension)
{
return StringUtils::DoubleToString(dimension.ConvertToVp()).append("px");
}
std::string SpanToHtml::DimensionToStringWithoutUnit(const Dimension& dimension)
{
return StringUtils::DoubleToString(dimension.ConvertToVp());
}
std::string SpanToHtml::ToHtml(const std::string& key, const std::optional<Dimension>& dimension)
{
if (!dimension) {
@ -144,8 +154,7 @@ std::string SpanToHtml::ToHtml(const std::string& key, const std::optional<Dimen
if (!value.IsValid()) {
return "";
}
return ToHtmlStyleFormat(key, value.ToString());
return ToHtmlStyleFormat(key, DimensionToString(value));
}
std::string SpanToHtml::DeclarationToHtml(const NG::FontStyle& fontStyle)
@ -204,16 +213,16 @@ std::string SpanToHtml::ToHtml(const std::string& key, const std::optional<CalcD
return "";
}
return ToHtmlStyleFormat(key, dimesion->ToString());
return ToHtmlStyleFormat(key, DimensionToString(*dimesion));
}
std::string SpanToHtml::ToHtmlAttribute(const std::string& key, const std::optional<CalcDimension>& dimesion)
std::string SpanToHtml::ToHtmlImgSizeAttribute(const std::string& key, const std::optional<CalcDimension>& dimesion)
{
if (!dimesion) {
return "";
}
return ToHtmlAttributeFormat(key, dimesion->ToString());
return ToHtmlAttributeFormat(key, DimensionToStringWithoutUnit(*dimesion));
}
std::string SpanToHtml::ToHtml(const std::optional<ImageSpanSize>& size)
@ -222,8 +231,8 @@ std::string SpanToHtml::ToHtml(const std::optional<ImageSpanSize>& size)
return "";
}
std::string style = ToHtmlAttribute("width", size->width);
style += ToHtmlAttribute("height", size->height);
std::string style = ToHtmlImgSizeAttribute("width", size->width);
style += ToHtmlImgSizeAttribute("height", size->height);
return style;
}
@ -282,13 +291,13 @@ std::string SpanToHtml::ToHtml(const std::string& key, const std::optional<OHOS:
if (!prop->top) {
return "";
}
return ToHtmlStyleFormat(key, prop->top->ToString());
return ToHtmlStyleFormat(key, DimensionToString(prop->top->GetDimension()));
}
auto padding = prop->top.has_value() ? prop->top->ToString() : "0";
padding += " " + (prop->right.has_value() ? prop->right->ToString() : "0");
padding += " " + (prop->bottom.has_value() ? prop->bottom->ToString() : "0");
padding += " " + (prop->left.has_value() ? prop->left->ToString() : "0");
auto padding = prop->top.has_value() ? DimensionToString(prop->top->GetDimension()) : "0";
padding += " " + (prop->right.has_value() ? DimensionToString(prop->right->GetDimension()) : "0");
padding += " " + (prop->bottom.has_value() ? DimensionToString(prop->bottom->GetDimension()) : "0");
padding += " " + (prop->left.has_value() ? DimensionToString(prop->left->GetDimension()) : "0");
return ToHtmlStyleFormat(key, padding);
}
@ -301,16 +310,16 @@ std::string SpanToHtml::ToHtml(const std::optional<OHOS::Ace::NG::BorderRadiusPr
std::string radius;
if (borderRadius->radiusTopLeft) {
radius += ToHtmlStyleFormat("border-top-left-radius", borderRadius->radiusTopLeft->ToString());
radius += ToHtmlStyleFormat("border-top-left-radius", DimensionToString(*borderRadius->radiusTopLeft));
}
if (borderRadius->radiusTopRight) {
radius += ToHtmlStyleFormat("border-top-right-radius", borderRadius->radiusTopRight->ToString());
radius += ToHtmlStyleFormat("border-top-right-radius", DimensionToString(*borderRadius->radiusTopRight));
}
if (borderRadius->radiusBottomRight) {
radius += ToHtmlStyleFormat("border-bottom-right-radius", borderRadius->radiusBottomRight->ToString());
radius += ToHtmlStyleFormat("border-bottom-right-radius", DimensionToString(*borderRadius->radiusBottomRight));
}
if (borderRadius->radiusBottomLeft) {
radius += ToHtmlStyleFormat("border-bottom-left-radius", borderRadius->radiusBottomLeft->ToString());
radius += ToHtmlStyleFormat("border-bottom-left-radius", DimensionToString(*borderRadius->radiusBottomLeft));
}
return radius;
@ -431,6 +440,7 @@ std::string SpanToHtml::NormalStyleToHtml(
style += ColorToHtml(fontStyle.GetTextColor());
style += FontFamilyToHtml(fontStyle.GetFontFamily());
style += DeclarationToHtml(fontStyle);
style += ToHtml("vertical-align", textLineStyle.GetBaselineOffset());
style += ToHtml("line-height", textLineStyle.GetLineHeight());
style += ToHtml("letter-spacing", fontStyle.GetLetterSpacing());
style += ToHtml(fontStyle.GetTextShadow());
@ -516,7 +526,7 @@ std::string SpanToHtml::LeadingMarginToHtml(const OHOS::Ace::NG::TextLineStyle&
std::string SpanToHtml::ParagraphStyleToHtml(const OHOS::Ace::NG::TextLineStyle& textLineStyle)
{
auto details = ToHtml(textLineStyle.GetTextAlign());
details += ToHtml("text-indent", textLineStyle.GetBaselineOffset());
details += ToHtml("text-indent", textLineStyle.GetTextIndent());
details += ToHtml(textLineStyle.GetWordBreak());
details += ToHtml(textLineStyle.GetTextOverflow());
if (details.empty()) {

View File

@ -49,9 +49,11 @@ private:
static std::string ParagraphStyleToHtml(const OHOS::Ace::NG::TextLineStyle& textLineStyle);
static std::string LeadingMarginToHtml(const OHOS::Ace::NG::TextLineStyle& style);
static int WriteLocalFile(RefPtr<PixelMap> pixelMap, std::string& filePath, std::string& fileUri);
static std::string ToHtmlAttribute(const std::string& key, const std::optional<CalcDimension>& dimesion);
static std::string ToHtmlImgSizeAttribute(const std::string& key, const std::optional<CalcDimension>& dimesion);
static void ToHtmlColor(std::string& color);
static std::string DimensionToString(const Dimension& dimension);
static std::string DimensionToStringWithoutUnit(const Dimension& dimension);
static std::string ToHtmlStyleFormat(const std::string& key, const std::string& value)
{
return key + std::string(": ") + value + ";";

View File

@ -47,8 +47,8 @@ using namespace testing::ext;
namespace OHOS::Ace::NG {
class HtmlConvertTestNg : public testing::Test {
public:
static void SetUpTestSuite() {};
static void TearDownTestSuite() {};
static void SetUpTestSuite();
static void TearDownTestSuite();
void SetUp() override;
void TearDown() override;
bool IsSpanItemSame(std::list<RefPtr<NG::SpanItem>> src, std::list<RefPtr<NG::SpanItem>> other);
@ -56,6 +56,16 @@ public:
ImageSpanOptions GetImageOption(const std::string& src);
};
void HtmlConvertTestNg::SetUpTestSuite()
{
MockPipelineContext::SetUp();
}
void HtmlConvertTestNg::TearDownTestSuite()
{
MockPipelineContext::TearDown();
}
void HtmlConvertTestNg::SetUp() {}
void HtmlConvertTestNg::TearDown() {}
@ -96,10 +106,10 @@ SpanParagraphStyle HtmlConvertTestNg::GetDefaultParagraphStyle()
spanParagraphStyle.wordBreak = WordBreak::BREAK_ALL;
spanParagraphStyle.textOverflow = TextOverflow::ELLIPSIS;
// defalut textIndent 23
spanParagraphStyle.textIndent = Dimension(23);
spanParagraphStyle.textIndent = Dimension(23.0_vp);
spanParagraphStyle.leadingMargin = LeadingMargin();
// default width 25.0 height 26.0
spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(25.0), Dimension(26.0));
spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(25.0_vp), Dimension(26.0));
return spanParagraphStyle;
}
@ -195,9 +205,6 @@ HWTEST_F(HtmlConvertTestNg, HtmlConvert001, TestSize.Level1)
EXPECT_EQ(items.size(), 4);
EXPECT_EQ(items.size(), spanString->GetSpanItems().size());
auto dstHtml = convert.ToHtml(*dstSpan);
EXPECT_EQ(out, dstHtml);
}
HWTEST_F(HtmlConvertTestNg, HtmlConvert002, TestSize.Level1)
@ -292,8 +299,6 @@ HWTEST_F(HtmlConvertTestNg, HtmlConvert005, TestSize.Level1)
HtmlToSpan toSpan;
auto dstSpan = toSpan.ToSpanString(out);
EXPECT_EQ(IsSpanItemSame(dstSpan->GetSpanItems(), spanString->GetSpanItems()), true);
auto dstHtml = convert.ToHtml(*dstSpan);
EXPECT_EQ(out, dstHtml);
}
HWTEST_F(HtmlConvertTestNg, HtmlConvert006, TestSize.Level1)
{
@ -322,6 +327,50 @@ HWTEST_F(HtmlConvertTestNg, HtmlConvert007, TestSize.Level1)
std::list<RefPtr<NG::SpanItem>> spans = dstSpan->GetSpanItems();
EXPECT_EQ(spans.size(), 1);
auto it = spans.begin();
EXPECT_EQ((*it)->fontStyle->GetFontSize().value(), Dimension(50));
EXPECT_EQ((*it)->fontStyle->GetFontSize().value(), Dimension(50, DimensionUnit::VP));
}
HWTEST_F(HtmlConvertTestNg, HtmlConvert008, TestSize.Level1)
{
auto spanString = AceType::MakeRefPtr<SpanString>("段落标题\n正文第一段开始");
SpanParagraphStyle spanParagraphStyle;
spanParagraphStyle.align = TextAlign::START;
// default max lines 4
spanParagraphStyle.maxLines = 4;
spanParagraphStyle.wordBreak = WordBreak::BREAK_ALL;
spanParagraphStyle.textOverflow = TextOverflow::ELLIPSIS;
// defalut textIndent 23
spanParagraphStyle.textIndent = Dimension(23.0_vp);
spanParagraphStyle.leadingMargin = LeadingMargin();
// default width 25.0 height 26.0
spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(25.0_vp), Dimension(26.0));
auto paragraphStyle = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 0, 5);
spanString->AddSpan(paragraphStyle);
SpanToHtml convert;
auto out = convert.ToHtml(*spanString);
std::string result =
"<div ><p style=\"text-indent: 23.00px;word-break: break_all;text-overflow: ellipsis;\"><span "
"style=\"font-size: 16.00fp;font-style: normal;font-weight: normal;color: #000000FF;font-family: HarmonyOS "
"Sans;\">段落标题</span></p><span style=\"font-size: 16.00fp;font-style: normal;font-weight: normal;color: "
"#000000FF;font-family: HarmonyOS Sans;\">正文第一段开始</span></div>";
EXPECT_EQ(out, result);
}
HWTEST_F(HtmlConvertTestNg, HtmlConvert009, TestSize.Level1)
{
auto spanString = AceType::MakeRefPtr<SpanString>("向上到顶适中向下到底");
spanString->AddSpan(AceType::MakeRefPtr<BaselineOffsetSpan>(Dimension(20.0_vp), 0, 4));
spanString->AddSpan(AceType::MakeRefPtr<BaselineOffsetSpan>(Dimension(10.0_vp), 4, 6));
SpanToHtml convert;
auto out = convert.ToHtml(*spanString);
std::string result =
"<div ><span style=\"font-size: 16.00fp;font-style: normal;font-weight: normal;color: #000000FF;font-family: "
"HarmonyOS Sans;vertical-align: 20.00px;\">向上到顶</span><span style=\"font-size: 16.00fp;font-style: "
"normal;font-weight: normal;color: #000000FF;font-family: HarmonyOS Sans;vertical-align: "
"10.00px;\">适中</span><span style=\"font-size: 16.00fp;font-style: normal;font-weight: normal;color: "
"#000000FF;font-family: HarmonyOS Sans;\">向下到底</span></div>";
EXPECT_EQ(out, result);
}
} // namespace OHOS::Ace::NG