1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.. All rights reserved. 3cb93a386Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cb93a386Sopenharmony_ci * you may not use this file except in compliance with the License. 5cb93a386Sopenharmony_ci * You may obtain a copy of the License at 6cb93a386Sopenharmony_ci * 7cb93a386Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cb93a386Sopenharmony_ci * 9cb93a386Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cb93a386Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cb93a386Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cb93a386Sopenharmony_ci * See the License for the specific language governing permissions and 13cb93a386Sopenharmony_ci * limitations under the License. 14cb93a386Sopenharmony_ci */ 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci#ifdef OHOS_SUPPORT 17cb93a386Sopenharmony_ci#include "ParagraphImpl.h" 18cb93a386Sopenharmony_ci#endif 19cb93a386Sopenharmony_ci#include "modules/skparagraph/src/RunBaseImpl.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_cinamespace skia { 22cb93a386Sopenharmony_cinamespace textlayout { 23cb93a386Sopenharmony_ciRunBaseImpl::RunBaseImpl( 24cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 25cb93a386Sopenharmony_ci sk_sp<SkTextBlob> blob, 26cb93a386Sopenharmony_ci#else 27cb93a386Sopenharmony_ci std::shared_ptr<RSTextBlob> blob, 28cb93a386Sopenharmony_ci#endif 29cb93a386Sopenharmony_ci SkPoint offset, 30cb93a386Sopenharmony_ci ParagraphPainter::SkPaintOrID paint, 31cb93a386Sopenharmony_ci bool clippingNeeded, 32cb93a386Sopenharmony_ci SkRect clipRect, 33cb93a386Sopenharmony_ci const Run* visitorRun, 34cb93a386Sopenharmony_ci size_t visitorPos, 35cb93a386Sopenharmony_ci#ifdef OHOS_SUPPORT 36cb93a386Sopenharmony_ci size_t visitorGlobalPos, 37cb93a386Sopenharmony_ci size_t trailSpaces, 38cb93a386Sopenharmony_ci#endif 39cb93a386Sopenharmony_ci size_t visitorSize) 40cb93a386Sopenharmony_ci : fBlob(blob), 41cb93a386Sopenharmony_ci fOffset(offset), 42cb93a386Sopenharmony_ci fClippingNeeded(clippingNeeded), 43cb93a386Sopenharmony_ci fClipRect(clipRect), 44cb93a386Sopenharmony_ci fVisitorRun(visitorRun), 45cb93a386Sopenharmony_ci fVisitorPos(visitorPos), 46cb93a386Sopenharmony_ci#ifdef OHOS_SUPPORT 47cb93a386Sopenharmony_ci fVisitorGlobalPos(visitorGlobalPos), 48cb93a386Sopenharmony_ci fTrailSpaces(trailSpaces), 49cb93a386Sopenharmony_ci#endif 50cb93a386Sopenharmony_ci fVisitorSize(visitorSize) 51cb93a386Sopenharmony_ci{ 52cb93a386Sopenharmony_ci if (std::holds_alternative<SkPaint>(paint)) { 53cb93a386Sopenharmony_ci fPaint = std::get<SkPaint>(paint); 54cb93a386Sopenharmony_ci } else if (std::holds_alternative<ParagraphPainter::PaintID>(paint)) { 55cb93a386Sopenharmony_ci fPaint = std::get<ParagraphPainter::PaintID>(paint); 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci} 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 61cb93a386Sopenharmony_ciconst SkFont& RunBaseImpl::font() const 62cb93a386Sopenharmony_ci#else 63cb93a386Sopenharmony_ciconst RSFont& RunBaseImpl::font() const 64cb93a386Sopenharmony_ci#endif 65cb93a386Sopenharmony_ci{ 66cb93a386Sopenharmony_ci if (!fVisitorRun) { 67cb93a386Sopenharmony_ci return {}; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci return fVisitorRun->font(); 70cb93a386Sopenharmony_ci} 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_cisize_t RunBaseImpl::size() const 73cb93a386Sopenharmony_ci{ 74cb93a386Sopenharmony_ci return fVisitorSize; 75cb93a386Sopenharmony_ci} 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_cistd::vector<uint16_t> RunBaseImpl::getGlyphs() const 78cb93a386Sopenharmony_ci{ 79cb93a386Sopenharmony_ci if (!fVisitorRun) { 80cb93a386Sopenharmony_ci return {}; 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci SkSpan<const SkGlyphID> glyphIDSpan = fVisitorRun->glyphs(); 83cb93a386Sopenharmony_ci SkSpan<const SkGlyphID> runGlyphIDSpan = glyphIDSpan.subspan(fVisitorPos, fVisitorSize); 84cb93a386Sopenharmony_ci return std::vector<uint16_t>(runGlyphIDSpan.begin(), runGlyphIDSpan.end()); 85cb93a386Sopenharmony_ci} 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_cistd::vector<RSPoint> RunBaseImpl::getPositions() const 88cb93a386Sopenharmony_ci{ 89cb93a386Sopenharmony_ci if (!fVisitorRun) { 90cb93a386Sopenharmony_ci return {}; 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci SkSpan<const SkPoint> positionSpan = fVisitorRun->positions(); 93cb93a386Sopenharmony_ci SkSpan<const SkPoint> runPositionSpan = positionSpan.subspan(fVisitorPos, fVisitorSize); 94cb93a386Sopenharmony_ci std::vector<RSPoint> positions; 95cb93a386Sopenharmony_ci for (size_t i = 0; i < runPositionSpan.size(); i++) { 96cb93a386Sopenharmony_ci RSPoint point(runPositionSpan[i].fX, runPositionSpan[i].fY); 97cb93a386Sopenharmony_ci positions.emplace_back(point); 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_ci return positions; 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci} 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_cistd::vector<RSPoint> RunBaseImpl::getOffsets() const 105cb93a386Sopenharmony_ci{ 106cb93a386Sopenharmony_ci if (!fVisitorRun) { 107cb93a386Sopenharmony_ci return {}; 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci SkSpan<const SkPoint> offsetSpan = fVisitorRun->offsets(); 110cb93a386Sopenharmony_ci SkSpan<const SkPoint> runOffsetSpan = offsetSpan.subspan(fVisitorPos, fVisitorSize); 111cb93a386Sopenharmony_ci std::vector<RSPoint> offsets; 112cb93a386Sopenharmony_ci for (size_t i = 0; i < runOffsetSpan.size(); i++) { 113cb93a386Sopenharmony_ci RSPoint point(runOffsetSpan[i].fX, runOffsetSpan[i].fY); 114cb93a386Sopenharmony_ci offsets.emplace_back(point); 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci return offsets; 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci} 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_civoid RunBaseImpl::paint(ParagraphPainter* painter, SkScalar x, SkScalar y) 122cb93a386Sopenharmony_ci{ 123cb93a386Sopenharmony_ci if (!painter) { 124cb93a386Sopenharmony_ci return; 125cb93a386Sopenharmony_ci } 126cb93a386Sopenharmony_ci if (fClippingNeeded) { 127cb93a386Sopenharmony_ci painter->save(); 128cb93a386Sopenharmony_ci painter->clipRect(fClipRect.makeOffset(x, y)); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci painter->drawTextBlob(fBlob, x + fOffset.x(), y + fOffset.y(), fPaint); 131cb93a386Sopenharmony_ci if (fClippingNeeded) { 132cb93a386Sopenharmony_ci painter->restore(); 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci} 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_cisize_t RunBaseImpl::getVisitorPos() const 137cb93a386Sopenharmony_ci{ 138cb93a386Sopenharmony_ci return fVisitorPos; 139cb93a386Sopenharmony_ci} 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_cisize_t RunBaseImpl::getVisitorSize() const 142cb93a386Sopenharmony_ci{ 143cb93a386Sopenharmony_ci return fVisitorSize; 144cb93a386Sopenharmony_ci} 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci#ifdef OHOS_SUPPORT 147cb93a386Sopenharmony_cistd::vector<uint16_t> RunBaseImpl::getGlyphs(int64_t start, int64_t length) const 148cb93a386Sopenharmony_ci{ 149cb93a386Sopenharmony_ci if (!fVisitorRun) { 150cb93a386Sopenharmony_ci return {}; 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci uint64_t actualLength = calculateActualLength(start, length); 153cb93a386Sopenharmony_ci if (actualLength == 0) { 154cb93a386Sopenharmony_ci return {}; 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci SkSpan<const SkGlyphID> glyphIdSpan = fVisitorRun->glyphs(); 157cb93a386Sopenharmony_ci SkSpan<const SkGlyphID> runGlyphIdSpan = glyphIdSpan.subspan(fVisitorPos + start, actualLength); 158cb93a386Sopenharmony_ci std::vector<uint16_t> glyphs; 159cb93a386Sopenharmony_ci for (size_t i = 0; i < runGlyphIdSpan.size(); i++) { 160cb93a386Sopenharmony_ci glyphs.emplace_back(runGlyphIdSpan[i]); 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci return glyphs; 164cb93a386Sopenharmony_ci} 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 167cb93a386Sopenharmony_cistd::vector<SkPoint> RunBaseImpl::getPositions(int64_t start, int64_t length) const 168cb93a386Sopenharmony_ci#else 169cb93a386Sopenharmony_cistd::vector<RSPoint> RunBaseImpl::getPositions(int64_t start, int64_t length) const 170cb93a386Sopenharmony_ci#endif 171cb93a386Sopenharmony_ci{ 172cb93a386Sopenharmony_ci if (!fVisitorRun) { 173cb93a386Sopenharmony_ci return {}; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci uint64_t actualLength = calculateActualLength(start, length); 176cb93a386Sopenharmony_ci if (actualLength == 0) { 177cb93a386Sopenharmony_ci return {}; 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci SkSpan<const SkPoint> positionSpan = fVisitorRun->positions(); 180cb93a386Sopenharmony_ci SkSpan<const SkPoint> runPositionSpan = positionSpan.subspan(fVisitorPos + start, actualLength); 181cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 182cb93a386Sopenharmony_ci std::vector<SkPoint> positions; 183cb93a386Sopenharmony_ci#else 184cb93a386Sopenharmony_ci std::vector<RSPoint> positions; 185cb93a386Sopenharmony_ci#endif 186cb93a386Sopenharmony_ci for (size_t i = 0; i < runPositionSpan.size(); i++) { 187cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 188cb93a386Sopenharmony_ci positions.emplace_back(SkPoint::Make(runPositionSpan[i].fX, runPositionSpan[i].fY)); 189cb93a386Sopenharmony_ci#else 190cb93a386Sopenharmony_ci positions.emplace_back(runPositionSpan[i].fX, runPositionSpan[i].fY); 191cb93a386Sopenharmony_ci#endif 192cb93a386Sopenharmony_ci } 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci return positions; 195cb93a386Sopenharmony_ci} 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_civoid RunBaseImpl::getStringRange(uint64_t* location, uint64_t* length) const 198cb93a386Sopenharmony_ci{ 199cb93a386Sopenharmony_ci if (location == nullptr || length == nullptr) { 200cb93a386Sopenharmony_ci return; 201cb93a386Sopenharmony_ci } else if (!fVisitorRun) { 202cb93a386Sopenharmony_ci *location = 0; 203cb93a386Sopenharmony_ci *length = 0; 204cb93a386Sopenharmony_ci return; 205cb93a386Sopenharmony_ci } 206cb93a386Sopenharmony_ci *location = fVisitorGlobalPos; 207cb93a386Sopenharmony_ci *length = fVisitorSize; 208cb93a386Sopenharmony_ci} 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_cistd::vector<uint64_t> RunBaseImpl::getStringIndices(int64_t start, int64_t length) const 211cb93a386Sopenharmony_ci{ 212cb93a386Sopenharmony_ci if (!fVisitorRun) { 213cb93a386Sopenharmony_ci return {}; 214cb93a386Sopenharmony_ci } 215cb93a386Sopenharmony_ci uint64_t actualLength = calculateActualLength(start, length); 216cb93a386Sopenharmony_ci if (actualLength == 0) { 217cb93a386Sopenharmony_ci return {}; 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci std::vector<uint64_t> indices; 220cb93a386Sopenharmony_ci for (size_t i = 0; i < actualLength; i++) { 221cb93a386Sopenharmony_ci indices.emplace_back(fVisitorGlobalPos + start + i); 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci return indices; 225cb93a386Sopenharmony_ci} 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ciSkRect RunBaseImpl::getAllGlyphRectInfo(SkSpan<const SkGlyphID>& runGlyphIdSpan, size_t startNotWhiteSpaceIndex, 228cb93a386Sopenharmony_ci SkScalar startWhiteSpaceWidth, size_t endWhiteSpaceNum, SkScalar endAdvance) const 229cb93a386Sopenharmony_ci{ 230cb93a386Sopenharmony_ci SkRect rect = {0.0, 0.0, 0.0, 0.0}; 231cb93a386Sopenharmony_ci SkScalar runNotWhiteSpaceWidth = 0.0; 232cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 233cb93a386Sopenharmony_ci SkRect joinRect{0.0, 0.0, 0.0, 0.0}; 234cb93a386Sopenharmony_ci SkRect endRect {0.0, 0.0, 0.0, 0.0}; 235cb93a386Sopenharmony_ci SkRect startRect {0.0, 0.0, 0.0, 0.0}; 236cb93a386Sopenharmony_ci#else 237cb93a386Sopenharmony_ci RSRect joinRect{0.0, 0.0, 0.0, 0.0}; 238cb93a386Sopenharmony_ci RSRect endRect {0.0, 0.0, 0.0, 0.0}; 239cb93a386Sopenharmony_ci RSRect startRect {0.0, 0.0, 0.0, 0.0}; 240cb93a386Sopenharmony_ci#endif 241cb93a386Sopenharmony_ci size_t end = runGlyphIdSpan.size() - endWhiteSpaceNum; 242cb93a386Sopenharmony_ci for (size_t i = startNotWhiteSpaceIndex; i < end; i++) { 243cb93a386Sopenharmony_ci // Get the bounds of each glyph 244cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 245cb93a386Sopenharmony_ci SkRect glyphBounds; 246cb93a386Sopenharmony_ci fVisitorRun->font().getBounds(&runGlyphIdSpan[i], 1, &glyphBounds, nullptr); 247cb93a386Sopenharmony_ci#else 248cb93a386Sopenharmony_ci RSRect glyphBounds; 249cb93a386Sopenharmony_ci fVisitorRun->font().GetWidths(&runGlyphIdSpan[i], 1, nullptr, &glyphBounds); 250cb93a386Sopenharmony_ci#endif 251cb93a386Sopenharmony_ci // Record the first non-blank glyph boundary 252cb93a386Sopenharmony_ci if (i == startNotWhiteSpaceIndex) { 253cb93a386Sopenharmony_ci startRect = glyphBounds; 254cb93a386Sopenharmony_ci } 255cb93a386Sopenharmony_ci if (i == end - 1) { 256cb93a386Sopenharmony_ci endRect = glyphBounds; 257cb93a386Sopenharmony_ci } 258cb93a386Sopenharmony_ci // Stitching removes glyph boundaries at the beginning and end of lines 259cb93a386Sopenharmony_ci joinRect.Join(glyphBounds); 260cb93a386Sopenharmony_ci auto& cluster = fVisitorRun->owner()->cluster(fVisitorGlobalPos + i); 261cb93a386Sopenharmony_ci // Calculates the width of the glyph with the beginning and end of the line removed 262cb93a386Sopenharmony_ci runNotWhiteSpaceWidth += cluster.width(); 263cb93a386Sopenharmony_ci } 264cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 265cb93a386Sopenharmony_ci // If the first glyph of run is a blank glyph, you need to add startWhitespaceWidth 266cb93a386Sopenharmony_ci SkScalar x = fClipRect.fLeft + startRect.x() + startWhiteSpaceWidth; 267cb93a386Sopenharmony_ci SkScalar y = joinRect.bottom(); 268cb93a386Sopenharmony_ci SkScalar width = runNotWhiteSpaceWidth - (endAdvance - endRect.x() - endRect.width()) - startRect.x(); 269cb93a386Sopenharmony_ci SkScalar height = joinRect.height(); 270cb93a386Sopenharmony_ci#else 271cb93a386Sopenharmony_ci SkScalar x = fClipRect.fLeft + startRect.GetLeft() + startWhiteSpaceWidth; 272cb93a386Sopenharmony_ci SkScalar y = joinRect.GetBottom(); 273cb93a386Sopenharmony_ci SkScalar width = runNotWhiteSpaceWidth - (endAdvance - endRect.GetLeft() - endRect.GetWidth()) - startRect.GetLeft(); 274cb93a386Sopenharmony_ci SkScalar height = joinRect.GetHeight(); 275cb93a386Sopenharmony_ci#endif 276cb93a386Sopenharmony_ci rect.setXYWH(x, y, width, height); 277cb93a386Sopenharmony_ci return rect; 278cb93a386Sopenharmony_ci} 279cb93a386Sopenharmony_ci 280cb93a386Sopenharmony_ci#ifndef USE_SKIA_TXT 281cb93a386Sopenharmony_ciSkRect RunBaseImpl::getImageBounds() const 282cb93a386Sopenharmony_ci#else 283cb93a386Sopenharmony_ciRSRect RunBaseImpl::getImageBounds() const 284cb93a386Sopenharmony_ci#endif 285cb93a386Sopenharmony_ci{ 286cb93a386Sopenharmony_ci if (!fVisitorRun) { 287cb93a386Sopenharmony_ci return {}; 288cb93a386Sopenharmony_ci } 289cb93a386Sopenharmony_ci SkSpan<const SkGlyphID> glyphIdSpan = fVisitorRun->glyphs(); 290cb93a386Sopenharmony_ci SkSpan<const SkGlyphID> runGlyphIdSpan = glyphIdSpan.subspan(fVisitorPos, fVisitorSize); 291cb93a386Sopenharmony_ci if (runGlyphIdSpan.size() == 0) { 292cb93a386Sopenharmony_ci return {}; 293cb93a386Sopenharmony_ci } 294cb93a386Sopenharmony_ci SkScalar endAdvance = 0.0; 295cb93a386Sopenharmony_ci SkScalar startWhiteSpaceWidth = 0.0; 296cb93a386Sopenharmony_ci size_t endWhiteSpaceNum = 0; 297cb93a386Sopenharmony_ci size_t startNotWhiteSpaceIndex = 0; 298cb93a386Sopenharmony_ci // Gets the width of the first non-blank glyph at the end 299cb93a386Sopenharmony_ci for (size_t i = runGlyphIdSpan.size() - 1; i >= 0; --i) { 300cb93a386Sopenharmony_ci auto& cluster = fVisitorRun->owner()->cluster(fVisitorGlobalPos + i); 301cb93a386Sopenharmony_ci if (!cluster.isWhitespaceBreak()) { 302cb93a386Sopenharmony_ci endAdvance = cluster.width(); 303cb93a386Sopenharmony_ci break; 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci ++endWhiteSpaceNum; 306cb93a386Sopenharmony_ci if (i == 0) { 307cb93a386Sopenharmony_ci break; 308cb93a386Sopenharmony_ci } 309cb93a386Sopenharmony_ci } 310cb93a386Sopenharmony_ci // Gets the width of the first non-blank glyph at the end 311cb93a386Sopenharmony_ci for (size_t i = 0; i < runGlyphIdSpan.size(); ++i) { 312cb93a386Sopenharmony_ci auto& cluster = fVisitorRun->owner()->cluster(fVisitorGlobalPos + i); 313cb93a386Sopenharmony_ci if (!cluster.isWhitespaceBreak()) { 314cb93a386Sopenharmony_ci break; 315cb93a386Sopenharmony_ci } 316cb93a386Sopenharmony_ci startWhiteSpaceWidth += cluster.width(); 317cb93a386Sopenharmony_ci ++startNotWhiteSpaceIndex; 318cb93a386Sopenharmony_ci } 319cb93a386Sopenharmony_ci SkRect rect = getAllGlyphRectInfo(runGlyphIdSpan, startNotWhiteSpaceIndex, startWhiteSpaceWidth, endWhiteSpaceNum, endAdvance); 320cb93a386Sopenharmony_ci return {rect.fLeft, rect.fTop, rect.fRight, rect.fBottom}; 321cb93a386Sopenharmony_ci} 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_cifloat RunBaseImpl::getTypographicBounds(float* ascent, float* descent, float* leading) const 324cb93a386Sopenharmony_ci{ 325cb93a386Sopenharmony_ci if (ascent == nullptr || descent == nullptr || leading == nullptr) { 326cb93a386Sopenharmony_ci return 0.0; 327cb93a386Sopenharmony_ci } 328cb93a386Sopenharmony_ci if (!fVisitorRun) { 329cb93a386Sopenharmony_ci *ascent = 0.0; 330cb93a386Sopenharmony_ci *descent = 0.0; 331cb93a386Sopenharmony_ci *leading = 0.0; 332cb93a386Sopenharmony_ci return 0.0; 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci *ascent = std::abs(fVisitorRun->ascent()); 335cb93a386Sopenharmony_ci *descent = fVisitorRun->descent(); 336cb93a386Sopenharmony_ci *leading = fVisitorRun->leading(); 337cb93a386Sopenharmony_ci return fClipRect.width() + calculateTrailSpacesWidth(); 338cb93a386Sopenharmony_ci} 339cb93a386Sopenharmony_ci 340cb93a386Sopenharmony_cifloat RunBaseImpl::calculateTrailSpacesWidth() const 341cb93a386Sopenharmony_ci{ 342cb93a386Sopenharmony_ci // Calculates the width of the whitespace character at the end of the line 343cb93a386Sopenharmony_ci if (!fVisitorRun || fTrailSpaces == 0) { 344cb93a386Sopenharmony_ci return 0.0; 345cb93a386Sopenharmony_ci } 346cb93a386Sopenharmony_ci SkScalar spaceWidth = 0; 347cb93a386Sopenharmony_ci for (size_t i = 0; i < fTrailSpaces; i++) { 348cb93a386Sopenharmony_ci auto& cluster = fVisitorRun->owner()->cluster(fVisitorGlobalPos + fVisitorSize + i); 349cb93a386Sopenharmony_ci // doesn't calculate the width of a hard line wrap at the end of a line 350cb93a386Sopenharmony_ci if (cluster.isHardBreak()) { 351cb93a386Sopenharmony_ci break; 352cb93a386Sopenharmony_ci } 353cb93a386Sopenharmony_ci spaceWidth += cluster.width(); 354cb93a386Sopenharmony_ci } 355cb93a386Sopenharmony_ci 356cb93a386Sopenharmony_ci return spaceWidth; 357cb93a386Sopenharmony_ci} 358cb93a386Sopenharmony_ci 359cb93a386Sopenharmony_ciuint64_t RunBaseImpl::calculateActualLength(int64_t start, int64_t length) const 360cb93a386Sopenharmony_ci{ 361cb93a386Sopenharmony_ci // Calculate the actual size of the run, 362cb93a386Sopenharmony_ci // start and length equal to 0 means that the data is obtained from start to end, so no filtering is required 363cb93a386Sopenharmony_ci if (start >= fVisitorSize || start < 0 || length < 0) { 364cb93a386Sopenharmony_ci return 0; 365cb93a386Sopenharmony_ci } 366cb93a386Sopenharmony_ci uint64_t actualLength = fVisitorSize - start; 367cb93a386Sopenharmony_ci actualLength = actualLength > length ? length: actualLength; 368cb93a386Sopenharmony_ci // If length is equal to 0, the end of the line is obtained 369cb93a386Sopenharmony_ci if (start >= 0 && length == 0) { 370cb93a386Sopenharmony_ci return fVisitorSize - start; 371cb93a386Sopenharmony_ci } 372cb93a386Sopenharmony_ci 373cb93a386Sopenharmony_ci return actualLength; 374cb93a386Sopenharmony_ci} 375cb93a386Sopenharmony_ci#endif 376cb93a386Sopenharmony_ci} // namespace textlayout 377cb93a386Sopenharmony_ci} // namespace skia