mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +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
|
|
@ -219,7 +219,7 @@ static std::vector<ShapedGlyph> lowLevelShape (Span<const juce_wchar> string,
|
|||
{
|
||||
static const auto language = SystemStats::getDisplayLanguage();
|
||||
|
||||
HbBuffer buffer { hb_buffer_create() };
|
||||
HbBuffer buffer { hb_buffer_create(), IncrementRef::no };
|
||||
hb_buffer_clear_contents (buffer.get());
|
||||
|
||||
hb_buffer_set_cluster_level (buffer.get(), HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES);
|
||||
|
|
@ -316,20 +316,14 @@ static std::vector<ShapedGlyph> lowLevelShape (Span<const juce_wchar> string,
|
|||
const auto xAdvanceBase = HbScale::hbToJuce (positions[visualIndex].x_advance);
|
||||
const auto yAdvanceBase = -HbScale::hbToJuce (positions[visualIndex].y_advance);
|
||||
|
||||
// For certain OS, Font and glyph ID combinations harfbuzz will not find extents data and
|
||||
// hb_font_get_glyph_extents will return false. In such cases Typeface::getGlyphBounds
|
||||
// will return an empty rectangle. Here we need to distinguish this situation from the one
|
||||
// where extents information is available and is an empty rectangle, which indicates a
|
||||
// whitespace.
|
||||
const auto extentsDataAvailable = std::invoke ([&]
|
||||
{
|
||||
hb_glyph_extents_t extents{};
|
||||
return hb_font_get_glyph_extents (font.getTypefacePtr()->getNativeDetails().getFont(),
|
||||
(hb_codepoint_t) glyphId,
|
||||
&extents);
|
||||
});
|
||||
// For certain OS, Font and glyph ID combinations harfbuzz will not find extents data.
|
||||
// In such cases Typeface::getGlyphBounds will return an empty rectangle. Here we need
|
||||
// to distinguish this situation from the one where extents information is available
|
||||
// and is an empty rectangle, which indicates a whitespace.
|
||||
const auto* native = font.getTypefacePtr()->getNativeDetails();
|
||||
const auto extents = native->getGlyphExtents (glyphId);
|
||||
|
||||
const auto whitespace = extentsDataAvailable
|
||||
const auto whitespace = extents.has_value()
|
||||
&& font.getTypefacePtr()->getGlyphBounds (font.getMetricsKind(), (int) glyphId).isEmpty()
|
||||
&& xAdvanceBase > 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ public:
|
|||
const ScopedLock lock (mutex);
|
||||
|
||||
if (auto ptr = getTypefacePtr (f))
|
||||
return ptr->getNativeDetails().getFontAtPointSizeAndScale (f.getHeightInPoints(), f.getHorizontalScale());
|
||||
return ptr->getNativeDetails()->getFontAtPointSizeAndScale (f.getHeightInPoints(), f.getHorizontalScale());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
@ -231,7 +231,7 @@ public:
|
|||
|
||||
if (auto ptr = getTypefacePtr (f))
|
||||
{
|
||||
const auto ascentDescent = ptr->getNativeDetails().getAscentDescent (f.getMetricsKind());
|
||||
const auto ascentDescent = ptr->getNativeDetails()->getAscentDescent (f.getMetricsKind());
|
||||
|
||||
auto adjusted = ascentDescent;
|
||||
adjusted.ascent = getAscentOverride().value_or (adjusted.ascent);
|
||||
|
|
@ -886,7 +886,7 @@ static bool characterNotRendered (uint32_t c)
|
|||
|
||||
static bool isFontSuitableForCodepoint (const Font& font, juce_wchar c)
|
||||
{
|
||||
const auto& hbFont = font.getNativeDetails().font;
|
||||
const auto hbFont = font.getNativeDetails().font;
|
||||
|
||||
if (hbFont == nullptr)
|
||||
return false;
|
||||
|
|
@ -994,7 +994,7 @@ Font::Native Font::getNativeDetails() const
|
|||
|
||||
Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
|
||||
{
|
||||
const auto resolvedTypeface = [&]() -> Typeface::Ptr
|
||||
const auto resolvedTypeface = std::invoke ([&]() -> Typeface::Ptr
|
||||
{
|
||||
if (font.getTypefaceName() != getSystemUIFontName())
|
||||
return {};
|
||||
|
|
@ -1010,7 +1010,7 @@ Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
|
|||
auto copy = font;
|
||||
copy.setTypefaceName (systemTypeface->getName());
|
||||
return getDefaultTypefaceForFont (copy);
|
||||
}();
|
||||
});
|
||||
|
||||
if (resolvedTypeface != nullptr)
|
||||
return resolvedTypeface;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
class HbScale
|
||||
{
|
||||
static constexpr float factor = 1 << 16;
|
||||
|
|
@ -53,6 +54,92 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
template <typename HbType, HbType* (*incRef) (HbType*), void (*decRef) (HbType*)>
|
||||
class HbPtr
|
||||
{
|
||||
public:
|
||||
HbPtr (HbType* i, IncrementRef incrementRefCount)
|
||||
: instance (i)
|
||||
{
|
||||
if (incrementRefCount == IncrementRef::yes)
|
||||
incRefIfNotNull();
|
||||
}
|
||||
|
||||
HbPtr() = default;
|
||||
|
||||
~HbPtr()
|
||||
{
|
||||
decRefIfNotNull();
|
||||
}
|
||||
|
||||
HbPtr (const HbPtr& other)
|
||||
: HbPtr (other.instance, IncrementRef::yes)
|
||||
{}
|
||||
|
||||
HbPtr (HbPtr&& other)
|
||||
{
|
||||
swap (other);
|
||||
}
|
||||
|
||||
HbPtr& operator= (const HbPtr& other)
|
||||
{
|
||||
HbPtr { other }.swap (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HbPtr& operator= (HbPtr&& other)
|
||||
{
|
||||
swap (other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HbPtr& operator= (std::nullptr_t)
|
||||
{
|
||||
return operator= (HbPtr { nullptr });
|
||||
}
|
||||
|
||||
HbType* get() const { return instance; }
|
||||
|
||||
bool operator== (std::nullptr_t) const
|
||||
{
|
||||
return instance == nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void incRefIfNotNull()
|
||||
{
|
||||
if (instance != nullptr)
|
||||
incRef (instance);
|
||||
}
|
||||
|
||||
void decRefIfNotNull()
|
||||
{
|
||||
if (instance != nullptr)
|
||||
decRef (instance);
|
||||
}
|
||||
|
||||
void swap (HbPtr& other) noexcept
|
||||
{
|
||||
std::swap (instance, other.instance);
|
||||
}
|
||||
|
||||
HbType* instance = nullptr;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
#define JUCE_HB_PTR_TYPE(type) \
|
||||
HbPtr<hb_ ## type ## _t, hb_ ## type ## _reference, hb_ ## type ## _destroy>
|
||||
|
||||
using HbFont = JUCE_HB_PTR_TYPE (font);
|
||||
using HbFontFuncs = JUCE_HB_PTR_TYPE (font_funcs);
|
||||
using HbFace = JUCE_HB_PTR_TYPE (face);
|
||||
using HbBuffer = JUCE_HB_PTR_TYPE (buffer);
|
||||
using HbBlob = JUCE_HB_PTR_TYPE (blob);
|
||||
using HbDrawFuncs = JUCE_HB_PTR_TYPE (draw_funcs);
|
||||
|
||||
#undef JUCE_HB_PTR_TYPE
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
template <CTFontOrientation orientation>
|
||||
|
|
@ -130,8 +217,7 @@ static auto getAdvancesFn()
|
|||
*/
|
||||
static void overrideCTFontAdvances (hb_font_t* hb, CTFontRef fontRef)
|
||||
{
|
||||
using HbFontFuncs = std::unique_ptr<hb_font_funcs_t, FunctionPointerDestructor<hb_font_funcs_destroy>>;
|
||||
const HbFontFuncs funcs { hb_font_funcs_create() };
|
||||
HbFontFuncs funcs { hb_font_funcs_create(), IncrementRef::no };
|
||||
|
||||
// We pass the CTFontRef as user data to each of these functions.
|
||||
// We don't pass a custom destructor for the user data, as that will be handled by the custom
|
||||
|
|
@ -170,30 +256,31 @@ struct TypefaceAscentDescent
|
|||
}
|
||||
};
|
||||
|
||||
using HbFont = std::unique_ptr<hb_font_t, FunctionPointerDestructor<hb_font_destroy>>;
|
||||
using HbFace = std::unique_ptr<hb_face_t, FunctionPointerDestructor<hb_face_destroy>>;
|
||||
using HbBuffer = std::unique_ptr<hb_buffer_t, FunctionPointerDestructor<hb_buffer_destroy>>;
|
||||
using HbBlob = std::unique_ptr<hb_blob_t, FunctionPointerDestructor<hb_blob_destroy>>;
|
||||
|
||||
struct TypefaceFallbackColourGlyphSupport
|
||||
{
|
||||
virtual ~TypefaceFallbackColourGlyphSupport() = default;
|
||||
virtual std::vector<GlyphLayer> getFallbackColourGlyphLayers (int, const AffineTransform&) const = 0;
|
||||
};
|
||||
|
||||
struct TypefaceNativeOptions
|
||||
{
|
||||
HbFont font;
|
||||
TypefaceAscentDescent metrics;
|
||||
TypefaceFallbackColourGlyphSupport* colourGlyphSupport{};
|
||||
};
|
||||
|
||||
class Typeface::Native
|
||||
{
|
||||
public:
|
||||
Native (hb_font_t* fontRef,
|
||||
TypefaceAscentDescent nonPortableMetricsIn,
|
||||
const TypefaceFallbackColourGlyphSupport* colourGlyphSupportIn = {})
|
||||
: font (fontRef),
|
||||
nonPortable (nonPortableMetricsIn),
|
||||
colourGlyphSupport (colourGlyphSupportIn)
|
||||
explicit Native (TypefaceNativeOptions options)
|
||||
: font (std::move (options.font)),
|
||||
nonPortable (options.metrics),
|
||||
colourGlyphSupport (options.colourGlyphSupport)
|
||||
{
|
||||
}
|
||||
|
||||
auto* getFont() const { return font; }
|
||||
// Returns the backing HarfBuzz font with a size of 1 pt (i.e. 1 pt per em).
|
||||
hb_font_t* getFont() const { return font.get(); }
|
||||
|
||||
TypefaceAscentDescent getAscentDescent (TypefaceMetricsKind kind) const
|
||||
{
|
||||
|
|
@ -209,52 +296,68 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
std::optional<hb_glyph_extents_t> getGlyphExtents (hb_codepoint_t glyphId) const
|
||||
{
|
||||
return glyphExtentsCache.get (glyphId, [this] (auto gid) -> std::optional<hb_glyph_extents_t>
|
||||
{
|
||||
hb_glyph_extents_t extents{};
|
||||
|
||||
if (hb_font_get_glyph_extents (getFont(), gid, &extents) == 0)
|
||||
return {};
|
||||
|
||||
return extents;
|
||||
});
|
||||
}
|
||||
|
||||
HbFont getFontAtPointSizeAndScale (float points, float horizontalScale) const
|
||||
{
|
||||
HbFont subFont { hb_font_create_sub_font (font) };
|
||||
return subFontCache.get ({ points, horizontalScale }, [this] (auto args)
|
||||
{
|
||||
const auto [p, h] = args;
|
||||
HbFont subFont { hb_font_create_sub_font (getFont()), IncrementRef::no };
|
||||
|
||||
hb_font_set_ptem (subFont.get(), points);
|
||||
hb_font_set_scale (subFont.get(), HbScale::juceToHb (points * horizontalScale), HbScale::juceToHb (points));
|
||||
hb_font_set_ptem (subFont.get(), p);
|
||||
hb_font_set_scale (subFont.get(), HbScale::juceToHb (p * h), HbScale::juceToHb (p));
|
||||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
overrideCTFontAdvances (subFont.get(), hb_coretext_font_get_ct_font (subFont.get()));
|
||||
#endif
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
overrideCTFontAdvances (subFont.get(), hb_coretext_font_get_ct_font (subFont.get()));
|
||||
#endif
|
||||
|
||||
return subFont;
|
||||
return subFont;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<GlyphLayer> getFallbackColourGlyphLayers (int glyph,
|
||||
const AffineTransform& transform) const
|
||||
{
|
||||
if (colourGlyphSupport != nullptr)
|
||||
return colourGlyphSupport->getFallbackColourGlyphLayers (glyph, transform);
|
||||
if (colourGlyphSupport == nullptr)
|
||||
return {};
|
||||
|
||||
return {};
|
||||
return colourGlyphSupport->getFallbackColourGlyphLayers (glyph, transform);
|
||||
}
|
||||
|
||||
private:
|
||||
static TypefaceAscentDescent findPortableMetrics (hb_font_t* f, TypefaceAscentDescent fallback)
|
||||
HbFont font;
|
||||
TypefaceAscentDescent nonPortable;
|
||||
TypefaceAscentDescent portable = std::invoke ([&]
|
||||
{
|
||||
hb_font_extents_t extents{};
|
||||
|
||||
if (! hb_font_get_h_extents (f, &extents))
|
||||
return fallback;
|
||||
if (! hb_font_get_h_extents (font.get(), &extents))
|
||||
return nonPortable;
|
||||
|
||||
const auto ascent = std::abs ((float) extents.ascender);
|
||||
const auto descent = std::abs ((float) extents.descender);
|
||||
const auto upem = (float) hb_face_get_upem (hb_font_get_face (f));
|
||||
const auto upem = (float) hb_face_get_upem (hb_font_get_face (font.get()));
|
||||
|
||||
TypefaceAscentDescent result;
|
||||
result.ascent = ascent / upem;
|
||||
result.descent = descent / upem;
|
||||
return result;
|
||||
}
|
||||
|
||||
hb_font_t* font = nullptr;
|
||||
|
||||
TypefaceAscentDescent nonPortable;
|
||||
TypefaceAscentDescent portable = findPortableMetrics (font, nonPortable);
|
||||
const TypefaceFallbackColourGlyphSupport* colourGlyphSupport = nullptr;
|
||||
});
|
||||
TypefaceFallbackColourGlyphSupport* colourGlyphSupport;
|
||||
mutable LruCache<std::tuple<float, float>, HbFont> subFontCache;
|
||||
mutable LruCache<hb_codepoint_t, std::optional<hb_glyph_extents_t>, 512> glyphExtentsCache;
|
||||
};
|
||||
|
||||
struct FontStyleHelpers
|
||||
|
|
@ -354,12 +457,13 @@ struct FontStyleHelpers
|
|||
(unsigned int) bytes.size(),
|
||||
HB_MEMORY_MODE_DUPLICATE,
|
||||
nullptr,
|
||||
nullptr) };
|
||||
nullptr),
|
||||
IncrementRef::no };
|
||||
|
||||
const auto count = hb_face_count (blob.get());
|
||||
|
||||
if (index < count)
|
||||
return HbFace { hb_face_create (blob.get(), index) };
|
||||
return { hb_face_create (blob.get(), index), IncrementRef::no };
|
||||
|
||||
// Attempted to create a font from invalid data. Perhaps the font format was unrecognised.
|
||||
jassertfalse;
|
||||
|
|
@ -367,20 +471,16 @@ struct FontStyleHelpers
|
|||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
Typeface::Typeface (const String& faceName, const String& faceStyle) noexcept
|
||||
: name (faceName),
|
||||
style (faceStyle)
|
||||
Typeface::Typeface (const String& nameIn, const String& styleIn)
|
||||
: name (nameIn), style (styleIn)
|
||||
{
|
||||
}
|
||||
|
||||
Typeface::~Typeface() = default;
|
||||
|
||||
using HbDrawFuncs = std::unique_ptr<hb_draw_funcs_t, FunctionPointerDestructor<hb_draw_funcs_destroy>>;
|
||||
|
||||
static HbDrawFuncs getPathDrawFuncs()
|
||||
{
|
||||
HbDrawFuncs funcs { hb_draw_funcs_create() };
|
||||
HbDrawFuncs funcs { hb_draw_funcs_create(), IncrementRef::no };
|
||||
|
||||
hb_draw_funcs_set_move_to_func (funcs.get(), [] (auto*, void* data, auto*, float x, float y, auto*)
|
||||
{
|
||||
|
|
@ -422,34 +522,32 @@ static HbDrawFuncs getPathDrawFuncs()
|
|||
|
||||
void Typeface::getOutlineForGlyph (TypefaceMetricsKind kind, int glyphNumber, Path& path) const
|
||||
{
|
||||
const auto native = getNativeDetails();
|
||||
auto* font = native.getFont();
|
||||
const auto metrics = native.getAscentDescent (kind);
|
||||
auto* font = getNativeDetails()->getFont();
|
||||
const auto metrics = getNativeDetails()->getAscentDescent (kind);
|
||||
const auto factor = metrics.getHeightToPointsFactor();
|
||||
jassert (! std::isinf (factor));
|
||||
const auto scale = factor / (float) hb_face_get_upem (hb_font_get_face (font));
|
||||
|
||||
// getTypefaceGlyph returns glyphs in em space, getOutlineForGlyph returns glyphs in "special JUCE units" space
|
||||
path = getGlyphPathInGlyphUnits ((hb_codepoint_t) glyphNumber, getNativeDetails().getFont());
|
||||
path = getGlyphPathInGlyphUnits ((hb_codepoint_t) glyphNumber, font);
|
||||
path.applyTransform (AffineTransform::scale (scale, -scale));
|
||||
}
|
||||
|
||||
Rectangle<float> Typeface::getGlyphBounds (TypefaceMetricsKind kind, int glyphNumber) const
|
||||
{
|
||||
auto* font = getNativeDetails().getFont();
|
||||
const auto extents = getNativeDetails()->getGlyphExtents ((hb_codepoint_t) glyphNumber);
|
||||
|
||||
hb_glyph_extents_t extents{};
|
||||
if (! hb_font_get_glyph_extents (font, (hb_codepoint_t) glyphNumber, &extents))
|
||||
if (! extents.has_value())
|
||||
return {};
|
||||
|
||||
const auto native = getNativeDetails();
|
||||
const auto metrics = native.getAscentDescent (kind);
|
||||
auto* font = getNativeDetails()->getFont();
|
||||
const auto metrics = getNativeDetails()->getAscentDescent (kind);
|
||||
const auto factor = metrics.getHeightToPointsFactor();
|
||||
jassert (! std::isinf (factor));
|
||||
const auto scale = factor / (float) hb_face_get_upem (hb_font_get_face (font));
|
||||
|
||||
return Rectangle { (float) extents.width, (float) extents.height }
|
||||
.withPosition ((float) extents.x_bearing, (float) extents.y_bearing)
|
||||
return Rectangle { (float) extents->width, (float) extents->height }
|
||||
.withPosition ((float) extents->x_bearing, (float) extents->y_bearing)
|
||||
.transformedBy (AffineTransform::scale (scale).scaled (1.0f, -1.0f));
|
||||
}
|
||||
|
||||
|
|
@ -477,7 +575,7 @@ static Colour makeColour (hb_color_t c)
|
|||
|
||||
static std::vector<GlyphLayer> getCOLRv0Layers (const Typeface& typeface, int glyphNumber, const AffineTransform& transform)
|
||||
{
|
||||
auto* font = typeface.getNativeDetails().getFont();
|
||||
auto* font = typeface.getNativeDetails()->getFont();
|
||||
auto* face = hb_font_get_face (font);
|
||||
constexpr auto palette = 0;
|
||||
|
||||
|
|
@ -519,9 +617,16 @@ static std::vector<GlyphLayer> getBitmapLayer (const Typeface& typeface, int gly
|
|||
if ((typeface.getColourGlyphFormats() & Typeface::colourGlyphFormatBitmap) == 0)
|
||||
return {};
|
||||
|
||||
auto* font = typeface.getNativeDetails().getFont();
|
||||
const auto* native = typeface.getNativeDetails();
|
||||
const auto extents = native->getGlyphExtents ((hb_codepoint_t) glyphNumber);
|
||||
|
||||
const HbBlob blob { hb_ot_color_glyph_reference_png (font, (hb_codepoint_t) glyphNumber) };
|
||||
if (! extents.has_value())
|
||||
return {};
|
||||
|
||||
auto* font = native->getFont();
|
||||
|
||||
HbBlob blob { hb_ot_color_glyph_reference_png (font, (hb_codepoint_t) glyphNumber),
|
||||
IncrementRef::no };
|
||||
|
||||
unsigned int imageDataSize{};
|
||||
const char* imageData = hb_blob_get_data (blob.get(), &imageDataSize);
|
||||
|
|
@ -530,16 +635,13 @@ static std::vector<GlyphLayer> getBitmapLayer (const Typeface& typeface, int gly
|
|||
if (juceImage.isNull())
|
||||
return {};
|
||||
|
||||
hb_glyph_extents_t extents{};
|
||||
hb_font_get_glyph_extents (font, (hb_codepoint_t) glyphNumber, &extents);
|
||||
|
||||
const auto wDenom = std::max (1, juceImage.getWidth());
|
||||
const auto hDenom = std::max (1, juceImage.getHeight());
|
||||
|
||||
const auto transform = AffineTransform::scale ((float) extents.width / (float) wDenom,
|
||||
(float) extents.height / (float) hDenom)
|
||||
.translated ((float) extents.x_bearing,
|
||||
(float) extents.y_bearing)
|
||||
const auto transform = AffineTransform::scale ((float) extents->width / (float) wDenom,
|
||||
(float) extents->height / (float) hDenom)
|
||||
.translated ((float) extents->x_bearing,
|
||||
(float) extents->y_bearing)
|
||||
.followedBy (t);
|
||||
return { GlyphLayer { ImageLayer { juceImage, transform } } };
|
||||
}
|
||||
|
|
@ -548,9 +650,8 @@ std::vector<GlyphLayer> Typeface::getLayersForGlyph (TypefaceMetricsKind kind,
|
|||
int glyphNumber,
|
||||
const AffineTransform& transform) const
|
||||
{
|
||||
auto native = getNativeDetails();
|
||||
auto* font = native.getFont();
|
||||
const auto metrics = native.getAscentDescent (kind);
|
||||
auto* font = getNativeDetails()->getFont();
|
||||
const auto metrics = getNativeDetails()->getAscentDescent (kind);
|
||||
const auto factor = metrics.getHeightToPointsFactor();
|
||||
jassert (! std::isinf (factor));
|
||||
const auto scale = factor / (float) hb_face_get_upem (hb_font_get_face (font));
|
||||
|
|
@ -569,7 +670,7 @@ std::vector<GlyphLayer> Typeface::getLayersForGlyph (TypefaceMetricsKind kind,
|
|||
// easily display. In such cases, we can use system facilities to render the glyph into a
|
||||
// bitmap. If the face has colour info that wasn't already handled, try rendering to a bitmap.
|
||||
if (getColourGlyphFormats() != 0)
|
||||
if (auto layer = native.getFallbackColourGlyphLayers (glyphNumber, combinedTransform); ! layer.empty())
|
||||
if (auto layer = getNativeDetails()->getFallbackColourGlyphLayers (glyphNumber, combinedTransform); ! layer.empty())
|
||||
return layer;
|
||||
|
||||
// No colour info available for this glyph, so just get a simple monochromatic outline
|
||||
|
|
@ -584,7 +685,7 @@ std::vector<GlyphLayer> Typeface::getLayersForGlyph (TypefaceMetricsKind kind,
|
|||
|
||||
int Typeface::getColourGlyphFormats() const
|
||||
{
|
||||
auto* face = hb_font_get_face (getNativeDetails().getFont());
|
||||
auto* face = hb_font_get_face (getNativeDetails()->getFont());
|
||||
return (hb_ot_color_has_png (face) ? colourGlyphFormatBitmap : 0)
|
||||
| (hb_ot_color_has_svg (face) ? colourGlyphFormatSvg : 0)
|
||||
| (hb_ot_color_has_layers (face) ? colourGlyphFormatCOLRv0 : 0)
|
||||
|
|
@ -593,7 +694,7 @@ int Typeface::getColourGlyphFormats() const
|
|||
|
||||
TypefaceMetrics Typeface::getMetrics (TypefaceMetricsKind kind) const
|
||||
{
|
||||
return getNativeDetails().getAscentDescent (kind).getTypefaceMetrics();
|
||||
return getNativeDetails()->getAscentDescent (kind).getTypefaceMetrics();
|
||||
}
|
||||
|
||||
Typeface::Ptr Typeface::createSystemTypefaceFor (const void* fontFileData, size_t fontFileDataSize)
|
||||
|
|
@ -604,7 +705,7 @@ Typeface::Ptr Typeface::createSystemTypefaceFor (const void* fontFileData, size_
|
|||
//==============================================================================
|
||||
std::optional<uint32_t> Typeface::getNominalGlyphForCodepoint (juce_wchar cp) const
|
||||
{
|
||||
auto* font = getNativeDetails().getFont();
|
||||
auto* font = getNativeDetails()->getFont();
|
||||
|
||||
if (font == nullptr)
|
||||
return {};
|
||||
|
|
@ -630,14 +731,14 @@ static float doSimpleShapeWithNoBreaks (const Typeface& typeface,
|
|||
float horizontalScale,
|
||||
Consumer&& consumer)
|
||||
{
|
||||
HbBuffer buffer { hb_buffer_create() };
|
||||
HbBuffer buffer { hb_buffer_create(), IncrementRef::no };
|
||||
hb_buffer_add_utf8 (buffer.get(), text.toRawUTF8(), -1, 0, -1);
|
||||
hb_buffer_set_cluster_level (buffer.get(), HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
|
||||
hb_buffer_guess_segment_properties (buffer.get());
|
||||
|
||||
const auto& native = typeface.getNativeDetails();
|
||||
const auto* native = typeface.getNativeDetails();
|
||||
const auto points = typeface.getMetrics (kind).heightToPoints * height;
|
||||
const auto sized = native.getFontAtPointSizeAndScale (points, horizontalScale);
|
||||
const auto sized = native->getFontAtPointSizeAndScale (points, horizontalScale);
|
||||
auto* font = sized.get();
|
||||
|
||||
// Disable ligatures, because TextEditor requires a 1:1 codepoint/glyph mapping for caret
|
||||
|
|
@ -737,7 +838,7 @@ std::vector<FontFeatureTag> Typeface::getSupportedFeatures() const
|
|||
HB_OT_TAG_GSUB
|
||||
};
|
||||
|
||||
auto* face = hb_font_get_face (getNativeDetails().getFont());
|
||||
auto* face = hb_font_get_face (getNativeDetails()->getFont());
|
||||
|
||||
for (auto table : tagTables)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -130,8 +130,6 @@ struct TypefaceMetrics
|
|||
class JUCE_API Typeface : public ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
Typeface (const String& name, const String& newStyle) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** A handy typedef for a pointer to a typeface. */
|
||||
using Ptr = ReferenceCountedObjectPtr<Typeface>;
|
||||
|
|
@ -315,17 +313,6 @@ public:
|
|||
*/
|
||||
std::optional<uint32_t> getNominalGlyphForCodepoint (juce_wchar) const;
|
||||
|
||||
/** @internal */
|
||||
class Native;
|
||||
|
||||
/** @internal
|
||||
|
||||
At the moment, this is a way to get at the hb_font_t that backs this typeface.
|
||||
The typeface's hb_font_t has a size of 1 pt (i.e. 1 pt per em).
|
||||
This is only for internal use!
|
||||
*/
|
||||
virtual Native getNativeDetails() const = 0;
|
||||
|
||||
/** Attempts to locate a font with a similar style that is capable of displaying the requested
|
||||
string.
|
||||
|
||||
|
|
@ -394,6 +381,16 @@ public:
|
|||
*/
|
||||
std::vector<FontFeatureTag> getSupportedFeatures() const;
|
||||
|
||||
/** @internal */
|
||||
class Native;
|
||||
|
||||
/** @internal */
|
||||
virtual const Native* getNativeDetails() const = 0;
|
||||
|
||||
protected:
|
||||
/** @internal */
|
||||
Typeface (const String&, const String&);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
String name;
|
||||
|
|
|
|||
|
|
@ -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