Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ static std::unique_ptr<PipelineT> CreateDefaultPipeline(

ContentContext::ContentContext(std::shared_ptr<Context> context)
: context_(std::move(context)),
tessellator_(std::make_shared<Tessellator>()) {
tessellator_(std::make_shared<Tessellator>()),
glyph_atlas_context_(std::make_shared<GlyphAtlasContext>()) {
if (!context_ || !context_->IsValid()) {
return;
}
Expand Down Expand Up @@ -291,6 +292,11 @@ std::shared_ptr<Tessellator> ContentContext::GetTessellator() const {
return tessellator_;
}

std::shared_ptr<GlyphAtlasContext> ContentContext::GetGlyphAtlasContext()
const {
return glyph_atlas_context_;
}

std::shared_ptr<Context> ContentContext::GetContext() const {
return context_;
}
Expand Down
5 changes: 5 additions & 0 deletions impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
#include "impeller/entity/position_color.vert.h"
#include "impeller/entity/position_uv.vert.h"

#include "impeller/typographer/glyph_atlas.h"

namespace impeller {

using LinearGradientFillPipeline =
Expand Down Expand Up @@ -376,6 +378,8 @@ class ContentContext {

std::shared_ptr<Context> GetContext() const;

std::shared_ptr<GlyphAtlasContext> GetGlyphAtlasContext() const;

using SubpassCallback =
std::function<bool(const ContentContext&, RenderPass&)>;

Expand Down Expand Up @@ -465,6 +469,7 @@ class ContentContext {

bool is_valid_ = false;
std::shared_ptr<Tessellator> tessellator_;
std::shared_ptr<GlyphAtlasContext> glyph_atlas_context_;

FML_DISALLOW_COPY_AND_ASSIGN(ContentContext);
};
Expand Down
10 changes: 6 additions & 4 deletions impeller/entity/contents/text_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ void TextContents::SetGlyphAtlas(std::shared_ptr<LazyGlyphAtlas> atlas) {

std::shared_ptr<GlyphAtlas> TextContents::ResolveAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
std::shared_ptr<Context> context) const {
FML_DCHECK(lazy_atlas_);
if (lazy_atlas_) {
return lazy_atlas_->CreateOrGetGlyphAtlas(type, context);
return lazy_atlas_->CreateOrGetGlyphAtlas(type, atlas_context, context);
}

return nullptr;
Expand Down Expand Up @@ -172,8 +173,9 @@ static bool CommonRender(const ContentContext& renderer,
bool TextContents::RenderSdf(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
auto atlas = ResolveAtlas(GlyphAtlas::Type::kSignedDistanceField,
renderer.GetContext());
auto atlas =
ResolveAtlas(GlyphAtlas::Type::kSignedDistanceField,
renderer.GetGlyphAtlasContext(), renderer.GetContext());

if (!atlas || !atlas->IsValid()) {
VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
Expand Down Expand Up @@ -208,7 +210,7 @@ bool TextContents::Render(const ContentContext& renderer,
auto atlas =
ResolveAtlas(lazy_atlas_->HasColor() ? GlyphAtlas::Type::kColorBitmap
: GlyphAtlas::Type::kAlphaBitmap,
renderer.GetContext());
renderer.GetGlyphAtlasContext(), renderer.GetContext());

if (!atlas || !atlas->IsValid()) {
VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
Expand Down
1 change: 1 addition & 0 deletions impeller/entity/contents/text_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class TextContents final : public Contents {

std::shared_ptr<GlyphAtlas> ResolveAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
std::shared_ptr<Context> context) const;

FML_DISALLOW_COPY_AND_ASSIGN(TextContents);
Expand Down
32 changes: 23 additions & 9 deletions impeller/typographer/backends/skia/text_render_context_skia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -340,25 +340,39 @@ static std::shared_ptr<Texture> UploadGlyphTextureAtlas(

std::shared_ptr<GlyphAtlas> TextRenderContextSkia::CreateGlyphAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
FrameIterator frame_iterator) const {
TRACE_EVENT0("impeller", __FUNCTION__);
if (!IsValid()) {
return nullptr;
}

auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
auto last_atlas = atlas_context->GetGlyphAtlas();

// ---------------------------------------------------------------------------
// Step 1: Collect unique font-glyph pairs in the frame.
// ---------------------------------------------------------------------------

auto font_glyph_pairs = CollectUniqueFontGlyphPairs(type, frame_iterator);
if (font_glyph_pairs.empty()) {
return glyph_atlas;
return last_atlas;
}

// ---------------------------------------------------------------------------
// Step 2: Get the optimum size of the texture atlas.
// Step 2: Determine if the atlas type and font glyph pairs are identical to
// the current atlas and reuse if possible.
// ---------------------------------------------------------------------------
if (last_atlas->GetType() == type) {
auto new_glyphs = last_atlas->FindNewGlyphs(font_glyph_pairs);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is actually good enough of a check. If glyphs are drawn at different sizes I think we'd need to account for that ... right? But based on my reading of the code its only one FontGlyphPair mapped to each rect, so a different size glyph has to be a unique font glyph pair ... right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the glyph size changes the rect won't match.

if (new_glyphs.empty()) {
return last_atlas;
}
}

auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
atlas_context->UpdateGlyphAtlas(glyph_atlas);

// ---------------------------------------------------------------------------
// Step 3: Get the optimum size of the texture atlas.
// ---------------------------------------------------------------------------
std::vector<Rect> glyph_positions;
const auto atlas_size =
Expand All @@ -368,7 +382,7 @@ std::shared_ptr<GlyphAtlas> TextRenderContextSkia::CreateGlyphAtlas(
}

// ---------------------------------------------------------------------------
// Step 3: Find location of font-glyph pairs in the atlas. We have this from
// Step 4: Find location of font-glyph pairs in the atlas. We have this from
// the last step. So no need to do create another rect packer. But just do a
// sanity check of counts. This could also be just an assertion as only a
// construction issue would cause such a failure.
Expand All @@ -378,23 +392,23 @@ std::shared_ptr<GlyphAtlas> TextRenderContextSkia::CreateGlyphAtlas(
}

// ---------------------------------------------------------------------------
// Step 4: Record the positions in the glyph atlas.
// Step 5: Record the positions in the glyph atlas.
// ---------------------------------------------------------------------------
for (size_t i = 0, count = glyph_positions.size(); i < count; i++) {
glyph_atlas->AddTypefaceGlyphPosition(font_glyph_pairs[i],
glyph_positions[i]);
}

// ---------------------------------------------------------------------------
// Step 5: Draw font-glyph pairs in the correct spot in the atlas.
// Step 6: Draw font-glyph pairs in the correct spot in the atlas.
// ---------------------------------------------------------------------------
auto bitmap = CreateAtlasBitmap(*glyph_atlas, atlas_size);
if (!bitmap) {
return nullptr;
}

// ---------------------------------------------------------------------------
// Step 6: Upload the atlas as a texture.
// Step 7: Upload the atlas as a texture.
// ---------------------------------------------------------------------------
PixelFormat format;
switch (type) {
Expand All @@ -416,7 +430,7 @@ std::shared_ptr<GlyphAtlas> TextRenderContextSkia::CreateGlyphAtlas(
}

// ---------------------------------------------------------------------------
// Step 7: Record the texture in the glyph atlas.
// Step 8: Record the texture in the glyph atlas.
// ---------------------------------------------------------------------------
glyph_atlas->SetTexture(std::move(texture));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class TextRenderContextSkia : public TextRenderContext {
// |TextRenderContext|
std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
FrameIterator iterator) const override;

private:
Expand Down
24 changes: 24 additions & 0 deletions impeller/typographer/glyph_atlas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@

namespace impeller {

GlyphAtlasContext::GlyphAtlasContext()
: atlas_(std::make_shared<GlyphAtlas>(GlyphAtlas::Type::kAlphaBitmap)) {}

GlyphAtlasContext::~GlyphAtlasContext() {}

std::shared_ptr<GlyphAtlas> GlyphAtlasContext::GetGlyphAtlas() const {
return atlas_;
}

void GlyphAtlasContext::UpdateGlyphAtlas(std::shared_ptr<GlyphAtlas> atlas) {
atlas_ = atlas;
}

GlyphAtlas::GlyphAtlas(Type type) : type_(type) {}

GlyphAtlas::~GlyphAtlas() = default;
Expand Down Expand Up @@ -61,4 +74,15 @@ size_t GlyphAtlas::IterateGlyphs(
return count;
}

FontGlyphPair::Vector GlyphAtlas::FindNewGlyphs(
Comment thread
jonahwilliams marked this conversation as resolved.
Outdated
const FontGlyphPair::Vector& new_glyphs) {
FontGlyphPair::Vector results;
for (const auto& pair : new_glyphs) {
if (positions_.find(pair) == positions_.end()) {
results.push_back(pair);
}
}
return results;
}

} // namespace impeller
34 changes: 34 additions & 0 deletions impeller/typographer/glyph_atlas.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ class GlyphAtlas {
///
std::optional<Rect> FindFontGlyphPosition(const FontGlyphPair& pair) const;

//----------------------------------------------------------------------------
/// @brief Find a list of all font-glyph pairs not currently in the
/// atlas.
///
/// @param[in] new_glyphs The full set of new glyphs
///
/// @return A vector of all glyphs in new_glyphs that are not in the
/// current atlas.
///
FontGlyphPair::Vector FindNewGlyphs(const FontGlyphPair::Vector& new_glyphs);

private:
const Type type_;
std::shared_ptr<Texture> texture_;
Expand All @@ -129,4 +140,27 @@ class GlyphAtlas {
FML_DISALLOW_COPY_AND_ASSIGN(GlyphAtlas);
};

//------------------------------------------------------------------------------
/// @brief A container for caching a glyph atlas across frames.
///
class GlyphAtlasContext {
public:
GlyphAtlasContext();

~GlyphAtlasContext();

//----------------------------------------------------------------------------
/// @brief Retrieve the current glyph atlas.
std::shared_ptr<GlyphAtlas> GetGlyphAtlas() const;

//----------------------------------------------------------------------------
/// @brief Update the context with a newly constructed glyph atlas.
void UpdateGlyphAtlas(std::shared_ptr<GlyphAtlas> atlas);

private:
std::shared_ptr<GlyphAtlas> atlas_;

FML_DISALLOW_COPY_AND_ASSIGN(GlyphAtlasContext);
};

} // namespace impeller
3 changes: 2 additions & 1 deletion impeller/typographer/lazy_glyph_atlas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ bool LazyGlyphAtlas::HasColor() const {

std::shared_ptr<GlyphAtlas> LazyGlyphAtlas::CreateOrGetGlyphAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
std::shared_ptr<Context> context) const {
{
auto atlas_it = atlas_map_.find(type);
Expand All @@ -47,7 +48,7 @@ std::shared_ptr<GlyphAtlas> LazyGlyphAtlas::CreateOrGetGlyphAtlas(
i++;
return &result;
};
auto atlas = text_context->CreateGlyphAtlas(type, iterator);
auto atlas = text_context->CreateGlyphAtlas(type, atlas_context, iterator);
if (!atlas || !atlas->IsValid()) {
VALIDATION_LOG << "Could not create valid atlas.";
return nullptr;
Expand Down
1 change: 1 addition & 0 deletions impeller/typographer/lazy_glyph_atlas.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class LazyGlyphAtlas {

std::shared_ptr<GlyphAtlas> CreateOrGetGlyphAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
std::shared_ptr<Context> context) const;

bool HasColor() const;
Expand Down
3 changes: 2 additions & 1 deletion impeller/typographer/text_render_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const std::shared_ptr<Context>& TextRenderContext::GetContext() const {

std::shared_ptr<GlyphAtlas> TextRenderContext::CreateGlyphAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
const TextFrame& frame) const {
size_t count = 0;
FrameIterator iterator = [&]() -> const TextFrame* {
Expand All @@ -43,7 +44,7 @@ std::shared_ptr<GlyphAtlas> TextRenderContext::CreateGlyphAtlas(
}
return nullptr;
};
return CreateGlyphAtlas(type, iterator);
return CreateGlyphAtlas(type, atlas_context, iterator);
}

} // namespace impeller
7 changes: 5 additions & 2 deletions impeller/typographer/text_render_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@ class TextRenderContext {

virtual std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
FrameIterator iterator) const = 0;

std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(GlyphAtlas::Type type,
const TextFrame& frame) const;
std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
GlyphAtlas::Type type,
std::shared_ptr<GlyphAtlasContext> atlas_context,
const TextFrame& frame) const;

protected:
//----------------------------------------------------------------------------
Expand Down
Loading