LCOV - code coverage report
Current view: top level - core/font - SPFontTextLayout.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 163 270 60.4 %
Date: 2024-05-12 00:16:13 Functions: 21 49 42.9 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "SPFontTextLayout.h"
      24             : 
      25             : namespace STAPPLER_VERSIONIZED stappler::font {
      26             : 
      27        8063 : inline static bool isSpaceOrLineBreak(char16_t c) {
      28        8063 :         return c == char16_t(0x0A) || chars::isspace(c);
      29             : }
      30             : 
      31             : template <typename Interface>
      32           0 : static geom::Rect getLabelLineStartRect(const TextLayoutData<Interface> &f, uint16_t lineId, float density, uint32_t c) {
      33           0 :         geom::Rect rect;
      34           0 :         const LineLayoutData &line = f.lines.at(lineId);
      35           0 :         if (line.count > 0) {
      36           0 :                 const CharLayoutData & firstChar = f.chars.at(std::max(line.start, c));
      37           0 :                 const CharLayoutData & lastChar = f.chars.at(line.start + line.count - 1);
      38           0 :                 rect.origin = geom::Vec2((firstChar.pos) / density, (line.pos) / density - line.height / density);
      39           0 :                 rect.size = geom::Size2((lastChar.pos + lastChar.advance - firstChar.pos) / density, line.height / density);
      40             :         }
      41             : 
      42           0 :         return rect;
      43             : }
      44             : 
      45             : template <typename Interface>
      46           0 : static geom::Rect getLabelLineEndRect(const TextLayoutData<Interface> &f, uint16_t lineId, float density, uint32_t c) {
      47           0 :         geom::Rect rect;
      48           0 :         const LineLayoutData &line = f.lines.at(lineId);
      49           0 :         if (line.count > 0) {
      50           0 :                 const CharLayoutData & firstChar = f.chars.at(line.start);
      51           0 :                 const CharLayoutData & lastChar = f.chars.at(std::min(line.start + line.count - 1, c));
      52           0 :                 rect.origin = geom::Vec2((firstChar.pos) / density, (line.pos) / density - line.height / density);
      53           0 :                 rect.size = geom::Size2((lastChar.pos + lastChar.advance - firstChar.pos) / density, line.height / density);
      54             :         }
      55           0 :         return rect;
      56             : }
      57             : 
      58             : template <typename Interface>
      59          25 : static geom::Rect getCharsRect(const TextLayoutData<Interface> &f, uint32_t lineId, uint32_t firstCharId, uint32_t lastCharId, float density) {
      60          25 :         geom::Rect rect;
      61          25 :         const LineLayoutData & line = f.lines.at(lineId);
      62          25 :         const CharLayoutData & firstChar = f.chars.at(firstCharId);
      63          25 :         const CharLayoutData & lastChar = f.chars.at(lastCharId);
      64          25 :         rect.origin = geom::Vec2((firstChar.pos) / density, (line.pos) / density - line.height / density);
      65          25 :         rect.size = geom::Size2((lastChar.pos + lastChar.advance - firstChar.pos) / density, line.height / density);
      66          25 :         return rect;
      67             : }
      68             : 
      69             : template <typename Interface>
      70         130 : static void TextLayoutData_str(const TextLayoutData<Interface> &f, const Callback<void(char16_t)> &cb, bool filter) {
      71        1153 :         for (auto it = f.begin(); it != f.end(); ++ it) {
      72        1023 :                 const RangeLayoutData &range = *it.range;
      73        1023 :                 if (!filter || range.align == VerticalAlign::Baseline) {
      74        1023 :                         size_t end = it.start() + it.count() - 1;
      75       12413 :                         for (size_t i = it.start(); i <= end; ++ i) {
      76       11390 :                                 const auto &spec = f.chars[i];
      77       11390 :                                 if (spec.charID != char16_t(0xAD) && spec.charID != char16_t(0xFFFF)) {
      78       11390 :                                         cb(spec.charID);
      79             :                                 }
      80             :                         }
      81             :                 }
      82             :         }
      83         130 : }
      84             : 
      85             : template <typename Interface>
      86         130 : static void TextLayoutData_str(const TextLayoutData<Interface> &f, const Callback<void(char16_t)> &cb,
      87             :                 uint32_t s_start, uint32_t s_end, size_t maxWords, bool ellipsis, bool filter) {
      88        1153 :         for (auto it = f.begin(); it != f.end(); ++ it) {
      89        1023 :                 const RangeLayoutData &range = *it.range;
      90        1023 :                 if (!filter || range.align == VerticalAlign::Baseline) {
      91           5 :                         size_t end = it.start() + it.count() - 1;
      92          60 :                         for (size_t i = it.start(); i <= end; ++ i) {
      93          55 :                                 const auto &spec = f.chars[i];
      94          55 :                                 if (spec.charID != char16_t(0xAD) && spec.charID != char16_t(0xFFFF)) {
      95          55 :                                         cb(spec.charID);
      96             :                                 }
      97             :                         }
      98             :                 }
      99             :         }
     100         130 : }
     101             : 
     102             : template <typename Interface>
     103         532 : static Pair<uint32_t, CharSelectMode> TextLayoutData_getChar(const TextLayoutData<Interface> &f, int32_t x, int32_t y, CharSelectMode mode) {
     104         532 :         int32_t yDistance = maxOf<int32_t>();
     105         532 :         const LineLayoutData *pLine = nullptr;
     106         532 :         if (!f.lines.empty()) {
     107        1088 :                 for (auto &l : f.lines) {
     108        1088 :                         int32_t dst = maxOf<int32_t>();
     109        1088 :                         switch (mode) {
     110         260 :                         case CharSelectMode::Center:
     111         260 :                                 dst = abs(y - (l.pos - l.height / 2));
     112         260 :                                 break;
     113         308 :                         case CharSelectMode::Best:
     114         308 :                                 dst = abs(y - (l.pos - l.height * 3 / 4));
     115         308 :                                 break;
     116         520 :                         case CharSelectMode::Prefix:
     117             :                         case CharSelectMode::Suffix:
     118         520 :                                 dst = abs(y - (l.pos - l.height));
     119         520 :                                 break;
     120             :                         };
     121        1088 :                         if (dst < yDistance) {
     122         556 :                                 pLine = &l;
     123         556 :                                 yDistance = dst;
     124             :                         } else {
     125         532 :                                 break;
     126             :                         }
     127             :                 }
     128             : 
     129         532 :                 if (f.chars.back().charID == char16_t(0x0A) && pLine == &f.lines.back() && (mode == CharSelectMode::Best || mode == CharSelectMode::Suffix)) {
     130           0 :                         int32_t dst = maxOf<int32_t>();
     131           0 :                         switch (mode) {
     132           0 :                         case CharSelectMode::Center:
     133           0 :                                 dst = abs(y - (f.height - pLine->height / 2));
     134           0 :                                 break;
     135           0 :                         case CharSelectMode::Best:
     136           0 :                                 dst = abs(y - (f.height - pLine->height * 3 / 4));
     137           0 :                                 break;
     138           0 :                         case CharSelectMode::Prefix:
     139             :                         case CharSelectMode::Suffix:
     140           0 :                                 dst = abs(y - (f.height - pLine->height));
     141           0 :                                 break;
     142             :                         };
     143           0 :                         if (dst < yDistance) {
     144           0 :                                 return pair(f.chars.size() - 1, CharSelectMode::Suffix);
     145             :                         }
     146             :                 }
     147             :         }
     148             : 
     149         532 :         if (!pLine) {
     150           0 :                 return pair(maxOf<uint32_t>(), mode);
     151             :         }
     152             : 
     153         532 :         if (yDistance > pLine->height * 3 / 2 && mode != CharSelectMode::Best) {
     154           0 :                 return pair(maxOf<uint32_t>(), mode);
     155             :         }
     156             : 
     157         532 :         CharSelectMode nextMode = mode;
     158         532 :         int32_t xDistance = maxOf<int32_t>();
     159         532 :         const CharLayoutData *pChar = nullptr;
     160         532 :         uint32_t charNumber = pLine->start;
     161        5144 :         for (uint32_t i = pLine->start; i < pLine->start + pLine->count; ++ i) {
     162        5087 :                 auto &c = f.chars[i];
     163        5087 :                 if (c.charID != char16_t(0xAD) && !isSpaceOrLineBreak(c.charID)) {
     164        4486 :                         int32_t dst = maxOf<int32_t>();
     165        4486 :                         CharSelectMode dstMode = mode;
     166        4486 :                         switch (mode) {
     167        1128 :                         case CharSelectMode::Center: dst = abs(x - (c.pos + c.advance / 2)); break;
     168        1128 :                         case CharSelectMode::Prefix: dst = abs(x - c.pos); break;
     169        1013 :                         case CharSelectMode::Suffix: dst = abs(x - (c.pos + c.advance)); break;
     170        1217 :                         case CharSelectMode::Best: {
     171        1217 :                                 int32_t prefixDst = abs(x - c.pos);
     172        1217 :                                 int32_t suffixDst = abs(x - (c.pos + c.advance));
     173        1217 :                                 if (prefixDst <= suffixDst) {
     174         128 :                                         dst = prefixDst; dstMode = CharSelectMode::Prefix;
     175             :                                 } else {
     176        1089 :                                         dst = suffixDst; dstMode = CharSelectMode::Suffix;
     177             :                                 }
     178        1217 :                         } break;
     179             :                         };
     180        4486 :                         if (dst < xDistance) {
     181        4011 :                                 pChar = &c;
     182        4011 :                                 xDistance = dst;
     183        4011 :                                 charNumber = i;
     184        4011 :                                 nextMode = dstMode;
     185             :                         } else {
     186         475 :                                 break;
     187             :                         }
     188             :                 }
     189             :         }
     190         532 :         if (pLine->count && f.chars[pLine->start + pLine->count - 1].charID == char16_t(0x0A)) {
     191         532 :                 auto &c = f.chars[pLine->start + pLine->count - 1];
     192         532 :                 int32_t dst = maxOf<int32_t>();
     193         532 :                 switch (mode) {
     194         130 :                 case CharSelectMode::Prefix: dst = abs(x - c.pos); break;
     195         142 :                 case CharSelectMode::Best: dst = abs(x - c.pos); break;
     196         260 :                 default: break;
     197             :                 };
     198         532 :                 if (dst < xDistance) {
     199          14 :                         pChar = &c;
     200          14 :                         xDistance = dst;
     201          14 :                         charNumber = pLine->start + pLine->count - 1;
     202          14 :                         nextMode = CharSelectMode::Prefix;
     203             :                 }
     204             :         }
     205             : 
     206         532 :         if ((mode == CharSelectMode::Best || mode == CharSelectMode::Suffix) && pLine == &(f.lines.back())) {
     207           0 :                 auto c = f.chars.back();
     208           0 :                 int32_t dst = abs(x - (c.pos + c.advance));
     209           0 :                 if (dst < xDistance) {
     210           0 :                         pChar = &c;
     211           0 :                         xDistance = dst;
     212           0 :                         charNumber = uint32_t(f.chars.size() - 1);
     213           0 :                         nextMode = CharSelectMode::Suffix;
     214             :                 }
     215             :         }
     216             : 
     217         532 :         if (!pChar) {
     218           0 :                 return pair(maxOf<uint32_t>(), mode);
     219             :         }
     220             : 
     221         532 :         return pair(charNumber, nextMode);
     222             : }
     223             : 
     224             : template <typename Interface>
     225         125 : const LineLayoutData *TextLayoutData_getLine(const TextLayoutData<Interface> &f, uint32_t idx) {
     226         125 :         const LineLayoutData *ret = nullptr;
     227         125 :         for (const LineLayoutData &it : f.lines) {
     228         125 :                 if (it.start <= idx && it.start + it.count > idx) {
     229         125 :                         ret = &it;
     230         125 :                         break;
     231             :                 }
     232             :         }
     233         125 :         return ret;
     234             : }
     235             : 
     236             : template <typename Interface>
     237         180 : uint32_t TextLayoutData_getLineNumber(const TextLayoutData<Interface> &f, uint32_t id) {
     238         180 :         uint16_t n = 0;
     239         440 :         for (auto &it : f.lines) {
     240         440 :                 if (id >= it.start && id < it.start + it.count) {
     241         180 :                         return n;
     242             :                 }
     243         260 :                 n++;
     244             :         }
     245           0 :         if (n >= f.lines.size()) {
     246           0 :                 n = f.lines.size() - 1;
     247             :         }
     248           0 :         return n;
     249             : }
     250             : 
     251             : template <typename Interface>
     252           0 : float TextLayoutData_getLinePosition(const TextLayoutData<Interface> &f, uint32_t firstCharId, uint32_t lastCharId, float density) {
     253           0 :         auto firstLine = TextLayoutData_getLine(f, firstCharId);
     254           0 :         auto lastLine = TextLayoutData_getLine(f, lastCharId);
     255             : 
     256           0 :         return ((firstLine->pos) / density + (lastLine->pos) / density) / 2.0f;
     257             : }
     258             : 
     259             : template <typename Interface>
     260         142 : Pair<uint32_t, uint32_t> TextLayoutData_selectWord(const TextLayoutData<Interface> &f, uint32_t origin) {
     261         142 :         Pair<uint32_t, uint32_t> ret(origin, origin);
     262        1863 :         while (ret.second + 1 < f.chars.size() && !isSpaceOrLineBreak(f.chars[ret.second + 1].charID)) {
     263        1721 :                 ++ ret.second;
     264             :         }
     265        1113 :         while (ret.first > 0 && !isSpaceOrLineBreak(f.chars[ret.first - 1].charID)) {
     266         971 :                 -- ret.first;
     267             :         }
     268         142 :         return Pair<uint32_t, uint32_t>(ret.first, ret.second + 1 - ret.first);
     269             : }
     270             : 
     271             : template <typename Interface>
     272         130 : geom::Rect TextLayoutData_getLineRect(const TextLayoutData<Interface> &f, uint32_t lineId, float density, const geom::Vec2 &origin) {
     273         130 :         if (lineId >= f.lines.size()) {
     274           0 :                 return geom::Rect::ZERO;
     275             :         }
     276         130 :         return TextLayoutData_getLineRect(f, f.lines[lineId], density, origin);
     277             : }
     278             : 
     279             : template <typename Interface>
     280        1153 : geom::Rect TextLayoutData_getLineRect(const TextLayoutData<Interface> &f, const LineLayoutData &line, float density, const geom::Vec2 &origin) {
     281        1153 :         geom::Rect rect;
     282        1153 :         if (line.count > 0) {
     283        1153 :                 const CharLayoutData & firstChar = f.chars.at(line.start);
     284        1153 :                 const CharLayoutData & lastChar = f.chars.at(line.start + line.count - 1);
     285        1153 :                 rect.origin = geom::Vec2((firstChar.pos) / density + origin.x, (line.pos) / density - line.height / density + origin.y);
     286        1153 :                 rect.size = geom::Size2((lastChar.pos + lastChar.advance - firstChar.pos) / density, line.height / density);
     287             :         }
     288        1153 :         return rect;
     289             : }
     290             : 
     291             : template <typename Interface>
     292          25 : void TextLayoutData_getLabelRects(const TextLayoutData<Interface> &f, const Callback<void(geom::Rect)> &cb,
     293             :                 uint32_t firstCharId, uint32_t lastCharId, float density, const geom::Vec2 &origin, const geom::Padding &p) {
     294          25 :         auto firstLine = TextLayoutData_getLineNumber(f, firstCharId);
     295          25 :         auto lastLine = TextLayoutData_getLineNumber(f, lastCharId);
     296             : 
     297          25 :         if (firstLine == lastLine) {
     298          25 :                 auto rect = getCharsRect(f, firstLine, firstCharId, lastCharId, density);
     299          25 :                 rect.origin.x += origin.x - p.left;
     300          25 :                 rect.origin.y += origin.y - p.top;
     301          25 :                 rect.size.width += p.left + p.right;
     302          25 :                 rect.size.height += p.bottom + p.top;
     303          25 :                 if (!rect.equals(geom::Rect::ZERO)) {
     304          25 :                         cb(rect);
     305             :                 }
     306             :         } else {
     307           0 :                 auto first = getLabelLineStartRect(f, firstLine, density, firstCharId);
     308           0 :                 if (!first.equals(geom::Rect::ZERO)) {
     309           0 :                         first.origin.x += origin.x;
     310           0 :                         first.origin.y += origin.y;
     311           0 :                         if (first.origin.x - p.left < 0.0f) {
     312           0 :                                 first.size.width += (first.origin.x);
     313           0 :                                 first.origin.x = 0.0f;
     314             :                         } else {
     315           0 :                                 first.origin.x -= p.left;
     316           0 :                                 first.size.width += p.left;
     317             :                         }
     318           0 :                         first.origin.y -= p.top;
     319           0 :                         first.size.height += p.bottom + p.top;
     320           0 :                         cb(first);
     321             :                 }
     322             : 
     323           0 :                 for (auto i = firstLine + 1; i < lastLine; i++) {
     324           0 :                         auto rect = f.getLineRect(i, density);
     325           0 :                         rect.origin.x += origin.x;
     326           0 :                         rect.origin.y += origin.y - p.top;
     327           0 :                         rect.size.height += p.bottom + p.top;
     328           0 :                         if (!rect.equals(geom::Rect::ZERO)) {
     329           0 :                                 cb(rect);
     330             :                         }
     331             :                 }
     332             : 
     333           0 :                 auto last = getLabelLineEndRect(f, lastLine, density, lastCharId);
     334           0 :                 if (!last.equals(geom::Rect::ZERO)) {
     335           0 :                         last.origin.x += origin.x;
     336           0 :                         last.origin.y += origin.y - p.top;
     337           0 :                         last.size.width += p.right;
     338           0 :                         last.size.height += p.bottom + p.top;
     339           0 :                         cb(last);
     340             :                 }
     341             :         }
     342          25 : }
     343             : 
     344             : template <>
     345         782 : void TextLayoutData<memory::StandartInterface>::reserve(size_t nchars, size_t nranges) {
     346         782 :         if (nchars) {
     347         522 :                 chars.reserve(nchars);
     348         522 :                 lines.reserve(nchars / 60);
     349             :         }
     350         782 :         if (nranges) {
     351           0 :                 ranges.reserve(nranges);
     352             :         }
     353         782 : }
     354             : 
     355             : template <>
     356           0 : void TextLayoutData<memory::PoolInterface>::reserve(size_t nchars, size_t nranges) {
     357           0 :         if (nchars) {
     358           0 :                 chars.reserve(nchars);
     359           0 :                 lines.reserve(nchars / 60);
     360             :         }
     361           0 :         if (nranges) {
     362           0 :                 ranges.reserve(nranges);
     363             :         }
     364           0 : }
     365             : 
     366             : template <>
     367         130 : void TextLayoutData<memory::StandartInterface>::str(const Callback<void(char16_t)> &cb, bool filter) const {
     368         130 :         TextLayoutData_str(*this, cb, filter);
     369         130 : }
     370             : 
     371             : template <>
     372           0 : void TextLayoutData<memory::PoolInterface>::str(const Callback<void(char16_t)> &cb, bool filter) const {
     373           0 :         TextLayoutData_str(*this, cb, filter);
     374           0 : }
     375             : 
     376             : template <>
     377         130 : void TextLayoutData<memory::StandartInterface>::str(const Callback<void(char16_t)> &cb,
     378             :                 uint32_t s_start, uint32_t s_end, size_t maxWords, bool ellipsis, bool filter) const {
     379         130 :         TextLayoutData_str(*this, cb, s_start, s_end, maxWords, ellipsis, filter);
     380         130 : }
     381             : 
     382             : template <>
     383           0 : void TextLayoutData<memory::PoolInterface>::str(const Callback<void(char16_t)> &cb,
     384             :                 uint32_t s_start, uint32_t s_end, size_t maxWords, bool ellipsis, bool filter) const {
     385           0 :         TextLayoutData_str(*this, cb, s_start, s_end, maxWords, ellipsis, filter);
     386           0 : }
     387             : 
     388             : template <>
     389         532 : Pair<uint32_t, CharSelectMode> TextLayoutData<memory::StandartInterface>::getChar(int32_t x, int32_t y, CharSelectMode mode) const {
     390         532 :         return TextLayoutData_getChar(*this, x, y, mode);
     391             : }
     392             : 
     393             : template <>
     394           0 : Pair<uint32_t, CharSelectMode> TextLayoutData<memory::PoolInterface>::getChar(int32_t x, int32_t y, CharSelectMode mode) const {
     395           0 :         return TextLayoutData_getChar(*this, x, y, mode);
     396             : }
     397             : 
     398             : template <>
     399         125 : const LineLayoutData *TextLayoutData<memory::StandartInterface>::getLine(uint32_t charIndex) const {
     400         125 :         return TextLayoutData_getLine(*this, charIndex);
     401             : }
     402             : 
     403             : template <>
     404           0 : const LineLayoutData *TextLayoutData<memory::PoolInterface>::getLine(uint32_t charIndex) const {
     405           0 :         return TextLayoutData_getLine(*this, charIndex);
     406             : }
     407             : 
     408             : template <>
     409         130 : uint32_t TextLayoutData<memory::StandartInterface>::getLineForChar(uint32_t charIndex) const {
     410         130 :         return TextLayoutData_getLineNumber(*this, charIndex);
     411             : }
     412             : 
     413             : template <>
     414           0 : uint32_t TextLayoutData<memory::PoolInterface>::getLineForChar(uint32_t charIndex) const {
     415           0 :         return TextLayoutData_getLineNumber(*this, charIndex);
     416             : }
     417             : 
     418             : template <>
     419           0 : float TextLayoutData<memory::StandartInterface>::getLinePosition(uint32_t firstCharId, uint32_t lastCharId, float density) const {
     420           0 :         return TextLayoutData_getLinePosition(*this, firstCharId, lastCharId, density);
     421             : }
     422             : 
     423             : template <>
     424           0 : float TextLayoutData<memory::PoolInterface>::getLinePosition(uint32_t firstCharId, uint32_t lastCharId, float density) const {
     425           0 :         return TextLayoutData_getLinePosition(*this, firstCharId, lastCharId, density);
     426             : }
     427             : 
     428             : template <>
     429         142 : Pair<uint32_t, uint32_t> TextLayoutData<memory::StandartInterface>::selectWord(uint32_t originChar) const {
     430         142 :         return TextLayoutData_selectWord(*this, originChar);
     431             : }
     432             : 
     433             : template <>
     434           0 : Pair<uint32_t, uint32_t> TextLayoutData<memory::PoolInterface>::selectWord(uint32_t originChar) const {
     435           0 :         return TextLayoutData_selectWord(*this, originChar);
     436             : }
     437             : 
     438             : template <>
     439         130 : geom::Rect TextLayoutData<memory::StandartInterface>::getLineRect(uint32_t lineId, float density, const geom::Vec2 &origin) const {
     440         130 :         return TextLayoutData_getLineRect(*this, lineId, density, origin);
     441             : }
     442             : 
     443             : template <>
     444           0 : geom::Rect TextLayoutData<memory::PoolInterface>::getLineRect(uint32_t lineId, float density, const geom::Vec2 &origin) const {
     445           0 :         return TextLayoutData_getLineRect(*this, lineId, density, origin);
     446             : }
     447             : 
     448             : template <>
     449        1023 : geom::Rect TextLayoutData<memory::StandartInterface>::getLineRect(const LineLayoutData &line, float density, const geom::Vec2 &origin) const {
     450        1023 :         return TextLayoutData_getLineRect(*this, line, density, origin);
     451             : }
     452             : 
     453             : template <>
     454           0 : geom::Rect TextLayoutData<memory::PoolInterface>::getLineRect(const LineLayoutData &line, float density, const geom::Vec2 &origin) const {
     455           0 :         return TextLayoutData_getLineRect(*this, line, density, origin);
     456             : }
     457             : 
     458             : template <>
     459          25 : void TextLayoutData<memory::StandartInterface>::getLabelRects(const Callback<void(geom::Rect)> &cb, uint32_t first, uint32_t last, float density,
     460             :                 const geom::Vec2 &origin, const geom::Padding &p) const {
     461          25 :         return TextLayoutData_getLabelRects(*this, cb, first, last, density, origin, p);
     462             : }
     463             : 
     464             : template <>
     465           0 : void TextLayoutData<memory::PoolInterface>::getLabelRects(const Callback<void(geom::Rect)> &cb, uint32_t first, uint32_t last, float density,
     466             :                 const geom::Vec2 &origin, const geom::Padding &p) const {
     467           0 :         return TextLayoutData_getLabelRects(*this, cb, first, last, density, origin, p);
     468             : }
     469             : 
     470             : }

Generated by: LCOV version 1.14