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 all commits
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
16 changes: 16 additions & 0 deletions impeller/toolkit/interop/impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1133,4 +1133,20 @@ void ImpellerTypographyContextRelease(ImpellerTypographyContext context) {
ObjectBase::SafeRelease(context);
}

IMPELLER_EXTERN_C
bool ImpellerTypographyContextRegisterFont(ImpellerTypographyContext context,
const ImpellerMapping* contents,
void* contents_on_release_user_data,
const char* family_name_alias) {
auto wrapped_contents = std::make_unique<fml::NonOwnedMapping>(
contents->data, // data ptr
contents->length, // data length
[contents, contents_on_release_user_data](auto, auto) {
contents->on_release(contents_on_release_user_data);
} // release callback
);
return GetPeer(context)->RegisterFont(std::move(wrapped_contents),
family_name_alias);
}

} // namespace impeller::interop
7 changes: 7 additions & 0 deletions impeller/toolkit/interop/impeller.h
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,13 @@ IMPELLER_EXPORT
void ImpellerTypographyContextRelease(
ImpellerTypographyContext IMPELLER_NULLABLE context);

IMPELLER_EXPORT
bool ImpellerTypographyContextRegisterFont(
ImpellerTypographyContext IMPELLER_NONNULL context,
const ImpellerMapping* IMPELLER_NONNULL contents,
void* IMPELLER_NULLABLE contents_on_release_user_data,
const char* IMPELLER_NULLABLE family_name_alias);

//------------------------------------------------------------------------------
// Paragraph Style
//------------------------------------------------------------------------------
Expand Down
74 changes: 74 additions & 0 deletions impeller/toolkit/interop/impeller_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,80 @@ TEST_P(InteropPlaygroundTest, CanCreateParagraphs) {
}));
}

TEST_P(InteropPlaygroundTest, CanCreateParagraphsWithCustomFont) {
// Create a typography context.
auto type_context = Adopt<TypographyContext>(ImpellerTypographyContextNew());
ASSERT_TRUE(type_context);

// Open the custom font file.
std::unique_ptr<fml::Mapping> font_data =
flutter::testing::OpenFixtureAsMapping("wtf.otf");
ASSERT_NE(font_data, nullptr);
ASSERT_GT(font_data->GetSize(), 0u);
ImpellerMapping font_data_mapping = {
.data = font_data->GetMapping(),
.length = font_data->GetSize(),
.on_release = [](auto ctx) {
delete reinterpret_cast<fml::Mapping*>(ctx);
}};
auto registered =
ImpellerTypographyContextRegisterFont(type_context.GetC(), //
&font_data_mapping, //
font_data.release(), //
nullptr //
);
ASSERT_TRUE(registered);

// Create a builder.
auto builder =
Adopt<ParagraphBuilder>(ImpellerParagraphBuilderNew(type_context.GetC()));
ASSERT_TRUE(builder);

// Create a paragraph style with the font size and foreground and background
// colors.
auto style = Adopt<ParagraphStyle>(ImpellerParagraphStyleNew());
ASSERT_TRUE(style);
ImpellerParagraphStyleSetFontSize(style.GetC(), 150.0f);
ImpellerParagraphStyleSetFontFamily(style.GetC(), "WhatTheFlutter");

{
auto paint = Adopt<Paint>(ImpellerPaintNew());
ASSERT_TRUE(paint);
ImpellerColor color = {0.0, 1.0, 1.0, 1.0};
ImpellerPaintSetColor(paint.GetC(), &color);
ImpellerParagraphStyleSetForeground(style.GetC(), paint.GetC());
}

// Push the style onto the style stack.
ImpellerParagraphBuilderPushStyle(builder.GetC(), style.GetC());
std::string text = "0F0F0F0";

// Add the paragraph text data.
ImpellerParagraphBuilderAddText(builder.GetC(),
reinterpret_cast<const uint8_t*>(text.data()),
text.size());

// Layout and build the paragraph.
auto paragraph = Adopt<Paragraph>(
ImpellerParagraphBuilderBuildParagraphNew(builder.GetC(), 1200.0f));
ASSERT_TRUE(paragraph);

// Create a display list with just the paragraph drawn into it.
auto dl_builder =
Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
ImpellerPoint point = {20, 20};
ImpellerDisplayListBuilderDrawParagraph(dl_builder.GetC(), paragraph.GetC(),
&point);
auto dl = Adopt<DisplayList>(
ImpellerDisplayListBuilderCreateDisplayListNew(dl_builder.GetC()));

ASSERT_TRUE(
OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
return true;
}));
} // namespace impeller::interop::testing

