Skip to content
Snippets Groups Projects
Unverified Commit bffedc7f authored by gaaclarke's avatar gaaclarke Committed by GitHub
Browse files

Backfill subpixel unit tests (#162710)

issue: https://github.com/flutter/flutter/issues/149652

I made these unit tests while investigating a fix for
https://github.com/flutter/flutter/issues/149652. The fixes have already
landed with different tests. I figured I'd land these too since they
were helpful to me.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
parent d8c92a44
No related merge requests found
......@@ -23,16 +23,24 @@ INSTANTIATE_PLAYGROUND_SUITE(TextContentsTest);
using ::testing::Return;
namespace {
struct TextOptions {
Scalar font_size = 50;
bool is_subpixel = false;
};
std::shared_ptr<TextFrame> MakeTextFrame(const std::string& text,
const std::string_view& font_fixture,
Scalar font_size) {
const TextOptions& options) {
auto c_font_fixture = std::string(font_fixture);
auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
if (!mapping) {
return nullptr;
}
sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
SkFont sk_font(font_mgr->makeFromData(mapping), options.font_size);
if (options.is_subpixel) {
sk_font.setSubpixel(true);
}
auto blob = SkTextBlob::MakeFromString(text.c_str(), sk_font);
if (!blob) {
return nullptr;
......@@ -48,9 +56,10 @@ std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
GlyphAtlas::Type type,
Scalar scale,
const std::shared_ptr<GlyphAtlasContext>& atlas_context,
const std::shared_ptr<TextFrame>& frame) {
frame->SetPerFrameData(scale, /*offset=*/Point(0, 0),
/*transform=*/Matrix(), /*properties=*/std::nullopt);
const std::shared_ptr<TextFrame>& frame,
Point offset) {
frame->SetPerFrameData(scale, /*offset=*/offset, /*transform=*/Matrix(),
/*properties=*/std::nullopt);
return typographer_context->CreateGlyphAtlas(context, type, host_buffer,
atlas_context, {frame});
}
......@@ -101,7 +110,7 @@ TEST_P(TextContentsTest, SimpleComputeVertexData) {
GlyphAtlasPipeline::VertexShader::PerVertexData data[6];
std::shared_ptr<TextFrame> text_frame =
MakeTextFrame("1", "ahem.ttf", /*font_size=*/50);
MakeTextFrame("1", "ahem.ttf", TextOptions{.font_size = 50});
std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
std::shared_ptr<GlyphAtlasContext> atlas_context =
......@@ -112,7 +121,7 @@ TEST_P(TextContentsTest, SimpleComputeVertexData) {
std::shared_ptr<GlyphAtlas> atlas =
CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
atlas_context, text_frame);
atlas_context, text_frame, /*offset=*/{0, 0});
ISize texture_size = atlas->GetTexture()->GetSize();
TextContents::ComputeVertexData(data, text_frame, /*scale=*/1.0,
......@@ -137,7 +146,7 @@ TEST_P(TextContentsTest, SimpleComputeVertexData2x) {
GlyphAtlasPipeline::VertexShader::PerVertexData data[6];
std::shared_ptr<TextFrame> text_frame =
MakeTextFrame("1", "ahem.ttf", /*font_size=*/50);
MakeTextFrame("1", "ahem.ttf", TextOptions{.font_size = 50});
std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
std::shared_ptr<GlyphAtlasContext> atlas_context =
......@@ -146,9 +155,10 @@ TEST_P(TextContentsTest, SimpleComputeVertexData2x) {
GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
ASSERT_TRUE(context && context->IsValid());
Scalar font_scale = 2.f;
std::shared_ptr<GlyphAtlas> atlas = CreateGlyphAtlas(
*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, font_scale, atlas_context, text_frame);
std::shared_ptr<GlyphAtlas> atlas =
CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, font_scale,
atlas_context, text_frame, /*offset=*/{0, 0});
ISize texture_size = atlas->GetTexture()->GetSize();
TextContents::ComputeVertexData(
......@@ -165,7 +175,7 @@ TEST_P(TextContentsTest, SimpleComputeVertexData2x) {
TEST_P(TextContentsTest, MaintainsShape) {
std::shared_ptr<TextFrame> text_frame =
MakeTextFrame("th", "ahem.ttf", /*font_size=*/50);
MakeTextFrame("th", "ahem.ttf", TextOptions{.font_size = 50});
std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
std::shared_ptr<GlyphAtlasContext> atlas_context =
......@@ -183,7 +193,7 @@ TEST_P(TextContentsTest, MaintainsShape) {
std::shared_ptr<GlyphAtlas> atlas =
CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, font_scale,
atlas_context, text_frame);
atlas_context, text_frame, /*offset=*/{0, 0});
ISize texture_size = atlas->GetTexture()->GetSize();
TextContents::ComputeVertexData(
......@@ -202,5 +212,159 @@ TEST_P(TextContentsTest, MaintainsShape) {
}
}
TEST_P(TextContentsTest, SimpleSubpixel) {
#ifndef FML_OS_MACOSX
GTEST_SKIP() << "Results aren't stable across linux and macos.";
#endif
GlyphAtlasPipeline::VertexShader::PerVertexData data[6];
std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
"1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
std::shared_ptr<GlyphAtlasContext> atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
ASSERT_TRUE(context && context->IsValid());
Point offset = Point(0.5, 0);
std::shared_ptr<GlyphAtlas> atlas =
CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
atlas_context, text_frame, offset);
ISize texture_size = atlas->GetTexture()->GetSize();
TextContents::ComputeVertexData(
data, text_frame, /*scale=*/1.0,
/*entity_transform=*/Matrix::MakeTranslation(offset), offset,
/*glyph_properties=*/std::nullopt, atlas);
Rect position_rect = PerVertexDataPositionToRect(data);
Rect uv_rect = PerVertexDataUVToRect(data, texture_size);
// The values at Point(0, 0).
// EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
// EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
}
TEST_P(TextContentsTest, SimpleSubpixel3x) {
#ifndef FML_OS_MACOSX
GTEST_SKIP() << "Results aren't stable across linux and macos.";
#endif
GlyphAtlasPipeline::VertexShader::PerVertexData data[6];
std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
"1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
std::shared_ptr<GlyphAtlasContext> atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
ASSERT_TRUE(context && context->IsValid());
Scalar font_scale = 3.f;
Point offset = {0.16667, 0};
std::shared_ptr<GlyphAtlas> atlas =
CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, font_scale,
atlas_context, text_frame, offset);
ISize texture_size = atlas->GetTexture()->GetSize();
TextContents::ComputeVertexData(
data, text_frame, font_scale,
/*entity_transform=*/
Matrix::MakeTranslation(offset) *
Matrix::MakeScale({font_scale, font_scale, 1}),
offset,
/*glyph_properties=*/std::nullopt, atlas);
Rect position_rect = PerVertexDataPositionToRect(data);
Rect uv_rect = PerVertexDataUVToRect(data, texture_size);
// Values at Point(0, 0)
// EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -121, 152, 152));
// EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 152, 152));
EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -121, 154, 152))
<< "position size:" << position_rect.GetSize();
EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 154, 152))
<< "position size:" << position_rect.GetSize();
}
TEST_P(TextContentsTest, SimpleSubpixel26) {
#ifndef FML_OS_MACOSX
GTEST_SKIP() << "Results aren't stable across linux and macos.";
#endif
GlyphAtlasPipeline::VertexShader::PerVertexData data[6];
std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
"1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
std::shared_ptr<GlyphAtlasContext> atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
ASSERT_TRUE(context && context->IsValid());
Point offset = Point(0.26, 0);
std::shared_ptr<GlyphAtlas> atlas =
CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
atlas_context, text_frame, offset);
ISize texture_size = atlas->GetTexture()->GetSize();
TextContents::ComputeVertexData(
data, text_frame, /*scale=*/1.0,
/*entity_transform=*/Matrix::MakeTranslation(offset), offset,
/*glyph_properties=*/std::nullopt, atlas);
Rect position_rect = PerVertexDataPositionToRect(data);
Rect uv_rect = PerVertexDataUVToRect(data, texture_size);
// The values without subpixel.
// EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
// EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
}
TEST_P(TextContentsTest, SimpleSubpixel80) {
#ifndef FML_OS_MACOSX
GTEST_SKIP() << "Results aren't stable across linux and macos.";
#endif
GlyphAtlasPipeline::VertexShader::PerVertexData data[6];
std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
"1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
std::shared_ptr<GlyphAtlasContext> atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
ASSERT_TRUE(context && context->IsValid());
Point offset = Point(0.80, 0);
std::shared_ptr<GlyphAtlas> atlas =
CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
atlas_context, text_frame, offset);
ISize texture_size = atlas->GetTexture()->GetSize();
TextContents::ComputeVertexData(
data, text_frame, /*scale=*/1.0,
/*entity_transform=*/Matrix::MakeTranslation(offset), offset,
/*glyph_properties=*/std::nullopt, atlas);
Rect position_rect = PerVertexDataPositionToRect(data);
Rect uv_rect = PerVertexDataUVToRect(data, texture_size);
// The values without subpixel.
// EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
// EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
}
} // namespace testing
} // namespace impeller
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment