Files
MagicSetEditor2/src/data/font.cpp
T
2025-08-11 16:17:13 +02:00

202 lines
6.7 KiB
C++

//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <data/font.hpp>
#include <wx/stdpaths.h>
#include <wx/dir.h>
#include <wx/font.h>
// ----------------------------------------------------------------------------- : Font
Font::Font()
: name()
, size(1)
, underline(false)
, scale_down_to(100000)
, max_stretch(1.0)
, color(Color(0,0,0))
, shadow_displacement_x(0)
, shadow_displacement_y(0)
, shadow_blur(0)
, separator_color(Color(0,0,0,128))
, flags(FONT_NORMAL)
{}
bool Font::PreloadResourceFonts(bool recursive) {
#if wxUSE_PRIVATE_FONTS
String pathSeparator(wxFileName::GetPathSeparator());
String appPath(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath());
wxDir appDir(appPath);
if (!appDir.IsOpened()) return true;
bool preloadHadErrors = false;
wxString folder;
bool cont = appDir.GetFirst(&folder, wxEmptyString, wxDIR_DIRS);
while (cont)
{
if (folder.Lower().Contains("fonts")) {
String folderPath = appPath + pathSeparator + folder + pathSeparator;
// tally fonts
vector<String> fontFilePaths;
TallyResourceFonts(folderPath, fontFilePaths, recursive);
// load fonts
for (const String& fontFilePath : fontFilePaths) {
if (!wxFont::AddPrivateFont(fontFilePath)) {
preloadHadErrors = true;
}
}
}
cont = appDir.GetNext(&folder);
}
return preloadHadErrors;
#endif // wxUSE_PRIVATE_FONTS
return false;
}
void Font::TallyResourceFonts(String fontsDirectoryPath, vector<String>& fontFilePaths, bool recursive) {
wxDir fontsDirectory(fontsDirectoryPath);
String fontFileName = wxEmptyString;
bool hasNext = fontsDirectory.GetFirst(&fontFileName);
while (hasNext) {
String fontFilePath = fontsDirectoryPath + fontFileName;
if (wxDirExists(fontFilePath)) {
if (recursive) {
TallyResourceFonts(fontFilePath + wxFileName::GetPathSeparator(), fontFilePaths, true);
}
}
else if (fontFilePath.EndsWith(_(".ttf")) || fontFilePath.EndsWith(_(".otf"))) {
fontFilePaths.push_back(fontFilePath);
}
hasNext = fontsDirectory.GetNext(&fontFileName);
}
}
bool Font::update(Context& ctx) {
bool changes = false;
changes |= name .update(ctx);
changes |= italic_name .update(ctx);
changes |= size .update(ctx);
changes |= weight .update(ctx);
changes |= style .update(ctx);
changes |= underline .update(ctx);
changes |= color .update(ctx);
changes |= shadow_color .update(ctx);
changes |= shadow_displacement_x.update(ctx);
changes |= shadow_displacement_y.update(ctx);
changes |= shadow_blur .update(ctx);
flags = (flags & ~FONT_BOLD & ~FONT_ITALIC)
| (weight() == _("bold") ? FONT_BOLD : FONT_NORMAL)
| (style() == _("italic") ? FONT_ITALIC : FONT_NORMAL);
return changes;
}
void Font::initDependencies(Context& ctx, const Dependency& dep) const {
name .initDependencies(ctx, dep);
italic_name .initDependencies(ctx, dep);
size .initDependencies(ctx, dep);
weight .initDependencies(ctx, dep);
style .initDependencies(ctx, dep);
underline .initDependencies(ctx, dep);
color .initDependencies(ctx, dep);
shadow_color .initDependencies(ctx, dep);
shadow_displacement_x.initDependencies(ctx, dep);
shadow_displacement_y.initDependencies(ctx, dep);
shadow_blur .initDependencies(ctx, dep);
}
FontP Font::make(int add_flags, bool add_underline, String const* other_family, Color const* other_color, double const* other_size) const {
FontP f(new Font(*this));
f->flags |= add_flags;
if (add_flags & FONT_CODE_STRING) {
f->color = Color(0,0,100);
}
if (add_flags & FONT_CODE) {
f->color = Color(128,0,0);
}
if (add_flags & FONT_CODE_KW) {
f->color = Color(158,100,0);
f->flags |= FONT_BOLD;
}
if (add_flags & FONT_SOFT) {
f->color = f->separator_color;
f->shadow_displacement_x = 0; // no shadow
f->shadow_displacement_y = 0; // no shadow
}
if (add_underline) {
f->underline = true;
}
if (other_color) {
f->color = *other_color;
}
if (other_size) {
f->size = *other_size;
}
if (other_family && !other_family->empty()) {
f->name = *other_family;
}
return f;
}
static const String BOLD_STRING = _(" Bold");
wxFont Font::toWxFont(double scale) const {
int size_i = to_int(scale * size);
wxFontWeight weight_i = flags & FONT_BOLD ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL;
wxFontStyle style_i = flags & FONT_ITALIC ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL;
// make font
wxFont font;
if (flags & FONT_CODE) {
if (size_i < 2) {
return wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, weight_i, underline(), _("Courier New"));
} else {
font = wxFont(size_i, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, weight_i, underline(), _("Courier New"));
}
} else if (name().empty()) {
font = *wxNORMAL_FONT;
font.SetPointSize(size > 1 ? size_i : int(scale * font.GetPointSize()));
return font;
} else if (flags & FONT_ITALIC && !italic_name().empty()) {
font = wxFont(size_i, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, weight_i, underline(), italic_name());
} else {
String familyName = name();
if(familyName.EndsWith(BOLD_STRING)) {
familyName = familyName.Left(familyName.length() - BOLD_STRING.length());
weight_i = wxFONTWEIGHT_BOLD;
}
font = wxFont(size_i, wxFONTFAMILY_DEFAULT, style_i, weight_i, underline(), familyName);
}
// fix size
#ifdef __WXMSW__
// make it independent of screen dpi, always use 96 dpi
// TODO: do something more sensible, and more portable
font.SetPixelSize(wxSize(0, -(int)(scale*size*96.0/72.0 + 0.5) ));
#endif
return font;
}
IMPLEMENT_REFLECTION_NO_SCRIPT(Font) {
REFLECT(name);
REFLECT(size);
REFLECT(weight);
REFLECT(style);
REFLECT(underline);
REFLECT(italic_name);
REFLECT(color);
REFLECT(scale_down_to);
REFLECT(max_stretch);
REFLECT(shadow_displacement_x);
REFLECT(shadow_displacement_y);
REFLECT(shadow_color);
REFLECT(shadow_blur);
REFLECT(separator_color);
}