| /* |
| * Copyright 2019 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #include "include/core/SkBitmap.h" |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkColor.h" |
| #include "include/core/SkFontMgr.h" |
| #include "include/core/SkFontStyle.h" |
| #include "include/core/SkPaint.h" |
| #include "include/core/SkPoint.h" |
| #include "include/core/SkRect.h" |
| #include "include/core/SkRefCnt.h" |
| #include "include/core/SkScalar.h" |
| #include "include/core/SkSpan.h" |
| #include "include/core/SkStream.h" |
| #include "include/core/SkString.h" |
| #include "include/core/SkTypeface.h" |
| #include "include/core/SkTypes.h" |
| #include "include/encode/SkPngEncoder.h" |
| #include "modules/skparagraph/include/DartTypes.h" |
| #include "modules/skparagraph/include/FontCollection.h" |
| #include "modules/skparagraph/include/Paragraph.h" |
| #include "modules/skparagraph/include/ParagraphCache.h" |
| #include "modules/skparagraph/include/ParagraphStyle.h" |
| #include "modules/skparagraph/include/TextShadow.h" |
| #include "modules/skparagraph/include/TextStyle.h" |
| #include "modules/skparagraph/include/TypefaceFontProvider.h" |
| #include "modules/skparagraph/src/OneLineShaper.h" |
| #include "modules/skparagraph/src/ParagraphBuilderImpl.h" |
| #include "modules/skparagraph/src/ParagraphImpl.h" |
| #include "modules/skparagraph/src/Run.h" |
| #include "modules/skparagraph/src/TextLine.h" |
| #include "modules/skparagraph/tests/SkShaperJSONWriter.h" |
| #include "modules/skparagraph/utils/TestFontCollection.h" |
| #include "modules/skshaper/utils/FactoryHelpers.h" |
| #include "src/base/SkTSort.h" |
| #include "src/core/SkOSFile.h" |
| #include "src/utils/SkOSPath.h" |
| #include "tests/Test.h" |
| #include "tools/Resources.h" |
| #include "tools/flags/CommandLineFlags.h" |
| #include "tools/fonts/FontToolUtils.h" |
| |
| #include <string.h> |
| #include <algorithm> |
| #include <limits> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| #include <thread> |
| |
| #include "modules/skunicode/include/SkUnicode.h" |
| |
| #if defined(SK_UNICODE_ICU_IMPLEMENTATION) |
| #include "modules/skunicode/include/SkUnicode_icu.h" |
| #endif |
| |
| #if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION) |
| #include "modules/skunicode/include/SkUnicode_libgrapheme.h" |
| #endif |
| |
| #if defined(SK_UNICODE_ICU4X_IMPLEMENTATION) |
| #include "modules/skunicode/include/SkUnicode_icu4x.h" |
| #endif |
| |
| using namespace skia_private; |
| |
| struct GrContextOptions; |
| |
| static DEFINE_string(paragraph_fonts, "", |
| "subdirectory of //resources for fonts to use for these tests"); |
| static DEFINE_bool(run_paragraph_tests_needing_system_fonts, true, |
| "Some tests are finicky and need certain system fonts. " |
| "Set this to false to skip those."); |
| |
| #define VeryLongCanvasWidth 1000000 |
| #define TestCanvasWidth 1000 |
| #define TestCanvasHeight 600 |
| |
| using namespace skia::textlayout; |
| namespace { |
| |
| SkScalar EPSILON100 = 0.01f; |
| SkScalar EPSILON50 = 0.02f; |
| SkScalar EPSILON20 = 0.05f; |
| SkScalar EPSILON10 = 0.1f; |
| SkScalar EPSILON5 = 0.20f; |
| SkScalar EPSILON2 = 0.50f; |
| |
| bool equal(const char* base, TextRange a, const char* b) { |
| return std::strncmp(b, base + a.start, a.width()) == 0; |
| } |
| |
| std::u16string mirror(const std::string& text) { |
| std::u16string result; |
| result += u"\u202E"; |
| for (auto i = text.size(); i > 0; --i) { |
| result += text[i - 1]; |
| } |
| //result += u"\u202C"; |
| return result; |
| } |
| |
| std::u16string straight(const std::string& text) { |
| std::u16string result; |
| result += u"\u202D"; |
| for (auto ch : text) { |
| result += ch; |
| } |
| return result; |
| } |
| |
| class ResourceFontCollection : public FontCollection { |
| static const std::vector<sk_sp<SkTypeface>>& getTypefaces() { |
| static std::vector<sk_sp<SkTypeface>> typefaces = []() -> std::vector<sk_sp<SkTypeface>> { |
| if (FLAGS_paragraph_fonts.size() == 0) { |
| return {}; |
| } |
| TArray<SkString> paths; |
| { |
| SkString fontResources = GetResourcePath(FLAGS_paragraph_fonts[0]); |
| const char* fontDir = fontResources.c_str(); |
| SkOSFile::Iter iter(fontDir); |
| SkString path; |
| while (iter.next(&path)) { |
| if ((false)) { |
| SkDebugf("Found font file: %s\n", path.c_str()); |
| } |
| SkString fullPath; |
| fullPath.printf("%s/%s", fontDir, path.c_str()); |
| paths.emplace_back(fullPath); |
| } |
| if (paths.size()) { |
| SkTQSort(paths.begin(), paths.end(), |
| [](const SkString& a, const SkString& b) { |
| return strcmp(a.c_str(), b.c_str()) < 0; |
| }); |
| } |
| } |
| |
| sk_sp<SkFontMgr> mgr = ToolUtils::TestFontMgr(); |
| std::vector<sk_sp<SkTypeface>> typefaces; |
| bool fontsFound = false; |
| for (auto&& path : paths) { |
| if ((false)) { |
| SkDebugf("Reading font: %s\n", path.c_str()); |
| } |
| auto stream = SkStream::MakeFromFile(path.c_str()); |
| SkASSERTF(stream, "%s not readable", path.c_str()); |
| sk_sp<SkTypeface> typeface = mgr->makeFromStream(std::move(stream), {}); |
| // Without --nativeFonts, DM will use the portable test font manager which does |
| // not know how to read in fonts from bytes. |
| if (typeface) { |
| if ((false)) { |
| SkString familyName; |
| typeface->getFamilyName(&familyName); |
| SkDebugf("Creating: %s size: %zu\n", |
| familyName.c_str(), |
| typeface->openExistingStream(nullptr)->getLength()); |
| } |
| if (path.endsWith("Roboto-Italic.ttf")) { |
| fontsFound = true; |
| } |
| typefaces.emplace_back(std::move(typeface)); |
| } else { |
| SkDEBUGF("%s was not turned into a Typeface. Did you set --nativeFonts?\n", |
| path.c_str()); |
| } |
| } |
| SkASSERTF_RELEASE(typefaces.size(), "--paragraph_fonts set but no fonts found." |
| "Did you set --nativeFonts?"); |
| SkASSERTF_RELEASE(fontsFound, "--paragraph_fonts set but Roboto-Italic.ttf not found"); |
| return typefaces; |
| }(); |
| return typefaces; |
| } |
| public: |
| ResourceFontCollection(bool testOnly = false) |
| : fFontsFound(false) |
| , fResolvedFonts(0) |
| , fFontProvider(sk_make_sp<TypefaceFontProvider>()) { |
| const std::vector<sk_sp<SkTypeface>>& typefaces = getTypefaces(); |
| fFontsFound = !typefaces.empty(); |
| for (auto&& typeface : typefaces) { |
| fFontProvider->registerTypeface(typeface); |
| } |
| |
| if (testOnly) { |
| this->setTestFontManager(std::move(fFontProvider)); |
| } else { |
| this->setAssetFontManager(std::move(fFontProvider)); |
| } |
| this->disableFontFallback(); |
| } |
| |
| size_t resolvedFonts() const { return fResolvedFonts; } |
| |
| // TODO: temp solution until we check in fonts |
| bool fontsFound() const { return fFontsFound; } |
| |
| private: |
| bool fFontsFound; |
| size_t fResolvedFonts; |
| sk_sp<TypefaceFontProvider> fFontProvider; |
| }; |
| |
| class TestCanvas { |
| public: |
| TestCanvas(const char* testName) : name(testName) { |
| bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight); |
| canvas = new SkCanvas(bits); |
| canvas->clear(SK_ColorWHITE); |
| } |
| |
| ~TestCanvas() { |
| SkString tmpDir = skiatest::GetTmpDir(); |
| if (!tmpDir.isEmpty()) { |
| SkString path = SkOSPath::Join(tmpDir.c_str(), name); |
| SkFILEWStream file(path.c_str()); |
| if (!SkPngEncoder::Encode(&file, bits.pixmap(), {})) { |
| SkDebugf("Cannot write a picture %s\n", name); |
| } |
| } |
| delete canvas; |
| } |
| |
| void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) { |
| |
| SkPaint paint; |
| if (!fill) { |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| } |
| paint.setColor(color); |
| for (auto& r : result) { |
| canvas->drawRect(r.rect, paint); |
| } |
| } |
| |
| void drawLine(SkColor color, SkRect rect, bool vertical = true) { |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| paint.setColor(color); |
| if (vertical) { |
| canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| } else { |
| canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint); |
| } |
| } |
| |
| void drawLines(SkColor color, std::vector<TextBox>& result) { |
| |
| for (auto& r : result) { |
| drawLine(color, r.rect); |
| } |
| } |
| |
| SkCanvas* get() { return canvas; } |
| private: |
| SkBitmap bits; |
| SkCanvas* canvas; |
| const char* name; |
| }; |
| |
| static sk_sp<SkUnicode> get_unicode() { |
| auto factory = SkShapers::BestAvailable(); |
| return sk_ref_sp<SkUnicode>(factory->getUnicode()); |
| } |
| |
| } // namespace |
| |
| // Skip tests which do not find the fonts, unless the user set --paragraph_fonts in which case |
| // we should make a loud error. |
| #define SKIP_IF_FONTS_NOT_FOUND(r, fontCollection) \ |
| if (!fontCollection->fontsFound()) { \ |
| if (FLAGS_paragraph_fonts.size() != 0) { \ |
| ERRORF(r, "SkParagraphTests Fonts not found!\n"); \ |
| } \ |
| return; \ |
| } |
| |
| #define NEED_SYSTEM_FONTS(fontCollection) \ |
| if (!FLAGS_run_paragraph_tests_needing_system_fonts) { \ |
| return; \ |
| } \ |
| fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr()); \ |
| fontCollection->enableFontFallback(); |
| |
| UNIX_ONLY_TEST(SkParagraph_SimpleParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| const char* text = "Hello World Text Dialog"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| |
| size_t index = 0; |
| for (auto& line : impl->lines()) { |
| line.scanStyles(StyleType::kDecorations, |
| [&index, reporter] |
| (TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| REPORTER_ASSERT(reporter, index == 0); |
| REPORTER_ASSERT(reporter, style.getColor() == SK_ColorBLACK); |
| ++index; |
| }); |
| } |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_Rounding_Off_LineBreaks, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| const char* text = "AAAAAAAAAA"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setApplyRoundingHack(false); |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Ahem")}); |
| text_style.setColor(SK_ColorBLACK); |
| |
| auto testFontSize = {1.5f, 10.0f/3, 10.0f/6, 10.0f}; |
| for (auto fontSize : testFontSize) { |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| text_style.setFontSize(fontSize); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(SK_ScalarInfinity); |
| // Slightly wider than the max intrinsic width. |
| REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0); |
| paragraph->layout(paragraph->getMaxIntrinsicWidth()); |
| |
| ParagraphImpl* impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->lines().size() == 1); |
| auto& line = impl->lines()[0]; |
| |
| const LineMetrics metrics = line.getMetrics(); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(metrics.fWidth, fontSize * len, EPSILON2)); |
| } |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0); |
| builder.addPlaceholder(placeholder1); |
| builder.addText(text, len); |
| builder.addPlaceholder(placeholder1); |
| |
| PlaceholderStyle placeholder2(5, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); |
| builder.addText(text, len); |
| builder.addPlaceholder(placeholder2); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder1); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder1); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorRED, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| |
| boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorGREEN, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| |
| boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| boxes = paragraph->getRectsForRange(4, 17, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 7); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 90.921f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 50, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 90.921f + 50, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 100, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.left(), 231.343f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.top(), 50, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.right(), 231.343f + 50, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.bottom(), 100, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.left(), 281.343f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.right(), 281.343f + 5, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.bottom(), 50, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.left(), 336.343f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.right(), 336.343f + 5, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 38.347f); |
| builder.addPlaceholder(placeholder); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100)); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 14.226f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kAboveBaseline, TextBaseline::kAlphabetic, 903129.129308f); |
| builder.addPlaceholder(placeholder); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.347f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 49.652f, EPSILON100)); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 25.531f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBelowBaseline, TextBaseline::kAlphabetic, 903129.129308f); |
| builder.addPlaceholder(placeholder); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100)); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.121f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBottom, TextBaseline::kAlphabetic, 0); |
| builder.addPlaceholder(placeholder); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| auto boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100)); |
| |
| boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 19.531f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kTop, TextBaseline::kAlphabetic, 0); |
| builder.addPlaceholder(placeholder); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| auto boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100)); |
| |
| boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kMiddle, TextBaseline::kAlphabetic, 0); |
| builder.addPlaceholder(placeholder); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| auto boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100)); |
| |
| boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 9.765f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "給能上目秘使"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Source Han Serif CN")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kIdeographic, 38.347f); |
| builder.addPlaceholder(placeholder); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| auto boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 162.5f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f + 55, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100)); |
| |
| boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 135.5f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 4.703f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50); |
| PlaceholderStyle placeholder2(25, 25, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 12.5f); |
| |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder1); |
| builder.addText(text, len); |
| |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); // 4 + 1 |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); // 6 + 1 |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); // 7 + 1 |
| |
| builder.addPlaceholder(placeholder1); |
| builder.addText(text, len); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); |
| |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder1); |
| |
| builder.addText(text, len); |
| |
| builder.addPlaceholder(placeholder2); |
| |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kTight; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorRED, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| |
| boxes = paragraph->getRectsForRange(175, 176, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorGREEN, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 31.695f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 218.531f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 47.292f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 249, EPSILON100)); |
| |
| boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| boxes = paragraph->getRectsForRange(4, 45, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 30); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 59.726f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.378f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56.847f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.left(), 606.343f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.top(), 38, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.right(), 631.343f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.bottom(), 63, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.left(), 0.5f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.top(), 63.5f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.right(), 50.5f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "012 34"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setLetterSpacing(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| |
| PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50); |
| PlaceholderStyle placeholder2(5, 20, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 10); |
| |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); // 8 + 1 |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); // 5 + 1 |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder1); // 8 + 0 |
| |
| builder.addText(text, len); |
| |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder2); // 1 + 2 |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder2); // 1 + 2 |
| |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); |
| builder.addText(text, len); // 11 |
| |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); |
| builder.addPlaceholder(placeholder1); |
| builder.addPlaceholder(placeholder2); |
| |
| builder.addText(text, len); |
| |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kMax; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| auto boxes = paragraph->getRectsForPlaceholders(); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 34); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 140.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.left(), 800.921f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.right(), 850.921f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.bottom(), 50, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.left(), 503.382f, EPSILON10)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.top(), 160, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.right(), 508.382f, EPSILON10)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.bottom(), 180, EPSILON100)); |
| |
| boxes = paragraph->getRectsForRange(30, 50, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 8); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 216.097f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 60, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 290.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 120, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 290.921f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 60, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 340.921f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 120, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.left(), 340.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top(), 60, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.right(), 345.921f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_SimpleRedParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| const char* text = "I am RED"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorRED); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| |
| size_t index = 0; |
| for (auto& line : impl->lines()) { |
| line.scanStyles(StyleType::kDecorations, |
| [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| REPORTER_ASSERT(reporter, index == 0); |
| REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED); |
| ++index; |
| return true; |
| }); |
| } |
| } |
| |
| // Checked: DIFF+ (Space between 1 & 2 style blocks) |
| UNIX_ONLY_TEST(SkParagraph_RainbowParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| TestCanvas canvas("SkParagraph_RainbowParagraph.png"); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| const char* text1 = "Red Roboto"; // [0:10) |
| const char* text2 = "big Greeen Default"; // [10:28) |
| const char* text3 = "Defcolor Homemade Apple"; // [28:51) |
| const char* text4 = "Small Blue Roboto"; // [51:68) |
| const char* text41 = "Small Blue "; |
| const char* text5 = |
| "Continue Last Style With lots of words to check if it overlaps " |
| "properly or not"; // [68:) |
| const char* text42 = |
| "Roboto" |
| "Continue Last Style With lots of words to check if it overlaps " |
| "properly or not"; |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setTextAlign(TextAlign::kLeft); |
| paragraph_style.setMaxLines(2); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style1; |
| text_style1.setFontFamilies({SkString("Roboto")}); |
| |
| text_style1.setColor(SK_ColorRED); |
| builder.pushStyle(text_style1); |
| builder.addText(text1, strlen(text1)); |
| |
| TextStyle text_style2; |
| text_style2.setFontFamilies({SkString("Roboto")}); |
| text_style2.setFontSize(50); |
| text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| text_style2.setLetterSpacing(10); |
| text_style2.setDecorationColor(SK_ColorBLACK); |
| text_style2.setDecoration((TextDecoration)( |
| TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough)); |
| text_style2.setWordSpacing(30); |
| text_style2.setColor(SK_ColorGREEN); |
| builder.pushStyle(text_style2); |
| builder.addText(text2, strlen(text2)); |
| |
| TextStyle text_style3; |
| text_style3.setFontFamilies({SkString("Homemade Apple")}); |
| text_style3.setColor(SK_ColorBLACK); |
| builder.pushStyle(text_style3); |
| builder.addText(text3, strlen(text3)); |
| |
| TextStyle text_style4; |
| text_style4.setFontFamilies({SkString("Roboto")}); |
| text_style4.setFontSize(14); |
| text_style4.setDecorationColor(SK_ColorBLACK); |
| text_style4.setDecoration((TextDecoration)( |
| TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough)); |
| text_style4.setColor(SK_ColorBLUE); |
| builder.pushStyle(text_style4); |
| builder.addText(text4, strlen(text4)); |
| |
| builder.addText(text5, strlen(text5)); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(1000); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 4); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 4); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 2); |
| |
| auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawRects(SK_ColorMAGENTA, rects); |
| |
| size_t index = 0; |
| impl->lines()[0].scanStyles( |
| StyleType::kAllAttributes, |
| [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| switch (index) { |
| case 0: |
| REPORTER_ASSERT(reporter, style.equals(text_style1)); |
| REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1)); |
| break; |
| case 1: |
| REPORTER_ASSERT(reporter, style.equals(text_style2)); |
| REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2)); |
| break; |
| case 2: |
| REPORTER_ASSERT(reporter, style.equals(text_style3)); |
| REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3)); |
| break; |
| case 3: |
| REPORTER_ASSERT(reporter, style.equals(text_style4)); |
| REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41)); |
| break; |
| default: |
| REPORTER_ASSERT(reporter, false); |
| break; |
| } |
| ++index; |
| return true; |
| }); |
| impl->lines()[1].scanStyles( |
| StyleType::kAllAttributes, |
| [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| switch (index) { |
| case 4: |
| REPORTER_ASSERT(reporter, style.equals(text_style4)); |
| REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42)); |
| break; |
| default: |
| REPORTER_ASSERT(reporter, false); |
| break; |
| } |
| ++index; |
| return true; |
| }); |
| REPORTER_ASSERT(reporter, index == 5); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_DefaultStyleParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png"); |
| const char* text = "No TextStyle! Uh Oh!"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| TextStyle defaultStyle; |
| defaultStyle.setFontFamilies({SkString("Roboto")}); |
| defaultStyle.setColor(SK_ColorBLACK); |
| paragraph_style.setTextStyle(defaultStyle); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| builder.addText(text, len); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 10.0, 15.0); |
| |
| REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 1); |
| |
| size_t index = 0; |
| impl->lines()[0].scanStyles( |
| StyleType::kAllAttributes, |
| [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle())); |
| REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text)); |
| ++index; |
| return true; |
| }); |
| REPORTER_ASSERT(reporter, index == 1); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_BoldParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_BoldParagraph.png"); |
| const char* text = "This is Red max bold text!"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorRED); |
| text_style.setFontSize(60); |
| text_style.setLetterSpacing(0); |
| text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(VeryLongCanvasWidth); |
| paragraph->paint(canvas.get(), 10.0, 60.0); |
| |
| REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 1); |
| |
| size_t index = 0; |
| impl->lines()[0].scanStyles( |
| StyleType::kAllAttributes, |
| [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| REPORTER_ASSERT(reporter, style.equals(text_style)); |
| REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text)); |
| ++index; |
| return true; |
| }); |
| REPORTER_ASSERT(reporter, index == 1); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_HeightOverrideParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png"); |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(10); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(20); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setHeight(3.6345f); |
| text_style.setHeightOverride(true); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 5); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorRED, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 0ull); |
| |
| boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 3ull); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_BasicHalfLeading, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| const size_t len = strlen(text); |
| |
| TestCanvas canvas("SkParagraph_BasicHalfLeading.png"); |
| |
| ParagraphStyle paragraph_style; |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(20.0f); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setLetterSpacing(0.0f); |
| text_style.setWordSpacing(0.0f); |
| text_style.setHeightOverride(true); |
| text_style.setHeight(3.6345f); |
| text_style.setHalfLeading(true); |
| |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| builder.pushStyle(text_style); |
| builder.addText(text); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| const RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| std::vector<TextBox> boxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kTight, rect_width_style); |
| std::vector<TextBox> lineBoxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kMax, rect_width_style); |
| |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 3ull); |
| REPORTER_ASSERT(reporter, lineBoxes.size() == boxes.size()); |
| |
| const auto line_spacing1 = boxes[1].rect.top() - boxes[0].rect.bottom(); |
| const auto line_spacing2 = boxes[2].rect.top() - boxes[1].rect.bottom(); |
| |
| // Uniform line spacing. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(line_spacing1, line_spacing2)); |
| |
| // line spacing is distributed evenly over and under the text. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[0].rect.bottom() - boxes[0].rect.bottom(), boxes[0].rect.top() - lineBoxes[0].rect.top())); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[1].rect.bottom() - boxes[1].rect.bottom(), boxes[1].rect.top() - lineBoxes[1].rect.top())); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[2].rect.bottom() - boxes[2].rect.bottom(), boxes[2].rect.top() - lineBoxes[2].rect.top())); |
| |
| // Half leading does not move the text horizontally. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_NearZeroHeightMixedDistribution, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "Cookies need love"; |
| const size_t len = strlen(text); |
| |
| TestCanvas canvas("SkParagraph_ZeroHeightHalfLeading.png"); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setTextHeightBehavior(TextHeightBehavior::kAll); |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(20.0f); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setLetterSpacing(0.0f); |
| text_style.setWordSpacing(0.0f); |
| text_style.setHeightOverride(true); |
| text_style.setHeight(0.001f); |
| |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| // First run, half leading. |
| text_style.setHalfLeading(true); |
| builder.pushStyle(text_style); |
| builder.addText(text); |
| |
| // Second run, no half leading. |
| text_style.setHalfLeading(false); |
| builder.pushStyle(text_style); |
| builder.addText(text); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 2); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 2); // paragraph style does not count |
| REPORTER_ASSERT(reporter, impl->lines().size() == 1ull); |
| |
| const RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| std::vector<TextBox> boxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kTight, rect_width_style); |
| std::vector<TextBox> lineBoxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kMax, rect_width_style); |
| |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1ull); |
| REPORTER_ASSERT(reporter, lineBoxes.size() == boxes.size()); |
| |
| // From font metrics. |
| const auto metricsAscent = -18.5546875f; |
| const auto metricsDescent = 4.8828125f; |
| |
| // As the height multiplier converges to 0 (but not 0 since 0 is used as a |
| // magic value to indicate there's no height multiplier), the `Run`s top |
| // edge and bottom edge will converge to a horizontal line: |
| // - When half leading is used the vertical line is roughly the center of |
| // of the glyphs in the run ((fontMetrics.descent - fontMetrics.ascent) / 2) |
| // - When half leading is disabled the line is the alphabetic baseline. |
| |
| // Expected values in baseline coordinate space: |
| const auto run1_ascent = (metricsAscent + metricsDescent) / 2; |
| const auto run1_descent = (metricsAscent + metricsDescent) / 2; |
| const auto run2_ascent = 0.0f; |
| const auto run2_descent = 0.0f; |
| const auto line_top = std::min(run1_ascent, run2_ascent); |
| const auto line_bottom = std::max(run1_descent, run2_descent); |
| |
| // Expected glyph height in linebox coordinate space: |
| const auto glyphs_top = metricsAscent - line_top; |
| const auto glyphs_bottom = metricsDescent - line_top; |
| |
| // kTight reports the glyphs' bounding box in the linebox's coordinate |
| // space. |
| const auto actual_glyphs_top = boxes[0].rect.top() - lineBoxes[0].rect.top(); |
| const auto actual_glyphs_bottom = boxes[0].rect.bottom() - lineBoxes[0].rect.top(); |
| |
| // Use a relatively large epsilon since the heightMultiplier is not actually |
| // 0. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(glyphs_top, actual_glyphs_top, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(glyphs_bottom, actual_glyphs_bottom, EPSILON20)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[0].rect.height(), line_bottom - line_top, EPSILON2)); |
| REPORTER_ASSERT(reporter, lineBoxes[0].rect.height() > 1); |
| |
| // Half leading does not move the text horizontally. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_StrutHalfLeadingSimple, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "A"; |
| const size_t len = strlen(text); |
| |
| TestCanvas canvas("SkParagraph_StrutHalfLeading.png"); |
| |
| ParagraphStyle paragraph_style; |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(100.0f); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setLetterSpacing(0.0f); |
| text_style.setWordSpacing(0.0f); |
| text_style.setHeightOverride(true); |
| text_style.setHeight(2.0f); |
| text_style.setHalfLeading(true); |
| |
| StrutStyle strut_style; |
| strut_style.setFontFamilies({SkString("Roboto")}); |
| strut_style.setFontSize(100.0f); |
| strut_style.setHeightOverride(true); |
| strut_style.setHeight(2.0f); |
| strut_style.setHalfLeading(true); |
| strut_style.setStrutEnabled(true); |
| strut_style.setForceStrutHeight(true); |
| |
| paragraph_style.setStrutStyle(strut_style); |
| paragraph_style.setTextStyle(text_style); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| builder.pushStyle(text_style); |
| builder.addText(text); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| const RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| std::vector<TextBox> boxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kTight, rect_width_style); |
| std::vector<TextBox> lineBoxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kMax, rect_width_style); |
| |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, lineBoxes.size() == boxes.size()); |
| |
| // line spacing is distributed evenly over and under the text. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[0].rect.bottom() - boxes[0].rect.bottom(), boxes[0].rect.top() - lineBoxes[0].rect.top())); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[0].rect.top(), 0.0f)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[0].rect.left(), 0.0f)); |
| |
| std::vector<LineMetrics> lineMetrics; |
| paragraph->getLineMetrics(lineMetrics); |
| LineMetrics& firstLine = lineMetrics[0]; |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(firstLine.fHeight, 200.0f)); |
| |
| // Half leading does not move the text horizontally. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_StrutHalfLeadingMultiline, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| const size_t len = strlen(text); |
| |
| TestCanvas canvas("SkParagraph_StrutHalfLeading.png"); |
| |
| ParagraphStyle paragraph_style; |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(20.0f); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setLetterSpacing(0.0f); |
| text_style.setWordSpacing(0.0f); |
| text_style.setHeightOverride(true); |
| text_style.setHeight(3.0f); |
| text_style.setHalfLeading(true); |
| |
| StrutStyle strut_style; |
| strut_style.setFontFamilies({SkString("Roboto")}); |
| strut_style.setFontSize(20.0f); |
| strut_style.setHeightOverride(true); |
| strut_style.setHeight(3.0f); |
| strut_style.setHalfLeading(true); |
| strut_style.setStrutEnabled(true); |
| strut_style.setForceStrutHeight(true); |
| |
| paragraph_style.setStrutStyle(strut_style); |
| paragraph_style.setTextStyle(text_style); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| builder.pushStyle(text_style); |
| builder.addText(text); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| const RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| std::vector<TextBox> boxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kTight, rect_width_style); |
| std::vector<TextBox> lineBoxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kMax, rect_width_style); |
| |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 3ull); |
| REPORTER_ASSERT(reporter, lineBoxes.size() == boxes.size()); |
| |
| const auto line_spacing1 = boxes[1].rect.top() - boxes[0].rect.bottom(); |
| const auto line_spacing2 = boxes[2].rect.top() - boxes[1].rect.bottom(); |
| |
| // Uniform line spacing. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(line_spacing1, line_spacing2)); |
| |
| // line spacing is distributed evenly over and under the text. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[0].rect.bottom() - boxes[0].rect.bottom(), boxes[0].rect.top() - lineBoxes[0].rect.top())); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[1].rect.bottom() - boxes[1].rect.bottom(), boxes[1].rect.top() - lineBoxes[1].rect.top())); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[2].rect.bottom() - boxes[2].rect.bottom(), boxes[2].rect.top() - lineBoxes[2].rect.top())); |
| |
| // Half leading does not move the text horizontally. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_TrimLeadingDistribution, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| const size_t len = strlen(text); |
| |
| TestCanvas canvas("SkParagraph_TrimHalfLeading.png"); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setTextHeightBehavior(TextHeightBehavior::kDisableAll); |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(20.0f); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setLetterSpacing(0.0f); |
| text_style.setWordSpacing(0.0f); |
| text_style.setHeightOverride(true); |
| text_style.setHeight(3.6345f); |
| text_style.setHalfLeading(true); |
| |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| builder.pushStyle(text_style); |
| builder.addText(text); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| const RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| |
| std::vector<TextBox> boxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kTight, rect_width_style); |
| std::vector<TextBox> lineBoxes = paragraph->getRectsForRange(0, len, RectHeightStyle::kMax, rect_width_style); |
| |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 3ull); |
| REPORTER_ASSERT(reporter, lineBoxes.size() == boxes.size()); |
| |
| const auto line_spacing1 = boxes[1].rect.top() - boxes[0].rect.bottom(); |
| const auto line_spacing2 = boxes[2].rect.top() - boxes[1].rect.bottom(); |
| |
| // Uniform line spacing. The delta is introduced by the height rounding. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(line_spacing1, line_spacing2, 1)); |
| |
| // Trim the first line's top leading. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[0].rect.top(), boxes[0].rect.top())); |
| // Trim the last line's bottom leading. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[2].rect.bottom(), boxes[2].rect.bottom())); |
| |
| const auto halfLeading = lineBoxes[0].rect.bottom() - boxes[0].rect.bottom(); |
| // Large epsilon because of rounding. |
| const auto epsilon = EPSILON10; |
| // line spacing is distributed evenly over and under the text. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top() - lineBoxes[1].rect.top(), halfLeading, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(lineBoxes[1].rect.bottom() - boxes[1].rect.bottom(), halfLeading)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top() - lineBoxes[2].rect.top(), halfLeading, epsilon)); |
| |
| // Half leading does not move the text horizontally. |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_LeftAlignParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_LeftAlignParagraph.png"); |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are nessecary. Very short. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum."; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kLeft); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(26); |
| text_style.setLetterSpacing(1); |
| text_style.setWordSpacing(5); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setHeight(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines()); |
| |
| double expected_y = 0; |
| double epsilon = 0.01f; |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon)); |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon)); |
| expected_y += 30 * 10; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon)); |
| |
| REPORTER_ASSERT(reporter, |
| paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign()); |
| |
| // Tests for GetGlyphPositionAtCoordinate() |
| REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0); |
| REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0); |
| REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68); |
| REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134); |
| REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_RightAlignParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_RightAlignParagraph.png"); |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are nessecary. Very short. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum."; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kRight); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(26); |
| text_style.setLetterSpacing(1); |
| text_style.setWordSpacing(5); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setHeight(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines()); |
| |
| double expected_y = 0; |
| double epsilon = 0.01f; |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon)); |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon)); |
| expected_y += 30 * 10; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon)); |
| |
| auto calculate = [](const TextLine& line) -> SkScalar { |
| return TestCanvasWidth - 100 - line.offset().fX - line.width(); |
| }; |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon)); |
| |
| REPORTER_ASSERT(reporter, |
| paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign()); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_CenterAlignParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_CenterAlignParagraph.png"); |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are nessecary. Very short. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum."; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kCenter); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(26); |
| text_style.setLetterSpacing(1); |
| text_style.setWordSpacing(5); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setHeight(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines()); |
| |
| double expected_y = 0; |
| double epsilon = 0.01f; |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon)); |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon)); |
| expected_y += 30 * 10; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon)); |
| |
| auto calculate = [](const TextLine& line) -> SkScalar { |
| return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width()); |
| }; |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon)); |
| |
| REPORTER_ASSERT(reporter, |
| paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign()); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_JustifyAlignParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png"); |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are nessecary. Very short. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat."; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kJustify); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(26); |
| text_style.setLetterSpacing(0); |
| text_style.setWordSpacing(5); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setHeight(1); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kMax; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| |
| double expected_y = 0; |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100)); |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100)); |
| expected_y += 30; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100)); |
| expected_y += 30 * 9; |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100)); |
| |
| auto calculate = [](const TextLine& line) -> SkScalar { |
| return line.offset().fX; |
| }; |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, |
| paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign()); |
| } |
| |
| // Checked: DIFF (ghost spaces as a separate box in TxtLib) |
| UNIX_ONLY_TEST(SkParagraph_JustifyRTL, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_JustifyRTL.png"); |
| const char* text = |
| "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ " |
| "אאאאאבּבּבּבּבּבּאאאאאבּבּבּבּבּבּאאאאאבּבּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּבּ"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kJustify); |
| paragraph_style.setTextDirection(TextDirection::kRtl); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Ahem")}); |
| text_style.setFontSize(26); |
| text_style.setColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| auto calculate = [](const TextLine& line) -> SkScalar { |
| return TestCanvasWidth - 100 - line.width(); |
| }; |
| for (auto& line : impl->lines()) { |
| if (&line == &impl->lines().back() || &line == &impl->lines()[impl->lines().size() - 2]) { |
| // Second-last line will be also right-aligned because it is only one cluster |
| REPORTER_ASSERT(reporter, calculate(line) > EPSILON100); |
| REPORTER_ASSERT(reporter, line.offset().fX > EPSILON100); |
| } else { |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100)); |
| } |
| } |
| |
| // Just make sure the the text is actually RTL |
| for (auto& run : impl->runs()) { |
| REPORTER_ASSERT(reporter, !run.leftToRight()); |
| } |
| |
| // Tests for GetRectsForRange() |
| RectHeightStyle rect_height_style = RectHeightStyle::kMax; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorRED, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 3); |
| |
| boxes = paragraph->getRectsForRange(226, 278, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorYELLOW, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 16, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100)); |
| |
| boxes = paragraph->getRectsForRange(292, 296, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorBLUE, boxes); |
| REPORTER_ASSERT(reporter, boxes.size() == 1); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 156, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 182, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_JustifyRTLNewLine, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png"); |
| const char* text = |
| "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kJustify); |
| paragraph_style.setTextDirection(TextDirection::kRtl); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Ahem")}); |
| text_style.setFontSize(26); |
| text_style.setColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| RectHeightStyle rect_height_style = RectHeightStyle::kMax; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| canvas.get()->drawRect(boxes[i].rect, paint); |
| } |
| REPORTER_ASSERT(reporter, boxes.size() == 2ull); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100)); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| canvas.get()->drawRect(boxes[i].rect, paint); |
| } |
| REPORTER_ASSERT(reporter, boxes.size() == 1ull); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100)); |
| |
| // All lines should be justified to the width of the paragraph |
| // except for #0 (new line) and #5 (the last one) |
| for (auto& line : impl->lines()) { |
| ptrdiff_t num = &line - impl->lines().data(); |
| if (num == 0 || num == 5) { |
| REPORTER_ASSERT(reporter, line.width() < TestCanvasWidth - 100); |
| } else { |
| REPORTER_ASSERT(reporter, |
| SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100), |
| "#%zd: %f <= %d\n", num, line.width(), TestCanvasWidth - 100); |
| } |
| } |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_LeadingSpaceRTL, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png"); |
| |
| const char* text = " leading space"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kJustify); |
| paragraph_style.setTextDirection(TextDirection::kRtl); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Ahem")}); |
| text_style.setFontSize(26); |
| text_style.setColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| RectHeightStyle rect_height_style = RectHeightStyle::kMax; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| canvas.get()->drawRect(boxes[i].rect, paint); |
| } |
| REPORTER_ASSERT(reporter, boxes.size() == 2ull); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_DecorationsParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_DecorationsParagraph.png"); |
| const char* text1 = "This text should be"; |
| const char* text2 = " decorated even when"; |
| const char* text3 = " wrapped around to"; |
| const char* text4 = " the next line."; |
| const char* text5 = " Otherwise, bad things happen."; |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kLeft); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(26); |
| text_style.setLetterSpacing(0); |
| text_style.setWordSpacing(5); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setHeight(2); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| text_style.setDecoration((TextDecoration)( |
| TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough)); |
| text_style.setDecorationStyle(TextDecorationStyle::kSolid); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| text_style.setDecorationThicknessMultiplier(2.0); |
| builder.pushStyle(text_style); |
| builder.addText(text1, strlen(text1)); |
| |
| text_style.setDecorationStyle(TextDecorationStyle::kDouble); |
| text_style.setDecorationColor(SK_ColorBLUE); |
| text_style.setDecorationThicknessMultiplier(1.0); |
| builder.pushStyle(text_style); |
| builder.addText(text2, strlen(text2)); |
| |
| text_style.setDecorationStyle(TextDecorationStyle::kDotted); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text3, strlen(text3)); |
| |
| text_style.setDecorationStyle(TextDecorationStyle::kDashed); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| text_style.setDecorationThicknessMultiplier(3.0); |
| builder.pushStyle(text_style); |
| builder.addText(text4, strlen(text4)); |
| |
| text_style.setDecorationStyle(TextDecorationStyle::kWavy); |
| text_style.setDecorationColor(SK_ColorRED); |
| text_style.setDecorationThicknessMultiplier(1.0); |
| builder.pushStyle(text_style); |
| builder.addText(text5, strlen(text5)); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| size_t index = 0; |
| for (auto& line : impl->lines()) { |
| line.scanStyles( |
| StyleType::kDecorations, |
| [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| auto decoration = (TextDecoration)(TextDecoration::kUnderline | |
| TextDecoration::kOverline | |
| TextDecoration::kLineThrough); |
| REPORTER_ASSERT(reporter, style.getDecorationType() == decoration); |
| switch (index) { |
| case 0: |
| REPORTER_ASSERT(reporter, style.getDecorationStyle() == |
| TextDecorationStyle::kSolid); |
| REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK); |
| REPORTER_ASSERT(reporter, |
| style.getDecorationThicknessMultiplier() == 2.0); |
| break; |
| case 1: // The style appears on 2 lines so it has 2 pieces |
| REPORTER_ASSERT(reporter, style.getDecorationStyle() == |
| TextDecorationStyle::kDouble); |
| REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE); |
| REPORTER_ASSERT(reporter, |
| style.getDecorationThicknessMultiplier() == 1.0); |
| break; |
| case 2: |
| REPORTER_ASSERT(reporter, style.getDecorationStyle() == |
| TextDecorationStyle::kDotted); |
| REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK); |
| REPORTER_ASSERT(reporter, |
| style.getDecorationThicknessMultiplier() == 1.0); |
| break; |
| case 3: |
| case 4: |
| REPORTER_ASSERT(reporter, style.getDecorationStyle() == |
| TextDecorationStyle::kDashed); |
| REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK); |
| REPORTER_ASSERT(reporter, |
| style.getDecorationThicknessMultiplier() == 3.0); |
| break; |
| case 5: |
| REPORTER_ASSERT(reporter, style.getDecorationStyle() == |
| TextDecorationStyle::kWavy); |
| REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED); |
| REPORTER_ASSERT(reporter, |
| style.getDecorationThicknessMultiplier() == 1.0); |
| break; |
| default: |
| REPORTER_ASSERT(reporter, false); |
| break; |
| } |
| ++index; |
| return true; |
| }); |
| } |
| } |
| |
| // TODO: Add test for wavy decorations. |
| |
| UNIX_ONLY_TEST(SkParagraph_ItalicsParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_ItalicsParagraph.png"); |
| const char* text1 = "No italic "; |
| const char* text2 = "Yes Italic "; |
| const char* text3 = "No Italic again."; |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(10); |
| text_style.setColor(SK_ColorRED); |
| builder.pushStyle(text_style); |
| builder.addText(text1, strlen(text1)); |
| |
| text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kItalic_Slant)); |
| builder.pushStyle(text_style); |
| builder.addText(text2, strlen(text2)); |
| builder.pop(); |
| builder.addText(text3, strlen(text3)); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->runs().size() == 3); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 3); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 1); |
| auto& line = impl->lines()[0]; |
| size_t index = 0; |
| line.scanStyles( |
| StyleType::kForeground, |
| [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| switch (index) { |
| case 0: |
| REPORTER_ASSERT( |
| reporter, |
| style.getFontStyle().slant() == SkFontStyle::kUpright_Slant); |
| break; |
| case 1: |
| REPORTER_ASSERT(reporter, |
| style.getFontStyle().slant() == SkFontStyle::kItalic_Slant); |
| break; |
| case 2: |
| REPORTER_ASSERT( |
| reporter, |
| style.getFontStyle().slant() == SkFontStyle::kUpright_Slant); |
| break; |
| default: |
| REPORTER_ASSERT(reporter, false); |
| break; |
| } |
| ++index; |
| return true; |
| }); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_ChineseParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_ChineseParagraph.png"); |
| const char* text = |
| " 左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育" |
| "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭" |
| "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探" |
| "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦" |
| "聞条年所在口。"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kJustify); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline | |
| TextDecoration::kLineThrough); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Source Han Serif CN")}); |
| text_style.setFontSize(35); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setLetterSpacing(2); |
| text_style.setHeight(1); |
| text_style.setDecoration(decoration); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| text_style.setDecorationStyle(TextDecorationStyle::kSolid); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 7); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| } |
| |
| // Checked: disabled for TxtLib |
| UNIX_ONLY_TEST(SkParagraph_ArabicParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_ArabicParagraph.png"); |
| const char* text = |
| "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة " |
| "بمباركة التقليدية قام عن. تصفح"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kJustify); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline | |
| TextDecoration::kLineThrough); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Katibeh")}); |
| text_style.setFontSize(35); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setLetterSpacing(2); |
| text_style.setDecoration(decoration); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| text_style.setDecorationStyle(TextDecorationStyle::kSolid); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 2); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| } |
| |
| // Checked: DIFF (2 boxes and each space is a word) |
| UNIX_ONLY_TEST(SkParagraph_ArabicRectsParagraph, reporter) { |
| |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png"); |
| const char* text = "بمباركة التقليدية قام عن. تصفح يد "; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kRight); |
| paragraph_style.setTextDirection(TextDirection::kRtl); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Noto Naskh Arabic")}); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kMax; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 1ull); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.120f, EPSILON100)); // DIFF: 510.09375 |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.280f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100)); |
| } |
| |
| // Checked DIFF+ |
| // This test shows now 2 boxes for [36:40) range: |
| // [36:38) for arabic text and [38:39) for the last space |
| // that has default paragraph direction (LTR) and is placed at the end of the paragraph |
| UNIX_ONLY_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) { |
| |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png"); |
| const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد "; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kLeft); |
| paragraph_style.setTextDirection(TextDirection::kLtr); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Noto Naskh Arabic")}); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 3); |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kMax; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| // There are 39 codepoints: [0:39); asking for [36:40) would give the same as for [36:39) |
| std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 2ull); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 65.65f, EPSILON100)); // DIFF: 89.40625 |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 86.89f, EPSILON100)); // DIFF: 121.87891 |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.0f, EPSILON100)); |
| } |
| |
| // Checked DIFF+ |
| UNIX_ONLY_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) { |
| |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png"); |
| const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد "; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| paragraph_style.setMaxLines(14); |
| paragraph_style.setTextAlign(TextAlign::kRight); |
| paragraph_style.setTextDirection(TextDirection::kLtr); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Noto Naskh Arabic")}); |
| text_style.setFontSize(26); |
| text_style.setWordSpacing(5); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setDecoration(TextDecoration::kUnderline); |
| text_style.setDecorationColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 3); |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle rect_height_style = RectHeightStyle::kMax; |
| RectWidthStyle rect_width_style = RectWidthStyle::kTight; |
| std::vector<TextBox> boxes = |
| paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style); |
| canvas.drawRects(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.1f, EPSILON100)); // DIFF |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 582.34f, EPSILON100)); // DIFF |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png"); |
| const char* text = |
| "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 " |
| "67890 12345"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kLeft); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| textStyle.setFontSize(50); |
| textStyle.setLetterSpacing(1); |
| textStyle.setWordSpacing(5); |
| textStyle.setHeight(1); |
| textStyle.setColor(SK_ColorBLACK); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| // Tests for getGlyphPositionAtCoordinate() |
| // NOTE: resulting values can be a few off from their respective positions in |
| // the original text because the final trailing whitespaces are sometimes not |
| // drawn (namely, when using "justify" alignment) and therefore are not active |
| // glyphs. |
| REPORTER_ASSERT(reporter, |
| paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1); |
| REPORTER_ASSERT(reporter, |
| paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18); |
| REPORTER_ASSERT(reporter, |
| paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77); |
| REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png"); |
| const char* text = |
| "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 " |
| "67890 12345"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kLeft); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(50); |
| textStyle.setColor(SK_ColorBLACK); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle heightStyle = RectHeightStyle::kMax; |
| RectWidthStyle widthStyle = RectWidthStyle::kTight; |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| { |
| auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorGREEN, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 4); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeTight, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png"); |
| const char* text = |
| "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)"; |
| const size_t len = strlen(text); |
| /* |
| ( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`) |
| S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S |
| G G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GG |
| W W W W W W W W W W W W W W W W W W W W |
| |
| */ |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kLeft); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Noto Sans CJK JP")}); |
| textStyle.setFontSize(50); |
| textStyle.setColor(SK_ColorBLACK); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle heightStyle = RectHeightStyle::kTight; |
| RectWidthStyle widthStyle = RectWidthStyle::kTight; |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| { |
| auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorGREEN, result); |
| REPORTER_ASSERT(reporter, result.size() == 2); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100)); |
| } |
| } |
| |
| // Checked: DIFF+ |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png"); |
| const char* text = |
| "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kLeft); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(50); |
| textStyle.setHeight(1.6f); |
| textStyle.setHeightOverride(true); |
| textStyle.setColor(SK_ColorBLACK); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle; |
| RectWidthStyle widthStyle = RectWidthStyle::kMax; |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorGREEN, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 8); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 2); // DIFF |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| } |
| |
| // Checked: NO DIFF+ |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png"); |
| const char* text = |
| "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kLeft); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(50); |
| textStyle.setHeight(1.6f); |
| textStyle.setHeightOverride(true); |
| textStyle.setColor(SK_ColorBLACK); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop; |
| RectWidthStyle widthStyle = RectWidthStyle::kMax; |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorGREEN, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorMAGENTA, result); |
| REPORTER_ASSERT(reporter, result.size() == 8); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLACK, result); |
| REPORTER_ASSERT(reporter, result.size() == 2); // DIFF |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| } |
| |
| // Checked: NO DIFF+ |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png"); |
| const char* text = |
| "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kLeft); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(50); |
| textStyle.setHeight(1.6f); |
| textStyle.setHeightOverride(true); |
| textStyle.setColor(SK_ColorBLACK); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom; |
| RectWidthStyle widthStyle = RectWidthStyle::kMax; |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorGREEN, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorMAGENTA, result); |
| REPORTER_ASSERT(reporter, result.size() == 8); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLACK, result); |
| REPORTER_ASSERT(reporter, result.size() == 2); // DIFF |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100)); |
| |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| } |
| |
| // This is the test I cannot accommodate |
| // Any text range gets a smallest glyph rectangle |
| DEF_TEST_DISABLED(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png"); |
| const char* text = "ดีสวัสดีชาวโลกที่น่ารัก"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kLeft); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(50); |
| textStyle.setLetterSpacing(1); |
| textStyle.setWordSpacing(5); |
| textStyle.setHeight(1); |
| textStyle.setColor(SK_ColorBLACK); |
| |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth - 100); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 1); |
| |
| RectHeightStyle heightStyle = RectHeightStyle::kTight; |
| RectWidthStyle widthStyle = RectWidthStyle::kTight; |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| { |
| auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle); |
| auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1); |
| REPORTER_ASSERT(reporter, second[0].rect == last[0].rect); |
| } |
| { |
| auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle); |
| auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle); |
| auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1); |
| REPORTER_ASSERT(reporter, second[0].rect == last[0].rect); |
| } |
| { |
| auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle); |
| auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle); |
| auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle); |
| auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1); |
| REPORTER_ASSERT(reporter, third[0].rect == last[0].rect); |
| } |
| } |
| |
| // Checked: NO DIFF |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png"); |
| // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces. |
| // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme. |
| // Any attempt to substitute one for another leads to errors |
| // (for instance, some fonts can use these hard coded characters for something that is visible) |
| const char* text = "01234 "; // includes ideographic space and english space. |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kCenter); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(50); |
| textStyle.setHeight(1); |
| textStyle.setColor(SK_ColorBLACK); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| // Some of the formatting lazily done on paint |
| RectHeightStyle heightStyle = RectHeightStyle::kMax; |
| RectWidthStyle widthStyle = RectWidthStyle::kTight; |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorGREEN, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLACK, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); // DIFF |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| } |
| |
| // Checked DIFF+ |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png"); |
| const char* text = "01234\n"; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kCenter); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(50); |
| textStyle.setHeight(1); |
| textStyle.setColor(SK_ColorBLACK); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 2); |
| |
| RectHeightStyle heightStyle = RectHeightStyle::kMax; |
| RectWidthStyle widthStyle = RectWidthStyle::kTight; |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100)); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100)); |
| } |
| } |
| |
| // Checked NO DIFF |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png"); |
| const char* text = "01234 \n0123 "; // includes ideographic space and english space. |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kCenter); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(50); |
| textStyle.setHeight(1); |
| textStyle.setColor(SK_ColorBLACK); |
| textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, |
| SkFontStyle::kUpright_Slant)); |
| |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| REPORTER_ASSERT(reporter, impl->lines().size() == 2); |
| |
| RectHeightStyle heightStyle = RectHeightStyle::kMax; |
| RectWidthStyle widthStyle = RectWidthStyle::kTight; |
| SkScalar epsilon = 0.01f; |
| { |
| auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| { |
| auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLUE, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorGREEN, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorYELLOW, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorCYAN, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle); |
| canvas.drawRects(SK_ColorBLACK, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon)); |
| } |
| { |
| auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle); |
| REPORTER_ASSERT(reporter, result.empty()); |
| } |
| } |
| |
| // Checked: DIFF (line height rounding error) |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeStrut, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png"); |
| const char* text = "Chinese 字典"; |
| const size_t len = strlen(text); |
| |
| StrutStyle strutStyle; |
| strutStyle.setStrutEnabled(true); |
| strutStyle.setFontFamilies({SkString("Roboto")}); |
| strutStyle.setFontSize(14.0); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setStrutStyle(strutStyle); |
| |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Noto Sans CJK JP")}); |
| textStyle.setFontSize(20); |
| textStyle.setColor(SK_ColorBLACK); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| { |
| auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax); |
| canvas.drawRects(SK_ColorGREEN, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| } |
| |
| { |
| auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax); |
| canvas.drawRects(SK_ColorRED, result); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2)); |
| } |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeStrutWithHeight, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| const char* text = "A"; |
| const size_t len = strlen(text); |
| |
| StrutStyle strutStyle; |
| strutStyle.setStrutEnabled(true); |
| strutStyle.setFontFamilies({SkString("Roboto")}); |
| strutStyle.setFontSize(14.0); |
| strutStyle.setHeightOverride(true); |
| strutStyle.setHeight(2.0); |
| strutStyle.setLeading(3.0); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setStrutStyle(strutStyle); |
| |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(10); |
| textStyle.setColor(SK_ColorBLACK); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| |
| auto result = paragraph->getRectsForRange(0, 1, RectHeightStyle::kStrut, RectWidthStyle::kMax); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| // Half of the strut leading: 3.0 * 14.0 / 2 |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 21.0, EPSILON100)); |
| // Strut height 2.0 * 14.0 |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.height(), 28.0, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeStrutWithHeightAndHalfLeading, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| const char* text = "A"; |
| const size_t len = strlen(text); |
| |
| StrutStyle strutStyle; |
| strutStyle.setStrutEnabled(true); |
| strutStyle.setFontFamilies({SkString("Roboto")}); |
| strutStyle.setFontSize(14.0); |
| strutStyle.setHeightOverride(true); |
| strutStyle.setHeight(2.0); |
| strutStyle.setLeading(3.0); |
| strutStyle.setHalfLeading(true); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setStrutStyle(strutStyle); |
| |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(10); |
| textStyle.setColor(SK_ColorBLACK); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| |
| // Produces the same results as halfLeading = false. |
| auto result = paragraph->getRectsForRange(0, 1, RectHeightStyle::kStrut, RectWidthStyle::kMax); |
| REPORTER_ASSERT(reporter, result.size() == 1); |
| // Half of the strut leading: 3.0 * 14.0 / 2 |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 21.0, EPSILON100)); |
| // Strut height 2.0 * 14.0 |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.height(), 28.0, EPSILON100)); |
| } |
| |
| UNIX_ONLY_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png"); |
| const char* text = "Chinese 字典"; |
| const size_t len = strlen(text); |
| |
| StrutStyle strutStyle; |
| strutStyle.setStrutEnabled(false); |
| |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setStrutStyle(strutStyle); |
| |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Noto Sans CJK JP")}); |
| textStyle.setFontSize(20); |
| textStyle.setColor(SK_ColorBLACK); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| |
| auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax); |
| canvas.drawRects(SK_ColorGREEN, result1); |
| REPORTER_ASSERT(reporter, result1.size() == 1); |
| |
| auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax); |
| canvas.drawRects(SK_ColorRED, result2); |
| REPORTER_ASSERT(reporter, result2.size() == 1); |
| |
| REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect); |
| } |
| |
| // Checked: DIFF (small in numbers) |
| UNIX_ONLY_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png"); |
| const char* text = "12345 67890 12345 67890 12345 67890 12345 " |
| "67890 12345 67890 12345 67890 12345"; |
| const size_t len = strlen(text); |
| ParagraphStyle paragraphStyle; |
| paragraphStyle.setTextAlign(TextAlign::kLeft); |
| paragraphStyle.setMaxLines(10); |
| paragraphStyle.turnHintingOff(); |
| TextStyle textStyle; |
| textStyle.setFontFamilies({SkString("Roboto")}); |
| textStyle.setFontSize(52); |
| textStyle.setLetterSpacing(1.19039f); |
| textStyle.setWordSpacing(5); |
| textStyle.setHeight(1.5); |
| textStyle.setHeightOverride(true); |
| textStyle.setColor(SK_ColorBLACK); |
| |
| ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode()); |
| builder.pushStyle(textStyle); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5)); |
| auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7)); |
| boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7)); |
| boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18)); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31)); |
| |
| boxes = paragraph->getRectsForRange(12, 13, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| boxes = paragraph->getRectsForRange(13, 14, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| boxes = paragraph->getRectsForRange(19, 20, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| boxes = paragraph->getRectsForRange(24, 25, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| boxes = paragraph->getRectsForRange(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight); |
| canvas.drawLines(SK_ColorRED, boxes); |
| |
| auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size(); |
| REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen)); |
| } |
| |
| // Checked: DIFF (unclear) |
| UNIX_ONLY_TEST(SkParagraph_SpacingParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_SpacingParagraph.png"); |
| ParagraphStyle paragraph_style; |
| paragraph_style.setMaxLines(10); |
| paragraph_style.setTextAlign(TextAlign::kLeft); |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setFontSize(50); |
| text_style.setLetterSpacing(20); |
| text_style.setWordSpacing(0); |
| text_style.setColor(SK_ColorBLACK); |
| builder.pushStyle(text_style); |
| builder.addText("H", 1); |
| builder.pop(); |
| |
| text_style.setLetterSpacing(10); |
| text_style.setWordSpacing(0); |
| builder.pushStyle(text_style); |
| builder.addText("H", 1); |
| builder.pop(); |
| |
| text_style.setLetterSpacing(20); |
| text_style.setWordSpacing(0); |
| builder.pushStyle(text_style); |
| builder.addText("H", 1); |
| builder.pop(); |
| |
| text_style.setLetterSpacing(0); |
| text_style.setWordSpacing(0); |
| builder.pushStyle(text_style); |
| builder.addText("|", 1); |
| builder.pop(); |
| |
| const char* hSpace = "H "; |
| const size_t len = strlen(hSpace); |
| |
| text_style.setLetterSpacing(0); |
| text_style.setWordSpacing(20); |
| builder.pushStyle(text_style); |
| builder.addText(hSpace, len); |
| builder.pop(); |
| |
| text_style.setLetterSpacing(0); |
| text_style.setWordSpacing(0); |
| builder.pushStyle(text_style); |
| builder.addText(hSpace, len); |
| builder.pop(); |
| |
| text_style.setLetterSpacing(0); |
| text_style.setLetterSpacing(0); |
| text_style.setWordSpacing(20); |
| builder.pushStyle(text_style); |
| builder.addText(hSpace, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(550); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 1); |
| size_t index = 0; |
| impl->lines().begin()->scanStyles(StyleType::kLetterSpacing, |
| [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| ++index; |
| return true; |
| }); |
| REPORTER_ASSERT(reporter, index == 4); |
| index = 0; |
| impl->lines().begin()->scanStyles(StyleType::kWordSpacing, |
| [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) { |
| ++index; |
| return true; |
| }); |
| REPORTER_ASSERT(reporter, index == 4); |
| } |
| |
| // Checked: NO DIFF |
| UNIX_ONLY_TEST(SkParagraph_LongWordParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_LongWordParagraph.png"); |
| const char* text = |
| "A " |
| "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat" |
| "wouldbeagoodthingbecausethebreakingisworking."; |
| const size_t len = strlen(text); |
| |
| ParagraphStyle paragraph_style; |
| paragraph_style.turnHintingOff(); |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Roboto")}); |
| text_style.setColor(SK_ColorRED); |
| text_style.setFontSize(31); |
| text_style.setLetterSpacing(0); |
| text_style.setWordSpacing(0); |
| text_style.setColor(SK_ColorBLACK); |
| text_style.setHeight(1); |
| builder.pushStyle(text_style); |
| builder.addText(text, len); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth / 2); |
| paragraph->paint(canvas.get(), 0, 0); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length()); |
| REPORTER_ASSERT(reporter, impl->runs().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles().size() == 1); |
| REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style)); |
| REPORTER_ASSERT(reporter, impl->lines().size() == 4); |
| |
| REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20); |
| REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20); |
| REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20); |
| } |
| |
| // Checked: DIFF? |
| UNIX_ONLY_TEST(SkParagraph_KernScaleParagraph, reporter) { |
| sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(); |
| SKIP_IF_FONTS_NOT_FOUND(reporter, fontCollection) |
| TestCanvas canvas("SkParagraph_KernScaleParagraph.png"); |
| |
| const char* text1 = "AVAVAWAH A0 V0 VA To The Lo"; |
| const char* text2 = " Dialog Text List lots of words to see " |
| "if kerning works on a bigger set of characters AVAVAW"; |
| float scale = 3.0f; |
| ParagraphStyle paragraph_style; |
| ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode()); |
| TextStyle text_style; |
| text_style.setFontFamilies({SkString("Droid Serif")}); |
| text_style.setFontSize(100 / scale); |
| text_style.setColor(SK_ColorBLACK); |
| |
| builder.pushStyle(text_style); |
| builder.addText(text1, strlen(text1)); |
| builder.pushStyle(text_style); |
| builder.addText("A", 1); |
| builder.pushStyle(text_style); |
| builder.addText("V", 1); |
| text_style.setFontSize(14 / scale); |
| builder.pushStyle(text_style); |
| builder.addText(text2, strlen(text2)); |
| builder.pop(); |
| |
| auto paragraph = builder.Build(); |
| paragraph->layout(TestCanvasWidth / scale); |
| canvas.get()->scale(scale, scale); |
| paragraph->paint(canvas.get(), 0, 0); |
| canvas.get()->scale(1, 1); |
| |
| auto impl = static_cast<ParagraphImpl*>(paragraph.get()); |
| |
| // First and second lines must have the same width, the third one must be bigger |
| REPORTER_ASSERT(reporter, impl->lines().size() == 3); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100)); |
| REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100)); |
| } |
| |
| // Checked: DIFF+ |
| UNIX_ONLY_TEST(SkParagraph_NewlineParagraph, reporter) { |
|