mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Render glyphs at the correct resolution with respect to the current transform (flutter/engine#101)
This commit is contained in:
parent
951cb1c1ee
commit
458ab4ebb2
@ -247,7 +247,8 @@ void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
|
||||
}
|
||||
|
||||
// |flutter::Dispatcher|
|
||||
void DisplayListDispatcher::setImageFilter(const flutter::DlImageFilter* filter) {
|
||||
void DisplayListDispatcher::setImageFilter(
|
||||
const flutter::DlImageFilter* filter) {
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
@ -609,9 +610,10 @@ void DisplayListDispatcher::drawDisplayList(
|
||||
void DisplayListDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
|
||||
SkScalar x,
|
||||
SkScalar y) {
|
||||
canvas_.DrawTextFrame(TextFrameFromTextBlob(blob), //
|
||||
impeller::Point{x, y}, //
|
||||
paint_ //
|
||||
Scalar scale = canvas_.GetCurrentTransformation().GetMaxBasisLength();
|
||||
canvas_.DrawTextFrame(TextFrameFromTextBlob(blob, scale), //
|
||||
impeller::Point{x, y}, //
|
||||
paint_ //
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -43,4 +43,7 @@ constexpr float kSqrt2 = 1.41421356237309504880;
|
||||
// 1/sqrt(2)
|
||||
constexpr float k1OverSqrt2 = 0.70710678118654752440;
|
||||
|
||||
// 0.001
|
||||
constexpr float kEhCloseEnough = 1e-3;
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -212,6 +212,21 @@ TEST(GeometryTest, MatrixTransformDirection) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GeometryTest, MatrixGetMaxBasisLength) {
|
||||
{
|
||||
auto m = Matrix::MakeScale({3, 1, 1});
|
||||
ASSERT_EQ(m.GetMaxBasisLength(), 3);
|
||||
|
||||
m = m * Matrix::MakeSkew(0, 4);
|
||||
ASSERT_EQ(m.GetMaxBasisLength(), 5);
|
||||
}
|
||||
|
||||
{
|
||||
auto m = Matrix::MakeScale({-3, 4, 2});
|
||||
ASSERT_EQ(m.GetMaxBasisLength(), 4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GeometryTest, QuaternionLerp) {
|
||||
auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0};
|
||||
auto q2 = Quaternion{{0.0, 0.0, 1.0}, M_PI_4};
|
||||
@ -570,6 +585,21 @@ TEST(GeometryTest, CanUsePointAssignmentOperators) {
|
||||
ASSERT_EQ(p.x, 1u);
|
||||
ASSERT_EQ(p.y, 2u);
|
||||
}
|
||||
|
||||
// Arithmetic type on RHS
|
||||
{
|
||||
IPoint p(1, 2);
|
||||
p *= 3;
|
||||
ASSERT_EQ(p.x, 3u);
|
||||
ASSERT_EQ(p.y, 6u);
|
||||
}
|
||||
|
||||
{
|
||||
IPoint p(3, 6);
|
||||
p /= 3;
|
||||
ASSERT_EQ(p.x, 1u);
|
||||
ASSERT_EQ(p.y, 2u);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GeometryTest, PointDotProduct) {
|
||||
|
||||
@ -193,6 +193,15 @@ Scalar Matrix::GetDeterminant() const {
|
||||
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
||||
}
|
||||
|
||||
Scalar Matrix::GetMaxBasisLength() const {
|
||||
Scalar max = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
max = std::max(max,
|
||||
e[i][0] * e[i][0] + e[i][1] * e[i][1] + e[i][2] * e[i][2]);
|
||||
}
|
||||
return std::sqrt(max);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adapted for Impeller from Graphics Gems:
|
||||
* http://www.realtimerendering.com/resources/GraphicsGems/gemsii/unmatrix.c
|
||||
|
||||
@ -219,6 +219,8 @@ struct Matrix {
|
||||
|
||||
Scalar GetDeterminant() const;
|
||||
|
||||
Scalar GetMaxBasisLength() const;
|
||||
|
||||
constexpr bool IsAffine() const {
|
||||
return (m[2] == 0 && m[3] == 0 && m[6] == 0 && m[7] == 0 && m[8] == 0 &&
|
||||
m[9] == 0 && m[10] == 1 && m[11] == 0 && m[14] == 0 && m[15] == 1);
|
||||
|
||||
@ -88,6 +88,13 @@ struct TPoint {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
|
||||
inline TPoint operator*=(U scale) {
|
||||
x *= static_cast<Type>(scale);
|
||||
y *= static_cast<Type>(scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline TPoint operator/=(const TPoint<U>& p) {
|
||||
x /= static_cast<Type>(p.x);
|
||||
@ -102,6 +109,13 @@ struct TPoint {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
|
||||
inline TPoint operator/=(U scale) {
|
||||
x /= static_cast<Type>(scale);
|
||||
y /= static_cast<Type>(scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr TPoint operator-() const { return {-x, -y}; }
|
||||
|
||||
constexpr TPoint operator+(const TPoint& p) const {
|
||||
|
||||
@ -14,8 +14,6 @@ namespace impeller {
|
||||
|
||||
using Scalar = float;
|
||||
|
||||
constexpr Scalar kEhCloseEnough = 1e-3f;
|
||||
|
||||
template <class T, class = std::enable_if_t<std::is_arithmetic_v<T>>>
|
||||
constexpr T Absolute(const T& val) {
|
||||
return val >= T{} ? val : -val;
|
||||
|
||||
@ -12,13 +12,14 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
static Font ToFont(const SkFont& font) {
|
||||
static Font ToFont(const SkFont& font, Scalar scale) {
|
||||
auto typeface = std::make_shared<TypefaceSkia>(font.refTypefaceOrDefault());
|
||||
|
||||
SkFontMetrics sk_metrics;
|
||||
font.getMetrics(&sk_metrics);
|
||||
|
||||
Font::Metrics metrics;
|
||||
metrics.scale = scale;
|
||||
metrics.point_size = font.getSize();
|
||||
metrics.ascent = sk_metrics.fAscent;
|
||||
metrics.descent = sk_metrics.fDescent;
|
||||
@ -28,7 +29,8 @@ static Font ToFont(const SkFont& font) {
|
||||
return Font{std::move(typeface), std::move(metrics)};
|
||||
}
|
||||
|
||||
TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob) {
|
||||
TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob,
|
||||
Scalar scale) {
|
||||
if (!blob) {
|
||||
return {};
|
||||
}
|
||||
@ -36,7 +38,7 @@ TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob) {
|
||||
TextFrame frame;
|
||||
|
||||
for (SkTextBlobRunIterator run(blob.get()); !run.done(); run.next()) {
|
||||
TextRun text_run(ToFont(run.font()));
|
||||
TextRun text_run(ToFont(run.font(), scale));
|
||||
const auto glyph_count = run.glyphCount();
|
||||
const auto* glyphs = run.glyphs();
|
||||
switch (run.positioning()) {
|
||||
|
||||
@ -10,6 +10,6 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob);
|
||||
TextFrame TextFrameFromTextBlob(sk_sp<SkTextBlob> blob, Scalar scale = 1.0f);
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -65,7 +65,8 @@ static bool PairsFitInAtlasOfSize(const FontGlyphPair::Vector& pairs,
|
||||
|
||||
for (const auto& pair : pairs) {
|
||||
const auto glyph_size =
|
||||
ISize::Ceil(pair.font.GetMetrics().GetBoundingBox().size);
|
||||
ISize::Ceil(pair.font.GetMetrics().GetBoundingBox().size *
|
||||
pair.font.GetMetrics().scale);
|
||||
SkIPoint16 location_in_atlas;
|
||||
if (!rect_packer->addRect(glyph_size.width, //
|
||||
glyph_size.height, //
|
||||
@ -125,7 +126,8 @@ static std::optional<SkBitmap> CreateAtlasBitmap(const GlyphAtlas& atlas,
|
||||
|
||||
SkFont sk_font(
|
||||
TypefaceSkia::Cast(*font_glyph.font.GetTypeface()).GetSkiaTypeface(),
|
||||
font_glyph.font.GetMetrics().point_size);
|
||||
font_glyph.font.GetMetrics().point_size *
|
||||
font_glyph.font.GetMetrics().scale);
|
||||
|
||||
const auto& metrics = font_glyph.font.GetMetrics();
|
||||
|
||||
@ -133,13 +135,14 @@ static std::optional<SkBitmap> CreateAtlasBitmap(const GlyphAtlas& atlas,
|
||||
|
||||
SkPaint glyph_paint;
|
||||
glyph_paint.setColor(glyph_color);
|
||||
canvas->drawGlyphs(1u, // count
|
||||
&glyph_id, // glyphs
|
||||
&position, // positions
|
||||
SkPoint::Make(-metrics.min_extent.x,
|
||||
-metrics.ascent), // origin
|
||||
sk_font, // font
|
||||
glyph_paint // paint
|
||||
canvas->drawGlyphs(
|
||||
1u, // count
|
||||
&glyph_id, // glyphs
|
||||
&position, // positions
|
||||
SkPoint::Make(-metrics.min_extent.x * metrics.scale,
|
||||
-metrics.ascent * metrics.scale), // origin
|
||||
sk_font, // font
|
||||
glyph_paint // paint
|
||||
);
|
||||
return true;
|
||||
});
|
||||
|
||||
@ -28,6 +28,12 @@ class Font : public Comparable<Font> {
|
||||
/// the baseline with an upper-left-origin coordinate system.
|
||||
///
|
||||
struct Metrics {
|
||||
//--------------------------------------------------------------------------
|
||||
/// The scaling factor that should be used when rendering this font to an
|
||||
/// atlas. This should normally be set in accordance with the transformation
|
||||
/// matrix that will be used to position glyph geometry.
|
||||
///
|
||||
Scalar scale = 1.0f;
|
||||
//--------------------------------------------------------------------------
|
||||
/// The point size of the font.
|
||||
///
|
||||
@ -69,9 +75,9 @@ class Font : public Comparable<Font> {
|
||||
}
|
||||
|
||||
constexpr bool operator==(const Metrics& o) const {
|
||||
return point_size == o.point_size && ascent == o.ascent &&
|
||||
descent == o.descent && min_extent == o.min_extent &&
|
||||
max_extent == o.max_extent;
|
||||
return scale == o.scale && point_size == o.point_size &&
|
||||
ascent == o.ascent && descent == o.descent &&
|
||||
min_extent == o.min_extent && max_extent == o.max_extent;
|
||||
}
|
||||
};
|
||||
|
||||
@ -107,6 +113,6 @@ class Font : public Comparable<Font> {
|
||||
template <>
|
||||
struct std::hash<impeller::Font::Metrics> {
|
||||
constexpr std::size_t operator()(const impeller::Font::Metrics& m) const {
|
||||
return fml::HashCombine(m.point_size, m.ascent, m.descent);
|
||||
return fml::HashCombine(m.scale, m.point_size, m.ascent, m.descent);
|
||||
}
|
||||
};
|
||||
|
||||
@ -47,7 +47,7 @@ class GlyphAtlas {
|
||||
const std::shared_ptr<Texture>& GetTexture() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Record there location of a specific font-glyph pair within the
|
||||
/// @brief Record the location of a specific font-glyph pair within the
|
||||
/// atlas.
|
||||
///
|
||||
/// @param[in] pair The font-glyph pair
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user