Files
rive-cpp/include/rive/text/font_hb.hpp
dskuza a629422a34 Support supplying mobile fallback fonts by style with caching
This pull request builds on top of fallback font support on iOS by including the ability to provide fallback fonts based on the styling of the missing character. Currently, the style information only contains weight. This weight is grabbed by calling `getAxisValue`. According to Luigi, this is a linear search, so perhaps there's room for a performance optimization later on.

There is one lower-level C++ change: `gFallbackProc` returns the font for the missing character, in addition _to_ the missing character (as a second parameter). This font will be used to generate the requested styling within the iOS runtime.

This adds a new class property to `RiveFont`: `fallbackFontCallback` (whose name I'm open to changing). This is a block (i.e closure) that will be called when a fallback font is requested. It supplies the styling of the missing character so that, for example, different fonts can be used based on the weight of the missing character. For example usage, see `SwiftFallbackFonts.swift`. This provider is what's used under-the-hood, and utilizes the pre-existing `fallbackFonts` class property

The "trickiest" bit here is the caching. NSDictionary requires equatable / hashable types as keys, and we want to minimize additional generation of a Rive font, so we cache any used fonts in a wrapper type, used as the value. When new fallback fonts are provided, either directly or when a new provider block is set, the cache will be reset. Once the weight is determined, generating the right key is as simple as calling the right initializer, and when set, generating the right value is simple as calling the right initializer with the created Rive font.

Finally, `RiveFactory` was getting a little bloated, so I did a little file cleanup.

This pull requests also includes Android support from #8621

Diffs=
7986d64d83 Support supplying mobile fallback fonts by style with caching (#8396)

Co-authored-by: David Skuza <david@rive.app>
Co-authored-by: Umberto <usonnino@gmail.com>
Co-authored-by: Umberto Sonnino <umberto@rive.app>
2024-11-27 16:50:58 +00:00

77 lines
2.4 KiB
C++

#ifndef _RIVE_FONT_HB_HPP_
#define _RIVE_FONT_HB_HPP_
#include "rive/factory.hpp"
#include "rive/text_engine.hpp"
#include <unordered_map>
struct hb_font_t;
struct hb_draw_funcs_t;
struct hb_feature_t;
class HBFont : public rive::Font
{
public:
// We assume ownership of font!
HBFont(hb_font_t* font);
~HBFont() override;
Axis getAxis(uint16_t index) const override;
uint16_t getAxisCount() const override;
float getAxisValue(uint32_t axisTag) const override;
uint32_t getFeatureValue(uint32_t featureTag) const override;
uint16_t getWeight() const override;
bool isItalic() const override;
rive::RawPath getPath(rive::GlyphID) const override;
rive::SimpleArray<rive::Paragraph> onShapeText(
rive::Span<const rive::Unichar>,
rive::Span<const rive::TextRun>,
int textDirectionFlag) const override;
rive::SimpleArray<uint32_t> features() const override;
rive::rcp<Font> withOptions(
rive::Span<const Coord> variableAxes,
rive::Span<const Feature> features) const override;
bool hasGlyph(const rive::Unichar) const override;
static rive::rcp<rive::Font> Decode(rive::Span<const uint8_t>);
static rive::rcp<rive::Font> FromSystem(void* systemFont,
bool useSystemShaper,
uint16_t weight,
uint8_t width);
static float GetStyle(hb_font_t*, uint32_t);
hb_font_t* font() const { return m_font; }
private:
HBFont(hb_font_t* font,
std::unordered_map<uint32_t, float> axisValues,
std::unordered_map<uint32_t, uint32_t> featureValues,
std::vector<hb_feature_t> features);
public:
hb_font_t* m_font;
virtual void shapeFallbackRun(
rive::SimpleArrayBuilder<rive::GlyphRun>& gruns,
const rive::Unichar text[],
const unsigned textStart,
const rive::TextRun& textRun,
const rive::TextRun& originalTextRun,
const uint32_t fallbackIndex);
// The features list to pass directly to Harfbuzz.
std::vector<hb_feature_t> m_features;
private:
hb_draw_funcs_t* m_drawFuncs;
// Feature value lookup based on tag.
std::unordered_map<uint32_t, uint32_t> m_featureValues;
// Axis value lookup based on for the feature.
std::unordered_map<uint32_t, float> m_axisValues;
};
#endif