Cache ICU break iterators in SkUnicode_icu
Change-Id: I2d6abd1a12d629b590a6616d0d1c71d71d5f4812 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/344476 Commit-Queue: Jason Simmons <jsimmons@google.com> Reviewed-by: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
parent
627c0022ff
commit
504451c7cc
@ -5,7 +5,9 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "include/core/SkString.h"
|
||||
#include "include/private/SkMutex.h"
|
||||
#include "include/private/SkTFitsIn.h"
|
||||
#include "include/private/SkTHash.h"
|
||||
#include "include/private/SkTemplates.h"
|
||||
#include "modules/skshaper/src/SkUnicode.h"
|
||||
#include "src/utils/SkUTF.h"
|
||||
@ -32,6 +34,16 @@ static inline SkUnichar utf8_next(const char** ptr, const char* end) {
|
||||
return val < 0 ? 0xFFFD : val;
|
||||
}
|
||||
|
||||
static UBreakIteratorType convertType(SkUnicode::BreakType type) {
|
||||
switch (type) {
|
||||
case SkUnicode::BreakType::kLines: return UBRK_LINE;
|
||||
case SkUnicode::BreakType::kGraphemes: return UBRK_CHARACTER;
|
||||
case SkUnicode::BreakType::kWords: return UBRK_WORD;
|
||||
default:
|
||||
return UBRK_CHARACTER;
|
||||
}
|
||||
}
|
||||
|
||||
class SkBidiIterator_icu : public SkBidiIterator {
|
||||
SkUnicodeBidi fBidi;
|
||||
public:
|
||||
@ -155,26 +167,41 @@ class SkBreakIterator_icu : public SkBreakIterator {
|
||||
fLastResult = 0;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static UBreakIteratorType convertType(SkUnicode::BreakType type) {
|
||||
switch (type) {
|
||||
case SkUnicode::BreakType::kLines: return UBRK_LINE;
|
||||
case SkUnicode::BreakType::kGraphemes: return UBRK_CHARACTER;
|
||||
case SkUnicode::BreakType::kWords: return UBRK_WORD;
|
||||
default:
|
||||
return UBRK_CHARACTER;
|
||||
}
|
||||
class SkIcuBreakIteratorCache {
|
||||
SkTHashMap<SkUnicode::BreakType, ICUBreakIterator> fBreakCache;
|
||||
SkMutex fBreakCacheMutex;
|
||||
|
||||
public:
|
||||
static SkIcuBreakIteratorCache& get() {
|
||||
static SkIcuBreakIteratorCache instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
static std::unique_ptr<SkBreakIterator> makeUtf8BreakIterator
|
||||
(const char locale[], SkUnicode::BreakType type) {
|
||||
ICUBreakIterator makeBreakIterator(SkUnicode::BreakType type) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ICUBreakIterator iterator(ubrk_open(convertType(type), locale, nullptr, 0, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
SkDEBUGF("Break error: %s", u_errorName(status));
|
||||
return nullptr;
|
||||
ICUBreakIterator* cachedIterator;
|
||||
{
|
||||
SkAutoMutexExclusive lock(fBreakCacheMutex);
|
||||
cachedIterator = fBreakCache.find(type);
|
||||
if (!cachedIterator) {
|
||||
ICUBreakIterator newIterator(ubrk_open(convertType(type), uloc_getDefault(), nullptr, 0, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
SkDEBUGF("Break error: %s", u_errorName(status));
|
||||
} else {
|
||||
cachedIterator = fBreakCache.set(type, std::move(newIterator));
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<SkBreakIterator>(new SkBreakIterator_icu(std::move(iterator)));
|
||||
ICUBreakIterator iterator;
|
||||
if (cachedIterator) {
|
||||
iterator.reset(ubrk_safeClone(cachedIterator->get(), nullptr, nullptr, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
SkDEBUGF("Break error: %s", u_errorName(status));
|
||||
}
|
||||
}
|
||||
return iterator;
|
||||
}
|
||||
};
|
||||
|
||||
@ -198,18 +225,6 @@ class SkScriptIterator_icu : public SkScriptIterator {
|
||||
};
|
||||
|
||||
class SkUnicode_icu : public SkUnicode {
|
||||
|
||||
static UBreakIteratorType convertType(BreakType type) {
|
||||
switch (type) {
|
||||
case BreakType::kLines: return UBRK_LINE;
|
||||
case BreakType::kGraphemes: return UBRK_CHARACTER;
|
||||
case BreakType::kWords: return UBRK_WORD;
|
||||
default:
|
||||
SkDEBUGF("Convert error: wrong break type");
|
||||
return UBRK_CHARACTER;
|
||||
}
|
||||
}
|
||||
|
||||
static bool extractBidi(const char utf8[],
|
||||
int utf8Units,
|
||||
TextDirection dir,
|
||||
@ -271,9 +286,8 @@ class SkUnicode_icu : public SkUnicode {
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
UBreakIteratorType breakType = convertType(BreakType::kWords);
|
||||
ICUBreakIterator iterator(ubrk_open(breakType, uloc_getDefault(), nullptr, 0, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
ICUBreakIterator iterator = SkIcuBreakIteratorCache::get().makeBreakIterator(BreakType::kWords);
|
||||
if (!iterator) {
|
||||
SkDEBUGF("Break error: %s", u_errorName(status));
|
||||
return false;
|
||||
}
|
||||
@ -313,9 +327,9 @@ class SkUnicode_icu : public SkUnicode {
|
||||
}
|
||||
SkASSERT(text);
|
||||
|
||||
ICUBreakIterator iterator(ubrk_open(convertType(type), uloc_getDefault(), nullptr, 0, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
SkDEBUGF("Break error: %s", u_errorName(status));
|
||||
ICUBreakIterator iterator = SkIcuBreakIteratorCache::get().makeBreakIterator(type);
|
||||
if (!iterator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ubrk_setUText(iterator.get(), text.get(), &status);
|
||||
@ -408,7 +422,13 @@ public:
|
||||
}
|
||||
std::unique_ptr<SkBreakIterator> makeBreakIterator(const char locale[],
|
||||
BreakType breakType) override {
|
||||
return SkBreakIterator_icu::makeUtf8BreakIterator(locale, breakType);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ICUBreakIterator iterator(ubrk_open(convertType(breakType), locale, nullptr, 0, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
SkDEBUGF("Break error: %s", u_errorName(status));
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<SkBreakIterator>(new SkBreakIterator_icu(std::move(iterator)));
|
||||
}
|
||||
std::unique_ptr<SkScriptIterator> makeScriptIterator() override {
|
||||
return SkScriptIterator_icu::makeScriptIterator();
|
||||
|
Loading…
Reference in New Issue
Block a user