Perform population UTF16Mapping only once

Bug: skia: https://bugs.chromium.org/p/skia/issues/detail?id=13396
Change-Id: I043ecfa175f18cde666a034af8290fe98a701855
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/547776
Reviewed-by: Julia Lavrova <jlavrova@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
Pavel.Sergeev 2022-06-10 16:53:01 +02:00 committed by SkCQ
parent 26282a522c
commit a9aac9d677
3 changed files with 73 additions and 23 deletions

View File

@ -1091,34 +1091,33 @@ TextIndex ParagraphImpl::findNextGraphemeBoundary(TextIndex utf8) {
}
void ParagraphImpl::ensureUTF16Mapping() {
if (!fUTF16IndexForUTF8Index.empty()) {
return;
}
// Fill out code points 16
auto ptr = fText.c_str();
auto end = fText.c_str() + fText.size();
while (ptr < end) {
fillUTF16MappingOnce([&] {
// Fill out code points 16
auto ptr = fText.c_str();
auto end = fText.c_str() + fText.size();
while (ptr < end) {
size_t index = ptr - fText.c_str();
SkUnichar u = SkUTF::NextUTF8(&ptr, end);
size_t index = ptr - fText.c_str();
SkUnichar u = SkUTF::NextUTF8(&ptr, end);
// All utf8 units refer to the same codepoint
size_t next = ptr - fText.c_str();
for (auto i = index; i < next; ++i) {
fUTF16IndexForUTF8Index.emplace_back(fUTF8IndexForUTF16Index.size());
}
SkASSERT(fUTF16IndexForUTF8Index.size() == next);
// All utf8 units refer to the same codepoint
size_t next = ptr - fText.c_str();
for (auto i = index; i < next; ++i) {
fUTF16IndexForUTF8Index.emplace_back(fUTF8IndexForUTF16Index.size());
}
SkASSERT(fUTF16IndexForUTF8Index.size() == next);
// One or two codepoints refer to the same text index
uint16_t buffer[2];
size_t count = SkUTF::ToUTF16(u, buffer);
fUTF8IndexForUTF16Index.emplace_back(index);
if (count > 1) {
// One or two codepoints refer to the same text index
uint16_t buffer[2];
size_t count = SkUTF::ToUTF16(u, buffer);
fUTF8IndexForUTF16Index.emplace_back(index);
if (count > 1) {
fUTF8IndexForUTF16Index.emplace_back(index);
}
}
}
fUTF16IndexForUTF8Index.emplace_back(fUTF8IndexForUTF16Index.size());
fUTF8IndexForUTF16Index.emplace_back(fText.size());
fUTF16IndexForUTF8Index.emplace_back(fUTF8IndexForUTF16Index.size());
fUTF8IndexForUTF16Index.emplace_back(fText.size());
});
}
void ParagraphImpl::visit(const Visitor& visitor) {

View File

@ -13,6 +13,7 @@
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/SkBitmaskEnum.h"
#include "include/private/SkOnce.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTHash.h"
#include "include/private/SkTemplates.h"
@ -255,6 +256,7 @@ private:
// They are filled lazily whenever they need and cached
SkTArray<TextIndex, true> fUTF8IndexForUTF16Index;
SkTArray<size_t, true> fUTF16IndexForUTF8Index;
SkOnce fillUTF16MappingOnce;
size_t fUnresolvedGlyphs;
SkTArray<TextLine, false> fLines; // kFormatted (cached: width, max lines, ellipsis, text align)

View File

@ -42,6 +42,7 @@
#include <string>
#include <utility>
#include <vector>
#include <thread>
struct GrContextOptions;
@ -6924,3 +6925,51 @@ UNIX_ONLY_TEST(SkParagraph_NonMonotonicGlyphsRTL, reporter) {
REPORTER_ASSERT(reporter, impl->lineNumber() == 1); // But it's still one line
paragraph->paint(canvas.get(), 0, 0);
}
void performGetRectsForRangeConcurrently(skiatest::Reporter* reporter) {
sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
if (!fontCollection->fontsFound()) {
INFOF(reporter, "No fonts found\n");
return;
}
auto const text = std::u16string(42000, 'x');
ParagraphStyle paragraphStyle;
TextStyle textStyle;
textStyle.setFontFamilies({SkString("Roboto")});
textStyle.setFontSize(14);
textStyle.setColor(SK_ColorBLACK);
textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
SkFontStyle::kUpright_Slant));
ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
builder.pushStyle(textStyle);
builder.addText(text);
builder.pop();
auto paragraph = builder.Build();
paragraph->layout(std::numeric_limits<float>::max());
RectHeightStyle heightStyle = RectHeightStyle::kMax;
RectWidthStyle widthStyle = RectWidthStyle::kMax;
auto t1 = std::thread([&] {
auto result = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
REPORTER_ASSERT(reporter, !result.empty());
});
auto t2 = std::thread([&] {
auto result = paragraph->getRectsForRange(5, 10, heightStyle, widthStyle);
REPORTER_ASSERT(reporter, !result.empty());
});
t1.join();
t2.join();
}
UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeConcurrently, reporter) {
auto const threads_count = 100;
std::thread threads[threads_count];
for (auto& thread : threads) {
thread = std::thread(performGetRectsForRangeConcurrently, reporter);
}
for (auto& thread : threads) {
thread.join();
}
}