1a3e0fd82Sopenharmony_ci/* 2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2022 Huawei Device Co., Ltd. 3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License. 5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at 6a3e0fd82Sopenharmony_ci * 7a3e0fd82Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8a3e0fd82Sopenharmony_ci * 9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and 13a3e0fd82Sopenharmony_ci * limitations under the License. 14a3e0fd82Sopenharmony_ci */ 15a3e0fd82Sopenharmony_ci 16a3e0fd82Sopenharmony_ci#include "draw/draw_label.h" 17a3e0fd82Sopenharmony_ci#include "common/typed_text.h" 18a3e0fd82Sopenharmony_ci#include "draw/draw_utils.h" 19a3e0fd82Sopenharmony_ci#include "engines/gfx/gfx_engine_manager.h" 20a3e0fd82Sopenharmony_ci#include "font/ui_font.h" 21a3e0fd82Sopenharmony_ci#include "font/ui_font_header.h" 22a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h" 23a3e0fd82Sopenharmony_ci 24a3e0fd82Sopenharmony_cinamespace OHOS { 25a3e0fd82Sopenharmony_ciuint16_t DrawLabel::DrawTextOneLine(BufferInfo& gfxDstBuffer, const LabelLineInfo& labelLine, uint16_t& letterIndex) 26a3e0fd82Sopenharmony_ci{ 27a3e0fd82Sopenharmony_ci if (labelLine.text == nullptr) { 28a3e0fd82Sopenharmony_ci return 0; 29a3e0fd82Sopenharmony_ci } 30a3e0fd82Sopenharmony_ci UIFont* fontEngine = UIFont::GetInstance(); 31a3e0fd82Sopenharmony_ci if (labelLine.direct == TEXT_DIRECT_RTL) { 32a3e0fd82Sopenharmony_ci labelLine.pos.x -= labelLine.offset.x; 33a3e0fd82Sopenharmony_ci } else { 34a3e0fd82Sopenharmony_ci labelLine.pos.x += labelLine.offset.x; 35a3e0fd82Sopenharmony_ci } 36a3e0fd82Sopenharmony_ci 37a3e0fd82Sopenharmony_ci uint32_t i = 0; 38a3e0fd82Sopenharmony_ci uint16_t retOffsetY = 0; // ret value elipse offsetY 39a3e0fd82Sopenharmony_ci uint16_t offsetPosY = 0; 40a3e0fd82Sopenharmony_ci uint8_t maxLetterSize = GetLineMaxLetterSize(labelLine.text, labelLine.lineLength, labelLine.fontId, 41a3e0fd82Sopenharmony_ci labelLine.fontSize, letterIndex, labelLine.spannableString); 42a3e0fd82Sopenharmony_ci GlyphNode glyphNode; 43a3e0fd82Sopenharmony_ci while (i < labelLine.lineLength) { 44a3e0fd82Sopenharmony_ci uint32_t letter = TypedText::GetUTF8Next(labelLine.text, i, i); 45a3e0fd82Sopenharmony_ci uint16_t fontId = labelLine.fontId; 46a3e0fd82Sopenharmony_ci uint8_t fontSize = labelLine.fontSize; 47a3e0fd82Sopenharmony_ci#if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE 48a3e0fd82Sopenharmony_ci TextStyle textStyle = TEXT_STYLE_NORMAL; 49a3e0fd82Sopenharmony_ci if (labelLine.textStyles) { 50a3e0fd82Sopenharmony_ci textStyle = labelLine.textStyles[letterIndex]; 51a3e0fd82Sopenharmony_ci } 52a3e0fd82Sopenharmony_ci#endif 53a3e0fd82Sopenharmony_ci bool haveLineBackgroundColor = false; 54a3e0fd82Sopenharmony_ci ColorType lineBackgroundColor; 55a3e0fd82Sopenharmony_ci bool havebackgroundColor = false; 56a3e0fd82Sopenharmony_ci ColorType backgroundColor; 57a3e0fd82Sopenharmony_ci ColorType foregroundColor = labelLine.style.textColor_; 58a3e0fd82Sopenharmony_ci 59a3e0fd82Sopenharmony_ci if (labelLine.spannableString != nullptr && labelLine.spannableString->GetSpannable(letterIndex)) { 60a3e0fd82Sopenharmony_ci labelLine.spannableString->GetFontId(letterIndex, fontId); 61a3e0fd82Sopenharmony_ci labelLine.spannableString->GetFontSize(letterIndex, fontSize); 62a3e0fd82Sopenharmony_ci havebackgroundColor = labelLine.spannableString->GetBackgroundColor(letterIndex, backgroundColor); 63a3e0fd82Sopenharmony_ci labelLine.spannableString->GetForegroundColor(letterIndex, foregroundColor); 64a3e0fd82Sopenharmony_ci#if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE 65a3e0fd82Sopenharmony_ci labelLine.spannableString->GetTextStyle(letterIndex, textStyle); 66a3e0fd82Sopenharmony_ci#endif 67a3e0fd82Sopenharmony_ci haveLineBackgroundColor = 68a3e0fd82Sopenharmony_ci labelLine.spannableString->GetLineBackgroundColor(letterIndex, lineBackgroundColor); 69a3e0fd82Sopenharmony_ci } 70a3e0fd82Sopenharmony_ci LabelLetterInfo letterInfo{labelLine.pos, 71a3e0fd82Sopenharmony_ci labelLine.mask, 72a3e0fd82Sopenharmony_ci foregroundColor, 73a3e0fd82Sopenharmony_ci labelLine.opaScale, 74a3e0fd82Sopenharmony_ci 0, 75a3e0fd82Sopenharmony_ci 0, 76a3e0fd82Sopenharmony_ci letter, 77a3e0fd82Sopenharmony_ci labelLine.direct, 78a3e0fd82Sopenharmony_ci fontId, 79a3e0fd82Sopenharmony_ci 0, 80a3e0fd82Sopenharmony_ci fontSize, 81a3e0fd82Sopenharmony_ci#if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE 82a3e0fd82Sopenharmony_ci textStyle, 83a3e0fd82Sopenharmony_ci#endif 84a3e0fd82Sopenharmony_ci labelLine.baseLine, 85a3e0fd82Sopenharmony_ci labelLine.style.letterSpace_, 86a3e0fd82Sopenharmony_ci labelLine.style.lineSpace_, 87a3e0fd82Sopenharmony_ci havebackgroundColor, 88a3e0fd82Sopenharmony_ci backgroundColor, 89a3e0fd82Sopenharmony_ci haveLineBackgroundColor, 90a3e0fd82Sopenharmony_ci lineBackgroundColor 91a3e0fd82Sopenharmony_ci }; 92a3e0fd82Sopenharmony_ci#if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE 93a3e0fd82Sopenharmony_ci glyphNode.textStyle = letterInfo.textStyle; 94a3e0fd82Sopenharmony_ci#endif 95a3e0fd82Sopenharmony_ci glyphNode.advance = 0; 96a3e0fd82Sopenharmony_ci uint8_t* fontMap = fontEngine->GetBitmap(letterInfo.letter, glyphNode, letterInfo.fontId, letterInfo.fontSize, 97a3e0fd82Sopenharmony_ci letterInfo.shapingId); 98a3e0fd82Sopenharmony_ci if (fontMap != nullptr) { 99a3e0fd82Sopenharmony_ci uint8_t weight = fontEngine->GetFontWeight(glyphNode.fontId); 100a3e0fd82Sopenharmony_ci // 16: rgb565->16 rgba8888->32 font with rgba 101a3e0fd82Sopenharmony_ci if (weight >= 16) { 102a3e0fd82Sopenharmony_ci DrawUtils::GetInstance()->DrawColorLetter(gfxDstBuffer, letterInfo, fontMap, 103a3e0fd82Sopenharmony_ci glyphNode, labelLine.lineHeight); 104a3e0fd82Sopenharmony_ci } else { 105a3e0fd82Sopenharmony_ci letterInfo.offsetY = labelLine.ellipsisOssetY == 0 ? offsetPosY : labelLine.ellipsisOssetY; 106a3e0fd82Sopenharmony_ci retOffsetY = offsetPosY; 107a3e0fd82Sopenharmony_ci DrawUtils::GetInstance()->DrawNormalLetter(gfxDstBuffer, letterInfo, fontMap, glyphNode, maxLetterSize); 108a3e0fd82Sopenharmony_ci } 109a3e0fd82Sopenharmony_ci } 110a3e0fd82Sopenharmony_ci if (labelLine.direct == TEXT_DIRECT_RTL) { 111a3e0fd82Sopenharmony_ci labelLine.pos.x -= (glyphNode.advance + labelLine.style.letterSpace_); 112a3e0fd82Sopenharmony_ci } else { 113a3e0fd82Sopenharmony_ci labelLine.pos.x += (glyphNode.advance + labelLine.style.letterSpace_); 114a3e0fd82Sopenharmony_ci } 115a3e0fd82Sopenharmony_ci letterIndex++; 116a3e0fd82Sopenharmony_ci } 117a3e0fd82Sopenharmony_ci return retOffsetY; 118a3e0fd82Sopenharmony_ci} 119a3e0fd82Sopenharmony_ci 120a3e0fd82Sopenharmony_ciuint8_t DrawLabel::GetLineMaxLetterSize(const char* text, uint16_t lineLength, uint16_t fontId, uint8_t fontSize, 121a3e0fd82Sopenharmony_ci uint16_t letterIndex, SpannableString* spannableString) 122a3e0fd82Sopenharmony_ci{ 123a3e0fd82Sopenharmony_ci if (spannableString == nullptr) { 124a3e0fd82Sopenharmony_ci return fontSize; 125a3e0fd82Sopenharmony_ci } 126a3e0fd82Sopenharmony_ci uint32_t i = 0; 127a3e0fd82Sopenharmony_ci uint8_t maxLetterSize = fontSize; 128a3e0fd82Sopenharmony_ci while (i < lineLength) { 129a3e0fd82Sopenharmony_ci uint32_t unicode = TypedText::GetUTF8Next(text, i, i); 130a3e0fd82Sopenharmony_ci if (TypedText::IsColourWord(unicode, fontId, fontSize)) { 131a3e0fd82Sopenharmony_ci letterIndex++; 132a3e0fd82Sopenharmony_ci continue; 133a3e0fd82Sopenharmony_ci } 134a3e0fd82Sopenharmony_ci if (spannableString != nullptr && spannableString->GetSpannable(letterIndex)) { 135a3e0fd82Sopenharmony_ci uint8_t tempSize = fontSize; 136a3e0fd82Sopenharmony_ci spannableString->GetFontSize(letterIndex, tempSize); 137a3e0fd82Sopenharmony_ci if (tempSize > maxLetterSize) { 138a3e0fd82Sopenharmony_ci maxLetterSize = tempSize; 139a3e0fd82Sopenharmony_ci } 140a3e0fd82Sopenharmony_ci } 141a3e0fd82Sopenharmony_ci letterIndex++; 142a3e0fd82Sopenharmony_ci } 143a3e0fd82Sopenharmony_ci return maxLetterSize; 144a3e0fd82Sopenharmony_ci} 145a3e0fd82Sopenharmony_ci 146a3e0fd82Sopenharmony_civoid DrawLabel::DrawArcText(BufferInfo& gfxDstBuffer, 147a3e0fd82Sopenharmony_ci const Rect& mask, 148a3e0fd82Sopenharmony_ci const char* text, 149a3e0fd82Sopenharmony_ci const Point& arcCenter, 150a3e0fd82Sopenharmony_ci uint16_t fontId, 151a3e0fd82Sopenharmony_ci uint8_t fontSize, 152a3e0fd82Sopenharmony_ci const ArcTextInfo arcTextInfo, 153a3e0fd82Sopenharmony_ci const float changeAngle, 154a3e0fd82Sopenharmony_ci TextOrientation orientation, 155a3e0fd82Sopenharmony_ci const Style& style, 156a3e0fd82Sopenharmony_ci OpacityType opaScale, 157a3e0fd82Sopenharmony_ci bool compatibilityMode) 158a3e0fd82Sopenharmony_ci{ 159a3e0fd82Sopenharmony_ci if ((text == nullptr) || (arcTextInfo.lineStart == arcTextInfo.lineEnd) || (arcTextInfo.radius == 0)) { 160a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("DrawLabel::DrawArcText invalid parameter\n"); 161a3e0fd82Sopenharmony_ci return; 162a3e0fd82Sopenharmony_ci } 163a3e0fd82Sopenharmony_ci OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.textOpa_); 164a3e0fd82Sopenharmony_ci if (opa == OPA_TRANSPARENT) { 165a3e0fd82Sopenharmony_ci return; 166a3e0fd82Sopenharmony_ci } 167a3e0fd82Sopenharmony_ci uint16_t letterWidth; 168a3e0fd82Sopenharmony_ci UIFont* fontEngine = UIFont::GetInstance(); 169a3e0fd82Sopenharmony_ci 170a3e0fd82Sopenharmony_ci uint16_t letterHeight = fontEngine->GetHeight(fontId, fontSize); 171a3e0fd82Sopenharmony_ci uint32_t i = arcTextInfo.lineStart; 172a3e0fd82Sopenharmony_ci bool orientationFlag = (orientation == TextOrientation::INSIDE); 173a3e0fd82Sopenharmony_ci bool directFlag = (arcTextInfo.direct == TEXT_DIRECT_LTR); 174a3e0fd82Sopenharmony_ci bool xorFlag = !directFlag; 175a3e0fd82Sopenharmony_ci if (compatibilityMode) { 176a3e0fd82Sopenharmony_ci xorFlag = !((orientationFlag && directFlag) || (!orientationFlag && !directFlag)); 177a3e0fd82Sopenharmony_ci } 178a3e0fd82Sopenharmony_ci float angle = directFlag ? (arcTextInfo.startAngle + changeAngle) : (arcTextInfo.startAngle - changeAngle); 179a3e0fd82Sopenharmony_ci 180a3e0fd82Sopenharmony_ci float posX; 181a3e0fd82Sopenharmony_ci float posY; 182a3e0fd82Sopenharmony_ci float rotateAngle; 183a3e0fd82Sopenharmony_ci while (i < arcTextInfo.lineEnd) { 184a3e0fd82Sopenharmony_ci uint32_t tmp = i; 185a3e0fd82Sopenharmony_ci uint32_t letter = TypedText::GetUTF8Next(text, tmp, i); 186a3e0fd82Sopenharmony_ci if (letter == 0) { 187a3e0fd82Sopenharmony_ci continue; 188a3e0fd82Sopenharmony_ci } 189a3e0fd82Sopenharmony_ci if ((letter == '\r') || (letter == '\n')) { 190a3e0fd82Sopenharmony_ci break; 191a3e0fd82Sopenharmony_ci } 192a3e0fd82Sopenharmony_ci letterWidth = fontEngine->GetWidth(letter, fontId, fontSize, 0); 193a3e0fd82Sopenharmony_ci if (!DrawLabel::CalculateAngle(letterWidth, letterHeight, style.letterSpace_, 194a3e0fd82Sopenharmony_ci arcTextInfo, xorFlag, tmp, orientation, 195a3e0fd82Sopenharmony_ci posX, posY, rotateAngle, angle, 196a3e0fd82Sopenharmony_ci arcCenter, compatibilityMode)) { 197a3e0fd82Sopenharmony_ci continue; 198a3e0fd82Sopenharmony_ci } 199a3e0fd82Sopenharmony_ci 200a3e0fd82Sopenharmony_ci ArcLetterInfo letterInfo; 201a3e0fd82Sopenharmony_ci letterInfo.InitData(fontId, fontSize, letter, { MATH_ROUND(posX), MATH_ROUND(posY) }, 202a3e0fd82Sopenharmony_ci static_cast<int16_t>(rotateAngle), style.textColor_, opaScale, arcTextInfo.startAngle, 203a3e0fd82Sopenharmony_ci arcTextInfo.endAngle, angle, arcTextInfo.radius, compatibilityMode, 204a3e0fd82Sopenharmony_ci directFlag, orientationFlag, arcTextInfo.hasAnimator); 205a3e0fd82Sopenharmony_ci 206a3e0fd82Sopenharmony_ci DrawLetterWithRotate(gfxDstBuffer, mask, letterInfo, posX, posY); 207a3e0fd82Sopenharmony_ci } 208a3e0fd82Sopenharmony_ci} 209a3e0fd82Sopenharmony_ci 210a3e0fd82Sopenharmony_cibool DrawLabel::CalculateAngle(uint16_t letterWidth, 211a3e0fd82Sopenharmony_ci uint16_t letterHeight, 212a3e0fd82Sopenharmony_ci int16_t letterSpace, 213a3e0fd82Sopenharmony_ci const ArcTextInfo arcTextInfo, 214a3e0fd82Sopenharmony_ci bool xorFlag, 215a3e0fd82Sopenharmony_ci uint32_t index, 216a3e0fd82Sopenharmony_ci TextOrientation orientation, 217a3e0fd82Sopenharmony_ci float& posX, 218a3e0fd82Sopenharmony_ci float& posY, 219a3e0fd82Sopenharmony_ci float& rotateAngle, 220a3e0fd82Sopenharmony_ci float& angle, 221a3e0fd82Sopenharmony_ci const Point& arcCenter, 222a3e0fd82Sopenharmony_ci bool compatibilityMode) 223a3e0fd82Sopenharmony_ci{ 224a3e0fd82Sopenharmony_ci const int DIVIDER_BY_TWO = 2; 225a3e0fd82Sopenharmony_ci if (compatibilityMode) { 226a3e0fd82Sopenharmony_ci if ((index == arcTextInfo.lineStart) && xorFlag) { 227a3e0fd82Sopenharmony_ci angle += TypedText::GetAngleForArcLen(static_cast<float>(letterWidth), letterHeight, arcTextInfo.radius, 228a3e0fd82Sopenharmony_ci arcTextInfo.direct, orientation); 229a3e0fd82Sopenharmony_ci } 230a3e0fd82Sopenharmony_ci uint16_t arcLen = letterWidth + letterSpace; 231a3e0fd82Sopenharmony_ci if (arcLen == 0) { 232a3e0fd82Sopenharmony_ci return false; 233a3e0fd82Sopenharmony_ci } 234a3e0fd82Sopenharmony_ci float incrementAngle = TypedText::GetAngleForArcLen(static_cast<float>(arcLen), letterHeight, 235a3e0fd82Sopenharmony_ci arcTextInfo.radius, arcTextInfo.direct, orientation); 236a3e0fd82Sopenharmony_ci 237a3e0fd82Sopenharmony_ci rotateAngle = (orientation == TextOrientation::INSIDE) ? angle : (angle - SEMICIRCLE_IN_DEGREE); 238a3e0fd82Sopenharmony_ci 239a3e0fd82Sopenharmony_ci // 2: half 240a3e0fd82Sopenharmony_ci float fineTuningAngle = incrementAngle * (static_cast<float>(letterWidth) / (DIVIDER_BY_TWO * arcLen)); 241a3e0fd82Sopenharmony_ci rotateAngle += (xorFlag ? -fineTuningAngle : fineTuningAngle); 242a3e0fd82Sopenharmony_ci TypedText::GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY); 243a3e0fd82Sopenharmony_ci angle += incrementAngle; 244a3e0fd82Sopenharmony_ci } else { 245a3e0fd82Sopenharmony_ci float incrementAngle = TypedText::GetAngleForArcLen(letterWidth, letterSpace, arcTextInfo.radius); 246a3e0fd82Sopenharmony_ci if (incrementAngle >= -EPSINON && incrementAngle <= EPSINON) { 247a3e0fd82Sopenharmony_ci return false; 248a3e0fd82Sopenharmony_ci } 249a3e0fd82Sopenharmony_ci 250a3e0fd82Sopenharmony_ci float fineTuningAngle = incrementAngle / DIVIDER_BY_TWO; 251a3e0fd82Sopenharmony_ci rotateAngle = xorFlag ? (angle - SEMICIRCLE_IN_DEGREE - fineTuningAngle) : (angle + fineTuningAngle); 252a3e0fd82Sopenharmony_ci TypedText::GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY); 253a3e0fd82Sopenharmony_ci angle = xorFlag ? (angle - incrementAngle) : (angle + incrementAngle); 254a3e0fd82Sopenharmony_ci } 255a3e0fd82Sopenharmony_ci 256a3e0fd82Sopenharmony_ci return true; 257a3e0fd82Sopenharmony_ci} 258a3e0fd82Sopenharmony_ci 259a3e0fd82Sopenharmony_civoid DrawLabel::DrawLetterWithRotate(BufferInfo& gfxDstBuffer, 260a3e0fd82Sopenharmony_ci const Rect& mask, 261a3e0fd82Sopenharmony_ci const ArcLetterInfo& letterInfo, 262a3e0fd82Sopenharmony_ci float posX, 263a3e0fd82Sopenharmony_ci float posY) 264a3e0fd82Sopenharmony_ci{ 265a3e0fd82Sopenharmony_ci UIFont* fontEngine = UIFont::GetInstance(); 266a3e0fd82Sopenharmony_ci FontHeader head; 267a3e0fd82Sopenharmony_ci GlyphNode node; 268a3e0fd82Sopenharmony_ci#if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE 269a3e0fd82Sopenharmony_ci node.textStyle = TEXT_STYLE_NORMAL; 270a3e0fd82Sopenharmony_ci#endif 271a3e0fd82Sopenharmony_ci if (fontEngine->GetFontHeader(head, letterInfo.fontId, letterInfo.fontSize) != 0) { 272a3e0fd82Sopenharmony_ci return; 273a3e0fd82Sopenharmony_ci } 274a3e0fd82Sopenharmony_ci 275a3e0fd82Sopenharmony_ci const uint8_t* fontMap = fontEngine->GetBitmap(letterInfo.letter, node, 276a3e0fd82Sopenharmony_ci letterInfo.fontId, letterInfo.fontSize, 0); 277a3e0fd82Sopenharmony_ci if (fontMap == nullptr) { 278a3e0fd82Sopenharmony_ci return; 279a3e0fd82Sopenharmony_ci } 280a3e0fd82Sopenharmony_ci uint8_t fontWeight = fontEngine->GetFontWeight(letterInfo.fontId); 281a3e0fd82Sopenharmony_ci ColorMode colorMode = fontEngine->GetColorType(letterInfo.fontId); 282a3e0fd82Sopenharmony_ci 283a3e0fd82Sopenharmony_ci int16_t offset = letterInfo.compatibilityMode ? head.ascender : 0; 284a3e0fd82Sopenharmony_ci Rect rectLetter; 285a3e0fd82Sopenharmony_ci rectLetter.Resize(node.cols, node.rows); 286a3e0fd82Sopenharmony_ci TransformMap transMap(rectLetter); 287a3e0fd82Sopenharmony_ci // Avoiding errors caused by rounding calculations 288a3e0fd82Sopenharmony_ci transMap.Translate(Vector2<float>(posX + node.left, posY + offset - node.top)); 289a3e0fd82Sopenharmony_ci transMap.Rotate(letterInfo.rotateAngle, Vector2<float>(posX, posY)); 290a3e0fd82Sopenharmony_ci 291a3e0fd82Sopenharmony_ci TransformDataInfo letterTranDataInfo = {ImageHeader{colorMode, 0, 0, 0, node.cols, node.rows}, fontMap, fontWeight, 292a3e0fd82Sopenharmony_ci BlurLevel::LEVEL0, TransformAlgorithm::BILINEAR}; 293a3e0fd82Sopenharmony_ci 294a3e0fd82Sopenharmony_ci uint8_t* buffer = nullptr; 295a3e0fd82Sopenharmony_ci if (letterInfo.hasAnimator) { 296a3e0fd82Sopenharmony_ci bool inRange = DrawLabel::CalculatedTransformDataInfo(&buffer, letterTranDataInfo, letterInfo); 297a3e0fd82Sopenharmony_ci if (inRange == false) { 298a3e0fd82Sopenharmony_ci if (buffer != nullptr) { 299a3e0fd82Sopenharmony_ci UIFree(buffer); 300a3e0fd82Sopenharmony_ci buffer = nullptr; 301a3e0fd82Sopenharmony_ci } 302a3e0fd82Sopenharmony_ci return; 303a3e0fd82Sopenharmony_ci } 304a3e0fd82Sopenharmony_ci } 305a3e0fd82Sopenharmony_ci 306a3e0fd82Sopenharmony_ci BaseGfxEngine::GetInstance()->DrawTransform(gfxDstBuffer, mask, Point { 0, 0 }, letterInfo.color, 307a3e0fd82Sopenharmony_ci letterInfo.opaScale, transMap, letterTranDataInfo); 308a3e0fd82Sopenharmony_ci if (buffer != nullptr) { 309a3e0fd82Sopenharmony_ci UIFree(buffer); 310a3e0fd82Sopenharmony_ci buffer = nullptr; 311a3e0fd82Sopenharmony_ci } 312a3e0fd82Sopenharmony_ci} 313a3e0fd82Sopenharmony_ci 314a3e0fd82Sopenharmony_cibool DrawLabel::CalculatedClipAngle(const ArcLetterInfo& letterInfo, float& angle) 315a3e0fd82Sopenharmony_ci{ 316a3e0fd82Sopenharmony_ci if (letterInfo.directFlag) { 317a3e0fd82Sopenharmony_ci if ((letterInfo.compatibilityMode && letterInfo.orientationFlag) || !letterInfo.compatibilityMode) { 318a3e0fd82Sopenharmony_ci if (letterInfo.currentAngle > letterInfo.endAngle) { 319a3e0fd82Sopenharmony_ci angle = letterInfo.currentAngle - letterInfo.endAngle; 320a3e0fd82Sopenharmony_ci } else if (letterInfo.currentAngle > letterInfo.startAngle) { 321a3e0fd82Sopenharmony_ci angle = letterInfo.currentAngle - letterInfo.startAngle; 322a3e0fd82Sopenharmony_ci } else { 323a3e0fd82Sopenharmony_ci return false; 324a3e0fd82Sopenharmony_ci } 325a3e0fd82Sopenharmony_ci } else { 326a3e0fd82Sopenharmony_ci if (letterInfo.currentAngle > letterInfo.endAngle) { 327a3e0fd82Sopenharmony_ci angle = letterInfo.currentAngle - letterInfo.endAngle; 328a3e0fd82Sopenharmony_ci } else if (letterInfo.currentAngle > letterInfo.startAngle) { 329a3e0fd82Sopenharmony_ci angle = letterInfo.currentAngle - letterInfo.startAngle; 330a3e0fd82Sopenharmony_ci } else { 331a3e0fd82Sopenharmony_ci return false; 332a3e0fd82Sopenharmony_ci } 333a3e0fd82Sopenharmony_ci } 334a3e0fd82Sopenharmony_ci } else { 335a3e0fd82Sopenharmony_ci if (letterInfo.compatibilityMode && letterInfo.orientationFlag) { 336a3e0fd82Sopenharmony_ci if (letterInfo.currentAngle < letterInfo.endAngle) { 337a3e0fd82Sopenharmony_ci angle = letterInfo.endAngle - letterInfo.currentAngle; 338a3e0fd82Sopenharmony_ci } else if (letterInfo.currentAngle < letterInfo.startAngle) { 339a3e0fd82Sopenharmony_ci angle = letterInfo.startAngle - letterInfo.currentAngle; 340a3e0fd82Sopenharmony_ci } else { 341a3e0fd82Sopenharmony_ci return false; 342a3e0fd82Sopenharmony_ci } 343a3e0fd82Sopenharmony_ci } else if ((letterInfo.compatibilityMode && !letterInfo.orientationFlag) || !letterInfo.compatibilityMode) { 344a3e0fd82Sopenharmony_ci if (letterInfo.currentAngle < letterInfo.endAngle) { 345a3e0fd82Sopenharmony_ci angle = letterInfo.endAngle - letterInfo.currentAngle; 346a3e0fd82Sopenharmony_ci } else if (letterInfo.currentAngle < letterInfo.startAngle) { 347a3e0fd82Sopenharmony_ci angle = letterInfo.startAngle - letterInfo.currentAngle; 348a3e0fd82Sopenharmony_ci } else { 349a3e0fd82Sopenharmony_ci return false; 350a3e0fd82Sopenharmony_ci } 351a3e0fd82Sopenharmony_ci } 352a3e0fd82Sopenharmony_ci } 353a3e0fd82Sopenharmony_ci 354a3e0fd82Sopenharmony_ci return true; 355a3e0fd82Sopenharmony_ci} 356a3e0fd82Sopenharmony_ci 357a3e0fd82Sopenharmony_civoid DrawLabel::OnCalculatedClockwise(const ArcLetterInfo& letterInfo, const uint16_t sizePerPx, 358a3e0fd82Sopenharmony_ci const uint16_t cols, const int16_t offsetX, uint16_t& begin, 359a3e0fd82Sopenharmony_ci uint16_t& copyCols, TextInRange& range) 360a3e0fd82Sopenharmony_ci{ 361a3e0fd82Sopenharmony_ci if (!letterInfo.directFlag) { 362a3e0fd82Sopenharmony_ci return; 363a3e0fd82Sopenharmony_ci } 364a3e0fd82Sopenharmony_ci if ((letterInfo.compatibilityMode && letterInfo.orientationFlag) || !letterInfo.compatibilityMode) { 365a3e0fd82Sopenharmony_ci if (letterInfo.currentAngle > letterInfo.endAngle) { 366a3e0fd82Sopenharmony_ci if (offsetX >= cols) { 367a3e0fd82Sopenharmony_ci range = TextInRange::OUT_RANGE; 368a3e0fd82Sopenharmony_ci } 369a3e0fd82Sopenharmony_ci copyCols = cols - offsetX; 370a3e0fd82Sopenharmony_ci } else if (letterInfo.currentAngle > letterInfo.startAngle) { 371a3e0fd82Sopenharmony_ci if (offsetX >= cols) { 372a3e0fd82Sopenharmony_ci range = TextInRange::IN_RANGE; 373a3e0fd82Sopenharmony_ci } 374a3e0fd82Sopenharmony_ci copyCols = offsetX; 375a3e0fd82Sopenharmony_ci begin = (cols - offsetX) * sizePerPx; 376a3e0fd82Sopenharmony_ci } 377a3e0fd82Sopenharmony_ci } else { 378a3e0fd82Sopenharmony_ci if (letterInfo.currentAngle > letterInfo.endAngle) { 379a3e0fd82Sopenharmony_ci if (offsetX >= cols) { 380a3e0fd82Sopenharmony_ci range = TextInRange::OUT_RANGE; 381a3e0fd82Sopenharmony_ci } 382a3e0fd82Sopenharmony_ci copyCols = cols - offsetX; 383a3e0fd82Sopenharmony_ci begin = offsetX * sizePerPx; 384a3e0fd82Sopenharmony_ci } else if (letterInfo.currentAngle > letterInfo.startAngle) { 385a3e0fd82Sopenharmony_ci if (offsetX >= cols) { 386a3e0fd82Sopenharmony_ci range = TextInRange::IN_RANGE; 387a3e0fd82Sopenharmony_ci } 388a3e0fd82Sopenharmony_ci copyCols = offsetX; 389a3e0fd82Sopenharmony_ci } 390a3e0fd82Sopenharmony_ci } 391a3e0fd82Sopenharmony_ci} 392a3e0fd82Sopenharmony_ci 393a3e0fd82Sopenharmony_civoid DrawLabel::OnCalculatedAnticlockwise(const ArcLetterInfo& letterInfo, const uint16_t sizePerPx, 394a3e0fd82Sopenharmony_ci const uint16_t cols, const int16_t offsetX, uint16_t& begin, 395a3e0fd82Sopenharmony_ci uint16_t& copyCols, TextInRange& range) 396a3e0fd82Sopenharmony_ci{ 397a3e0fd82Sopenharmony_ci if (letterInfo.directFlag) { 398a3e0fd82Sopenharmony_ci return; 399a3e0fd82Sopenharmony_ci } 400a3e0fd82Sopenharmony_ci if (letterInfo.compatibilityMode && letterInfo.orientationFlag) { 401a3e0fd82Sopenharmony_ci if (letterInfo.currentAngle < letterInfo.endAngle) { 402a3e0fd82Sopenharmony_ci if (offsetX >= cols) { 403a3e0fd82Sopenharmony_ci range = TextInRange::OUT_RANGE; 404a3e0fd82Sopenharmony_ci } 405a3e0fd82Sopenharmony_ci copyCols = cols - offsetX; 406a3e0fd82Sopenharmony_ci begin = offsetX * sizePerPx; 407a3e0fd82Sopenharmony_ci } else if (letterInfo.currentAngle < letterInfo.startAngle) { 408a3e0fd82Sopenharmony_ci if (offsetX >= cols) { 409a3e0fd82Sopenharmony_ci range = TextInRange::IN_RANGE; 410a3e0fd82Sopenharmony_ci } 411a3e0fd82Sopenharmony_ci copyCols = offsetX; 412a3e0fd82Sopenharmony_ci } 413a3e0fd82Sopenharmony_ci } else if ((letterInfo.compatibilityMode && !letterInfo.orientationFlag) || !letterInfo.compatibilityMode) { 414a3e0fd82Sopenharmony_ci if (letterInfo.currentAngle < letterInfo.endAngle) { 415a3e0fd82Sopenharmony_ci if (offsetX >= cols) { 416a3e0fd82Sopenharmony_ci range = TextInRange::OUT_RANGE; 417a3e0fd82Sopenharmony_ci } 418a3e0fd82Sopenharmony_ci copyCols = cols - offsetX; 419a3e0fd82Sopenharmony_ci } else if (letterInfo.currentAngle < letterInfo.startAngle) { 420a3e0fd82Sopenharmony_ci if (offsetX >= cols) { 421a3e0fd82Sopenharmony_ci range = TextInRange::IN_RANGE; 422a3e0fd82Sopenharmony_ci } 423a3e0fd82Sopenharmony_ci copyCols = offsetX; 424a3e0fd82Sopenharmony_ci begin = (cols - offsetX) * sizePerPx; 425a3e0fd82Sopenharmony_ci } 426a3e0fd82Sopenharmony_ci } 427a3e0fd82Sopenharmony_ci} 428a3e0fd82Sopenharmony_ci 429a3e0fd82Sopenharmony_civoid DrawLabel::CalculatedBeginAndCopySize(const ArcLetterInfo& letterInfo, const uint16_t sizePerPx, 430a3e0fd82Sopenharmony_ci const uint16_t cols, const int16_t offsetX, uint16_t& begin, 431a3e0fd82Sopenharmony_ci uint16_t& copyCols, TextInRange& range) 432a3e0fd82Sopenharmony_ci{ 433a3e0fd82Sopenharmony_ci if (letterInfo.directFlag) { 434a3e0fd82Sopenharmony_ci OnCalculatedClockwise(letterInfo, sizePerPx, cols, offsetX, begin, copyCols, range); 435a3e0fd82Sopenharmony_ci } else { 436a3e0fd82Sopenharmony_ci OnCalculatedAnticlockwise(letterInfo, sizePerPx, cols, offsetX, begin, copyCols, range); 437a3e0fd82Sopenharmony_ci } 438a3e0fd82Sopenharmony_ci} 439a3e0fd82Sopenharmony_ci 440a3e0fd82Sopenharmony_cibool DrawLabel::CalculatedTransformDataInfo(uint8_t** buffer, TransformDataInfo& letterTranDataInfo, 441a3e0fd82Sopenharmony_ci const ArcLetterInfo& letterInfo) 442a3e0fd82Sopenharmony_ci{ 443a3e0fd82Sopenharmony_ci float angle = 0.0f; 444a3e0fd82Sopenharmony_ci if (DrawLabel::CalculatedClipAngle(letterInfo, angle) == false) { 445a3e0fd82Sopenharmony_ci return false; 446a3e0fd82Sopenharmony_ci } 447a3e0fd82Sopenharmony_ci if (angle >= -EPSINON && angle <= EPSINON) { 448a3e0fd82Sopenharmony_ci return true; 449a3e0fd82Sopenharmony_ci } 450a3e0fd82Sopenharmony_ci 451a3e0fd82Sopenharmony_ci int16_t offsetX = static_cast<uint16_t>(angle * letterInfo.radius * UI_PI / SEMICIRCLE_IN_DEGREE); 452a3e0fd82Sopenharmony_ci uint16_t copyCols = 0; 453a3e0fd82Sopenharmony_ci uint16_t begin = 0; 454a3e0fd82Sopenharmony_ci uint16_t sizePerPx = letterTranDataInfo.pxSize / 8; // 8 bit 455a3e0fd82Sopenharmony_ci TextInRange range = TextInRange::NEED_CLIP; 456a3e0fd82Sopenharmony_ci uint16_t cols = letterTranDataInfo.header.width; 457a3e0fd82Sopenharmony_ci uint16_t rows = letterTranDataInfo.header.height; 458a3e0fd82Sopenharmony_ci DrawLabel::CalculatedBeginAndCopySize(letterInfo, sizePerPx, cols, offsetX, begin, copyCols, range); 459a3e0fd82Sopenharmony_ci if (range == TextInRange::IN_RANGE) { 460a3e0fd82Sopenharmony_ci return true; 461a3e0fd82Sopenharmony_ci } else if (range == TextInRange::OUT_RANGE) { 462a3e0fd82Sopenharmony_ci return false; 463a3e0fd82Sopenharmony_ci } 464a3e0fd82Sopenharmony_ci 465a3e0fd82Sopenharmony_ci const uint8_t* fontMap = letterTranDataInfo.data; 466a3e0fd82Sopenharmony_ci 467a3e0fd82Sopenharmony_ci uint32_t size = cols * rows * sizePerPx; 468a3e0fd82Sopenharmony_ci *buffer = static_cast<uint8_t*>(UIMalloc(size)); 469a3e0fd82Sopenharmony_ci if (*buffer == nullptr) { 470a3e0fd82Sopenharmony_ci return false; 471a3e0fd82Sopenharmony_ci } 472a3e0fd82Sopenharmony_ci 473a3e0fd82Sopenharmony_ci if (memset_s(*buffer, size, 0, size) != EOK) { 474a3e0fd82Sopenharmony_ci UIFree(*buffer); 475a3e0fd82Sopenharmony_ci return false; 476a3e0fd82Sopenharmony_ci } 477a3e0fd82Sopenharmony_ci 478a3e0fd82Sopenharmony_ci for (uint16_t i = 0; i < rows; i++) { 479a3e0fd82Sopenharmony_ci uint16_t beginSize = i * cols * sizePerPx + begin; 480a3e0fd82Sopenharmony_ci uint16_t copySize = copyCols * sizePerPx; 481a3e0fd82Sopenharmony_ci if (memcpy_s(*buffer + beginSize, copySize, fontMap + beginSize, copySize) != EOK) { 482a3e0fd82Sopenharmony_ci UIFree(*buffer); 483a3e0fd82Sopenharmony_ci return false; 484a3e0fd82Sopenharmony_ci } 485a3e0fd82Sopenharmony_ci } 486a3e0fd82Sopenharmony_ci letterTranDataInfo.data = *buffer; 487a3e0fd82Sopenharmony_ci return true; 488a3e0fd82Sopenharmony_ci} 489a3e0fd82Sopenharmony_ci 490a3e0fd82Sopenharmony_civoid DrawLabel::GetLineBackgroundColor(uint16_t letterIndex, List<LineBackgroundColor>* linebackgroundColor, 491a3e0fd82Sopenharmony_ci bool& havelinebackground, ColorType& linebgColor) 492a3e0fd82Sopenharmony_ci{ 493a3e0fd82Sopenharmony_ci if (linebackgroundColor->Size() > 0) { 494a3e0fd82Sopenharmony_ci ListNode<LineBackgroundColor>* lbColor = linebackgroundColor->Begin(); 495a3e0fd82Sopenharmony_ci for (; lbColor != linebackgroundColor->End(); lbColor = lbColor->next_) { 496a3e0fd82Sopenharmony_ci uint32_t start = lbColor->data_.start; 497a3e0fd82Sopenharmony_ci uint32_t end = lbColor->data_.end; 498a3e0fd82Sopenharmony_ci if (letterIndex >= start && letterIndex <= end) { 499a3e0fd82Sopenharmony_ci havelinebackground = true; 500a3e0fd82Sopenharmony_ci linebgColor = lbColor->data_.linebackgroundColor ; 501a3e0fd82Sopenharmony_ci } 502a3e0fd82Sopenharmony_ci } 503a3e0fd82Sopenharmony_ci } 504a3e0fd82Sopenharmony_ci}; 505a3e0fd82Sopenharmony_ci 506a3e0fd82Sopenharmony_civoid DrawLabel::GetBackgroundColor(uint16_t letterIndex, List<BackgroundColor>* backgroundColor, 507a3e0fd82Sopenharmony_ci bool& havebackground, ColorType& bgColor) 508a3e0fd82Sopenharmony_ci{ 509a3e0fd82Sopenharmony_ci if (backgroundColor->Size() > 0) { 510a3e0fd82Sopenharmony_ci ListNode<BackgroundColor>* bColor = backgroundColor->Begin(); 511a3e0fd82Sopenharmony_ci for (; bColor != backgroundColor->End(); bColor = bColor->next_) { 512a3e0fd82Sopenharmony_ci uint16_t start = bColor->data_.start; 513a3e0fd82Sopenharmony_ci uint16_t end = bColor->data_.end; 514a3e0fd82Sopenharmony_ci if (letterIndex >= start && letterIndex <= end) { 515a3e0fd82Sopenharmony_ci havebackground = true; 516a3e0fd82Sopenharmony_ci bgColor = bColor->data_.backgroundColor ; 517a3e0fd82Sopenharmony_ci } 518a3e0fd82Sopenharmony_ci } 519a3e0fd82Sopenharmony_ci } 520a3e0fd82Sopenharmony_ci}; 521a3e0fd82Sopenharmony_ci 522a3e0fd82Sopenharmony_civoid DrawLabel::GetForegroundColor(uint16_t letterIndex, List<ForegroundColor>* foregroundColor, ColorType& fgColor) 523a3e0fd82Sopenharmony_ci{ 524a3e0fd82Sopenharmony_ci if (foregroundColor->Size() > 0) { 525a3e0fd82Sopenharmony_ci ListNode<ForegroundColor>* fColor = foregroundColor->Begin(); 526a3e0fd82Sopenharmony_ci for (; fColor != foregroundColor->End(); fColor = fColor->next_) { 527a3e0fd82Sopenharmony_ci uint32_t start = fColor->data_.start; 528a3e0fd82Sopenharmony_ci uint32_t end = fColor->data_.end; 529a3e0fd82Sopenharmony_ci if (letterIndex >= start && letterIndex <= end) { 530a3e0fd82Sopenharmony_ci fgColor = fColor->data_.fontColor; 531a3e0fd82Sopenharmony_ci } 532a3e0fd82Sopenharmony_ci } 533a3e0fd82Sopenharmony_ci } 534a3e0fd82Sopenharmony_ci}; 535a3e0fd82Sopenharmony_ci 536a3e0fd82Sopenharmony_civoid DrawLabel::DrawLineBackgroundColor(BufferInfo& gfxDstBuffer, uint16_t letterIndex, const LabelLineInfo& labelLine) 537a3e0fd82Sopenharmony_ci{ 538a3e0fd82Sopenharmony_ci uint32_t i = 0; 539a3e0fd82Sopenharmony_ci while (i < labelLine.lineLength) { 540a3e0fd82Sopenharmony_ci TypedText::GetUTF8Next(labelLine.text, i, i); 541a3e0fd82Sopenharmony_ci bool havelinebackground = false; 542a3e0fd82Sopenharmony_ci ColorType linebackgroundColor; 543a3e0fd82Sopenharmony_ci if (labelLine.spannableString != nullptr && 544a3e0fd82Sopenharmony_ci labelLine.spannableString->GetSpannable(letterIndex)) { 545a3e0fd82Sopenharmony_ci havelinebackground = 546a3e0fd82Sopenharmony_ci labelLine.spannableString->GetLineBackgroundColor( 547a3e0fd82Sopenharmony_ci letterIndex, linebackgroundColor); 548a3e0fd82Sopenharmony_ci } 549a3e0fd82Sopenharmony_ci if (havelinebackground) { 550a3e0fd82Sopenharmony_ci Style style; 551a3e0fd82Sopenharmony_ci style.bgColor_ = linebackgroundColor; 552a3e0fd82Sopenharmony_ci Rect linebackground(labelLine.mask.GetLeft(), labelLine.pos.y, 553a3e0fd82Sopenharmony_ci labelLine.mask.GetRight(), 554a3e0fd82Sopenharmony_ci labelLine.pos.y + labelLine.lineHeight); 555a3e0fd82Sopenharmony_ci BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, labelLine.mask, 556a3e0fd82Sopenharmony_ci linebackground, style, 557a3e0fd82Sopenharmony_ci linebackgroundColor.alpha); 558a3e0fd82Sopenharmony_ci } 559a3e0fd82Sopenharmony_ci letterIndex++; 560a3e0fd82Sopenharmony_ci } 561a3e0fd82Sopenharmony_ci}; 562a3e0fd82Sopenharmony_ci} // namespace OHOS 563