Adding locale
Change-Id: I4f118f37a1226f4259d0e5be3b6b557b38b3b316 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/222785 Commit-Queue: Julia Lavrova <jlavrova@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
65eb084e78
commit
35f88226bb
@ -29,7 +29,7 @@ public:
|
||||
|
||||
sk_sp<SkTypeface> matchTypeface(const char familyName[], SkFontStyle fontStyle);
|
||||
sk_sp<SkTypeface> matchDefaultTypeface(SkFontStyle fontStyle);
|
||||
sk_sp<SkTypeface> defaultFallback(SkUnichar unicode, SkFontStyle fontStyle);
|
||||
sk_sp<SkTypeface> defaultFallback(SkUnichar unicode, SkFontStyle fontStyle, SkString locale);
|
||||
|
||||
void disableFontFallback();
|
||||
bool fontFallbackEnabled() { return fEnableFontFallback; }
|
||||
|
@ -18,12 +18,9 @@ skparagraph_public = [
|
||||
|
||||
skparagraph_sources = [
|
||||
"$_src/FontCollection.cpp",
|
||||
"$_src/FontIterator.h",
|
||||
"$_src/FontIterator.cpp",
|
||||
"$_src/FontResolver.h",
|
||||
"$_src/FontResolver.cpp",
|
||||
"$_src/TextLine.h",
|
||||
"$_src/TextLine.cpp",
|
||||
"$_src/Iterator.h",
|
||||
"$_src/ParagraphBuilderImpl.h",
|
||||
"$_src/ParagraphBuilderImpl.cpp",
|
||||
"$_src/ParagraphImpl.h",
|
||||
@ -31,6 +28,8 @@ skparagraph_sources = [
|
||||
"$_src/ParagraphStyle.cpp",
|
||||
"$_src/Run.h",
|
||||
"$_src/Run.cpp",
|
||||
"$_src/TextLine.h",
|
||||
"$_src/TextLine.cpp",
|
||||
"$_src/TextShadow.cpp",
|
||||
"$_src/TextStyle.cpp",
|
||||
"$_src/TextWrapper.h",
|
||||
|
@ -117,10 +117,13 @@ sk_sp<SkTypeface> FontCollection::matchDefaultTypeface(SkFontStyle fontStyle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> FontCollection::defaultFallback(SkUnichar unicode, SkFontStyle fontStyle) {
|
||||
sk_sp<SkTypeface> FontCollection::defaultFallback(SkUnichar unicode, SkFontStyle fontStyle, SkString locale) {
|
||||
|
||||
for (const auto& manager : this->getFontManagerOrder()) {
|
||||
std::vector<const char*> bcp47;
|
||||
if (!locale.isEmpty()) {
|
||||
bcp47.push_back(locale.c_str());
|
||||
}
|
||||
sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
|
||||
0, fontStyle, bcp47.data(), bcp47.size(), unicode));
|
||||
if (typeface != nullptr) {
|
||||
|
@ -1,68 +0,0 @@
|
||||
// Copyright 2019 Google LLC.
|
||||
#include "modules/skparagraph/src/FontIterator.h"
|
||||
#include <unicode/brkiter.h>
|
||||
#include <unicode/ubidi.h>
|
||||
#include "include/core/SkBlurTypes.h"
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkFontMgr.h"
|
||||
#include "include/core/SkPictureRecorder.h"
|
||||
#include "modules/skparagraph/src/ParagraphImpl.h"
|
||||
#include "src/core/SkSpan.h"
|
||||
#include "src/utils/SkUTF.h"
|
||||
|
||||
// TODO: FontCollection and FontIterator have common functionality
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
|
||||
FontIterator::FontIterator(SkSpan<const char> utf8,
|
||||
SkSpan<TextBlock> styles,
|
||||
sk_sp<FontCollection> fonts)
|
||||
: fText(utf8)
|
||||
, fStyles(styles)
|
||||
, fCurrentChar(utf8.begin())
|
||||
, fFontResolver(std::move(fonts)) {
|
||||
findAllFontsForAllStyledBlocks();
|
||||
}
|
||||
|
||||
void FontIterator::consume() {
|
||||
SkASSERT(fCurrentChar < fText.end());
|
||||
auto found = fFontResolver.findFirst(fCurrentChar, &fFont, &fLineHeight);
|
||||
SkASSERT(found);
|
||||
|
||||
// Move until we find the first character that cannot be resolved with the current font
|
||||
while (++fCurrentChar != fText.end()) {
|
||||
SkFont font;
|
||||
SkScalar height;
|
||||
found = fFontResolver.findNext(fCurrentChar, &font, &height);
|
||||
if (found) {
|
||||
if (fFont == font && fLineHeight == height) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FontIterator::findAllFontsForAllStyledBlocks() {
|
||||
TextBlock combined;
|
||||
for (auto& block : fStyles) {
|
||||
SkASSERT(combined.text().begin() == nullptr ||
|
||||
combined.text().end() == block.text().begin());
|
||||
|
||||
if (combined.text().begin() != nullptr &&
|
||||
block.style().matchOneAttribute(StyleType::kFont, combined.style())) {
|
||||
combined.add(block.text());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!combined.text().empty()) {
|
||||
fFontResolver.findAllFontsForStyledBlock(combined.style(), combined.text());
|
||||
}
|
||||
|
||||
combined = block;
|
||||
}
|
||||
fFontResolver.findAllFontsForStyledBlock(combined.style(), combined.text());
|
||||
}
|
||||
|
||||
} // namespace textlayout
|
||||
} // namespace skia
|
@ -1,52 +0,0 @@
|
||||
// Copyright 2019 Google LLC.
|
||||
#ifndef FontIterator_DEFINED
|
||||
#define FontIterator_DEFINED
|
||||
|
||||
#include <unicode/brkiter.h>
|
||||
#include <unicode/ubidi.h>
|
||||
#include "include/core/SkBlurTypes.h"
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkFontMgr.h"
|
||||
#include "include/core/SkPictureRecorder.h"
|
||||
#include "modules/skparagraph/src/FontResolver.h"
|
||||
#include "modules/skparagraph/src/ParagraphImpl.h"
|
||||
#include "src/core/SkSpan.h"
|
||||
#include "src/utils/SkUTF.h"
|
||||
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
|
||||
class FontIterator final : public SkShaper::FontRunIterator {
|
||||
public:
|
||||
FontIterator(SkSpan<const char> utf8,
|
||||
SkSpan<TextBlock> styles,
|
||||
sk_sp<FontCollection> fonts);
|
||||
|
||||
void consume() override;
|
||||
|
||||
size_t endOfCurrentRun() const override { return fCurrentChar - fText.begin(); }
|
||||
bool atEnd() const override { return fCurrentChar == fText.end(); }
|
||||
const SkFont& currentFont() const override { return fFont; }
|
||||
SkScalar lineHeight() const { return fLineHeight; }
|
||||
|
||||
private:
|
||||
struct Hash {
|
||||
uint32_t operator()(const std::pair<SkFont, SkScalar>& key) const {
|
||||
return SkTypeface::UniqueID(key.first.getTypeface()) +
|
||||
SkScalarCeilToInt(key.first.getSize()) + SkScalarCeilToInt(key.second);
|
||||
}
|
||||
};
|
||||
|
||||
void findAllFontsForAllStyledBlocks();
|
||||
|
||||
SkSpan<const char> fText;
|
||||
SkSpan<TextBlock> fStyles;
|
||||
const char* fCurrentChar;
|
||||
SkFont fFont;
|
||||
SkScalar fLineHeight;
|
||||
FontResolver fFontResolver;
|
||||
};
|
||||
} // namespace textlayout
|
||||
} // namespace skia
|
||||
|
||||
#endif // FontIterator_DEFINED
|
@ -22,9 +22,6 @@ SkUnichar utf8_next(const char** ptr, const char* end) {
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
|
||||
FontResolver::FontResolver(sk_sp<FontCollection> fontCollection)
|
||||
: fFontCollection(fontCollection) {}
|
||||
|
||||
bool FontResolver::findFirst(const char* codepoint, SkFont* font, SkScalar* height) {
|
||||
auto found = fFontMapping.find(codepoint);
|
||||
if (found == nullptr) {
|
||||
@ -34,8 +31,8 @@ bool FontResolver::findFirst(const char* codepoint, SkFont* font, SkScalar* heig
|
||||
if (found == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*font = found->first;
|
||||
*height = found->second;
|
||||
*font = found->fFont;
|
||||
*height = found->fHeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -44,8 +41,8 @@ bool FontResolver::findNext(const char* codepoint, SkFont* font, SkScalar* heigh
|
||||
if (found == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*font = found->first;
|
||||
*height = found->second;
|
||||
*font = found->fFont;
|
||||
*height = found->fHeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -93,7 +90,7 @@ void FontResolver::findAllFontsForStyledBlock(const TextStyle& style, SkSpan<con
|
||||
if (fUnresolved > 0 && fFontCollection->fontFallbackEnabled()) {
|
||||
while (fUnresolved > 0) {
|
||||
auto unicode = firstUnresolved();
|
||||
auto typeface = fFontCollection->defaultFallback(unicode, style.getFontStyle());
|
||||
auto typeface = fFontCollection->defaultFallback(unicode, style.getFontStyle(), style.getLocale());
|
||||
if (typeface == nullptr) {
|
||||
break;
|
||||
}
|
||||
@ -110,11 +107,12 @@ void FontResolver::findAllFontsForStyledBlock(const TextStyle& style, SkSpan<con
|
||||
|
||||
// In case something still unresolved
|
||||
if (fResolvedFonts.count() == 0) {
|
||||
makeFont(fFontCollection->defaultFallback(firstUnresolved(), style.getFontStyle()),
|
||||
style.getFontSize(), style.getHeight());
|
||||
if (fFirstResolvedFont.first.getTypeface() != nullptr) {
|
||||
makeFont(fFontCollection->defaultFallback(firstUnresolved(), style.getFontStyle(), style.getLocale()),
|
||||
style.getFontSize(),
|
||||
style.getHeight());
|
||||
if (fFirstResolvedFont.fFont.getTypeface() != nullptr) {
|
||||
SkString name;
|
||||
fFirstResolvedFont.first.getTypeface()->getFamilyName(&name);
|
||||
fFirstResolvedFont.fFont.getTypeface()->getFamilyName(&name);
|
||||
SkDebugf("Urgent font resolution: %s\n", name.c_str());
|
||||
} else {
|
||||
SkDebugf("No font!!!\n");
|
||||
@ -122,11 +120,11 @@ void FontResolver::findAllFontsForStyledBlock(const TextStyle& style, SkSpan<con
|
||||
}
|
||||
}
|
||||
|
||||
size_t FontResolver::resolveAllCharactersByFont(std::pair<SkFont, SkScalar> font) {
|
||||
size_t FontResolver::resolveAllCharactersByFont(const FontDescr& font) {
|
||||
// Consolidate all unresolved unicodes in one array to make a batch call
|
||||
SkTArray<SkGlyphID> glyphs(fUnresolved);
|
||||
glyphs.push_back_n(fUnresolved, SkGlyphID(0));
|
||||
font.first.getTypeface()->unicharsToGlyphs(
|
||||
font.fFont.getTypeface()->unicharsToGlyphs(
|
||||
fUnresolved == fCodepoints.size() ? fCodepoints.data() : fUnresolvedCodepoints.data(),
|
||||
fUnresolved, glyphs.data());
|
||||
|
||||
@ -209,24 +207,23 @@ void FontResolver::addResolvedWhitespacesToMapping() {
|
||||
fUnresolved -= resolvedWhitespaces;
|
||||
}
|
||||
|
||||
std::pair<SkFont, SkScalar> FontResolver::makeFont(sk_sp<SkTypeface> typeface,
|
||||
SkScalar size,
|
||||
SkScalar height) {
|
||||
FontResolver::FontDescr FontResolver::makeFont(sk_sp<SkTypeface> typeface,
|
||||
SkScalar size,
|
||||
SkScalar height) {
|
||||
SkFont font(typeface, size);
|
||||
font.setEdging(SkFont::Edging::kAntiAlias);
|
||||
font.setHinting(SkFontHinting::kSlight);
|
||||
font.setSubpixel(true);
|
||||
auto pair = std::make_pair(font, height);
|
||||
FontDescr descr(font, height);
|
||||
|
||||
auto foundFont = fResolvedFonts.find(pair);
|
||||
const FontDescr* foundFont = fResolvedFonts.find(descr);
|
||||
if (foundFont == nullptr) {
|
||||
if (fResolvedFonts.count() == 0) {
|
||||
fFirstResolvedFont = pair;
|
||||
fFirstResolvedFont = descr;
|
||||
}
|
||||
fResolvedFonts.add(pair);
|
||||
fResolvedFonts.add(descr);
|
||||
}
|
||||
|
||||
return pair;
|
||||
return descr;
|
||||
}
|
||||
|
||||
SkUnichar FontResolver::firstUnresolved() {
|
||||
@ -236,5 +233,31 @@ SkUnichar FontResolver::firstUnresolved() {
|
||||
auto index = firstTry ? 0 : fUnresolvedIndexes[0];
|
||||
return fCodepoints[index];
|
||||
}
|
||||
|
||||
void FontResolver::findAllFontsForAllStyledBlocks(SkSpan<const char> utf8,
|
||||
SkSpan<TextBlock> styles,
|
||||
sk_sp<FontCollection> fontCollection) {
|
||||
fFontCollection = fontCollection;
|
||||
fStyles = styles;
|
||||
fText = utf8;
|
||||
TextBlock combined;
|
||||
for (auto& block : fStyles) {
|
||||
SkASSERT(combined.text().begin() == nullptr ||
|
||||
combined.text().end() == block.text().begin());
|
||||
|
||||
if (combined.text().begin() != nullptr &&
|
||||
block.style().matchOneAttribute(StyleType::kFont, combined.style())) {
|
||||
combined.add(block.text());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!combined.text().empty()) {
|
||||
this->findAllFontsForStyledBlock(combined.style(), combined.text());
|
||||
}
|
||||
|
||||
combined = block;
|
||||
}
|
||||
this->findAllFontsForStyledBlock(combined.style(), combined.text());
|
||||
}
|
||||
} // namespace textlayout
|
||||
} // namespace skia
|
||||
|
@ -2,54 +2,70 @@
|
||||
#ifndef FontResolver_DEFINED
|
||||
#define FontResolver_DEFINED
|
||||
|
||||
#include "src/core/SkSpan.h"
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include "modules/skparagraph/src/TextLine.h"
|
||||
#include "include/core/SkFontMgr.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/SkTHash.h"
|
||||
#include "modules/skparagraph/include/FontCollection.h"
|
||||
#include "modules/skparagraph/include/TextStyle.h"
|
||||
#include "src/core/SkSpan.h"
|
||||
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
|
||||
class FontResolver {
|
||||
public:
|
||||
FontResolver(sk_sp<FontCollection> fontCollection);
|
||||
struct FontDescr {
|
||||
FontDescr() {}
|
||||
FontDescr(SkFont font, SkScalar height)
|
||||
: fFont(font), fHeight(height) {}
|
||||
bool operator==(const FontDescr& a) const {
|
||||
return this->fFont == a.fFont && this->fHeight == a.fHeight;
|
||||
}
|
||||
SkFont fFont;
|
||||
SkScalar fHeight;
|
||||
};
|
||||
|
||||
FontResolver() = default;
|
||||
~FontResolver() = default;
|
||||
|
||||
void findAllFontsForStyledBlock(const TextStyle& style, SkSpan<const char> text);
|
||||
void findAllFontsForAllStyledBlocks(SkSpan<const char> utf8,
|
||||
SkSpan<TextBlock> styles,
|
||||
sk_sp<FontCollection> fontCollection);
|
||||
bool findFirst(const char* codepoint, SkFont* font, SkScalar* height);
|
||||
bool findNext(const char* codepoint, SkFont* font, SkScalar* height);
|
||||
|
||||
private:
|
||||
std::pair<SkFont, SkScalar> makeFont(sk_sp<SkTypeface> typeface, SkScalar size,
|
||||
SkScalar height);
|
||||
|
||||
size_t resolveAllCharactersByFont(std::pair<SkFont, SkScalar> font);
|
||||
void findAllFontsForStyledBlock(const TextStyle& style, SkSpan<const char> text);
|
||||
FontDescr makeFont(sk_sp<SkTypeface> typeface, SkScalar size, SkScalar height);
|
||||
size_t resolveAllCharactersByFont(const FontDescr& fontDescr);
|
||||
void addResolvedWhitespacesToMapping();
|
||||
|
||||
struct Hash {
|
||||
uint32_t operator()(const std::pair<SkFont, SkScalar>& key) const {
|
||||
return SkTypeface::UniqueID(key.first.getTypeface()) +
|
||||
SkScalarCeilToInt(key.first.getSize()) + SkScalarCeilToInt(key.second);
|
||||
uint32_t operator()(const FontDescr& key) const {
|
||||
return SkTypeface::UniqueID(key.fFont.getTypeface()) +
|
||||
SkScalarCeilToInt(key.fFont.getSize()) +
|
||||
SkScalarCeilToInt(key.fHeight);
|
||||
}
|
||||
};
|
||||
|
||||
SkUnichar firstUnresolved();
|
||||
|
||||
sk_sp<FontCollection> fFontCollection;
|
||||
SkSpan<const char> fText;
|
||||
SkSpan<TextBlock> fStyles;
|
||||
|
||||
SkTHashMap<const char*, std::pair<SkFont, SkScalar>> fFontMapping;
|
||||
SkTHashSet<std::pair<SkFont, SkScalar>, Hash> fResolvedFonts;
|
||||
std::pair<SkFont, SkScalar> fFirstResolvedFont;
|
||||
SkTHashMap<const char*, FontDescr> fFontMapping;
|
||||
SkTHashSet<FontDescr, Hash> fResolvedFonts;
|
||||
FontDescr fFirstResolvedFont;
|
||||
|
||||
SkTArray<SkUnichar> fCodepoints;
|
||||
SkTArray<const char*> fCharacters;
|
||||
SkTArray<size_t> fUnresolvedIndexes;
|
||||
SkTArray<SkUnichar> fUnresolvedCodepoints;
|
||||
SkTHashMap<size_t, std::pair<SkFont, SkScalar>> fWhitespaces;
|
||||
SkTHashMap<size_t, FontDescr> fWhitespaces;
|
||||
size_t fUnresolved;
|
||||
};
|
||||
} // namespace textlayout
|
||||
|
100
modules/skparagraph/src/Iterators.h
Normal file
100
modules/skparagraph/src/Iterators.h
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright 2019 Google LLC.
|
||||
#ifndef FontIterator_DEFINED
|
||||
#define FontIterator_DEFINED
|
||||
|
||||
#include <unicode/brkiter.h>
|
||||
#include <unicode/ubidi.h>
|
||||
#include "include/core/SkBlurTypes.h"
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkFontMgr.h"
|
||||
#include "include/core/SkPictureRecorder.h"
|
||||
#include "modules/skparagraph/src/FontResolver.h"
|
||||
#include "modules/skparagraph/src/ParagraphImpl.h"
|
||||
#include "src/core/SkSpan.h"
|
||||
#include "src/utils/SkUTF.h"
|
||||
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
|
||||
class FontIterator final : public SkShaper::FontRunIterator {
|
||||
public:
|
||||
FontIterator(SkSpan<const char> utf8, FontResolver* fontResolver)
|
||||
: fText(utf8), fCurrentChar(utf8.begin()), fFontResolver(fontResolver) { }
|
||||
|
||||
void consume() override {
|
||||
SkASSERT(fCurrentChar < fText.end());
|
||||
SkString locale;
|
||||
auto found = fFontResolver->findFirst(fCurrentChar, &fFont, &fLineHeight);
|
||||
SkASSERT(found);
|
||||
|
||||
// Move until we find the first character that cannot be resolved with the current font
|
||||
while (++fCurrentChar != fText.end()) {
|
||||
SkFont font;
|
||||
SkScalar height;
|
||||
SkString locale;
|
||||
found = fFontResolver->findNext(fCurrentChar, &font, &height);
|
||||
if (found) {
|
||||
if (fFont == font && fLineHeight == height) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t endOfCurrentRun() const override { return fCurrentChar - fText.begin(); }
|
||||
bool atEnd() const override { return fCurrentChar == fText.end(); }
|
||||
const SkFont& currentFont() const override { return fFont; }
|
||||
SkScalar currentLineHeight() const { return fLineHeight; }
|
||||
|
||||
private:
|
||||
|
||||
SkSpan<const char> fText;
|
||||
const char* fCurrentChar;
|
||||
SkFont fFont;
|
||||
SkScalar fLineHeight;
|
||||
FontResolver* fFontResolver;
|
||||
};
|
||||
|
||||
class LangIterator final : public SkShaper::LanguageRunIterator {
|
||||
public:
|
||||
LangIterator(SkSpan<const char> utf8, SkSpan<TextBlock> styles, TextStyle defaultStyle)
|
||||
: fText(utf8)
|
||||
, fTextStyles(styles)
|
||||
, fCurrentChar(utf8.begin())
|
||||
, fCurrentStyle(fTextStyles.begin())
|
||||
, fCurrentLocale(defaultStyle.getLocale()) {}
|
||||
|
||||
void consume() override {
|
||||
SkASSERT(fCurrentChar < fText.end());
|
||||
|
||||
if (fCurrentStyle == fTextStyles.end()) {
|
||||
fCurrentChar = fText.end();
|
||||
return;
|
||||
}
|
||||
|
||||
fCurrentChar = fCurrentStyle->text().end();
|
||||
fCurrentLocale = fCurrentStyle->style().getLocale();
|
||||
while (++fCurrentStyle != fTextStyles.end()) {
|
||||
if (fCurrentStyle->style().getLocale() != fCurrentLocale) {
|
||||
break;
|
||||
}
|
||||
fCurrentChar = fCurrentStyle->text().end();
|
||||
}
|
||||
}
|
||||
|
||||
size_t endOfCurrentRun() const override { return fCurrentChar - fText.begin(); }
|
||||
bool atEnd() const override { return fCurrentChar == fText.end(); }
|
||||
const char* currentLanguage() const override { return fCurrentLocale.c_str(); }
|
||||
|
||||
private:
|
||||
SkSpan<const char> fText;
|
||||
SkSpan<TextBlock> fTextStyles;
|
||||
const char* fCurrentChar;
|
||||
TextBlock* fCurrentStyle;
|
||||
SkString fCurrentLocale;
|
||||
};
|
||||
} // namespace textlayout
|
||||
} // namespace skia
|
||||
|
||||
#endif // FontIterator_DEFINED
|
@ -7,7 +7,7 @@
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkFontMgr.h"
|
||||
#include "include/core/SkPictureRecorder.h"
|
||||
#include "modules/skparagraph/src/FontIterator.h"
|
||||
#include "modules/skparagraph/src/Iterators.h"
|
||||
#include "modules/skparagraph/src/Run.h"
|
||||
#include "modules/skparagraph/src/TextWrapper.h"
|
||||
#include "src/core/SkSpan.h"
|
||||
@ -85,6 +85,24 @@ private:
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
|
||||
ParagraphImpl::ParagraphImpl(const SkString& text,
|
||||
ParagraphStyle style,
|
||||
std::vector<Block> blocks,
|
||||
sk_sp<FontCollection> fonts)
|
||||
: Paragraph(std::move(style), std::move(fonts))
|
||||
, fText(text)
|
||||
, fTextSpan(fText.c_str(), fText.size())
|
||||
, fDirtyLayout(true)
|
||||
, fOldWidth(0)
|
||||
, fPicture(nullptr) {
|
||||
fTextStyles.reserve(blocks.size());
|
||||
for (auto& block : blocks) {
|
||||
fTextStyles.emplace_back(
|
||||
SkSpan<const char>(fTextSpan.begin() + block.fStart, block.fEnd - block.fStart),
|
||||
block.fStyle);
|
||||
}
|
||||
}
|
||||
|
||||
ParagraphImpl::ParagraphImpl(const std::u16string& utf16text,
|
||||
ParagraphStyle style,
|
||||
std::vector<Block> blocks,
|
||||
@ -124,11 +142,10 @@ void ParagraphImpl::layout(SkScalar width) {
|
||||
|
||||
if (fRuns.empty()) {
|
||||
fClusters.reset();
|
||||
|
||||
if (!this->shapeTextIntoEndlessLine()) {
|
||||
// Apply the last style to the empty text
|
||||
FontIterator font(SkMakeSpan(" "),
|
||||
SkSpan<TextBlock>(&fTextStyles.back(), 1),
|
||||
fFontCollection);
|
||||
FontIterator font(SkMakeSpan(" "), &fFontResolver);
|
||||
// Get the font metrics
|
||||
font.consume();
|
||||
LineMetrics lineMetrics(font.currentFont());
|
||||
@ -311,7 +328,7 @@ bool ParagraphImpl::shapeTextIntoEndlessLine() {
|
||||
TRACE_EVENT0("skia", TRACE_FUNC);
|
||||
auto& run = fParagraph->fRuns.emplace_back(fParagraph->text(),
|
||||
info,
|
||||
fFontIterator->lineHeight(),
|
||||
fFontIterator->currentLineHeight(),
|
||||
fParagraph->fRuns.count(),
|
||||
fAdvance.fX);
|
||||
return run.newRunBuffer();
|
||||
@ -340,8 +357,11 @@ bool ParagraphImpl::shapeTextIntoEndlessLine() {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkSpan<TextBlock> styles(fTextStyles.begin(), fTextStyles.size());
|
||||
FontIterator font(fTextSpan, styles, fFontCollection);
|
||||
// This is a pretty big step - resolving all characters against all given fonts
|
||||
fFontResolver.findAllFontsForAllStyledBlocks(fTextSpan, styles(), fFontCollection);
|
||||
|
||||
LangIterator lang(fTextSpan, styles(), paragraphStyle().getTextStyle());
|
||||
FontIterator font(fTextSpan, &fFontResolver);
|
||||
ShapeHandler handler(*this, &font);
|
||||
std::unique_ptr<SkShaper> shaper = SkShaper::MakeShapeDontWrapOrReorder();
|
||||
SkASSERT_RELEASE(shaper != nullptr);
|
||||
@ -352,9 +372,8 @@ bool ParagraphImpl::shapeTextIntoEndlessLine() {
|
||||
return false;
|
||||
}
|
||||
auto script = SkShaper::MakeHbIcuScriptRunIterator(fTextSpan.begin(), fTextSpan.size());
|
||||
auto lang = SkShaper::MakeStdLanguageRunIterator(fTextSpan.begin(), fTextSpan.size());
|
||||
|
||||
shaper->shape(fTextSpan.begin(), fTextSpan.size(), font, *bidi, *script, *lang,
|
||||
shaper->shape(fTextSpan.begin(), fTextSpan.size(), font, *bidi, *script, lang,
|
||||
std::numeric_limits<SkScalar>::max(), &handler);
|
||||
return true;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#ifndef ParagraphImpl_DEFINED
|
||||
#define ParagraphImpl_DEFINED
|
||||
|
||||
#include "FontResolver.h"
|
||||
#include "include/core/SkPicture.h"
|
||||
#include "include/private/SkTHash.h"
|
||||
#include "modules/skparagraph/include/Paragraph.h"
|
||||
@ -28,20 +29,7 @@ public:
|
||||
ParagraphImpl(const SkString& text,
|
||||
ParagraphStyle style,
|
||||
std::vector<Block> blocks,
|
||||
sk_sp<FontCollection> fonts)
|
||||
: Paragraph(std::move(style), std::move(fonts))
|
||||
, fText(text)
|
||||
, fTextSpan(fText.c_str(), fText.size())
|
||||
, fDirtyLayout(true)
|
||||
, fOldWidth(0)
|
||||
, fPicture(nullptr) {
|
||||
fTextStyles.reserve(blocks.size());
|
||||
for (auto& block : blocks) {
|
||||
fTextStyles.emplace_back(
|
||||
SkSpan<const char>(fTextSpan.begin() + block.fStart, block.fEnd - block.fStart),
|
||||
block.fStyle);
|
||||
}
|
||||
}
|
||||
sk_sp<FontCollection> fonts);
|
||||
|
||||
ParagraphImpl(const std::u16string& utf16text,
|
||||
ParagraphStyle style,
|
||||
@ -107,6 +95,7 @@ private:
|
||||
SkTArray<Cluster, true> fClusters;
|
||||
SkTArray<TextLine> fLines;
|
||||
LineMetrics fStrutMetrics;
|
||||
FontResolver fFontResolver;
|
||||
|
||||
bool fDirtyLayout;
|
||||
SkScalar fOldWidth;
|
||||
|
@ -23,6 +23,7 @@ TextStyle::TextStyle() : fFontStyle() {
|
||||
fHasBackground = false;
|
||||
fHasForeground = false;
|
||||
fTextBaseline = TextBaseline::kAlphabetic;
|
||||
fLocale = "";
|
||||
}
|
||||
|
||||
bool TextStyle::equals(const TextStyle& other) const {
|
||||
|
@ -1220,7 +1220,6 @@ protected:
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
/*
|
||||
const char* text =
|
||||
"// Create a raised button.\n"
|
||||
"RaisedButton(\n"
|
||||
@ -1254,7 +1253,7 @@ protected:
|
||||
TextStyle text_style;
|
||||
text_style.setFontFamilies({});
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
text_style.setFontSize(20);
|
||||
text_style.setFontSize(50);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text);
|
||||
builder.pop();
|
||||
@ -1268,31 +1267,7 @@ protected:
|
||||
paint.setColor(SK_ColorLTGRAY);
|
||||
canvas->drawRect(result[0].rect, paint);
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
*/
|
||||
std::vector<uint16_t> text;
|
||||
for (uint16_t i = 0; i < 64; ++i) {
|
||||
text.push_back(i % 5 == 0 ? ' ' : i);
|
||||
}
|
||||
std::u16string u16_text(text.data(), text.data() + text.size());
|
||||
TextStyle default_style;
|
||||
default_style.setFontFamilies({SkString("Roboto")});
|
||||
ParagraphStyle paragraph_style;
|
||||
paragraph_style.setTextStyle(default_style);
|
||||
TextStyle text_style;
|
||||
text_style.setFontFamilies({SkString("Roboto")});
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(u16_text);
|
||||
builder.pop();
|
||||
auto paragraph = builder.Build();
|
||||
size_t count = 10;
|
||||
while (--count > 0) {
|
||||
paragraph->layout(300);
|
||||
paragraph->paint(canvas, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user