static void DrawTextFrame(ImpellerTypographyContext tc,
ImpellerDisplayListBuilder builder,
ImpellerParagraphStyle p_style,
Expand Down
48 changes: 48 additions & 0 deletions impeller/toolkit/interop/typography_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <mutex>

#include "flutter/fml/icu_util.h"
#include "flutter/third_party/txt/src/txt/platform.h"
#include "impeller/base/validation.h"
#include "impeller/toolkit/interop/embedded_icu_data.h"

namespace impeller::interop {
Expand All @@ -19,7 +21,12 @@ TypographyContext::TypographyContext()
impeller_embedded_icu_data_data, impeller_embedded_icu_data_length);
fml::icu::InitializeICUFromMapping(std::move(icu_data));
});
// The fallback for all fonts. Looks in platform specific locations.
collection_->SetupDefaultFontManager(0u);

// Looks for fonts in user supplied blobs.
asset_font_manager_ = sk_make_sp<skia::textlayout::TypefaceFontProvider>();
collection_->SetAssetFontManager(asset_font_manager_);
}

TypographyContext::~TypographyContext() = default;
Expand All @@ -33,4 +40,45 @@ TypographyContext::GetFontCollection() const {
return collection_;
}

static sk_sp<SkTypeface> CreateTypefaceFromFontData(
std::unique_ptr<fml::Mapping> font_data) {
if (!font_data) {
VALIDATION_LOG << "Invalid font data.";
return nullptr;
}
auto sk_data_context = font_data.release();
auto sk_data = SkData::MakeWithProc(
sk_data_context->GetMapping(), // data ptr
sk_data_context->GetSize(), // data size
[](const void*, void* context) {
delete reinterpret_cast<decltype(sk_data_context)>(context);
}, // release callback
sk_data_context // release callback context
);
auto sk_data_stream = SkMemoryStream::Make(sk_data);
auto sk_typeface =
txt::GetDefaultFontManager()->makeFromStream(std::move(sk_data_stream));
if (!sk_typeface) {
VALIDATION_LOG << "Could not create typeface with data.";
return nullptr;
}
return sk_typeface;
}

bool TypographyContext::RegisterFont(std::unique_ptr<fml::Mapping> font_data,
const char* family_name_alias) {
auto typeface = CreateTypefaceFromFontData(std::move(font_data));
if (typeface == nullptr) {
return false;
}
size_t result = 0u;
if (family_name_alias == nullptr) {
result = asset_font_manager_->registerTypeface(std::move(typeface));
} else {
result = asset_font_manager_->registerTypeface(std::move(typeface),
SkString{family_name_alias});
}
return result != 0;
}

} // namespace impeller::interop
15 changes: 15 additions & 0 deletions impeller/toolkit/interop/typography_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <memory>

#include "flutter/third_party/skia/modules/skparagraph/include/TypefaceFontProvider.h"
#include "flutter/third_party/txt/src/txt/font_collection.h"
#include "impeller/toolkit/interop/impeller.h"
#include "impeller/toolkit/interop/object.h"
Expand All @@ -29,8 +30,22 @@ class TypographyContext final

const std::shared_ptr<txt::FontCollection>& GetFontCollection() const;

//----------------------------------------------------------------------------
/// @brief Registers custom font data. If an alias for the family name is
/// provided, subsequent lookups will need to use that same alias.
/// If not, the family name will be read from the font data.
///
/// @param[in] font_data The font data
/// @param[in] family_name_alias The family name alias
///
/// @return If the font data could be successfully registered.
///
bool RegisterFont(std::unique_ptr<fml::Mapping> font_data,
const char* family_name_alias);

private:
std::shared_ptr<txt::FontCollection> collection_;
sk_sp<skia::textlayout::TypefaceFontProvider> asset_font_manager_;
};

} // namespace impeller::interop
Expand Down