621 lines
29 KiB
C++
621 lines
29 KiB
C++
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "minikin/MeasuredText.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "minikin/LineBreaker.h"
|
|
#include "minikin/Measurement.h"
|
|
|
|
#include "FontTestUtils.h"
|
|
#include "UnicodeUtils.h"
|
|
|
|
namespace minikin {
|
|
|
|
constexpr float CHAR_WIDTH = 10.0; // Mock implementation always returns 10.0 for advance.
|
|
|
|
TEST(MeasuredTextTest, RunTests) {
|
|
constexpr uint32_t CHAR_COUNT = 6;
|
|
constexpr float REPLACEMENT_WIDTH = 20.0f;
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
|
|
MinikinPaint paint1(font);
|
|
paint1.size = 10.0f; // make 1em = 10px
|
|
builder.addStyleRun(0, 2, std::move(paint1), lbStyle, lbWordStyle, false /* is RTL */);
|
|
builder.addReplacementRun(2, 4, REPLACEMENT_WIDTH, 0 /* locale list id */);
|
|
MinikinPaint paint2(font);
|
|
paint2.size = 10.0f; // make 1em = 10px
|
|
builder.addStyleRun(4, 6, std::move(paint2), lbStyle, lbWordStyle, false /* is RTL */);
|
|
|
|
std::vector<uint16_t> text(CHAR_COUNT, 'a');
|
|
|
|
std::unique_ptr<MeasuredText> measuredText =
|
|
builder.build(text, true /* compute hyphenation */, false /* compute full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
ASSERT_TRUE(measuredText);
|
|
|
|
// ReplacementRun assigns all width to the first character and leave zeros others.
|
|
std::vector<float> expectedWidths = {CHAR_WIDTH, CHAR_WIDTH, REPLACEMENT_WIDTH,
|
|
0, CHAR_WIDTH, CHAR_WIDTH};
|
|
|
|
EXPECT_EQ(expectedWidths, measuredText->widths);
|
|
}
|
|
|
|
TEST(MeasuredTextTest, getBoundsTest) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(0, 0)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(1, 2)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 130.0f, 0.0f), mt->getBounds(text, Range(0, text.size())));
|
|
}
|
|
|
|
TEST(MeasuredTextTest, getBoundsTest_LTR) {
|
|
auto text = utf8ToUtf16("\u0028"); // U+0028 has 1em in LTR, 3em in RTL.
|
|
auto font = buildFontCollection("Bbox.ttf");
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
|
|
}
|
|
|
|
TEST(MeasuredTextTest, getBoundsTest_RTL) {
|
|
auto text = utf8ToUtf16("\u0028"); // U+0028 has 1em in LTR, 3em in RTL.
|
|
auto font = buildFontCollection("Bbox.ttf");
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, true /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
|
|
}
|
|
|
|
TEST(MeasuredTextTest, getBoundsTest_multiStyle) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
uint32_t helloLength = 7; // length of "Hello, "
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, helloLength, std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
MinikinPaint paint2(font);
|
|
paint2.size = 20.0f;
|
|
builder.addStyleRun(helloLength, text.size(), std::move(paint2), lbStyle, lbWordStyle,
|
|
false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(0, 0)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(1, 2)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(7, 7)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), mt->getBounds(text, Range(7, 8)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 30.0f, 0.0f), mt->getBounds(text, Range(6, 8)));
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 190.0f, 0.0f), mt->getBounds(text, Range(0, text.size())));
|
|
}
|
|
|
|
TEST(MeasuredTextTest, getExtentTest) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kernign */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(0, 0)));
|
|
EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 1)));
|
|
EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 2)));
|
|
EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(1, 2)));
|
|
EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, text.size())));
|
|
}
|
|
|
|
TEST(MeasuredTextTest, getExtentTest_multiStyle) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
uint32_t helloLength = 7; // length of "Hello, "
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, helloLength, std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
MinikinPaint paint2(font);
|
|
paint2.size = 20.0f;
|
|
builder.addStyleRun(helloLength, text.size(), std::move(paint2), 0 /* no line break */,
|
|
0 /* no line break word style */, false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(0, 0)));
|
|
EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 1)));
|
|
EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 2)));
|
|
EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(1, 2)));
|
|
EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(7, 7)));
|
|
EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(7, 8)));
|
|
EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(6, 8)));
|
|
EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(0, text.size())));
|
|
}
|
|
|
|
TEST(MeasuredTextTest, buildLayoutTest) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
Range fullContext(0, text.size());
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
MinikinRect rect;
|
|
MinikinPaint samePaint(font);
|
|
samePaint.size = 10.0f;
|
|
|
|
Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, samePaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
EXPECT_EQ(0u, layout.nGlyphs());
|
|
|
|
layout = mt->buildLayout(text, Range(0, 1), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(10.0f, layout.getAdvance());
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(0, 1), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(0, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(2u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(10.0f, layout.getX(1));
|
|
EXPECT_EQ(0.0f, layout.getY(1));
|
|
EXPECT_EQ(20.0f, layout.getAdvance());
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(1));
|
|
EXPECT_EQ(2u, layout.getAdvances().size());
|
|
getBounds(text, Range(0, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(1, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(10.0f, layout.getAdvance());
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(1, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(0, text.size()), fullContext, samePaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(text.size(), layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
for (uint32_t i = 0; i < text.size(); ++i) {
|
|
EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
|
|
EXPECT_EQ(10.0f * i, layout.getX(i)) << i;
|
|
EXPECT_EQ(0.0f, layout.getY(i)) << i;
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(i)) << i;
|
|
}
|
|
EXPECT_EQ(130.0f, layout.getAdvance());
|
|
EXPECT_EQ(text.size(), layout.getAdvances().size());
|
|
getBounds(text, Range(0, text.size()), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 130.0f, 0.0f), rect);
|
|
}
|
|
|
|
TEST(MeasuredTextTest, buildLayoutTest_multiStyle) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
uint32_t helloLength = 7; // length of "Hello, "
|
|
Range fullContext(0, text.size());
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, helloLength, std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
MinikinPaint paint2(font);
|
|
paint2.size = 20.0f;
|
|
builder.addStyleRun(helloLength, text.size(), std::move(paint2), lbStyle, lbWordStyle,
|
|
false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
MinikinRect rect;
|
|
MinikinPaint samePaint(font);
|
|
samePaint.size = 10.0f;
|
|
|
|
Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, samePaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
EXPECT_EQ(0u, layout.nGlyphs());
|
|
|
|
layout = mt->buildLayout(text, Range(0, 1), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(10.0f, layout.getAdvance());
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(0, 1), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(0, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(2u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(10.0f, layout.getX(1));
|
|
EXPECT_EQ(0.0f, layout.getY(1));
|
|
EXPECT_EQ(20.0f, layout.getAdvance());
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(1));
|
|
EXPECT_EQ(2u, layout.getAdvances().size());
|
|
getBounds(text, Range(0, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(1, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(10.0f, layout.getAdvance());
|
|
EXPECT_EQ(10.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(1, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(7, 7), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT);
|
|
EXPECT_EQ(0u, layout.nGlyphs());
|
|
|
|
MinikinPaint samePaint2(font);
|
|
samePaint2.size = 20.0f;
|
|
layout = mt->buildLayout(text, Range(7, 8), fullContext, samePaint2, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(20.0f, layout.getAdvance());
|
|
EXPECT_EQ(20.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(7, 8), Bidi::LTR, samePaint2, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
|
|
}
|
|
|
|
TEST(MeasuredTextTest, buildLayoutTest_differentPaint) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
Range fullContext(0, text.size());
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
MinikinRect rect;
|
|
MinikinPaint differentPaint(font);
|
|
differentPaint.size = 20.0f;
|
|
|
|
Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
EXPECT_EQ(0u, layout.nGlyphs());
|
|
|
|
layout = mt->buildLayout(text, Range(0, 1), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(20.0f, layout.getAdvance());
|
|
EXPECT_EQ(20.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(0, 1), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(0, 2), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(2u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(20.0f, layout.getX(1));
|
|
EXPECT_EQ(0.0f, layout.getY(1));
|
|
EXPECT_EQ(40.0f, layout.getAdvance());
|
|
EXPECT_EQ(20.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(20.0f, layout.getCharAdvance(1));
|
|
EXPECT_EQ(2u, layout.getAdvances().size());
|
|
getBounds(text, Range(0, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 20.0f, 40.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(1, 2), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(20.0f, layout.getAdvance());
|
|
EXPECT_EQ(20.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(1, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(0, text.size()), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(text.size(), layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
for (uint32_t i = 0; i < text.size(); ++i) {
|
|
EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
|
|
EXPECT_EQ(20.0f * i, layout.getX(i)) << i;
|
|
EXPECT_EQ(0.0f, layout.getY(i)) << i;
|
|
EXPECT_EQ(20.0f, layout.getCharAdvance(i)) << i;
|
|
}
|
|
EXPECT_EQ(260.0f, layout.getAdvance());
|
|
EXPECT_EQ(text.size(), layout.getAdvances().size());
|
|
getBounds(text, Range(0, text.size()), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 20.0f, 260.0f, 0.0f), rect);
|
|
}
|
|
|
|
TEST(MeasuredTextTest, buildLayoutTest_multiStyle_differentPaint) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
uint32_t helloLength = 7; // length of "Hello, "
|
|
Range fullContext(0, text.size());
|
|
int lbStyle = (int)LineBreakStyle::None;
|
|
int lbWordStyle = (int)LineBreakWordStyle::None;
|
|
|
|
MeasuredTextBuilder builder;
|
|
MinikinPaint paint(font);
|
|
paint.size = 10.0f;
|
|
builder.addStyleRun(0, helloLength, std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
|
|
MinikinPaint paint2(font);
|
|
paint2.size = 20.0f;
|
|
builder.addStyleRun(helloLength, text.size(), std::move(paint2), lbStyle, lbWordStyle,
|
|
false /* is RTL */);
|
|
auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
MinikinRect rect;
|
|
MinikinPaint differentPaint(font);
|
|
differentPaint.size = 30.0f;
|
|
|
|
Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
EXPECT_EQ(0u, layout.nGlyphs());
|
|
|
|
layout = mt->buildLayout(text, Range(0, 1), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(30.0f, layout.getAdvance());
|
|
EXPECT_EQ(30.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(0, 1), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(0, 2), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(2u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(30.0f, layout.getX(1));
|
|
EXPECT_EQ(0.0f, layout.getY(1));
|
|
EXPECT_EQ(60.0f, layout.getAdvance());
|
|
EXPECT_EQ(30.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(30.0f, layout.getCharAdvance(1));
|
|
EXPECT_EQ(2u, layout.getAdvances().size());
|
|
getBounds(text, Range(0, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 30.0f, 60.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(1, 2), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(30.0f, layout.getAdvance());
|
|
EXPECT_EQ(30.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(1, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(7, 7), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
EXPECT_EQ(0u, layout.nGlyphs());
|
|
|
|
layout = mt->buildLayout(text, Range(7, 8), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(1u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(30.0f, layout.getAdvance());
|
|
EXPECT_EQ(30.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(1u, layout.getAdvances().size());
|
|
getBounds(text, Range(7, 8), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(6, 8), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(2u, layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
|
|
EXPECT_EQ(0.0f, layout.getX(0));
|
|
EXPECT_EQ(0.0f, layout.getY(0));
|
|
EXPECT_EQ(30.0f, layout.getX(1));
|
|
EXPECT_EQ(0.0f, layout.getY(1));
|
|
EXPECT_EQ(60.0f, layout.getAdvance());
|
|
EXPECT_EQ(30.0f, layout.getCharAdvance(0));
|
|
EXPECT_EQ(30.0f, layout.getCharAdvance(1));
|
|
EXPECT_EQ(2u, layout.getAdvances().size());
|
|
getBounds(text, Range(6, 8), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 30.0f, 60.0f, 0.0f), rect);
|
|
|
|
layout = mt->buildLayout(text, Range(0, text.size()), fullContext, differentPaint,
|
|
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
|
|
ASSERT_EQ(text.size(), layout.nGlyphs());
|
|
EXPECT_TRUE(layout.getFont(0));
|
|
for (uint32_t i = 0; i < text.size(); ++i) {
|
|
EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
|
|
EXPECT_EQ(30.0f * i, layout.getX(i)) << i;
|
|
EXPECT_EQ(0.0f, layout.getY(i)) << i;
|
|
EXPECT_EQ(30.0f, layout.getCharAdvance(i)) << i;
|
|
}
|
|
EXPECT_EQ(390.0f, layout.getAdvance());
|
|
EXPECT_EQ(text.size(), layout.getAdvances().size());
|
|
getBounds(text, Range(0, text.size()), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
|
|
EndHyphenEdit::NO_EDIT, &rect);
|
|
EXPECT_EQ(MinikinRect(0.0f, 30.0f, 390.0f, 0.0f), rect);
|
|
}
|
|
|
|
TEST(MeasuredTextTest, testLineBreakStyle_from_builder) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
int lbStyle = (int)LineBreakStyle::Loose; // loose
|
|
int lbWordStyle = (int)LineBreakWordStyle::Phrase; // phrase
|
|
|
|
MeasuredTextBuilder looseStyleBuilder;
|
|
MinikinPaint paint(font);
|
|
looseStyleBuilder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false);
|
|
auto mt = looseStyleBuilder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ((size_t)1, mt->runs.size());
|
|
EXPECT_EQ(LineBreakStyle::Loose, mt->runs[0]->lineBreakStyle());
|
|
EXPECT_EQ(LineBreakWordStyle::Phrase, mt->runs[0]->lineBreakWordStyle());
|
|
|
|
lbStyle = (int)LineBreakStyle::Normal; // normal
|
|
MeasuredTextBuilder normalStyleBuilder;
|
|
MinikinPaint normalStylePaint(font);
|
|
normalStyleBuilder.addStyleRun(0, text.size(), std::move(normalStylePaint), lbStyle,
|
|
lbWordStyle, false);
|
|
mt = normalStyleBuilder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ((size_t)1, mt->runs.size());
|
|
EXPECT_EQ(LineBreakStyle::Normal, mt->runs[0]->lineBreakStyle());
|
|
EXPECT_EQ(LineBreakWordStyle::Phrase, mt->runs[0]->lineBreakWordStyle());
|
|
|
|
lbStyle = (int)LineBreakStyle::Strict; // strict
|
|
lbWordStyle = (int)LineBreakWordStyle::None; // no word style
|
|
MeasuredTextBuilder strictStyleBuilder;
|
|
MinikinPaint strictStylePaint(font);
|
|
strictStyleBuilder.addStyleRun(0, text.size(), std::move(strictStylePaint), lbStyle,
|
|
lbWordStyle, false);
|
|
mt = strictStyleBuilder.build(text, true /* hyphenation */, true /* full layout */,
|
|
false /* ignore kerning */, nullptr /* no hint */);
|
|
|
|
EXPECT_EQ((size_t)1, mt->runs.size());
|
|
EXPECT_EQ(LineBreakStyle::Strict, mt->runs[0]->lineBreakStyle());
|
|
EXPECT_EQ(LineBreakWordStyle::None, mt->runs[0]->lineBreakWordStyle());
|
|
}
|
|
|
|
TEST(MeasuredTextTest, testLineBreakStyle_from_run) {
|
|
auto text = utf8ToUtf16("Hello, World!");
|
|
auto font = buildFontCollection("Ascii.ttf");
|
|
int lbStyle = (int)LineBreakStyle::Strict;
|
|
int lbWordStyle = (int)LineBreakWordStyle::Phrase;
|
|
Range range(0, text.size());
|
|
MinikinPaint paint(font);
|
|
|
|
StyleRun styleRun(range, std::move(paint), lbStyle, lbWordStyle, false /* isRtl */);
|
|
EXPECT_EQ(LineBreakStyle::Strict, styleRun.lineBreakStyle());
|
|
EXPECT_EQ(LineBreakWordStyle::Phrase, styleRun.lineBreakWordStyle());
|
|
|
|
ReplacementRun replacementRun(range, 10.0f /* width */, 0 /* locale list id */);
|
|
EXPECT_EQ(LineBreakStyle::None, replacementRun.lineBreakStyle());
|
|
EXPECT_EQ(LineBreakWordStyle::None, replacementRun.lineBreakWordStyle());
|
|
}
|
|
|
|
} // namespace minikin
|