mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-21 13:34:27 +08:00
Separate into class files
This commit is contained in:
parent
01d0f96720
commit
a34a4954bd
73
src/libslic3r/NSVGUtils.cpp
Normal file
73
src/libslic3r/NSVGUtils.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "NSVGUtils.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
|
||||
void NSVGUtils::flatten_cubic_bez(Polygon &polygon,
|
||||
float tessTol,
|
||||
Vec2f p1,
|
||||
Vec2f p2,
|
||||
Vec2f p3,
|
||||
Vec2f p4,
|
||||
int level)
|
||||
{
|
||||
Vec2f p12 = (p1 + p2) * 0.5f;
|
||||
Vec2f p23 = (p2 + p3) * 0.5f;
|
||||
Vec2f p34 = (p3 + p4) * 0.5f;
|
||||
Vec2f p123 = (p12 + p23) * 0.5f;
|
||||
|
||||
Vec2f pd = p4 - p1;
|
||||
Vec2f pd2 = p2 - p4;
|
||||
float d2 = std::abs(pd2.x() * pd.y() - pd2.y() * pd.x());
|
||||
Vec2f pd3 = p3 - p4;
|
||||
float d3 = std::abs(pd3.x() * pd.y() - pd3.y() * pd.x());
|
||||
float d23 = d2 + d3;
|
||||
|
||||
if ((d23 * d23) < tessTol * (pd.x() * pd.x() + pd.y() * pd.y())) {
|
||||
polygon.points.emplace_back(p4.x(), p4.y());
|
||||
return;
|
||||
}
|
||||
|
||||
--level;
|
||||
if (level == 0) return;
|
||||
Vec2f p234 = (p23 + p34) * 0.5f;
|
||||
Vec2f p1234 = (p123 + p234) * 0.5f;
|
||||
flatten_cubic_bez(polygon, tessTol, p1, p12, p123, p1234, level);
|
||||
flatten_cubic_bez(polygon, tessTol, p1234, p234, p34, p4, level);
|
||||
}
|
||||
|
||||
ExPolygons NSVGUtils::to_ExPolygons(NSVGimage *image,
|
||||
float tessTol,
|
||||
int max_level)
|
||||
{
|
||||
Polygons polygons;
|
||||
for (NSVGshape *shape = image->shapes; shape != NULL;
|
||||
shape = shape->next) {
|
||||
if (!(shape->flags & NSVG_FLAGS_VISIBLE)) continue;
|
||||
Slic3r::Polygon polygon;
|
||||
if (shape->fill.type != NSVG_PAINT_NONE) {
|
||||
for (NSVGpath *path = shape->paths; path != NULL;
|
||||
path = path->next) {
|
||||
// Flatten path
|
||||
polygon.points.emplace_back(path->pts[0], path->pts[1]);
|
||||
for (size_t i = 0; i < path->npts - 1; i += 3) {
|
||||
float *p = &path->pts[i * 2];
|
||||
Vec2f p1(p[0], p[1]), p2(p[2], p[3]), p3(p[4], p[5]),
|
||||
p4(p[6], p[7]);
|
||||
flatten_cubic_bez(polygon, tessTol, p1, p2, p3, p4,
|
||||
max_level);
|
||||
}
|
||||
if (path->closed) {
|
||||
polygons.push_back(polygon);
|
||||
polygon = Slic3r::Polygon();
|
||||
}
|
||||
}
|
||||
}
|
||||
polygons.push_back(polygon);
|
||||
}
|
||||
|
||||
// Fix Y axis
|
||||
for (Polygon &polygon : polygons)
|
||||
for (Point &p : polygon.points) p.y() *= -1;
|
||||
|
||||
return Slic3r::union_ex(polygons);
|
||||
}
|
30
src/libslic3r/NSVGUtils.hpp
Normal file
30
src/libslic3r/NSVGUtils.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef slic3r_NSVGUtils_hpp_
|
||||
#define slic3r_NSVGUtils_hpp_
|
||||
|
||||
#include "Polygon.hpp"
|
||||
#include "ExPolygon.hpp"
|
||||
#include "nanosvg/nanosvg.h" // load SVG file
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Helper function to work with nano svg
|
||||
class NSVGUtils
|
||||
{
|
||||
public:
|
||||
NSVGUtils() = delete;
|
||||
|
||||
// inspired by nanosvgrast.h function nsvgRasterize->nsvg__flattenShape
|
||||
static void flatten_cubic_bez(Polygon &polygon,
|
||||
float tessTol,
|
||||
Vec2f p1,
|
||||
Vec2f p2,
|
||||
Vec2f p3,
|
||||
Vec2f p4,
|
||||
int level);
|
||||
// convert svg image to ExPolygons
|
||||
static ExPolygons to_ExPolygons(NSVGimage *image,
|
||||
float tessTol = 10.,
|
||||
int max_level = 10);
|
||||
};
|
||||
} // namespace Slic3r
|
||||
#endif // slic3r_NSVGUtils_hpp_
|
@ -232,6 +232,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
Utils/Duet.hpp
|
||||
Utils/FlashAir.cpp
|
||||
Utils/FlashAir.hpp
|
||||
Utils/FontConfigHelp.cpp
|
||||
Utils/FontConfigHelp.hpp
|
||||
Utils/AstroBox.cpp
|
||||
Utils/AstroBox.hpp
|
||||
Utils/Repetier.cpp
|
||||
@ -253,6 +255,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
Utils/TCPConsole.hpp
|
||||
Utils/MKS.cpp
|
||||
Utils/MKS.hpp
|
||||
Utils/WxFontUtils.cpp
|
||||
Utils/WxFontUtils.hpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
@ -11,11 +11,13 @@
|
||||
#include "slic3r/GUI/CameraUtils.hpp"
|
||||
#include "slic3r/GUI/Jobs/EmbossJob.hpp"
|
||||
#include "slic3r/GUI/Jobs/NotificationProgressIndicator.hpp"
|
||||
#include "slic3r/Utils/WxFontUtils.hpp"
|
||||
|
||||
// TODO: remove include
|
||||
#include "libslic3r/SVG.hpp" // debug store
|
||||
#include "libslic3r/Geometry.hpp" // covex hull 2d
|
||||
|
||||
#include "libslic3r/NSVGUtils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp" // union_ex
|
||||
#include "libslic3r/AppConfig.hpp" // store/load font list
|
||||
@ -41,156 +43,12 @@
|
||||
// Font Config must exist
|
||||
#include <wx/filename.h>
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include "slic3r/Utils/FontConfigHelp.hpp"
|
||||
#endif
|
||||
|
||||
// uncomment for easier debug
|
||||
//#define ALLOW_DEBUG_MODE
|
||||
|
||||
namespace Slic3r {
|
||||
class WxFontUtils
|
||||
{
|
||||
public:
|
||||
WxFontUtils() = delete;
|
||||
|
||||
// os specific load of wxFont
|
||||
static std::optional<Slic3r::Emboss::Font> load_font(const wxFont &font);
|
||||
|
||||
static FontItem::Type get_actual_type();
|
||||
static FontItem get_font_item(const wxFont &font);
|
||||
|
||||
// load font used by Operating system as default GUI
|
||||
static FontItem get_os_font();
|
||||
static std::string get_human_readable_name(const wxFont &font);
|
||||
|
||||
// serialize / deserialize font
|
||||
static std::string store_wxFont(const wxFont &font);
|
||||
static std::optional<wxFont> load_wxFont(const std::string &font_descriptor);
|
||||
|
||||
// Try to create similar font, loaded from 3mf from different Computer
|
||||
static std::optional<wxFont> create_wxFont(const FontItem &fi, const FontProp &fp);
|
||||
// update font property by wxFont
|
||||
static void update_property(FontProp& font_prop, const wxFont& font);
|
||||
|
||||
// map to convert wxFont type to string and vice versa
|
||||
static const std::map<wxFontFamily, std::string> from_family;
|
||||
static const std::map<std::string, wxFontFamily> to_family;
|
||||
|
||||
static const std::map<wxFontStyle, std::string> from_style;
|
||||
static const std::map<std::string, wxFontStyle> to_style;
|
||||
|
||||
static const std::map<wxFontWeight, std::string> from_weight;
|
||||
static const std::map<std::string, wxFontWeight> to_weight;
|
||||
};
|
||||
|
||||
class NSVGUtils
|
||||
{
|
||||
public:
|
||||
NSVGUtils() = delete;
|
||||
|
||||
// inspired by nanosvgrast.h function nsvgRasterize->nsvg__flattenShape
|
||||
static void flatten_cubic_bez(Polygon &polygon, float tessTol,
|
||||
Vec2f p1, Vec2f p2, Vec2f p3,Vec2f p4, int level);
|
||||
// convert svg image to ExPolygons
|
||||
static ExPolygons to_ExPolygons(NSVGimage *image, float tessTol = 10., int max_level = 10);
|
||||
};
|
||||
|
||||
#ifdef __linux__
|
||||
class FontConfigHelp
|
||||
{
|
||||
public:
|
||||
FontConfigHelp() { FcInit(); }
|
||||
~FontConfigHelp() { FcFini(); }
|
||||
// inspired by wxpdfdoc - https://github.com/utelle/wxpdfdoc/blob/5bdcdb9953327d06dc50ec312685ccd9bc8400e0/src/pdffontmanager.cpp
|
||||
std::string get_font_path(const wxFont &font) {
|
||||
FcConfig *fc = FcInitLoadConfigAndFonts();
|
||||
if (fc == nullptr) return "";
|
||||
ScopeGuard sg_fc([fc]() { FcConfigDestroy(fc); });
|
||||
|
||||
wxString fontDesc = font.GetNativeFontInfoUserDesc();
|
||||
wxString faceName = font.GetFaceName();
|
||||
const wxScopedCharBuffer faceNameBuffer = faceName.ToUTF8();
|
||||
const char* fontFamily = faceNameBuffer;
|
||||
|
||||
// Check font slant
|
||||
int slant = FC_SLANT_ROMAN;
|
||||
if (fontDesc.Find(wxS("Oblique")) != wxNOT_FOUND) slant = FC_SLANT_OBLIQUE;
|
||||
else if (fontDesc.Find(wxS("Italic")) != wxNOT_FOUND) slant = FC_SLANT_ITALIC;
|
||||
|
||||
// Check font weight
|
||||
int weight = FC_WEIGHT_NORMAL;
|
||||
if (fontDesc.Find(wxS("Book")) != wxNOT_FOUND) weight = FC_WEIGHT_BOOK;
|
||||
else if (fontDesc.Find(wxS("Medium")) != wxNOT_FOUND) weight = FC_WEIGHT_MEDIUM;
|
||||
#ifdef FC_WEIGHT_ULTRALIGHT
|
||||
else if (fontDesc.Find(wxS("Ultra-Light")) != wxNOT_FOUND) weight = FC_WEIGHT_ULTRALIGHT;
|
||||
#endif
|
||||
else if (fontDesc.Find(wxS("Light")) != wxNOT_FOUND) weight = FC_WEIGHT_LIGHT;
|
||||
else if (fontDesc.Find(wxS("Semi-Bold")) != wxNOT_FOUND) weight = FC_WEIGHT_DEMIBOLD;
|
||||
#ifdef FC_WEIGHT_ULTRABOLD
|
||||
else if (fontDesc.Find(wxS("Ultra-Bold")) != wxNOT_FOUND) weight = FC_WEIGHT_ULTRABOLD;
|
||||
#endif
|
||||
else if (fontDesc.Find(wxS("Bold")) != wxNOT_FOUND) weight = FC_WEIGHT_BOLD;
|
||||
else if (fontDesc.Find(wxS("Heavy")) != wxNOT_FOUND) weight = FC_WEIGHT_BLACK;
|
||||
|
||||
// Check font width
|
||||
int width = FC_WIDTH_NORMAL;
|
||||
if (fontDesc.Find(wxS("Ultra-Condensed")) != wxNOT_FOUND) width = FC_WIDTH_ULTRACONDENSED;
|
||||
else if (fontDesc.Find(wxS("Extra-Condensed")) != wxNOT_FOUND) width = FC_WIDTH_EXTRACONDENSED;
|
||||
else if (fontDesc.Find(wxS("Semi-Condensed")) != wxNOT_FOUND) width = FC_WIDTH_SEMICONDENSED;
|
||||
else if (fontDesc.Find(wxS("Condensed")) != wxNOT_FOUND) width = FC_WIDTH_CONDENSED;
|
||||
else if (fontDesc.Find(wxS("Ultra-Expanded")) != wxNOT_FOUND) width = FC_WIDTH_ULTRAEXPANDED;
|
||||
else if (fontDesc.Find(wxS("Extra-Expanded")) != wxNOT_FOUND) width = FC_WIDTH_EXTRAEXPANDED;
|
||||
else if (fontDesc.Find(wxS("Semi-Expanded")) != wxNOT_FOUND) width = FC_WIDTH_SEMIEXPANDED;
|
||||
else if (fontDesc.Find(wxS("Expanded")) != wxNOT_FOUND) width = FC_WIDTH_EXPANDED;
|
||||
|
||||
FcResult res;
|
||||
FcPattern* matchPattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, (FcChar8*) fontFamily, NULL);
|
||||
ScopeGuard sg_mp([matchPattern]() { FcPatternDestroy(matchPattern); });
|
||||
|
||||
FcPatternAddInteger(matchPattern, FC_SLANT, slant);
|
||||
FcPatternAddInteger(matchPattern, FC_WEIGHT, weight);
|
||||
FcPatternAddInteger(matchPattern, FC_WIDTH, width);
|
||||
|
||||
FcConfigSubstitute (NULL, matchPattern, FcMatchPattern);
|
||||
FcDefaultSubstitute (matchPattern);
|
||||
|
||||
FcPattern* resultPattern = FcFontMatch (NULL, matchPattern, &res);
|
||||
if (resultPattern == nullptr) return "";
|
||||
ScopeGuard sg_rp([resultPattern]() { FcPatternDestroy(resultPattern); });
|
||||
|
||||
|
||||
FcChar8 *fileName;
|
||||
if (FcPatternGetString(resultPattern, FC_FILE, 0, &fileName) != FcResultMatch) return "";
|
||||
wxString fontFileName = wxString::FromUTF8((char *) fileName);
|
||||
|
||||
if (fontFileName.IsEmpty()) return "";
|
||||
|
||||
// find full file path
|
||||
wxFileName myFileName(fontFileName);
|
||||
if (!myFileName.IsOk()) return "";
|
||||
|
||||
if (myFileName.IsRelative()) {
|
||||
// Check whether the file is relative to the current working directory
|
||||
if (!(myFileName.MakeAbsolute() && myFileName.FileExists())) {
|
||||
return "";
|
||||
// File not found, search in given search paths
|
||||
//wxString foundFileName = m_searchPaths.FindAbsoluteValidPath(fileName);
|
||||
//if (!foundFileName.IsEmpty()) {
|
||||
// myFileName.Assign(foundFileName);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
if (!myFileName.FileExists() || !myFileName.IsFileReadable()) return "";
|
||||
|
||||
// File exists and is accessible
|
||||
wxString fullFileName = myFileName.GetFullPath();
|
||||
return std::string(fullFileName.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __linux__
|
||||
} // namespace Slic3r
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
@ -1937,203 +1795,6 @@ void GLGizmoEmboss::update_emboss_volume(TriangleMesh && mesh,
|
||||
canvas->reload_scene(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WxFontUtils - Start definition
|
||||
/// </summary>
|
||||
std::optional<Emboss::Font> WxFontUtils::load_font(const wxFont &font)
|
||||
{
|
||||
if (!font.IsOk()) return {};
|
||||
#ifdef _WIN32
|
||||
return Emboss::load_font(font.GetHFONT());
|
||||
#elif defined(__APPLE__)
|
||||
// use file path
|
||||
const wxNativeFontInfo *info = font.GetNativeFontInfo();
|
||||
if (info == nullptr) return {};
|
||||
CTFontDescriptorRef descriptor = info->GetCTFontDescriptor();
|
||||
CFURLRef typeref = (CFURLRef)
|
||||
CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute);
|
||||
CFStringRef url = CFURLGetString(typeref);
|
||||
if (url == NULL) return {};
|
||||
wxString file_uri;
|
||||
wxCFTypeRef(url).GetValue(file_uri);
|
||||
std::string file_path(wxURI::Unescape(file_uri).c_str());
|
||||
size_t start = std::string("file://").size();
|
||||
if (file_path.empty() || file_path.size() <= start) return {};
|
||||
file_path = file_path.substr(start, file_path.size() - start);
|
||||
return Emboss::load_font(file_path.c_str());
|
||||
#elif defined(__linux__)
|
||||
static FontConfigHelp help;
|
||||
std::string font_path = help.get_font_path(font);
|
||||
if (font_path.empty()) return {};
|
||||
return Emboss::load_font(font_path.c_str());
|
||||
#else
|
||||
// HERE is place to add implementation for another platform
|
||||
// to convert wxFont to font data as windows or font file path as linux
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
FontItem::Type WxFontUtils::get_actual_type()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return FontItem::Type::wx_win_font_descr;
|
||||
#elif defined(__APPLE__)
|
||||
return FontItem::Type::wx_mac_font_descr;
|
||||
#elif defined(__linux__)
|
||||
return FontItem::Type::wx_mac_font_descr;
|
||||
#else
|
||||
return FontItem::Type::undefined;
|
||||
#endif
|
||||
}
|
||||
|
||||
FontItem WxFontUtils::get_font_item(const wxFont &font)
|
||||
{
|
||||
std::string name = get_human_readable_name(font);
|
||||
std::string fontDesc = store_wxFont(font);
|
||||
FontItem::Type type = get_actual_type();
|
||||
// wxFont f = font; // copy
|
||||
return FontItem(name, fontDesc, type);
|
||||
}
|
||||
|
||||
FontItem WxFontUtils::get_os_font()
|
||||
{
|
||||
wxSystemFont system_font = wxSYS_DEFAULT_GUI_FONT;
|
||||
wxFont font = wxSystemSettings::GetFont(system_font);
|
||||
FontItem fi = get_font_item(font);
|
||||
fi.name += std::string(" (" + _u8L("OS default") + ")");
|
||||
return get_font_item(font);
|
||||
}
|
||||
|
||||
std::string WxFontUtils::get_human_readable_name(const wxFont &font)
|
||||
{
|
||||
if (!font.IsOk()) return "Font is NOT ok.";
|
||||
// Face name is optional in wxFont
|
||||
if (!font.GetFaceName().empty()) {
|
||||
return std::string(font.GetFaceName().c_str());
|
||||
} else {
|
||||
return std::string((font.GetFamilyString() + " " +
|
||||
font.GetStyleString() + " " +
|
||||
font.GetWeightString())
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string WxFontUtils::store_wxFont(const wxFont &font)
|
||||
{
|
||||
// wxString os = wxPlatformInfo::Get().GetOperatingSystemIdName();
|
||||
wxString font_descriptor = font.GetNativeFontInfoDesc();
|
||||
return std::string(font_descriptor.c_str());
|
||||
}
|
||||
|
||||
std::optional<wxFont> WxFontUtils::load_wxFont(
|
||||
const std::string &font_descriptor)
|
||||
{
|
||||
wxString font_descriptor_wx(font_descriptor);
|
||||
wxFont wx_font(font_descriptor_wx);
|
||||
if (!wx_font.IsOk()) return {};
|
||||
return wx_font;
|
||||
}
|
||||
|
||||
const std::map<wxFontFamily, std::string> WxFontUtils::from_family(
|
||||
{{wxFONTFAMILY_DEFAULT, "default"},
|
||||
{wxFONTFAMILY_DECORATIVE, "decorative"},
|
||||
{wxFONTFAMILY_ROMAN, "roman"},
|
||||
{wxFONTFAMILY_SCRIPT, "script"},
|
||||
{wxFONTFAMILY_SWISS, "swiss"},
|
||||
{wxFONTFAMILY_MODERN, "modern"},
|
||||
{wxFONTFAMILY_TELETYPE, "teletype"},
|
||||
{wxFONTFAMILY_MAX, "max"},
|
||||
{wxFONTFAMILY_UNKNOWN, "unknown"}});
|
||||
const std::map<std::string, wxFontFamily> WxFontUtils::to_family =
|
||||
MapUtils::create_oposit(WxFontUtils::from_family);
|
||||
|
||||
const std::map<wxFontStyle, std::string> WxFontUtils::from_style(
|
||||
{{wxFONTSTYLE_ITALIC, "italic"},
|
||||
{wxFONTSTYLE_SLANT, "slant"},
|
||||
{wxFONTSTYLE_NORMAL, "normal"}});
|
||||
const std::map<std::string, wxFontStyle> WxFontUtils::to_style =
|
||||
MapUtils::create_oposit(WxFontUtils::from_style);
|
||||
|
||||
const std::map<wxFontWeight, std::string> WxFontUtils::from_weight(
|
||||
{{wxFONTWEIGHT_THIN, "thin"},
|
||||
{wxFONTWEIGHT_EXTRALIGHT, "extraLight"},
|
||||
{wxFONTWEIGHT_LIGHT, "light"},
|
||||
{wxFONTWEIGHT_NORMAL, "normal"},
|
||||
{wxFONTWEIGHT_MEDIUM, "medium"},
|
||||
{wxFONTWEIGHT_SEMIBOLD, "semibold"},
|
||||
{wxFONTWEIGHT_BOLD, "bold"},
|
||||
{wxFONTWEIGHT_EXTRABOLD, "extraBold"},
|
||||
{wxFONTWEIGHT_HEAVY, "heavy"},
|
||||
{wxFONTWEIGHT_EXTRAHEAVY, "extraHeavy"}});
|
||||
const std::map<std::string, wxFontWeight> WxFontUtils::to_weight =
|
||||
MapUtils::create_oposit(WxFontUtils::from_weight);
|
||||
|
||||
std::optional<wxFont> WxFontUtils::create_wxFont(const FontItem &fi,
|
||||
const FontProp &fp)
|
||||
{
|
||||
double point_size = static_cast<double>(fp.size_in_mm);
|
||||
wxFontInfo info(point_size);
|
||||
if (fp.family.has_value()) {
|
||||
auto it = to_family.find(*fp.style);
|
||||
if (it != to_family.end()) info.Family(it->second);
|
||||
}
|
||||
if (fp.face_name.has_value()) {
|
||||
wxString face_name(*fp.face_name);
|
||||
info.FaceName(face_name);
|
||||
}
|
||||
if (fp.style.has_value()) {
|
||||
auto it = to_style.find(*fp.style);
|
||||
if (it != to_style.end()) info.Style(it->second);
|
||||
}
|
||||
if (fp.weight.has_value()) {
|
||||
auto it = to_weight.find(*fp.weight);
|
||||
if (it != to_weight.end()) info.Weight(it->second);
|
||||
}
|
||||
|
||||
// Improve: load descriptor instead of store to font property to 3mf
|
||||
// switch (fi.type) {
|
||||
// case FontItem::Type::wx_lin_font_descr:
|
||||
// case FontItem::Type::wx_win_font_descr:
|
||||
// case FontItem::Type::file_path:
|
||||
// case FontItem::Type::undefined:
|
||||
// default:
|
||||
//}
|
||||
|
||||
wxFont font(info);
|
||||
if (!font.IsOk()) return {};
|
||||
return font;
|
||||
}
|
||||
|
||||
void WxFontUtils::update_property(FontProp &font_prop, const wxFont &font)
|
||||
{
|
||||
// The point size is defined as 1/72 of the Anglo-Saxon inch (25.4 mm): it
|
||||
// is approximately 0.0139 inch or 352.8 um. But it is too small, so I
|
||||
// decide use point size as mm for emboss
|
||||
font_prop.size_in_mm = font.GetPointSize(); // *0.3528f;
|
||||
|
||||
wxString wx_face_name = font.GetFaceName();
|
||||
std::string face_name((const char *) wx_face_name.ToUTF8());
|
||||
if (!face_name.empty()) font_prop.face_name = face_name;
|
||||
|
||||
wxFontFamily wx_family = font.GetFamily();
|
||||
if (wx_family != wxFONTFAMILY_DEFAULT) {
|
||||
auto it = from_family.find(wx_family);
|
||||
if (it != from_family.end()) font_prop.family = it->second;
|
||||
}
|
||||
|
||||
wxFontStyle wx_style = font.GetStyle();
|
||||
if (wx_style != wxFONTSTYLE_NORMAL) {
|
||||
auto it = from_style.find(wx_style);
|
||||
if (it != from_style.end()) font_prop.style = it->second;
|
||||
}
|
||||
|
||||
wxFontWeight wx_weight = font.GetWeight();
|
||||
if (wx_weight != wxFONTWEIGHT_NORMAL) {
|
||||
auto it = from_weight.find(wx_weight);
|
||||
if (it != from_weight.end()) font_prop.weight = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void NSVGUtils::flatten_cubic_bez(Polygon &polygon,
|
||||
float tessTol,
|
||||
Vec2f p1,
|
||||
|
119
src/slic3r/Utils/FontConfigHelp.cpp
Normal file
119
src/slic3r/Utils/FontConfigHelp.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include "FontConfigHelp.hpp"
|
||||
|
||||
#ifdef EXIST_FONT_CONFIG_INCLUDE
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
FontConfigHelp::FontConfigHelp() { FcInit(); }
|
||||
FontConfigHelp::~FontConfigHelp() { FcFini(); }
|
||||
|
||||
std::string FontConfigHelp::get_font_path(const wxFont &font)
|
||||
{
|
||||
FcConfig *fc = FcInitLoadConfigAndFonts();
|
||||
if (fc == nullptr) return "";
|
||||
ScopeGuard sg_fc([fc]() { FcConfigDestroy(fc); });
|
||||
|
||||
wxString fontDesc = font.GetNativeFontInfoUserDesc();
|
||||
wxString faceName = font.GetFaceName();
|
||||
const wxScopedCharBuffer faceNameBuffer = faceName.ToUTF8();
|
||||
const char * fontFamily = faceNameBuffer;
|
||||
|
||||
// Check font slant
|
||||
int slant = FC_SLANT_ROMAN;
|
||||
if (fontDesc.Find(wxS("Oblique")) != wxNOT_FOUND)
|
||||
slant = FC_SLANT_OBLIQUE;
|
||||
else if (fontDesc.Find(wxS("Italic")) != wxNOT_FOUND)
|
||||
slant = FC_SLANT_ITALIC;
|
||||
|
||||
// Check font weight
|
||||
int weight = FC_WEIGHT_NORMAL;
|
||||
if (fontDesc.Find(wxS("Book")) != wxNOT_FOUND)
|
||||
weight = FC_WEIGHT_BOOK;
|
||||
else if (fontDesc.Find(wxS("Medium")) != wxNOT_FOUND)
|
||||
weight = FC_WEIGHT_MEDIUM;
|
||||
#ifdef FC_WEIGHT_ULTRALIGHT
|
||||
else if (fontDesc.Find(wxS("Ultra-Light")) != wxNOT_FOUND)
|
||||
weight = FC_WEIGHT_ULTRALIGHT;
|
||||
#endif
|
||||
else if (fontDesc.Find(wxS("Light")) != wxNOT_FOUND)
|
||||
weight = FC_WEIGHT_LIGHT;
|
||||
else if (fontDesc.Find(wxS("Semi-Bold")) != wxNOT_FOUND)
|
||||
weight = FC_WEIGHT_DEMIBOLD;
|
||||
#ifdef FC_WEIGHT_ULTRABOLD
|
||||
else if (fontDesc.Find(wxS("Ultra-Bold")) != wxNOT_FOUND)
|
||||
weight = FC_WEIGHT_ULTRABOLD;
|
||||
#endif
|
||||
else if (fontDesc.Find(wxS("Bold")) != wxNOT_FOUND)
|
||||
weight = FC_WEIGHT_BOLD;
|
||||
else if (fontDesc.Find(wxS("Heavy")) != wxNOT_FOUND)
|
||||
weight = FC_WEIGHT_BLACK;
|
||||
|
||||
// Check font width
|
||||
int width = FC_WIDTH_NORMAL;
|
||||
if (fontDesc.Find(wxS("Ultra-Condensed")) != wxNOT_FOUND)
|
||||
width = FC_WIDTH_ULTRACONDENSED;
|
||||
else if (fontDesc.Find(wxS("Extra-Condensed")) != wxNOT_FOUND)
|
||||
width = FC_WIDTH_EXTRACONDENSED;
|
||||
else if (fontDesc.Find(wxS("Semi-Condensed")) != wxNOT_FOUND)
|
||||
width = FC_WIDTH_SEMICONDENSED;
|
||||
else if (fontDesc.Find(wxS("Condensed")) != wxNOT_FOUND)
|
||||
width = FC_WIDTH_CONDENSED;
|
||||
else if (fontDesc.Find(wxS("Ultra-Expanded")) != wxNOT_FOUND)
|
||||
width = FC_WIDTH_ULTRAEXPANDED;
|
||||
else if (fontDesc.Find(wxS("Extra-Expanded")) != wxNOT_FOUND)
|
||||
width = FC_WIDTH_EXTRAEXPANDED;
|
||||
else if (fontDesc.Find(wxS("Semi-Expanded")) != wxNOT_FOUND)
|
||||
width = FC_WIDTH_SEMIEXPANDED;
|
||||
else if (fontDesc.Find(wxS("Expanded")) != wxNOT_FOUND)
|
||||
width = FC_WIDTH_EXPANDED;
|
||||
|
||||
FcResult res;
|
||||
FcPattern *matchPattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString,
|
||||
(FcChar8 *) fontFamily, NULL);
|
||||
ScopeGuard sg_mp([matchPattern]() { FcPatternDestroy(matchPattern); });
|
||||
|
||||
FcPatternAddInteger(matchPattern, FC_SLANT, slant);
|
||||
FcPatternAddInteger(matchPattern, FC_WEIGHT, weight);
|
||||
FcPatternAddInteger(matchPattern, FC_WIDTH, width);
|
||||
|
||||
FcConfigSubstitute(NULL, matchPattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(matchPattern);
|
||||
|
||||
FcPattern *resultPattern = FcFontMatch(NULL, matchPattern, &res);
|
||||
if (resultPattern == nullptr) return "";
|
||||
ScopeGuard sg_rp([resultPattern]() { FcPatternDestroy(resultPattern); });
|
||||
|
||||
FcChar8 *fileName;
|
||||
if (FcPatternGetString(resultPattern, FC_FILE, 0, &fileName) !=
|
||||
FcResultMatch)
|
||||
return "";
|
||||
wxString fontFileName = wxString::FromUTF8((char *) fileName);
|
||||
|
||||
if (fontFileName.IsEmpty()) return "";
|
||||
|
||||
// find full file path
|
||||
wxFileName myFileName(fontFileName);
|
||||
if (!myFileName.IsOk()) return "";
|
||||
|
||||
if (myFileName.IsRelative()) {
|
||||
// Check whether the file is relative to the current working directory
|
||||
if (!(myFileName.MakeAbsolute() && myFileName.FileExists())) {
|
||||
return "";
|
||||
// File not found, search in given search paths
|
||||
// wxString foundFileName =
|
||||
// m_searchPaths.FindAbsoluteValidPath(fileName); if
|
||||
// (!foundFileName.IsEmpty()) {
|
||||
// myFileName.Assign(foundFileName);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
if (!myFileName.FileExists() || !myFileName.IsFileReadable()) return "";
|
||||
|
||||
// File exists and is accessible
|
||||
wxString fullFileName = myFileName.GetFullPath();
|
||||
return std::string(fullFileName.c_str());
|
||||
}
|
||||
|
||||
#endif // EXIST_FONT_CONFIG_INCLUDE
|
40
src/slic3r/Utils/FontConfigHelp.hpp
Normal file
40
src/slic3r/Utils/FontConfigHelp.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef slic3r_FontConfigHelp_hpp_
|
||||
#define slic3r_FontConfigHelp_hpp_
|
||||
|
||||
#ifdef __linux__
|
||||
#define EXIST_FONT_CONFIG_INCLUDE
|
||||
#endif
|
||||
|
||||
#ifdef EXIST_FONT_CONFIG_INCLUDE
|
||||
#include <wx/font.h>
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
/// <summary>
|
||||
/// helper object for RAII access to font config
|
||||
/// initialize & finalize FontConfig
|
||||
/// </summary>
|
||||
class FontConfigHelp
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// initialize font config
|
||||
/// </summary>
|
||||
FontConfigHelp();
|
||||
|
||||
/// <summary>
|
||||
/// free font config resources
|
||||
/// </summary>
|
||||
~FontConfigHelp();
|
||||
|
||||
/// <summary>
|
||||
/// initialize font config
|
||||
/// Convert wx widget font to file path
|
||||
/// inspired by wxpdfdoc -
|
||||
/// https://github.com/utelle/wxpdfdoc/blob/5bdcdb9953327d06dc50ec312685ccd9bc8400e0/src/pdffontmanager.cpp
|
||||
/// </summary>
|
||||
std::string get_font_path(const wxFont &font);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
#endif // EXIST_FONT_CONFIG_INCLUDE
|
||||
#endif // slic3r_FontConfigHelp_hpp_
|
200
src/slic3r/Utils/WxFontUtils.cpp
Normal file
200
src/slic3r/Utils/WxFontUtils.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
#include "WxFontUtils.hpp"
|
||||
#include "libslic3r/MapUtils.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
std::optional<Emboss::Font> WxFontUtils::load_font(const wxFont &font)
|
||||
{
|
||||
if (!font.IsOk()) return {};
|
||||
#ifdef _WIN32
|
||||
return Emboss::load_font(font.GetHFONT());
|
||||
#elif defined(__APPLE__)
|
||||
// use file path
|
||||
const wxNativeFontInfo *info = font.GetNativeFontInfo();
|
||||
if (info == nullptr) return {};
|
||||
CTFontDescriptorRef descriptor = info->GetCTFontDescriptor();
|
||||
CFURLRef typeref = (CFURLRef)
|
||||
CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute);
|
||||
CFStringRef url = CFURLGetString(typeref);
|
||||
if (url == NULL) return {};
|
||||
wxString file_uri;
|
||||
wxCFTypeRef(url).GetValue(file_uri);
|
||||
std::string file_path(wxURI::Unescape(file_uri).c_str());
|
||||
size_t start = std::string("file://").size();
|
||||
if (file_path.empty() || file_path.size() <= start) return {};
|
||||
file_path = file_path.substr(start, file_path.size() - start);
|
||||
return Emboss::load_font(file_path.c_str());
|
||||
#elif defined(__linux__)
|
||||
static FontConfigHelp help;
|
||||
std::string font_path = help.get_font_path(font);
|
||||
if (font_path.empty()) return {};
|
||||
return Emboss::load_font(font_path.c_str());
|
||||
#else
|
||||
// HERE is place to add implementation for another platform
|
||||
// to convert wxFont to font data as windows or font file path as linux
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
FontItem::Type WxFontUtils::get_actual_type()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return FontItem::Type::wx_win_font_descr;
|
||||
#elif defined(__APPLE__)
|
||||
return FontItem::Type::wx_mac_font_descr;
|
||||
#elif defined(__linux__)
|
||||
return FontItem::Type::wx_lin_font_descr;
|
||||
#else
|
||||
return FontItem::Type::undefined;
|
||||
#endif
|
||||
}
|
||||
|
||||
FontItem WxFontUtils::get_font_item(const wxFont &font)
|
||||
{
|
||||
std::string name = get_human_readable_name(font);
|
||||
std::string fontDesc = store_wxFont(font);
|
||||
FontItem::Type type = get_actual_type();
|
||||
// wxFont f = font; // copy
|
||||
return FontItem(name, fontDesc, type);
|
||||
}
|
||||
|
||||
FontItem WxFontUtils::get_os_font()
|
||||
{
|
||||
wxSystemFont system_font = wxSYS_DEFAULT_GUI_FONT;
|
||||
wxFont font = wxSystemSettings::GetFont(system_font);
|
||||
FontItem fi = get_font_item(font);
|
||||
fi.name += std::string(" (OS default)");
|
||||
return get_font_item(font);
|
||||
}
|
||||
|
||||
std::string WxFontUtils::get_human_readable_name(const wxFont &font)
|
||||
{
|
||||
if (!font.IsOk()) return "Font is NOT ok.";
|
||||
// Face name is optional in wxFont
|
||||
if (!font.GetFaceName().empty()) {
|
||||
return std::string(font.GetFaceName().c_str());
|
||||
} else {
|
||||
return std::string((font.GetFamilyString() + " " +
|
||||
font.GetStyleString() + " " +
|
||||
font.GetWeightString())
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string WxFontUtils::store_wxFont(const wxFont &font)
|
||||
{
|
||||
// wxString os = wxPlatformInfo::Get().GetOperatingSystemIdName();
|
||||
wxString font_descriptor = font.GetNativeFontInfoDesc();
|
||||
return std::string(font_descriptor.c_str());
|
||||
}
|
||||
|
||||
std::optional<wxFont> WxFontUtils::load_wxFont(
|
||||
const std::string &font_descriptor)
|
||||
{
|
||||
wxString font_descriptor_wx(font_descriptor);
|
||||
wxFont wx_font(font_descriptor_wx);
|
||||
if (!wx_font.IsOk()) return {};
|
||||
return wx_font;
|
||||
}
|
||||
|
||||
const std::map<wxFontFamily, std::string> WxFontUtils::from_family(
|
||||
{{wxFONTFAMILY_DEFAULT, "default"},
|
||||
{wxFONTFAMILY_DECORATIVE, "decorative"},
|
||||
{wxFONTFAMILY_ROMAN, "roman"},
|
||||
{wxFONTFAMILY_SCRIPT, "script"},
|
||||
{wxFONTFAMILY_SWISS, "swiss"},
|
||||
{wxFONTFAMILY_MODERN, "modern"},
|
||||
{wxFONTFAMILY_TELETYPE, "teletype"},
|
||||
{wxFONTFAMILY_MAX, "max"},
|
||||
{wxFONTFAMILY_UNKNOWN, "unknown"}});
|
||||
const std::map<std::string, wxFontFamily> WxFontUtils::to_family =
|
||||
MapUtils::create_oposit(WxFontUtils::from_family);
|
||||
|
||||
const std::map<wxFontStyle, std::string> WxFontUtils::from_style(
|
||||
{{wxFONTSTYLE_ITALIC, "italic"},
|
||||
{wxFONTSTYLE_SLANT, "slant"},
|
||||
{wxFONTSTYLE_NORMAL, "normal"}});
|
||||
const std::map<std::string, wxFontStyle> WxFontUtils::to_style =
|
||||
MapUtils::create_oposit(WxFontUtils::from_style);
|
||||
|
||||
const std::map<wxFontWeight, std::string> WxFontUtils::from_weight(
|
||||
{{wxFONTWEIGHT_THIN, "thin"},
|
||||
{wxFONTWEIGHT_EXTRALIGHT, "extraLight"},
|
||||
{wxFONTWEIGHT_LIGHT, "light"},
|
||||
{wxFONTWEIGHT_NORMAL, "normal"},
|
||||
{wxFONTWEIGHT_MEDIUM, "medium"},
|
||||
{wxFONTWEIGHT_SEMIBOLD, "semibold"},
|
||||
{wxFONTWEIGHT_BOLD, "bold"},
|
||||
{wxFONTWEIGHT_EXTRABOLD, "extraBold"},
|
||||
{wxFONTWEIGHT_HEAVY, "heavy"},
|
||||
{wxFONTWEIGHT_EXTRAHEAVY, "extraHeavy"}});
|
||||
const std::map<std::string, wxFontWeight> WxFontUtils::to_weight =
|
||||
MapUtils::create_oposit(WxFontUtils::from_weight);
|
||||
|
||||
std::optional<wxFont> WxFontUtils::create_wxFont(const FontItem &fi,
|
||||
const FontProp &fp)
|
||||
{
|
||||
double point_size = static_cast<double>(fp.size_in_mm);
|
||||
wxFontInfo info(point_size);
|
||||
if (fp.family.has_value()) {
|
||||
auto it = to_family.find(*fp.style);
|
||||
if (it != to_family.end()) info.Family(it->second);
|
||||
}
|
||||
if (fp.face_name.has_value()) {
|
||||
wxString face_name(*fp.face_name);
|
||||
info.FaceName(face_name);
|
||||
}
|
||||
if (fp.style.has_value()) {
|
||||
auto it = to_style.find(*fp.style);
|
||||
if (it != to_style.end()) info.Style(it->second);
|
||||
}
|
||||
if (fp.weight.has_value()) {
|
||||
auto it = to_weight.find(*fp.weight);
|
||||
if (it != to_weight.end()) info.Weight(it->second);
|
||||
}
|
||||
|
||||
// Improve: load descriptor instead of store to font property to 3mf
|
||||
// switch (fi.type) {
|
||||
// case FontItem::Type::wx_lin_font_descr:
|
||||
// case FontItem::Type::wx_win_font_descr:
|
||||
// case FontItem::Type::wx_mac_font_descr:
|
||||
// case FontItem::Type::file_path:
|
||||
// case FontItem::Type::undefined:
|
||||
// default:
|
||||
//}
|
||||
|
||||
wxFont font(info);
|
||||
if (!font.IsOk()) return {};
|
||||
return font;
|
||||
}
|
||||
|
||||
void WxFontUtils::update_property(FontProp &font_prop, const wxFont &font)
|
||||
{
|
||||
// The point size is defined as 1/72 of the Anglo-Saxon inch (25.4 mm): it
|
||||
// is approximately 0.0139 inch or 352.8 um. But it is too small, so I
|
||||
// decide use point size as mm for emboss
|
||||
font_prop.size_in_mm = font.GetPointSize(); // *0.3528f;
|
||||
|
||||
wxString wx_face_name = font.GetFaceName();
|
||||
std::string face_name((const char *) wx_face_name.ToUTF8());
|
||||
if (!face_name.empty()) font_prop.face_name = face_name;
|
||||
|
||||
wxFontFamily wx_family = font.GetFamily();
|
||||
if (wx_family != wxFONTFAMILY_DEFAULT) {
|
||||
auto it = from_family.find(wx_family);
|
||||
if (it != from_family.end()) font_prop.family = it->second;
|
||||
}
|
||||
|
||||
wxFontStyle wx_style = font.GetStyle();
|
||||
if (wx_style != wxFONTSTYLE_NORMAL) {
|
||||
auto it = from_style.find(wx_style);
|
||||
if (it != from_style.end()) font_prop.style = it->second;
|
||||
}
|
||||
|
||||
wxFontWeight wx_weight = font.GetWeight();
|
||||
if (wx_weight != wxFONTWEIGHT_NORMAL) {
|
||||
auto it = from_weight.find(wx_weight);
|
||||
if (it != from_weight.end()) font_prop.weight = it->second;
|
||||
}
|
||||
}
|
50
src/slic3r/Utils/WxFontUtils.hpp
Normal file
50
src/slic3r/Utils/WxFontUtils.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef slic3r_WxFontUtils_hpp_
|
||||
#define slic3r_WxFontUtils_hpp_
|
||||
|
||||
#include <optional>
|
||||
#include <wx/font.h>
|
||||
#include "libslic3r/Emboss.hpp"
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
// Help class to work with wx widget font object( wxFont )
|
||||
class WxFontUtils
|
||||
{
|
||||
public:
|
||||
// only static functions
|
||||
WxFontUtils() = delete;
|
||||
|
||||
// os specific load of wxFont
|
||||
static std::optional<Slic3r::Emboss::Font> load_font(const wxFont &font);
|
||||
|
||||
static FontItem::Type get_actual_type();
|
||||
static FontItem get_font_item(const wxFont &font);
|
||||
|
||||
// load font used by Operating system as default GUI
|
||||
static FontItem get_os_font();
|
||||
static std::string get_human_readable_name(const wxFont &font);
|
||||
|
||||
// serialize / deserialize font
|
||||
static std::string store_wxFont(const wxFont &font);
|
||||
static std::optional<wxFont> load_wxFont(
|
||||
const std::string &font_descriptor);
|
||||
|
||||
// Try to create similar font, loaded from 3mf from different Computer
|
||||
static std::optional<wxFont> create_wxFont(const FontItem &fi,
|
||||
const FontProp &fp);
|
||||
// update font property by wxFont
|
||||
static void update_property(FontProp &font_prop, const wxFont &font);
|
||||
|
||||
// map to convert wxFont type to string and vice versa
|
||||
static const std::map<wxFontFamily, std::string> from_family;
|
||||
static const std::map<std::string, wxFontFamily> to_family;
|
||||
|
||||
static const std::map<wxFontStyle, std::string> from_style;
|
||||
static const std::map<std::string, wxFontStyle> to_style;
|
||||
|
||||
static const std::map<wxFontWeight, std::string> from_weight;
|
||||
static const std::map<std::string, wxFontWeight> to_weight;
|
||||
};
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
#endif // slic3r_WxFontUtils_hpp_
|
Loading…
x
Reference in New Issue
Block a user