mirror of
https://github.com/openharmony/graphic_ui.git
synced 2026-06-30 23:17:56 -04:00
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:
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user