Skip to content

Commit

Permalink
Pull fonts on-demand, but with a font cache
Browse files Browse the repository at this point in the history
  • Loading branch information
timothyschoen committed Dec 3, 2024
1 parent 94c44d2 commit 5946e9d
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 68 deletions.
29 changes: 16 additions & 13 deletions Source/Components/PropertiesPanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,37 +324,40 @@ class PropertiesPanel : public Component {
StringArray options = Font::findAllTypefaceNames();
bool isFontMissing = false;

FontComponent(String const& propertyName, Value& value, bool appendPatchFonts = false)
FontComponent(String const& propertyName, Value& value, File const& extraFontsDir = File())
: PropertiesPanelProperty(propertyName)
{
StringArray patchFontOptions;
StringArray extraFontOptions;

auto patchFonts = Fonts::getPatchFonts();
if (appendPatchFonts) {
if(extraFontsDir.isDirectory() && !extraFontsDir.isRoot()) {
auto patchFonts = Fonts::getFontsInFolder(extraFontsDir);
for (int n = 0; n < patchFonts.size(); n++) {
patchFontOptions.addIfNotAlreadyThere(patchFonts[n]->getName());
extraFontOptions.addIfNotAlreadyThere(patchFonts[n].getFileNameWithoutExtension());
}
}
patchFontOptions.addIfNotAlreadyThere("Inter Regular");
#if JUCE_WINDOWS
extraFontOptions.addIfNotAlreadyThere("Inter Regular");
#else
extraFontOptions.addIfNotAlreadyThere("Inter");
#endif

auto offset = patchFontOptions.size();
auto offset = extraFontOptions.size();
extraFontOptions.addArray(options);

patchFontOptions.addArray(options);

for (int n = 0; n < patchFontOptions.size(); n++) {
for (int n = 0; n < extraFontOptions.size(); n++) {
if (n == offset)
comboBox.getRootMenu()->addSeparator();

comboBox.getRootMenu()->addCustomItem(n + 1, std::make_unique<FontEntry>(patchFontOptions[n]), nullptr, patchFontOptions[n]);
comboBox.getRootMenu()->addCustomItem(n + 1, std::make_unique<FontEntry>(extraFontOptions[n]), nullptr, extraFontOptions[n]);

}

comboBox.setText(value.toString());
comboBox.getProperties().set("Style", "Inspector");
fontValue.referTo(value);

comboBox.onChange = [this, patchFontOptions, propertyName]() {
auto fontName = patchFontOptions[comboBox.getSelectedItemIndex()];
comboBox.onChange = [this, extraFontOptions, propertyName]() {
auto fontName = extraFontOptions[comboBox.getSelectedItemIndex()];

if (fontName.isEmpty()) {
isFontMissing = true;
Expand Down
4 changes: 2 additions & 2 deletions Source/Objects/NoteObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,9 @@ class NoteObject final : public ObjectBase {
if (typefaceName.isEmpty() || typefaceName == "Inter") {
return Fonts::getVariableFont().withStyle(style).withHeight(fontHeight);
}

// Check if there is a patch font loaded via the patch loading
if (auto patchFont = Fonts::getPatchTypefaceFor(typefaceName); patchFont.has_value())
if (auto patchFont = Fonts::findFont(cnv->patch.getCurrentFile(), typefaceName); patchFont.has_value())
return (*patchFont).withStyle(style).withHeight(fontHeight);

return { typefaceName, static_cast<float>(fontHeight), style };
Expand Down
13 changes: 10 additions & 3 deletions Source/Sidebar/Inspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ class Inspector : public Component {
panel.setContentWidth(getWidth() - 16);
}

static PropertiesPanelProperty* createPanel(int type, String const& name, Value* value, StringArray& options, std::function<void(bool)> onInteractionFn = nullptr)
PropertiesPanelProperty* createPanel(int type, String const& name, Value* value, StringArray& options, std::function<void(bool)> onInteractionFn = nullptr)
{

switch (type) {
case tString:
return new PropertiesPanel::EditableComponent<String>(name, *value);
Expand All @@ -135,8 +136,14 @@ class Inspector : public Component {
return new PropertiesPanel::RangeComponent(name, *value, false);
case tRangeInt:
return new PropertiesPanel::RangeComponent(name, *value, true);
case tFont:
return new PropertiesPanel::FontComponent(name, *value, true);
case tFont: {
if (auto* editor = findParentComponentOfClass<PluginEditor>()) {
if(auto* cnv = editor->getCurrentCanvas()) {
return new PropertiesPanel::FontComponent(name, *value, cnv->patch.getCurrentFile().getParentDirectory());
}
}
return new PropertiesPanel::FontComponent(name, *value);
}
default:
return new PropertiesPanel::EditableComponent<String>(name, *value);
}
Expand Down
13 changes: 1 addition & 12 deletions Source/TabComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,7 @@ Canvas* TabComponent::openPatch(const URL& path)
}
}
}

// Find any font files that are inside the root directory of the patch (recursive)
auto dir = patchFile.getParentDirectory();

Array<File> fontFiles;

auto foundFonts = dir.findChildFiles(File::findFiles, true, "*.ttf;*.otf;*.woff;*.woff2;*.eot");

for (auto font : foundFonts) {
Fonts::addPatchTypeface(font);
}


auto patch = pd->loadPatch(path);
return openPatch(patch, true);
}
Expand Down
67 changes: 31 additions & 36 deletions Source/Utility/Fonts.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,45 +63,40 @@ struct Fonts {

static Font setCurrentFont(Font const& font) { return instance->currentTypeface = font.getTypefacePtr(); }

static void addPatchTypeface(const File& fontFile)
{
if (fontFile.existsAsFile())
{
auto fileStream = fontFile.createInputStream();
if (fileStream == nullptr)
return;

MemoryBlock fontData;
fileStream->readIntoMemoryBlock(fontData);
auto fontToLoad = Typeface::createSystemTypefaceFor(fontData.getData(), fontData.getSize());
if (fontToLoad == nullptr)
return;

auto fontsName = fontToLoad->getName();
bool uniqueFont = true;
for (auto fonts: instance->patchTypefaces) {
if (fonts->getName() == fontsName)
uniqueFont = false;
static Array<File> getFontsInFolder(File const& patchFile)
{
return patchFile.getParentDirectory().findChildFiles(File::findFiles, true, "*.ttf;*.otf;");
}

static std::optional<Font> findFont(File const& dirToSearch, String const& typefaceFileName)
{
Array<File> fontFiles = dirToSearch.getParentDirectory().findChildFiles(File::findFiles, true, "*.ttf;*.otf;");

for (auto font : fontFiles) {
if(font.getFileNameWithoutExtension() == typefaceFileName)
{
auto it = fontTable.find(font.getFullPathName());
if(it != fontTable.end())
{
return it->second;
}
else if (font.existsAsFile())
{
auto fileStream = font.createInputStream();
if (fileStream == nullptr) break;

MemoryBlock fontData;
fileStream->readIntoMemoryBlock(fontData);
auto typeface = Typeface::createSystemTypefaceFor(fontData.getData(), fontData.getSize());
fontTable[font.getFullPathName()] = typeface;
return typeface;
}
}
if (uniqueFont)
instance->patchTypefaces.add(fontToLoad);
}
}

static std::optional<Font> getPatchTypefaceFor(String const& typefaceName)
{
for (auto font : instance->patchTypefaces) {
if (font->getName() == typefaceName)
return font;
}

return std::nullopt;
}

static SmallArray<Typeface::Ptr> getPatchFonts()
{
return instance->patchTypefaces;
}

// For drawing icons with icon font
static void drawIcon(Graphics& g, String const& icon, Rectangle<int> bounds, Colour colour, int fontHeight = -1, bool centred = true)
{
Expand Down Expand Up @@ -226,6 +221,6 @@ struct Fonts {
Typeface::Ptr monoTypeface;
Typeface::Ptr variableTypeface;
Typeface::Ptr tabularTypeface;

SmallArray<Typeface::Ptr> patchTypefaces;
static inline UnorderedMap<String, Font> fontTable = UnorderedMap<String, Font>();
};
4 changes: 2 additions & 2 deletions Tests/Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ void runTests(PluginEditor* editor)
std::thread testRunnerThread([editor] {
ObjectFuzzTest objectFuzzer(editor);
HelpFileFuzzTest helpfileFuzzer(editor);

UnitTestRunner runner;
runner.runTests({&objectFuzzer, &helpfileFuzzer}, 1);
runner.runTests({&objectFuzzer, &helpfileFuzzer}, 23);
});
testRunnerThread.detach();
}

0 comments on commit 5946e9d

Please sign in to comment.