Description: Modification of Arc-shaped Text Layout Algorithm

IssueNo: https://gitee.com/openharmony/graphic_ui/issues/I71DPY
Feature or Bugfix: Feature
Binary Source:No
Signed-off-by: youbing54<youbing3@huawei.com>
This commit is contained in:
youbing
2023-05-08 19:30:51 +08:00
parent daa4bc90e4
commit 095d72f112
6 changed files with 116 additions and 16 deletions
+16
View File
@@ -162,6 +162,22 @@ float TypedText::GetAngleForArcLen(float len,
return (direct == TEXT_DIRECT_LTR) ? angle : -angle;
}
float TypedText::GetAngleForArcLen(uint16_t letterWidth, int16_t letterSpace, uint16_t radius)
{
if (radius == 0) {
return 0.0f;
}
const int TWOX_COEFFICIENT = 2;
const float FLOATING_POINT_TWO = 2.0f;
float sinA = (letterWidth + letterSpace) / (FLOATING_POINT_TWO * radius);
float a = asin(sinA);
if (a >= -EPSINON && a <= EPSINON) {
return 0.0f;
}
return static_cast<float>(TWOX_COEFFICIENT * a * SEMICIRCLE_IN_DEGREE / UI_PI);
}
void TypedText::GetArcLetterPos(const Point& arcCenter, uint16_t radius, float angle, float& posX, float& posY)
{
posX = arcCenter.x + (static_cast<float>(radius) * Sin(angle));
+2
View File
@@ -74,6 +74,8 @@ public:
UITextLanguageDirect direct,
TextOrientation orientation);
static float GetAngleForArcLen(uint16_t letterWidth, int16_t letterSpace, uint16_t radius);
static void GetArcLetterPos(const Point& arcCenter, uint16_t radius, float angle, float& posX, float& posY);
#else // _FONT_TOOL
+13 -4
View File
@@ -24,6 +24,7 @@
namespace OHOS {
UIArcLabel::UIArcLabel()
: arcLabelText_(nullptr),
compatibilityMode_(true),
needRefresh_(false),
textSize_({0, 0}),
radius_(0),
@@ -138,7 +139,8 @@ void UIArcLabel::DrawArcText(BufferInfo& gfxDstBuffer,
center.x = arcTextInfo_.arcCenter.x + GetRect().GetX();
center.y = arcTextInfo_.arcCenter.y + GetRect().GetY();
DrawLabel::DrawArcText(gfxDstBuffer, mask, arcLabelText_->GetText(), center, arcLabelText_->GetFontId(),
arcLabelText_->GetFontSize(), arcTextInfo, orientation, *style_, opaScale);
arcLabelText_->GetFontSize(), arcTextInfo,
orientation, *style_, opaScale, compatibilityMode_);
}
Rect UIArcLabel::GetArcTextRect(const char* text, uint16_t fontId, uint8_t fontSize, const Point& arcCenter,
@@ -173,8 +175,11 @@ void UIArcLabel::ReMeasure()
int16_t arcTextWidth = textRect.GetWidth();
int16_t arcTextHeight = textRect.GetHeight();
SetPosition(textRect.GetX(), textRect.GetY());
Resize(arcTextWidth, arcTextHeight);
if (compatibilityMode_) {
SetPosition(textRect.GetX(), textRect.GetY());
Resize(arcTextWidth, arcTextHeight);
}
arcTextInfo_.arcCenter.x = arcCenter_.x - GetX() + style_->borderWidth_ + style_->paddingLeft_;
arcTextInfo_.arcCenter.y = arcCenter_.y - GetY() + style_->borderWidth_ + style_->paddingTop_;
textSize_.x = arcTextWidth;
@@ -189,7 +194,11 @@ void UIArcLabel::MeasureArcTextInfo()
return;
}
uint16_t letterHeight = UIFont::GetInstance()->GetHeight(arcLabelText_->GetFontId(), arcLabelText_->GetFontSize());
arcTextInfo_.radius = ((orientation_ == TextOrientation::INSIDE) ? radius_ : (radius_ - letterHeight));
if (compatibilityMode_) {
arcTextInfo_.radius = ((orientation_ == TextOrientation::INSIDE) ? radius_ : (radius_ - letterHeight));
} else {
arcTextInfo_.radius = radius_;
}
if (arcTextInfo_.radius == 0) {
return;
}
+54 -10
View File
@@ -144,7 +144,8 @@ void DrawLabel::DrawArcText(BufferInfo& gfxDstBuffer,
const ArcTextInfo arcTextInfo,
TextOrientation orientation,
const Style& style,
OpacityType opaScale)
OpacityType opaScale,
bool compatibilityMode)
{
if ((text == nullptr) || (arcTextInfo.lineStart == arcTextInfo.lineEnd) || (arcTextInfo.radius == 0)) {
GRAPHIC_LOGE("DrawLabel::DrawArcText invalid parameter\n");
@@ -176,13 +177,41 @@ void DrawLabel::DrawArcText(BufferInfo& gfxDstBuffer,
break;
}
letterWidth = UIFont::GetInstance()->GetWidth(letter, fontId, fontSize, 0);
if ((tmp == arcTextInfo.lineStart) && xorFlag) {
if (!DrawLabel::CalculateAngle(letterWidth, letterHeight, style.letterSpace_,
arcTextInfo, xorFlag, tmp, orientation,
posX, posY, rotateAngle, angle,
arcCenter, compatibilityMode)) {
continue;
}
DrawLetterWithRotate(gfxDstBuffer, mask, fontId, fontSize, letter, Point { MATH_ROUND(posX), MATH_ROUND(posY) },
static_cast<int16_t>(rotateAngle), style.textColor_, opaScale, compatibilityMode);
}
}
bool DrawLabel::CalculateAngle(uint16_t letterWidth,
uint16_t letterHeight,
int16_t letterSpace,
const ArcTextInfo arcTextInfo,
bool xorFlag,
uint32_t index,
TextOrientation orientation,
float& posX,
float& posY,
float& rotateAngle,
float& angle,
const Point& arcCenter,
bool compatibilityMode)
{
const int DIVIDER_BY_TWO = 2;
if (compatibilityMode) {
if ((index == arcTextInfo.lineStart) && xorFlag) {
angle += TypedText::GetAngleForArcLen(static_cast<float>(letterWidth), letterHeight, arcTextInfo.radius,
arcTextInfo.direct, orientation);
}
uint16_t arcLen = letterWidth + style.letterSpace_;
uint16_t arcLen = letterWidth + letterSpace;
if (arcLen == 0) {
continue;
return false;
}
float incrementAngle = TypedText::GetAngleForArcLen(static_cast<float>(arcLen), letterHeight,
arcTextInfo.radius, arcTextInfo.direct, orientation);
@@ -190,14 +219,26 @@ void DrawLabel::DrawArcText(BufferInfo& gfxDstBuffer,
rotateAngle = (orientation == TextOrientation::INSIDE) ? angle : (angle - SEMICIRCLE_IN_DEGREE);
// 2: half
float fineTuningAngle = incrementAngle * (static_cast<float>(letterWidth) / (2 * arcLen));
float fineTuningAngle = incrementAngle * (static_cast<float>(letterWidth) / (DIVIDER_BY_TWO * arcLen));
rotateAngle += (xorFlag ? -fineTuningAngle : fineTuningAngle);
TypedText::GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
angle += incrementAngle;
} else {
if ((index == arcTextInfo.lineStart) && xorFlag) {
angle += TypedText::GetAngleForArcLen(letterWidth, letterSpace, arcTextInfo.radius);
}
float incrementAngle = TypedText::GetAngleForArcLen(letterWidth, letterSpace, arcTextInfo.radius);
if (incrementAngle >= -EPSINON && incrementAngle <= EPSINON) {
return false;
}
DrawLetterWithRotate(gfxDstBuffer, mask, fontId, fontSize, letter, Point { MATH_ROUND(posX), MATH_ROUND(posY) },
static_cast<int16_t>(rotateAngle), style.textColor_, opaScale);
float fineTuningAngle = incrementAngle / DIVIDER_BY_TWO;
rotateAngle = xorFlag ? (angle - SEMICIRCLE_IN_DEGREE - fineTuningAngle) : (angle + fineTuningAngle);
TypedText::GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
angle = xorFlag ? (angle - incrementAngle) : (angle + incrementAngle);
}
return true;
}
void DrawLabel::DrawLetterWithRotate(BufferInfo& gfxDstBuffer,
@@ -208,7 +249,8 @@ void DrawLabel::DrawLetterWithRotate(BufferInfo& gfxDstBuffer,
const Point& pos,
int16_t rotateAngle,
const ColorType& color,
OpacityType opaScale)
OpacityType opaScale,
bool compatibilityMode)
{
UIFont* fontEngine = UIFont::GetInstance();
FontHeader head;
@@ -226,11 +268,13 @@ void DrawLabel::DrawLetterWithRotate(BufferInfo& gfxDstBuffer,
}
uint8_t fontWeight = fontEngine->GetFontWeight(fontId);
ColorMode colorMode = fontEngine->GetColorType(fontId);
int16_t offset = compatibilityMode ? head.ascender : 0;
Rect rectLetter;
rectLetter.SetPosition(pos.x + node.left, pos.y + head.ascender - node.top);
rectLetter.SetPosition(pos.x + node.left, pos.y + offset - node.top);
rectLetter.Resize(node.cols, node.rows);
TransformMap transMap(rectLetter);
transMap.Rotate(rotateAngle, Vector2<float>(-node.left, node.top - head.ascender));
transMap.Rotate(rotateAngle, Vector2<float>(-node.left, node.top - offset));
TransformDataInfo letterTranDataInfo = {ImageHeader{colorMode, 0, 0, 0, node.cols, node.rows}, fontMap, fontWeight,
BlurLevel::LEVEL0, TransformAlgorithm::BILINEAR};
BaseGfxEngine::GetInstance()->DrawTransform(gfxDstBuffer, mask, Point { 0, 0 }, color, opaScale, transMap,
+17 -2
View File
@@ -30,7 +30,21 @@ public:
static void DrawArcText(BufferInfo& gfxDstBuffer, const Rect& mask, const char* text, const Point& arcCenter,
uint16_t fontId, uint8_t fontSize, const ArcTextInfo arcTextInfo,
TextOrientation orientation, const Style& style, uint8_t opaScale);
TextOrientation orientation, const Style& style, uint8_t opaScale, bool compatibilityMode);
static bool CalculateAngle(uint16_t letterWidth,
uint16_t letterHeight,
int16_t letterSpace,
const ArcTextInfo arcTextInfo,
bool xorFlag,
uint32_t index,
TextOrientation orientation,
float& posX,
float& posY,
float& rotateAngle,
float& angle,
const Point& arcCenter,
bool compatibilityMode);
static void DrawLetterWithRotate(BufferInfo& gfxDstBuffer,
const Rect& mask,
@@ -40,7 +54,8 @@ public:
const Point& pos,
int16_t rotateAngle,
const ColorType& color,
OpacityType opaScale);
OpacityType opaScale,
bool compatibilityMode);
static uint8_t GetLineMaxLetterSize(const char* text, uint16_t lineLength, uint16_t fontId, uint8_t fontSize,
uint16_t letterIndex, SizeSpan* sizeSpans);
+14
View File
@@ -327,6 +327,19 @@ public:
return orientation_;
}
/**
* @brief Is it compatible with older versions.
*
* @param compatibilityMode Indicates compatible with older versions.
*/
void SetCompatibilityMode(bool compatibilityMode)
{
if (compatibilityMode_ != compatibilityMode) {
compatibilityMode_ = compatibilityMode;
RefreshArcLabel();
}
}
/**
* @brief Draws an arc text.
*
@@ -338,6 +351,7 @@ public:
protected:
Text* arcLabelText_;
bool compatibilityMode_;
virtual void InitArcLabelText()
{