mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Font: Cache HarfBuzz fonts and font details
This commit is contained in:
parent
c0f164ee28
commit
5b0a2b9b80
8 changed files with 287 additions and 186 deletions
|
|
@ -130,11 +130,6 @@ public:
|
|||
return fromFont (dwFont, customFontCollection, nullptr, MetricsMechanism::gdiWithDwriteFallback);
|
||||
}
|
||||
|
||||
Native getNativeDetails() const override
|
||||
{
|
||||
return Native { hbFont.get(), nonPortableMetrics };
|
||||
}
|
||||
|
||||
Typeface::Ptr createSystemFallback (const String& c, const String& language) const override
|
||||
{
|
||||
auto factory = factories->getDWriteFactory().getInterface<IDWriteFactory2>();
|
||||
|
|
@ -171,6 +166,11 @@ public:
|
|||
|
||||
ComSmartPtr<IDWriteFontFace> getIDWriteFontFace() const { return dwFontFace; }
|
||||
|
||||
const Native* getNativeDetails() const override
|
||||
{
|
||||
return native.get();
|
||||
}
|
||||
|
||||
static Typeface::Ptr findSystemTypeface()
|
||||
{
|
||||
NONCLIENTMETRICS nonClientMetrics{};
|
||||
|
|
@ -295,8 +295,7 @@ private:
|
|||
collection (std::move (collectionIn)),
|
||||
dwFont (font),
|
||||
dwFontFace (face),
|
||||
hbFont (std::move (hbFontIn)),
|
||||
nonPortableMetrics (metrics)
|
||||
native (std::make_unique<Native> (TypefaceNativeOptions { std::move (hbFontIn), metrics }))
|
||||
{
|
||||
if (collection != nullptr)
|
||||
factories->getFonts().addCollection (collection);
|
||||
|
|
@ -341,8 +340,9 @@ private:
|
|||
const auto name = getLocalisedFamilyName (*dwFont);
|
||||
const auto style = getLocalisedStyle (*dwFont);
|
||||
|
||||
const HbFace hbFace { hb_directwrite_face_create (dwFace) };
|
||||
HbFont font { hb_font_create (hbFace.get()) };
|
||||
HbFace hbFace { hb_directwrite_face_create (dwFace), IncrementRef::no };
|
||||
HbFont font { hb_font_create (hbFace.get()), IncrementRef::no };
|
||||
|
||||
const auto dwMetrics = getDwriteMetrics (*dwFace);
|
||||
|
||||
const auto metrics = mm == MetricsMechanism::gdiWithDwriteFallback
|
||||
|
|
@ -411,8 +411,7 @@ private:
|
|||
ComSmartPtr<IDWriteFontCollection> collection;
|
||||
ComSmartPtr<IDWriteFont> dwFont;
|
||||
ComSmartPtr<IDWriteFontFace> dwFontFace;
|
||||
HbFont hbFont;
|
||||
TypefaceAscentDescent nonPortableMetrics;
|
||||
std::unique_ptr<Native> native;
|
||||
};
|
||||
|
||||
struct DefaultFontNames
|
||||
|
|
|
|||
|
|
@ -93,9 +93,9 @@ std::unique_ptr<InputStream> makeAndroidInputStreamWrapper (LocalRef<jobject> st
|
|||
|
||||
struct AndroidCachedTypeface
|
||||
{
|
||||
std::shared_ptr<hb_font_t> font;
|
||||
HbFont font;
|
||||
GlobalRef javaFont;
|
||||
TypefaceAscentDescent nonPortableMetrics;
|
||||
TypefaceAscentDescent metrics;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -235,7 +235,7 @@ public:
|
|||
{
|
||||
return new AndroidTypeface (DoCache::no,
|
||||
result->font,
|
||||
result->nonPortableMetrics,
|
||||
result->metrics,
|
||||
font.getTypefaceName(),
|
||||
font.getTypefaceStyle(),
|
||||
result->javaFont);
|
||||
|
|
@ -251,7 +251,7 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
HbFont hbFont { hb_font_create (face.get()) };
|
||||
HbFont hbFont { hb_font_create (face.get()), IncrementRef::no };
|
||||
FontStyleHelpers::initSynthetics (hbFont.get(), font);
|
||||
|
||||
const auto androidFont = shouldStoreAndroidFont (face.get())
|
||||
|
|
@ -271,11 +271,6 @@ public:
|
|||
return fromMemory (DoCache::yes, blob, index);
|
||||
}
|
||||
|
||||
Native getNativeDetails() const override
|
||||
{
|
||||
return Native { hbFont.get(), nonPortableMetrics, this };
|
||||
}
|
||||
|
||||
Typeface::Ptr createSystemFallback (const String& text, const String& language) const override
|
||||
{
|
||||
if (__builtin_available (android 29, *))
|
||||
|
|
@ -293,6 +288,11 @@ public:
|
|||
c->remove ({ getName(), getStyle() });
|
||||
}
|
||||
|
||||
const Native* getNativeDetails() const override
|
||||
{
|
||||
return native.get();
|
||||
}
|
||||
|
||||
static Typeface::Ptr findSystemTypeface()
|
||||
{
|
||||
if (__builtin_available (android 29, *))
|
||||
|
|
@ -358,8 +358,8 @@ private:
|
|||
|
||||
const AFontMatcherPtr matcher { AFontMatcher_create() };
|
||||
|
||||
const auto weight = hb_style_get_value (hbFont.get(), HB_STYLE_TAG_WEIGHT);
|
||||
const auto italic = hb_style_get_value (hbFont.get(), HB_STYLE_TAG_ITALIC) != 0.0f;
|
||||
const auto weight = hb_style_get_value (native->getFont(), HB_STYLE_TAG_WEIGHT);
|
||||
const auto italic = hb_style_get_value (native->getFont(), HB_STYLE_TAG_ITALIC) != 0.0f;
|
||||
AFontMatcher_setStyle (matcher.get(), (uint16_t) weight, italic);
|
||||
|
||||
AFontMatcher_setLocales (matcher.get(), language.toRawUTF8());
|
||||
|
|
@ -367,7 +367,7 @@ private:
|
|||
const auto utf16 = text.toUTF16();
|
||||
|
||||
const AFontPtr matched { AFontMatcher_match (matcher.get(),
|
||||
readFontName (hb_font_get_face (hbFont.get()),
|
||||
readFontName (hb_font_get_face (native->getFont()),
|
||||
HB_OT_NAME_ID_FONT_FAMILY,
|
||||
nullptr).toRawUTF8(),
|
||||
unalignedPointerCast<const uint16_t*> (utf16.getAddress()),
|
||||
|
|
@ -442,7 +442,7 @@ private:
|
|||
const auto metrics = findNonPortableMetricsForData (blob);
|
||||
|
||||
return new AndroidTypeface (cache,
|
||||
HbFont { hb_font_create (face.get()) },
|
||||
HbFont (hb_font_create (face.get()), IncrementRef::no),
|
||||
metrics,
|
||||
readFontName (face.get(), HB_OT_NAME_ID_FONT_FAMILY, nullptr),
|
||||
readFontName (face.get(), HB_OT_NAME_ID_FONT_SUBFAMILY, nullptr),
|
||||
|
|
@ -461,20 +461,19 @@ private:
|
|||
}
|
||||
|
||||
AndroidTypeface (DoCache cache,
|
||||
std::shared_ptr<hb_font_t> fontIn,
|
||||
HbFont fontIn,
|
||||
TypefaceAscentDescent nonPortableMetricsIn,
|
||||
const String& name,
|
||||
const String& style,
|
||||
GlobalRef javaFontIn)
|
||||
: Typeface (name, style),
|
||||
hbFont (std::move (fontIn)),
|
||||
doCache (cache),
|
||||
nonPortableMetrics (nonPortableMetricsIn),
|
||||
javaFont (std::move (javaFontIn))
|
||||
javaFont (std::move (javaFontIn)),
|
||||
native (std::make_unique<Native> (TypefaceNativeOptions { std::move (fontIn), nonPortableMetricsIn, this }))
|
||||
{
|
||||
if (doCache == DoCache::yes)
|
||||
if (auto* c = MemoryFontCache::getInstance())
|
||||
c->add ({ name, style }, { hbFont, javaFont, nonPortableMetrics });
|
||||
c->add ({ name, style }, { fontIn, javaFont, nonPortableMetricsIn });
|
||||
}
|
||||
|
||||
static std::tuple<MemoryBlock, TypefaceAscentDescent> getBlobForFont (const Font& font)
|
||||
|
|
@ -664,22 +663,22 @@ private:
|
|||
|
||||
auto* env = getEnv();
|
||||
|
||||
hb_glyph_extents_t extents{};
|
||||
const auto extents = native->getGlyphExtents ((hb_codepoint_t) glyph);
|
||||
|
||||
if (! hb_font_get_glyph_extents (hbFont.get(), (hb_codepoint_t) glyph, &extents))
|
||||
if (! extents.has_value())
|
||||
{
|
||||
// Trying to retrieve an image for a glyph that's not present in the font?
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto upem = (jint) hb_face_get_upem (hb_font_get_face (hbFont.get()));
|
||||
const auto upem = (jint) hb_face_get_upem (hb_font_get_face (native->getFont()));
|
||||
constexpr jint referenceSize = 128;
|
||||
|
||||
const jint pixelW = (referenceSize * abs (extents.width)) / upem;
|
||||
const jint pixelH = (referenceSize * abs (extents.height)) / upem;
|
||||
const jint pixelBearingX = (referenceSize * extents.x_bearing) / upem;
|
||||
const jint pixelBearingY = (referenceSize * extents.y_bearing) / upem;
|
||||
const jint pixelW = (referenceSize * abs (extents->width)) / upem;
|
||||
const jint pixelH = (referenceSize * abs (extents->height)) / upem;
|
||||
const jint pixelBearingX = (referenceSize * extents->x_bearing) / upem;
|
||||
const jint pixelBearingY = (referenceSize * extents->y_bearing) / upem;
|
||||
|
||||
const jint pixelPadding = 2;
|
||||
|
||||
|
|
@ -760,10 +759,9 @@ private:
|
|||
.followedBy (transform) } } };
|
||||
}
|
||||
|
||||
std::shared_ptr<hb_font_t> hbFont;
|
||||
DoCache doCache;
|
||||
TypefaceAscentDescent nonPortableMetrics;
|
||||
GlobalRef javaFont;
|
||||
std::unique_ptr<Native> native;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -394,10 +394,8 @@ public:
|
|||
if (face == nullptr)
|
||||
return {};
|
||||
|
||||
auto* hbFace = hb_ft_face_create_referenced (face->face);
|
||||
const ScopeGuard scope { [&] { hb_face_destroy (hbFace); } };
|
||||
|
||||
HbFont hb { hb_font_create (hbFace) };
|
||||
HbFace hbFace { hb_ft_face_create_referenced (face->face), IncrementRef::no };
|
||||
HbFont hb { hb_font_create (hbFace.get()), IncrementRef::no };
|
||||
|
||||
if (hb == nullptr)
|
||||
return {};
|
||||
|
|
@ -413,10 +411,8 @@ public:
|
|||
if (face == nullptr)
|
||||
return {};
|
||||
|
||||
auto* hbFace = hb_ft_face_create_referenced (face->face);
|
||||
const ScopeGuard scope { [&] { hb_face_destroy (hbFace); } };
|
||||
|
||||
HbFont hb { hb_font_create (hbFace) };
|
||||
HbFace hbFace { hb_ft_face_create_referenced (face->face), IncrementRef::no };
|
||||
HbFont hb { hb_font_create (hbFace.get()), IncrementRef::no };
|
||||
|
||||
if (hb == nullptr)
|
||||
return {};
|
||||
|
|
@ -424,11 +420,6 @@ public:
|
|||
return new FreeTypeTypeface (DoCache::yes, face, std::move (hb), face->face->family_name, face->face->style_name);
|
||||
}
|
||||
|
||||
Native getNativeDetails() const override
|
||||
{
|
||||
return Native { hb.get(), nonPortableMetrics };
|
||||
}
|
||||
|
||||
Typeface::Ptr createSystemFallback ([[maybe_unused]] const String& text,
|
||||
[[maybe_unused]] const String& language) const override
|
||||
{
|
||||
|
|
@ -478,11 +469,18 @@ public:
|
|||
|
||||
~FreeTypeTypeface() override
|
||||
{
|
||||
native.reset();
|
||||
|
||||
if (doCache == DoCache::yes)
|
||||
if (auto* list = FTTypefaceList::getInstanceWithoutCreating())
|
||||
list->removeMemoryFace (ftFace);
|
||||
}
|
||||
|
||||
const Native* getNativeDetails() const override
|
||||
{
|
||||
return native.get();
|
||||
}
|
||||
|
||||
static Typeface::Ptr findSystemTypeface()
|
||||
{
|
||||
#if JUCE_USE_FONTCONFIG
|
||||
|
|
@ -530,8 +528,8 @@ private:
|
|||
if (face == nullptr)
|
||||
return {};
|
||||
|
||||
const HbFace hbFace { hb_ft_face_create_referenced (face->face) };
|
||||
HbFont cachedFont { hb_font_create (hbFace.get()) };
|
||||
HbFace hbFace { hb_ft_face_create_referenced (face->face), IncrementRef::no };
|
||||
HbFont cachedFont { hb_font_create (hbFace.get()), IncrementRef::no };
|
||||
|
||||
if (cachedFont == nullptr)
|
||||
return {};
|
||||
|
|
@ -541,6 +539,15 @@ private:
|
|||
}
|
||||
#endif
|
||||
|
||||
static TypefaceAscentDescent getNativeMetrics (FTFaceWrapper::Ptr ftFace)
|
||||
{
|
||||
const auto upem = (float) ftFace->face->units_per_EM;
|
||||
const auto ascent = (float) std::abs (ftFace->face->ascender) / upem;
|
||||
const auto descent = (float) std::abs (ftFace->face->descender) / upem;
|
||||
|
||||
return { ascent, descent };
|
||||
}
|
||||
|
||||
FreeTypeTypeface (DoCache cache,
|
||||
FTFaceWrapper::Ptr ftFaceIn,
|
||||
HbFont hbIn,
|
||||
|
|
@ -548,8 +555,8 @@ private:
|
|||
const String& styleIn)
|
||||
: Typeface (nameIn, styleIn),
|
||||
ftFace (ftFaceIn),
|
||||
hb (std::move (hbIn)),
|
||||
doCache (cache)
|
||||
doCache (cache),
|
||||
native (std::make_unique<Native> (TypefaceNativeOptions { std::move (hbIn), getNativeMetrics (ftFaceIn) }))
|
||||
{
|
||||
if (doCache == DoCache::yes)
|
||||
if (auto* list = FTTypefaceList::getInstance())
|
||||
|
|
@ -557,10 +564,8 @@ private:
|
|||
}
|
||||
|
||||
FTFaceWrapper::Ptr ftFace;
|
||||
HbFont hb;
|
||||
DoCache doCache;
|
||||
TypefaceAscentDescent nonPortableMetrics { (float) std::abs (ftFace->face->ascender) / (float) ftFace->face->units_per_EM,
|
||||
(float) std::abs (ftFace->face->descender) / (float) ftFace->face->units_per_EM };
|
||||
std::unique_ptr<Native> native;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (FreeTypeTypeface)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -174,14 +174,17 @@ public:
|
|||
if (ctFont == nullptr)
|
||||
return {};
|
||||
|
||||
HbFont result { hb_coretext_font_create (ctFont.get()) };
|
||||
HbFont result { hb_coretext_font_create (ctFont.get()), IncrementRef::no };
|
||||
|
||||
if (result == nullptr)
|
||||
return {};
|
||||
|
||||
FontStyleHelpers::initSynthetics (result.get(), font);
|
||||
|
||||
return new CoreTextTypeface (std::move (ctFont), std::move (result), font.getTypefaceName(), font.getTypefaceStyle());
|
||||
return new CoreTextTypeface (std::move (ctFont),
|
||||
std::move (result),
|
||||
font.getTypefaceName(),
|
||||
font.getTypefaceStyle());
|
||||
}
|
||||
|
||||
static Typeface::Ptr from (Span<const std::byte> data)
|
||||
|
|
@ -220,7 +223,7 @@ public:
|
|||
if (ctFont == nullptr)
|
||||
return {};
|
||||
|
||||
HbFont result { hb_coretext_font_create (ctFont.get()) };
|
||||
HbFont result { hb_coretext_font_create (ctFont.get()), IncrementRef::no };
|
||||
|
||||
if (result == nullptr)
|
||||
return {};
|
||||
|
|
@ -235,11 +238,6 @@ public:
|
|||
std::move (copy));
|
||||
}
|
||||
|
||||
Native getNativeDetails() const override
|
||||
{
|
||||
return Native { hb.get(), nonPortableMetrics };
|
||||
}
|
||||
|
||||
Typeface::Ptr createSystemFallback (const String& c, const String& language) const override
|
||||
{
|
||||
const CFUniquePtr<CFStringRef> cfText { c.toCFString() };
|
||||
|
|
@ -261,7 +259,7 @@ public:
|
|||
const CFUniquePtr<CFStringRef> newStyle { (CFStringRef) CTFontDescriptorCopyAttribute (descriptor.get(),
|
||||
kCTFontStyleNameAttribute) };
|
||||
|
||||
HbFont result { hb_coretext_font_create (newFont.get()) };
|
||||
HbFont result { hb_coretext_font_create (newFont.get()), IncrementRef::no };
|
||||
|
||||
if (result == nullptr)
|
||||
return {};
|
||||
|
|
@ -293,6 +291,11 @@ public:
|
|||
return ctFont.get();
|
||||
}
|
||||
|
||||
const Native* getNativeDetails() const override
|
||||
{
|
||||
return native.get();
|
||||
}
|
||||
|
||||
static Typeface::Ptr findSystemTypeface()
|
||||
{
|
||||
CFUniquePtr<CTFontRef> defaultCtFont (CTFontCreateUIFontForLanguage (kCTFontUIFontSystem, 0.0, nullptr));
|
||||
|
|
@ -301,7 +304,7 @@ public:
|
|||
const CFUniquePtr<CFStringRef> newStyle { (CFStringRef) CTFontDescriptorCopyAttribute (descriptor.get(),
|
||||
kCTFontStyleNameAttribute) };
|
||||
|
||||
HbFont result { hb_coretext_font_create (defaultCtFont.get()) };
|
||||
HbFont result { hb_coretext_font_create (defaultCtFont.get()), IncrementRef::no };
|
||||
|
||||
if (result == nullptr)
|
||||
return {};
|
||||
|
|
@ -314,6 +317,17 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
static TypefaceAscentDescent getNativeMetrics (CTFontRef ctFont)
|
||||
{
|
||||
const CFUniquePtr<CGFontRef> cgFont { CTFontCopyGraphicsFont (ctFont, nullptr) };
|
||||
|
||||
const auto upem = (float) CGFontGetUnitsPerEm (cgFont.get());
|
||||
const auto ascent = std::abs ((float) CGFontGetAscent (cgFont.get()) / upem);
|
||||
const auto descent = std::abs ((float) CGFontGetDescent (cgFont.get()) / upem);
|
||||
|
||||
return { ascent, descent };
|
||||
}
|
||||
|
||||
CoreTextTypeface (CFUniquePtr<CTFontRef> nativeFont,
|
||||
HbFont fontIn,
|
||||
const String& name,
|
||||
|
|
@ -321,8 +335,8 @@ private:
|
|||
MemoryBlock data = {})
|
||||
: Typeface (name, style),
|
||||
ctFont (std::move (nativeFont)),
|
||||
hb (std::move (fontIn)),
|
||||
storage (std::move (data))
|
||||
storage (std::move (data)),
|
||||
native (std::make_unique<Native> (TypefaceNativeOptions { std::move (fontIn), getNativeMetrics (ctFont.get()) }))
|
||||
{
|
||||
if (! storage.isEmpty())
|
||||
getRegistered().add (ctFont.get());
|
||||
|
|
@ -342,15 +356,8 @@ private:
|
|||
// We store this, rather than calling hb_coretext_font_get_ct_font, because harfbuzz may
|
||||
// override the font cascade list in the returned font.
|
||||
CFUniquePtr<CTFontRef> ctFont;
|
||||
HbFont hb;
|
||||
MemoryBlock storage;
|
||||
TypefaceAscentDescent nonPortableMetrics = [&]
|
||||
{
|
||||
const CFUniquePtr<CGFontRef> cgFont { CTFontCopyGraphicsFont (ctFont.get(), nullptr) };
|
||||
const auto upem = (float) CGFontGetUnitsPerEm (cgFont.get());
|
||||
return TypefaceAscentDescent { (float) std::abs (CGFontGetAscent (cgFont.get()) / upem),
|
||||
(float) std::abs (CGFontGetDescent (cgFont.get()) / upem) };
|
||||
}();
|
||||
std::unique_ptr<Native> native;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreTextTypeface)
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue