Adding TestFontCollection
Change-Id: I43c20616dd842e9ffeaac614c853be4702a819a7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/222104 Commit-Queue: Julia Lavrova <jlavrova@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
fa97463793
commit
9af5cc4d98
@ -30,7 +30,28 @@ if (skia_enable_skparagraph) {
|
||||
]
|
||||
}
|
||||
|
||||
config("utils_config") {
|
||||
include_dirs = [ "utils" ]
|
||||
}
|
||||
|
||||
if (defined(is_skia_standalone) && skia_enable_tools) {
|
||||
|
||||
source_set("utils") {
|
||||
import("skparagraph.gni")
|
||||
public_configs = [ ":utils_config" ]
|
||||
configs += [ "../../:skia_private" ]
|
||||
if (skia_use_icu && skia_use_harfbuzz) {
|
||||
sources = skparagraph_utils
|
||||
} else {
|
||||
sources = []
|
||||
}
|
||||
deps = [
|
||||
"../..:skia",
|
||||
"../skshaper",
|
||||
"//third_party/icu",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("tests") {
|
||||
if (skia_use_icu && skia_use_harfbuzz && paragraph_tests_enabled) {
|
||||
testonly = true
|
||||
@ -71,6 +92,7 @@ if (skia_enable_skparagraph) {
|
||||
deps = [
|
||||
"../..:skia",
|
||||
":skparagraph",
|
||||
":utils",
|
||||
"../skshaper",
|
||||
"//third_party/icu",
|
||||
]
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
|
||||
virtual size_t lineNumber() = 0;
|
||||
|
||||
virtual void markDirty() = 0;
|
||||
|
||||
protected:
|
||||
sk_sp<FontCollection> fFontCollection;
|
||||
ParagraphStyle fParagraphStyle;
|
||||
|
@ -3,6 +3,7 @@
|
||||
# Things are easiest for everyone if these source paths are absolute.
|
||||
_src = get_path_info("src", "abspath")
|
||||
_include = get_path_info("include", "abspath")
|
||||
_utils = get_path_info("utils", "abspath")
|
||||
|
||||
skparagraph_public = [
|
||||
"$_include/ParagraphStyle.h",
|
||||
@ -12,7 +13,7 @@ skparagraph_public = [
|
||||
"$_include/Paragraph.h",
|
||||
"$_include/ParagraphBuilder.h",
|
||||
"$_include/DartTypes.h",
|
||||
"$_src/TypefaceFontProvider.h",
|
||||
"$_include/TypefaceFontProvider.h",
|
||||
]
|
||||
|
||||
skparagraph_sources = [
|
||||
@ -36,3 +37,8 @@ skparagraph_sources = [
|
||||
"$_src/TextWrapper.cpp",
|
||||
"$_src/TypefaceFontProvider.cpp",
|
||||
]
|
||||
|
||||
skparagraph_utils = [
|
||||
"$_utils/TestFontCollection.h",
|
||||
"$_utils/TestFontCollection.cpp",
|
||||
]
|
||||
|
@ -87,11 +87,13 @@ namespace textlayout {
|
||||
|
||||
ParagraphImpl::ParagraphImpl(const std::u16string& utf16text,
|
||||
ParagraphStyle style,
|
||||
std::vector<Block>
|
||||
blocks,
|
||||
sk_sp<FontCollection>
|
||||
fonts)
|
||||
: Paragraph(std::move(style), std::move(fonts)), fPicture(nullptr) {
|
||||
std::vector<Block> blocks,
|
||||
sk_sp<FontCollection> fonts)
|
||||
: Paragraph(std::move(style)
|
||||
, std::move(fonts))
|
||||
, fDirtyLayout(true)
|
||||
, fOldWidth(0)
|
||||
, fPicture(nullptr) {
|
||||
icu::UnicodeString unicode((UChar*)utf16text.data(), SkToS32(utf16text.size()));
|
||||
std::string str;
|
||||
unicode.toUTF8String(str);
|
||||
@ -110,28 +112,48 @@ ParagraphImpl::~ParagraphImpl() = default;
|
||||
|
||||
void ParagraphImpl::layout(SkScalar width) {
|
||||
TRACE_EVENT0("skia", TRACE_FUNC);
|
||||
this->resetContext();
|
||||
|
||||
this->resolveStrut();
|
||||
|
||||
if (!this->shapeTextIntoEndlessLine()) {
|
||||
// Apply the last style to the empty text
|
||||
FontIterator font(SkSpan<const char>(" "),
|
||||
SkSpan<TextBlock>(&fTextStyles.back(), 1),
|
||||
fFontCollection);
|
||||
// Get the font metrics
|
||||
font.consume();
|
||||
LineMetrics lineMetrics(font.currentFont());
|
||||
// Set the important values that are not zero
|
||||
fHeight = lineMetrics.height();
|
||||
fAlphabeticBaseline = lineMetrics.alphabeticBaseline();
|
||||
fIdeographicBaseline = lineMetrics.ideographicBaseline();
|
||||
return;
|
||||
if (fDirtyLayout) {
|
||||
this->fRuns.reset();
|
||||
this->fClusters.reset();
|
||||
this->fLines.reset();
|
||||
this->fPicture = nullptr;
|
||||
} else if (fOldWidth != width) {
|
||||
this->fLines.reset();
|
||||
}
|
||||
|
||||
this->buildClusterTable();
|
||||
if (fRuns.empty()) {
|
||||
fClusters.reset();
|
||||
if (!this->shapeTextIntoEndlessLine()) {
|
||||
// Apply the last style to the empty text
|
||||
FontIterator font(SkSpan<const char>(" "),
|
||||
SkSpan<TextBlock>(&fTextStyles.back(), 1),
|
||||
fFontCollection);
|
||||
// Get the font metrics
|
||||
font.consume();
|
||||
LineMetrics lineMetrics(font.currentFont());
|
||||
// Set the important values that are not zero
|
||||
fHeight = lineMetrics.height();
|
||||
fAlphabeticBaseline = lineMetrics.alphabeticBaseline();
|
||||
fIdeographicBaseline = lineMetrics.ideographicBaseline();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->breakShapedTextIntoLines(width);
|
||||
if (fClusters.empty()) {
|
||||
this->buildClusterTable();
|
||||
this->fLines.reset();
|
||||
}
|
||||
|
||||
if (fLines.empty()) {
|
||||
this->fPicture = nullptr;
|
||||
this->resetContext();
|
||||
this->resolveStrut();
|
||||
this->breakShapedTextIntoLines(width);
|
||||
}
|
||||
|
||||
this->fOldWidth = width;
|
||||
this->fDirtyLayout = false;
|
||||
}
|
||||
|
||||
void ParagraphImpl::resolveStrut() {
|
||||
@ -184,11 +206,6 @@ void ParagraphImpl::resetContext() {
|
||||
fMaxIntrinsicWidth = 0;
|
||||
fMinIntrinsicWidth = 0;
|
||||
fMaxLineWidth = 0;
|
||||
|
||||
fPicture = nullptr;
|
||||
fRuns.reset();
|
||||
fClusters.reset();
|
||||
fLines.reset();
|
||||
}
|
||||
|
||||
// Clusters in the order of the input text
|
||||
@ -349,8 +366,7 @@ void ParagraphImpl::breakShapedTextIntoLines(SkScalar maxWidth) {
|
||||
this,
|
||||
maxWidth,
|
||||
[&](SkSpan<const char> text,
|
||||
SkSpan<const char>
|
||||
textWithSpaces,
|
||||
SkSpan<const char> textWithSpaces,
|
||||
Cluster* start,
|
||||
Cluster* end,
|
||||
size_t startPos,
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
: 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) {
|
||||
@ -81,6 +83,8 @@ public:
|
||||
}
|
||||
LineMetrics strutMetrics() const { return fStrutMetrics; }
|
||||
|
||||
void markDirty() override { fDirtyLayout = true; }
|
||||
|
||||
private:
|
||||
friend class ParagraphBuilder;
|
||||
|
||||
@ -104,6 +108,9 @@ private:
|
||||
SkTArray<TextLine> fLines;
|
||||
LineMetrics fStrutMetrics;
|
||||
|
||||
bool fDirtyLayout;
|
||||
SkScalar fOldWidth;
|
||||
|
||||
// Painting
|
||||
sk_sp<SkPicture> fPicture;
|
||||
};
|
||||
|
@ -35,7 +35,7 @@ class TextWrapper {
|
||||
class TextStretch {
|
||||
public:
|
||||
TextStretch() : fStart(), fEnd(), fWidth(0) {}
|
||||
explicit TextStretch(Cluster* s, Cluster* e)
|
||||
TextStretch(Cluster* s, Cluster* e)
|
||||
: fStart(s, 0), fEnd(e, e->endPos()), fMetrics(), fWidth(0) {
|
||||
for (auto c = s; c <= e; ++c) {
|
||||
if (c->run() != nullptr) {
|
||||
@ -65,6 +65,9 @@ class TextWrapper {
|
||||
}
|
||||
|
||||
void extend(Cluster* cluster) {
|
||||
if (fStart.cluster() == nullptr) {
|
||||
fStart = ClusterPos(cluster, cluster->startPos());
|
||||
}
|
||||
fEnd = ClusterPos(cluster, cluster->endPos());
|
||||
fMetrics.add(cluster->run());
|
||||
fWidth += cluster->width();
|
||||
|
27
modules/skparagraph/utils/TestFontCollection.cpp
Normal file
27
modules/skparagraph/utils/TestFontCollection.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2019 Google LLC.
|
||||
#include "modules/skparagraph/utils/TestFontCollection.h"
|
||||
#include "modules/skparagraph/include/TypefaceFontProvider.h"
|
||||
#include "src/core/SkOSFile.h"
|
||||
#include "src/utils/SkUTF.h"
|
||||
#include "tools/Resources.h"
|
||||
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
TestFontCollection::TestFontCollection(const std::string& resourceDir)
|
||||
: fResourceDir(resourceDir)
|
||||
, fFontsFound(0) {
|
||||
auto fontProvider = sk_make_sp<TypefaceFontProvider>();
|
||||
|
||||
SkOSFile::Iter iter(fResourceDir.c_str());
|
||||
SkString path;
|
||||
while (iter.next(&path)) {
|
||||
SkString file_path;
|
||||
file_path.printf("%s/%s", fResourceDir.c_str(), path.c_str());
|
||||
fontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
|
||||
}
|
||||
fFontsFound = fontProvider->countFamilies();
|
||||
this->setTestFontManager(std::move(fontProvider));
|
||||
this->disableFontFallback();
|
||||
}
|
||||
} // namespace textlayout
|
||||
} // namespace skia
|
18
modules/skparagraph/utils/TestFontCollection.h
Normal file
18
modules/skparagraph/utils/TestFontCollection.h
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2019 Google LLC.
|
||||
#include "modules/skparagraph/include/FontCollection.h"
|
||||
|
||||
namespace skia {
|
||||
namespace textlayout {
|
||||
class TestFontCollection : public FontCollection {
|
||||
public:
|
||||
TestFontCollection(const std::string& resourceDir);
|
||||
~TestFontCollection() = default;
|
||||
|
||||
size_t fontsFound() const { return fFontsFound; }
|
||||
|
||||
private:
|
||||
std::string fResourceDir;
|
||||
size_t fFontsFound;
|
||||
};
|
||||
} // namespace textlayout
|
||||
} // namespace skia
|
@ -17,6 +17,7 @@
|
||||
#include "modules/skparagraph/include/TypefaceFontProvider.h"
|
||||
#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
|
||||
#include "modules/skparagraph/src/ParagraphImpl.h"
|
||||
#include "modules/skparagraph/utils/TestFontCollection.h"
|
||||
#include "samplecode/Sample.h"
|
||||
#include "src/core/SkOSFile.h"
|
||||
#include "src/shaders/SkColorShader.h"
|
||||
@ -31,29 +32,6 @@ sk_sp<SkShader> setgrad(const SkRect& r, SkColor c0, SkColor c1) {
|
||||
SkPoint pts[] = {{r.fLeft, r.fTop}, {r.fRight, r.fTop}};
|
||||
return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
|
||||
}
|
||||
|
||||
class TestFontCollection : public FontCollection {
|
||||
public:
|
||||
TestFontCollection() : fResourceDir(GetResourcePath("fonts").c_str()) {
|
||||
auto fontProvider = sk_make_sp<TypefaceFontProvider>();
|
||||
|
||||
SkOSFile::Iter iter(fResourceDir.c_str());
|
||||
SkString path;
|
||||
while (iter.next(&path)) {
|
||||
SkString file_path;
|
||||
file_path.printf("%s/%s", fResourceDir.c_str(), path.c_str());
|
||||
fontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
|
||||
}
|
||||
|
||||
this->setTestFontManager(std::move(fontProvider));
|
||||
this->disableFontFallback();
|
||||
}
|
||||
|
||||
~TestFontCollection() = default;
|
||||
|
||||
private:
|
||||
std::string fResourceDir;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
class ParagraphView1 : public Sample {
|
||||
@ -279,7 +257,9 @@ protected:
|
||||
TextStyle defaultStyle;
|
||||
defaultStyle.setFontSize(20);
|
||||
paraStyle.setTextStyle(defaultStyle);
|
||||
ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paraStyle, fontCollection);
|
||||
|
||||
SkPaint foreground;
|
||||
foreground.setColor(fg);
|
||||
@ -632,7 +612,9 @@ protected:
|
||||
const char* logo5 = "google_lo";
|
||||
const char* logo6 = "go";
|
||||
{
|
||||
ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paraStyle, fontCollection);
|
||||
|
||||
builder.pushStyle(style0);
|
||||
builder.addText(logo1);
|
||||
@ -728,7 +710,9 @@ protected:
|
||||
|
||||
paraStyle.setEllipsis(ellipsis);
|
||||
|
||||
ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paraStyle, fontCollection);
|
||||
|
||||
if (text.empty()) {
|
||||
const std::u16string text0 = u"\u202Dabc";
|
||||
@ -894,7 +878,9 @@ protected:
|
||||
const char* logo5 = "Ski";
|
||||
const char* logo6 = "a";
|
||||
{
|
||||
ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paraStyle, fontCollection);
|
||||
|
||||
builder.pushStyle(style0);
|
||||
builder.addText(logo1);
|
||||
@ -934,7 +920,9 @@ protected:
|
||||
const char* logo15 = "S";
|
||||
const char* logo16 = "S";
|
||||
{
|
||||
ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paraStyle, fontCollection);
|
||||
|
||||
builder.pushStyle(style0);
|
||||
builder.addText(logo11);
|
||||
@ -1011,7 +999,9 @@ protected:
|
||||
textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
|
||||
SkFontStyle::kUpright_Slant));
|
||||
|
||||
ParagraphBuilderImpl builder(paragraphStyle, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
|
||||
builder.pushStyle(textStyle);
|
||||
builder.addText(line);
|
||||
builder.pop();
|
||||
@ -1087,7 +1077,9 @@ protected:
|
||||
textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
|
||||
SkFontStyle::kUpright_Slant));
|
||||
|
||||
ParagraphBuilderImpl builder(paragraphStyle, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
|
||||
builder.pushStyle(textStyle);
|
||||
builder.addText(line);
|
||||
builder.pop();
|
||||
@ -1185,7 +1177,9 @@ protected:
|
||||
textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
|
||||
SkFontStyle::kUpright_Slant));
|
||||
|
||||
ParagraphBuilderImpl builder(paragraphStyle, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
|
||||
builder.pushStyle(textStyle);
|
||||
builder.addText(text);
|
||||
builder.pop();
|
||||
@ -1250,7 +1244,9 @@ protected:
|
||||
const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
|
||||
ParagraphStyle paragraph_style;
|
||||
paragraph_style.turnHintingOff();
|
||||
ParagraphBuilderImpl builder(paragraph_style, sk_make_sp<TestFontCollection>());
|
||||
auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
|
||||
SkASSERT(fontCollection->fontsFound() != 0);
|
||||
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
|
||||
|
||||
TextStyle text_style;
|
||||
text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji"),
|
||||
@ -1291,7 +1287,7 @@ protected:
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawColor(SK_ColorWHITE);
|
||||
|
||||
/*
|
||||
const char* text =
|
||||
"// Create a raised button.\n"
|
||||
"RaisedButton(\n"
|
||||
@ -1318,27 +1314,52 @@ protected:
|
||||
" // Perform some action\n"
|
||||
" },\n"
|
||||
");";
|
||||
|
||||
ParagraphStyle paragraph_style;
|
||||
paragraph_style.turnHintingOff();
|
||||
ParagraphBuilderImpl builder(paragraph_style, sk_make_sp<FontCollection>());
|
||||
|
||||
TextStyle text_style;
|
||||
text_style.setFontFamilies({SkString("monospace")});
|
||||
text_style.setFontFamilies({});
|
||||
text_style.setColor(SK_ColorBLACK);
|
||||
text_style.setFontSize(10);
|
||||
text_style.setFontSize(20);
|
||||
builder.pushStyle(text_style);
|
||||
builder.addText(text);
|
||||
builder.pop();
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->layout(1000);
|
||||
paragraph->layout(500);
|
||||
|
||||
auto result =
|
||||
paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight, RectWidthStyle::kTight);
|
||||
SkPaint paint;
|
||||
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