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:
Julia Lavrova 2019-06-19 13:32:01 -04:00 committed by Skia Commit-Bot
parent fa97463793
commit 9af5cc4d98
9 changed files with 191 additions and 69 deletions

View File

@ -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",
]

View File

@ -62,6 +62,8 @@ public:
virtual size_t lineNumber() = 0;
virtual void markDirty() = 0;
protected:
sk_sp<FontCollection> fFontCollection;
ParagraphStyle fParagraphStyle;

View File

@ -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",
]

View File

@ -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,

View File

@ -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;
};

View File

@ -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();

View 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

View 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

View File

@ -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: