diff --git a/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts.dei b/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts.dei index e75cb40097..7153c72a93 100644 --- a/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts.dei +++ b/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts.dei @@ -53,14 +53,14 @@ group { font default { family: Source Sans Pro - size $: gui.scale("12pt", DisplayMode.PIXEL_RATIO) + size: 12pt weight: normal style: normal } font monospace inherits default { family: Source Code Pro - size $: gui.scale("9pt", DisplayMode.PIXEL_RATIO) + size: 9pt } } @@ -70,28 +70,23 @@ group { script { # Define mappings for native font styles and weights. import App - if Version.OS == 'macx' - prefix = '.SFNS' - else - prefix = '.SFUI' - end - App.addFontMapping("SF UI Text", { - ['regular', 25]: prefix + 'Text-Light', - ['regular', 50]: prefix + 'Text-Regular', - ['regular', 75]: prefix + 'Text-Bold', - ['italic', 25]: prefix + 'Text-LightItalic', - ['italic', 50]: prefix + 'Text-Italic', - ['italic', 75]: prefix + 'Text-BoldItalic' - }) - App.addFontMapping("SF UI Display", { - ['regular', 25]: prefix + 'Display-Thin', - ['regular', 50]: prefix + 'Display-Regular', - ['regular', 75]: prefix + 'Display-Bold', - ['italic', 25]: prefix + 'Text-LightItalic', # Only non-italic available. - ['italic', 50]: prefix + 'Text-Italic', - ['italic', 75]: prefix + 'Text-BoldItalic' + App.addFontMapping("Apple UI", { + ['regular', 25]: '#system-light', + ['regular', 50]: '#system', + ['regular', 75]: '#system-bold', + ['italic', 25]: '#system-italic-light', + ['italic', 50]: '#system-italic', + ['italic', 75]: '#system-italic-bold' }) - App.addFontMapping("Menlo", { + #App.addFontMapping("SF UI Display", { + # ['regular', 25]: prefix + 'Display-Thin', + # ['regular', 50]: prefix + 'Display-Regular', + # ['regular', 75]: prefix + 'Display-Bold', + # ['italic', 25]: prefix + 'Text-LightItalic', # Only non-italic available. + # ['italic', 50]: prefix + 'Text-Italic', + # ['italic', 75]: prefix + 'Text-BoldItalic' + #}) + App.addFontMapping("Apple Mono", { ['regular', 25]: 'Menlo-Regular', ['regular', 50]: 'Menlo-Regular', ['regular', 75]: 'Menlo-Bold', @@ -102,15 +97,15 @@ group { } font default { - family: SF UI Text - size $: gui.scale('16pt', DisplayMode.PIXEL_RATIO) + family: Apple UI + size: 16pt weight: normal style: normal } font monospace inherits default { - family: Menlo - size $: gui.scale('12pt', DisplayMode.PIXEL_RATIO) + family: Apple Mono + size: 12pt } } @@ -123,13 +118,13 @@ font heading inherits title { size $: gui.scale(default.size, 1.2) } -script { - if Version.OS in ['macx', 'ios'] - # Use the larger variant. - title.family = "SF UI Display" - heading.family = "SF UI Display" - end -} +# script { +# if Version.OS in ['macx', 'ios'] +# # Use the larger variant. +# title.family = "SF UI Display" +# heading.family = "SF UI Display" +# end +# } font small inherits default { size $: gui.scale(self.size, 0.75) diff --git a/doomsday/libs/gui/CMakeLists.txt b/doomsday/libs/gui/CMakeLists.txt index 543cf6ac40..fec4be2d7d 100644 --- a/doomsday/libs/gui/CMakeLists.txt +++ b/doomsday/libs/gui/CMakeLists.txt @@ -28,7 +28,7 @@ add_definitions (-D__LIBGUI__=1) # Source and header files. file (GLOB_RECURSE HEADERS include/de/*) -file (GLOB SOURCES src/stb_impl.c src/*.cpp src/*.h src/input/*.c) +file (GLOB SOURCES src/stb_impl.c src/*.cpp src/*.h src/input/*.c src/text/*.m) deng_merge_sources (audio src/audio/*.cpp) deng_merge_sources (dialogs src/dialogs/*.cpp) diff --git a/doomsday/libs/gui/include/de/text/font.h b/doomsday/libs/gui/include/de/text/font.h index db510e6b10..9f2b772992 100644 --- a/doomsday/libs/gui/include/de/text/font.h +++ b/doomsday/libs/gui/include/de/text/font.h @@ -36,15 +36,15 @@ namespace de { struct FontParams { String family; - float size; // points + float pointSize; NativeFont::Spec spec; FontParams(); FontParams(const NativeFont &font); - bool operator==(FontParams const &other) const + bool operator==(const FontParams &other) const { - return fequal(size, other.size) && spec == other.spec && family == other.family; + return fequal(pointSize, other.pointSize) && spec == other.spec && family == other.family; } }; /** @@ -292,7 +292,7 @@ class LIBGUI_PUBLIC Font * * @return Rectangle covered by the text. */ - Rectanglei measure(String const &textLine) const; + Rectanglei measure(const String &textLine) const; /** * Determines the size of the given line of rich text, i.e., how large an @@ -303,7 +303,7 @@ class LIBGUI_PUBLIC Font * * @return Rectangle covered by the text. */ - Rectanglei measure(RichFormatRef const &format) const; + Rectanglei measure(const RichFormatRef &format) const; /** * Returns the advance width of a line of text. This may not be the same as diff --git a/doomsday/libs/gui/include/de/text/nativefont.h b/doomsday/libs/gui/include/de/text/nativefont.h index 5ce10f46de..43dd227318 100644 --- a/doomsday/libs/gui/include/de/text/nativefont.h +++ b/doomsday/libs/gui/include/de/text/nativefont.h @@ -57,16 +57,16 @@ class LIBGUI_PUBLIC NativeFont : public Asset struct Spec { Style style; - dint weight; + int weight; Transform transform; - Spec(Style s = Regular, dint w = Normal, Transform xform = NoTransform) + Spec(Style s = Regular, int w = Normal, Transform xform = NoTransform) : style(s), weight(w), transform(xform) {} - bool operator == (Spec const &other) const { + bool operator == (const Spec &other) const { return style == other.style && weight == other.weight && transform == other.transform; } - bool operator < (Spec const &other) const { // Map key order + bool operator < (const Spec &other) const { // Map key order if (weight < other.weight) return true; if (weight > other.weight) return false; if (style == other.style) { @@ -85,22 +85,22 @@ class LIBGUI_PUBLIC NativeFont : public Asset * @param family Native font family name. * @param mapping Mapping of styles to native font names. */ - static void defineMapping(String const &family, StyleMapping const &mapping); + static void defineMapping(const String &family, const StyleMapping &mapping); public: - NativeFont(String const &family = ""); - NativeFont(NativeFont const &other); + NativeFont(const String &family = ""); + NativeFont(const NativeFont &other); - void setFamily(String const &family); - void setSize(dfloat size); + void setFamily(const String &family); + void setPointSize(float pointSize); void setStyle(Style style); - void setWeight(dint weight); + void setWeight(int weight); void setTransform(Transform transform); String family() const; - dfloat size() const; + float pointSize() const; Style style() const; - dint weight() const; + int weight() const; Transform transform() const; /** @@ -108,37 +108,54 @@ class LIBGUI_PUBLIC NativeFont : public Asset */ String nativeFontName() const; + // Metrics are returned as pixels: int ascent() const; int descent() const; int height() const; int lineSpacing() const; /** - * Measures the extents of a line of text. + * Measures the extents of a line of text as pixels. * * @param text Text line. * - * @return Boundaries. + * @return Boundaries as pixels. The coordinat eorigin (0,0) is on the baseline. */ - Rectanglei measure(String const &text) const; + Rectanglei measure(const String &text) const; - int width(String const &text) const; + /** + * Width of a text string as pixels. + * + * @param text Text string. + * + * @return Pixel width. + */ + int width(const String &text) const; /** * Draws a line of text using the font into an image. * - * @param text Text line. + * @param text Text line. * @param foreground Foreground/text color. * @param background Background color. * * @return Image of the text, with the same dimensions as returned by measure(). */ - Image rasterize(String const & text, - Image::Color const &foreground, - Image::Color const &background) const; + Image rasterize(const String & text, + const Image::Color &foreground, + const Image::Color &background) const; + + /** + * Sets the pixels-per-point ratio for measuring and rasterizing text. + * + * @param pixelRatio Number of pixels per point. + */ + static void setPixelRatio(float pixelRatio); + + static float pixelRatio(); protected: - NativeFont &operator = (NativeFont const &other); + NativeFont &operator=(const NativeFont &other); /** * Called when the font is needed to be used but it isn't marked Ready. @@ -150,11 +167,11 @@ class LIBGUI_PUBLIC NativeFont : public Asset virtual int nativeFontHeight() const = 0; virtual int nativeFontLineSpacing() const = 0; - virtual int nativeFontWidth(String const &text) const = 0; - virtual Rectanglei nativeFontMeasure(String const &text) const = 0; - virtual Image nativeFontRasterize(String const & text, - Image::Color const &foreground, - Image::Color const &background) const = 0; + virtual int nativeFontWidth(const String &text) const = 0; + virtual Rectanglei nativeFontMeasure(const String &text) const = 0; + virtual Image nativeFontRasterize(const String & text, + const Image::Color &foreground, + const Image::Color &background) const = 0; private: DE_PRIVATE(d) diff --git a/doomsday/libs/gui/src/graphics/glwindow.cpp b/doomsday/libs/gui/src/graphics/glwindow.cpp index dbe846dbeb..1318dcd7ea 100644 --- a/doomsday/libs/gui/src/graphics/glwindow.cpp +++ b/doomsday/libs/gui/src/graphics/glwindow.cpp @@ -105,10 +105,10 @@ DE_PIMPL(GLWindow) void updatePixelRatio() { - int dw, dh, w, h; - SDL_GetWindowSize(window, &w, &h); - SDL_GL_GetDrawableSize(window, &dw, &dh); - const double ratio = double(dw) / double(w); + int points, pixels; + SDL_GetWindowSize(window, &points, nullptr); + SDL_GL_GetDrawableSize(window, &pixels, nullptr); + const double ratio = double(pixels) / double(points); if (!fequal(ratio, pixelRatio)) { pixelRatio = ratio; diff --git a/doomsday/libs/gui/src/guiapp.cpp b/doomsday/libs/gui/src/guiapp.cpp index 3941241411..855e65abe3 100644 --- a/doomsday/libs/gui/src/guiapp.cpp +++ b/doomsday/libs/gui/src/guiapp.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -169,7 +170,8 @@ GuiApp::GuiApp(const StringList &args) } } - d->determineDevicePixelRatio(); + d->determineDevicePixelRatio(); + NativeFont::setPixelRatio(d->windowPixelRatio); static ImageFile::Interpreter intrpImageFile; fileSystem().addInterpreter(intrpImageFile); @@ -216,6 +218,8 @@ void GuiApp::setPixelRatio(float pixelRatio) d->pixelRatio->set(pixelRatio); scriptSystem()["DisplayMode"].set("PIXEL_RATIO", Value::Number(pixelRatio)); } + + NativeFont::setPixelRatio(pixelRatio); } void GuiApp::setMetadata(const String &orgName, diff --git a/doomsday/libs/gui/src/style.cpp b/doomsday/libs/gui/src/style.cpp index 3f8a5bcd4b..1170d88050 100644 --- a/doomsday/libs/gui/src/style.cpp +++ b/doomsday/libs/gui/src/style.cpp @@ -70,7 +70,7 @@ DE_PIMPL(Style) void updateFontSizeFactor() { - float fontSize = 1.f; + float fontSize = 1.0f; if (CommandLine::ArgWithParams arg = App::commandLine().check("-fontsize", 1)) { fontSize = arg.params.at(0).toFloat(); @@ -102,6 +102,7 @@ DE_PIMPL(Style) { LOG_MSG("UI style being updated due to pixel ratio change"); +#if 0 #if defined (WIN32) /* * KLUDGE: The operating system provides fonts scaled according to the desktop @@ -110,6 +111,7 @@ DE_PIMPL(Style) * DisplayMode.PIXEL_RATIO directly. (Should do that on Windows, too?) */ updateFontSizeFactor(); +#endif #endif self().performUpdate(); } diff --git a/doomsday/libs/gui/src/text/coretextnativefont_macx.cpp b/doomsday/libs/gui/src/text/coretextnativefont_macx.cpp index edbd070a27..bf941a5ed9 100644 --- a/doomsday/libs/gui/src/text/coretextnativefont_macx.cpp +++ b/doomsday/libs/gui/src/text/coretextnativefont_macx.cpp @@ -16,7 +16,8 @@ * http://www.gnu.org/licenses */ -#include "../src/text/coretextnativefont_macx.h" +#include "coretextnativefont_macx.h" +#include "fonts_macx.h" #include #include #include @@ -31,26 +32,24 @@ struct CoreTextFontCache : public Lockable { struct Key { String name; - dfloat size; + float pointSize; - Key(String const &n = "", dfloat s = 12.f) + Key(const String &n = {}, float s = 12.f) : name(n) - , size(s) + , pointSize(s) {} bool operator<(Key const &other) const { if (name == other.name) { - return size < other.size && !fequal(size, other.size); + return pointSize < other.pointSize && !fequal(pointSize, other.pointSize); } return name < other.name; } }; - typedef Map Fonts; - Fonts fonts; - - CGColorSpaceRef _colorspace; ///< Shared by all fonts. + Map fonts; + CGColorSpaceRef _colorspace; ///< Shared by all fonts. CoreTextFontCache() : _colorspace(nullptr) {} @@ -76,14 +75,13 @@ struct CoreTextFontCache : public Lockable void clear() { DE_GUARD(this); - for (const auto &ref : fonts) { CFRelease(ref.second); } } - CTFontRef getFont(String const &postScriptName, dfloat pointSize) + CTFontRef getFont(const String postScriptName, float pointSize) { CTFontRef font; @@ -93,17 +91,43 @@ struct CoreTextFontCache : public Lockable { DE_GUARD(this); - Key const key(postScriptName, pointSize); + const Key key(postScriptName, pointSize); if (fonts.contains(key)) { // Already got it. return fonts[key]; } - // Get a reference to the font. - CFStringRef name = CFStringCreateWithCString(nil, postScriptName.c_str(), kCFStringEncodingUTF8); - font = CTFontCreateWithName(name, pointSize, nil); - CFRelease(name); + // System fonts. + if (postScriptName.beginsWith("#")) + { + int weight = 50; + if (postScriptName.contains("-bold")) weight = 75; + else if (postScriptName.contains("-light")) weight = 25; + else if (postScriptName.contains("-black")) weight = 100; + else if (postScriptName.contains("-ultralight")) weight = 0; + + const int italic = postScriptName.contains("-italic"); + + void *nsFont = nullptr; + if (postScriptName.beginsWith("#system")) + { + nsFont = Apple_CreateSystemFont(pointSize, weight, italic); + } + else + { + nsFont = Apple_CreateMonospaceSystemFont(pointSize, weight, italic); + } + font = reinterpret_cast(nsFont); + CFRetain(font); + } + else + { + CFStringRef name = + CFStringCreateWithCString(nil, postScriptName.c_str(), kCFStringEncodingUTF8); + font = CTFontCreateWithName(name, pointSize, nil); + CFRelease(name); + } fonts.insert(key, font); } @@ -223,13 +247,13 @@ DE_PIMPL(CoreTextNativeFont) release(); // Get a reference to the font. - font = fontCache.getFont(self().nativeFontName(), self().size()); + font = fontCache.getFont(self().nativeFontName(), self().pointSize()); - // Get basic metrics about the font. - ascent = ceil(CTFontGetAscent(font)); - descent = ceil(CTFontGetDescent(font)); + // Get basic metrics about the font (in points). + ascent = float(CTFontGetAscent(font)); + descent = float(CTFontGetDescent(font)); height = ascent + descent; - lineSpacing = height + CTFontGetLeading(font); + lineSpacing = height + float(CTFontGetLeading(font)); } CachedLine &makeLine(String const &text, CGColorRef color = nullptr) @@ -267,16 +291,6 @@ CoreTextNativeFont::CoreTextNativeFont(String const &family) : NativeFont(family), d(new Impl(this)) {} -//CoreTextNativeFont::CoreTextNativeFont(QFont const &font) -// : NativeFont(font.family()), d(new Impl(this)) -//{ -// setSize (font.pointSizeF()); -// setWeight (font.weight()); -// setStyle (font.italic()? Italic : Regular); -// setTransform(font.capitalization() == QFont::AllUppercase? Uppercase : -// font.capitalization() == QFont::AllLowercase? Lowercase : NoTransform); -//} - CoreTextNativeFont::CoreTextNativeFont(CoreTextNativeFont const &other) : NativeFont(other) , d(new Impl(this, *other.d)) @@ -301,22 +315,22 @@ void CoreTextNativeFont::commit() const int CoreTextNativeFont::nativeFontAscent() const { - return roundi(d->ascent); + return roundi(d->ascent * pixelRatio()); } int CoreTextNativeFont::nativeFontDescent() const { - return roundi(d->descent); + return roundi(d->descent * pixelRatio()); } int CoreTextNativeFont::nativeFontHeight() const { - return roundi(d->height); + return roundi(d->height * pixelRatio()); } int CoreTextNativeFont::nativeFontLineSpacing() const { - return roundi(d->lineSpacing); + return roundi(d->lineSpacing * pixelRatio()); } Rectanglei CoreTextNativeFont::nativeFontMeasure(String const &text) const @@ -325,9 +339,10 @@ Rectanglei CoreTextNativeFont::nativeFontMeasure(String const &text) const //CGLineGetImageBounds(d->line, d->gc); // more accurate but slow - Rectanglei rect(Vec2i(0, -d->ascent), - Vec2i(roundi(CTLineGetTypographicBounds(d->cache.line, NULL, NULL, NULL)), - d->descent)); + Rectanglei rect( + Vec2i(0, roundi(-d->ascent * pixelRatio())), + Vec2i(roundi(CTLineGetTypographicBounds(d->cache.line, NULL, NULL, NULL) * pixelRatio()), + roundi(d->descent * pixelRatio()))); return rect; } @@ -335,7 +350,7 @@ Rectanglei CoreTextNativeFont::nativeFontMeasure(String const &text) const int CoreTextNativeFont::nativeFontWidth(String const &text) const { auto &cachedLine = d->makeLine(d->applyTransformation(text)); - return roundi(CTLineGetTypographicBounds(cachedLine.line, NULL, NULL, NULL)); + return roundi(CTLineGetTypographicBounds(cachedLine.line, NULL, NULL, NULL) * pixelRatio()); } Image CoreTextNativeFont::nativeFontRasterize(const String &text, @@ -357,7 +372,7 @@ Image CoreTextNativeFont::nativeFontRasterize(const String &text, d->makeLine(d->applyTransformation(text), fgColor); // Set up the bitmap for drawing into. - Rectanglei const bounds = measure(d->cache.lineText); + const Rectanglei bounds = measure(d->cache.lineText); Image backbuffer(bounds.size(), Image::RGBA_8888); backbuffer.fill(background); @@ -367,6 +382,7 @@ Image CoreTextNativeFont::nativeFontRasterize(const String &text, 8, 4 * backbuffer.width(), fontCache.colorspace(), kCGImageAlphaPremultipliedLast); + CGContextScaleCTM(gc, pixelRatio(), pixelRatio()); CGContextSetTextPosition(gc, 0, d->descent); CTLineDraw(d->cache.line, gc); diff --git a/doomsday/libs/gui/src/text/coretextnativefont_macx.h b/doomsday/libs/gui/src/text/coretextnativefont_macx.h index 3797cfb416..879ebd71a9 100644 --- a/doomsday/libs/gui/src/text/coretextnativefont_macx.h +++ b/doomsday/libs/gui/src/text/coretextnativefont_macx.h @@ -30,10 +30,10 @@ namespace de { class CoreTextNativeFont : public NativeFont { public: - CoreTextNativeFont(String const &family = ""); - CoreTextNativeFont(CoreTextNativeFont const &other); + CoreTextNativeFont(const String &family = {}); + CoreTextNativeFont(const CoreTextNativeFont &other); - CoreTextNativeFont &operator=(CoreTextNativeFont const &other); + CoreTextNativeFont &operator=(const CoreTextNativeFont &other); protected: void commit() const; @@ -43,8 +43,8 @@ class CoreTextNativeFont : public NativeFont int nativeFontHeight() const; int nativeFontLineSpacing() const; - Rectanglei nativeFontMeasure(String const &text) const; - int nativeFontWidth(String const &text) const; + Rectanglei nativeFontMeasure(const String &text) const; + int nativeFontWidth(const String &text) const; Image nativeFontRasterize(const String & text, const Image::Color &foreground, const Image::Color &background) const; diff --git a/doomsday/libs/gui/src/text/font.cpp b/doomsday/libs/gui/src/text/font.cpp index 0768c31d25..508b563255 100644 --- a/doomsday/libs/gui/src/text/font.cpp +++ b/doomsday/libs/gui/src/text/font.cpp @@ -36,7 +36,7 @@ template<> struct hash { std::size_t operator()(const de::FontParams &fp) const { return hash()(fp.family) - ^ hash()(int(100 * fp.size)) + ^ hash()(int(100 * fp.pointSize)) ^ hash()(fp.spec.weight) ^ hash()(int(fp.spec.style)) ^ hash()(fp.spec.transform); @@ -47,13 +47,13 @@ struct hash { namespace de { namespace internal { - struct ThreadFonts - { - PlatformFont font; - Hash fontMods; +struct ThreadFonts +{ + PlatformFont font; + Hash fontMods; - ~ThreadFonts() { fontMods.deleteAll(); } - }; + ~ThreadFonts() { fontMods.deleteAll(); } +}; } // namespace internal @@ -81,7 +81,7 @@ DE_PIMPL(Font) createRules(); } - Impl(Public * i, const FontParams &fp) + Impl(Public *i, const FontParams &fp) : Base(i) , fontParams(fp) { @@ -117,7 +117,7 @@ DE_PIMPL(Font) if (found != hash.end()) { auto &tf = found->second; - if (fequal(tf.font.size(), fontParams.size)) + if (fequal(tf.font.pointSize(), fontParams.pointSize)) { return tf; } @@ -127,7 +127,7 @@ DE_PIMPL(Font) } auto &font = hash[thisPublic].font; font.setFamily(fontParams.family); - font.setSize(fontParams.size); + font.setPointSize(fontParams.pointSize); font.setStyle(fontParams.spec.style); font.setTransform(fontParams.spec.transform); font.setWeight(fontParams.spec.weight); @@ -158,7 +158,7 @@ DE_PIMPL(Font) { PlatformFont pf; pf.setFamily(params.family); - pf.setSize(params.size); + pf.setPointSize(params.pointSize); pf.setStyle(params.spec.style); pf.setWeight(params.spec.weight); pf.setTransform(params.spec.transform); @@ -199,7 +199,7 @@ DE_PIMPL(Font) // Size change. if (!fequal(rich.sizeFactor(), 1.f)) { - modParams.size *= rich.sizeFactor(); + modParams.pointSize *= rich.sizeFactor(); } // Style change (including monospace). @@ -378,22 +378,6 @@ Image Font::rasterize(RichFormatRef const &format, const String part = iter.range(); - /* -#ifdef WIN32 - // Kludge: No light-weight fonts available, so reduce opacity to give the - // illusion of thinness. - if (iter.weight() == RichFormat::Light) - { - if (Vec3ub(60, 60, 60) > fg) // dark - fg.w *= .66f; - else if (Vec3ub(230, 230, 230) < fg) // light - fg.w *= .85f; - else - fg.w *= .925f; - } -#endif - */ - Image fragment = font->rasterize(part, fg, bg); Rectanglei const bounds = font->measure(part); @@ -442,7 +426,7 @@ FontParams::FontParams() FontParams::FontParams(const NativeFont &font) { family = font.family(); - size = font.size(); + pointSize = font.pointSize(); spec.weight = font.weight(); spec.style = font.style(); spec.transform = font.transform(); diff --git a/doomsday/libs/gui/src/text/fontbank.cpp b/doomsday/libs/gui/src/text/fontbank.cpp index 47fe13caf6..70f1d17254 100644 --- a/doomsday/libs/gui/src/text/fontbank.cpp +++ b/doomsday/libs/gui/src/text/fontbank.cpp @@ -50,28 +50,24 @@ DE_PIMPL(FontBank) // Size. String size = def["size"]; + font.pointSize = size.toInt(nullptr, 10, String::AllowSuffix) * bank.d->fontSizeFactor; if (size.endsWith("px")) { - DE_ASSERT_FAIL("Convert font size from pixels to points"); - //font.setPixelSize(size.toInt(0, 10, String::AllowSuffix) * bank.d->fontSizeFactor); - } - else - { - font.size = size.toInt(nullptr, 10, String::AllowSuffix) * bank.d->fontSizeFactor; + font.pointSize /= NativeFont::pixelRatio(); } // Weight. - String const weight = def["weight"]; + const String weight = def["weight"]; font.spec.weight = (weight == "light"? NativeFont::Light : weight == "bold"? NativeFont::Bold : NativeFont::Normal); // Style. - String const style = def["style"]; + const String style = def["style"]; font.spec.style = (style == "italic"? NativeFont::Italic : NativeFont::Regular); // Transformation function. - String const caps = def.gets("transform", "normal"); + const String caps = def.gets("transform", "normal"); font.spec.transform = (caps == "uppercase"? NativeFont::Uppercase : caps == "lowercase"? NativeFont::Lowercase : NativeFont::NoTransform); @@ -134,8 +130,8 @@ Font const &FontBank::font(const DotPath &path) const void FontBank::setFontSizeFactor(float sizeFactor) { // The overall UI scale factor affects fonts. - d->fontSizeFactor = clamp(.1f, sizeFactor, 20.f); - + d->fontSizeFactor = clamp(0.1f, sizeFactor, 20.0f); +#if 0 #if defined (WIN32) /* * On Windows, fonts are automatically scaled by the operating system according @@ -145,6 +141,7 @@ void FontBank::setFontSizeFactor(float sizeFactor) */ d->fontSizeFactor *= Config::get().getf("ui.scaleFactor", 1.f); #endif +#endif } void FontBank::reload() diff --git a/doomsday/libs/gui/src/text/fonts_macx.h b/doomsday/libs/gui/src/text/fonts_macx.h new file mode 100644 index 0000000000..c534fd2f95 --- /dev/null +++ b/doomsday/libs/gui/src/text/fonts_macx.h @@ -0,0 +1,32 @@ +/** @file fonts_macx.h System font routines for macOS. + * + * @authors Copyright (c) 2019 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ +#ifndef LIBGUI_FONTS_MACX_H +#define LIBGUI_FONTS_MACX_H + +#if defined (__cplusplus) +extern "C" { +#endif + +void * Apple_CreateSystemFont (float size, int weight, int italic); +void * Apple_CreateMonospaceSystemFont (float size, int weight, int italic); + +#if defined (__cplusplus) +} // extern "C" +#endif + +#endif // LIBGUI_FONTS_MACX_H diff --git a/doomsday/libs/gui/src/text/fonts_macx.m b/doomsday/libs/gui/src/text/fonts_macx.m new file mode 100644 index 0000000000..b0bd8baa5e --- /dev/null +++ b/doomsday/libs/gui/src/text/fonts_macx.m @@ -0,0 +1,57 @@ +/** @file fonts_macx.m System font routines for macOS. + * + * @authors Copyright (c) 2019 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#import +#import + +static NSFontWeight fontWeight(int weight) +{ + return (weight == 0 ? NSFontWeightUltraLight : + weight == 25 ? NSFontWeightLight : + weight == 75 ? NSFontWeightBold : + weight == 100 ? NSFontWeightBlack : + NSFontWeightRegular); +} + +static NSFont *applyStyle(NSFont *font, int monospace, int italic) +{ + if (italic || monospace) + { + NSFontTraitMask style = (monospace ? NSFixedPitchFontMask : 0) | + (italic ? NSItalicFontMask : 0); + NSFont *conv = [[NSFontManager sharedFontManager] convertFont:font + toHaveTrait:style]; + if (conv != font) + { + [font release]; + return conv; + } + } + return font; +} + +void *Apple_CreateSystemFont(float size, int weight, int italic) +{ + // Just ask for .NSSFUIText and .NSSFUIDisplay + return applyStyle([NSFont systemFontOfSize:size weight:fontWeight(weight)], 0, italic); +} + +void *Apple_CreateMonospaceSystemFont(float size, int weight, int italic) +{ + return applyStyle([NSFont systemFontOfSize:size weight:fontWeight(weight)], 1, italic); +} diff --git a/doomsday/libs/gui/src/text/nativefont.cpp b/doomsday/libs/gui/src/text/nativefont.cpp index 2a687813b0..2b00689d2a 100644 --- a/doomsday/libs/gui/src/text/nativefont.cpp +++ b/doomsday/libs/gui/src/text/nativefont.cpp @@ -19,19 +19,21 @@ #include "de/NativeFont" #include #include +#include namespace de { -typedef Hash Families; -static Families families; +static Hash s_families; -static int const MAX_CACHE_STRING_LENGTH = 200; -static int const MAX_CACHE_STRINGS = 500; +static constexpr int MAX_CACHE_STRING_LENGTH = 200; +static constexpr int MAX_CACHE_STRINGS = 500; + +DE_STATIC_PROPERTY(NativeFontPixelRatio, float) DE_PIMPL(NativeFont) { String family; - dfloat size; + float pointSize; Style style; int weight; Transform transform; @@ -40,11 +42,13 @@ DE_PIMPL(NativeFont) Impl(Public *i) : Base(i) - , size(12.f) + , pointSize(12.0f) , style(Regular) , weight(Normal) , transform(NoTransform) - {} + { + pNativeFontPixelRatio.audienceForChange() += [this]() { markNotReady(); }; + } void prepare() { @@ -65,7 +69,7 @@ DE_PIMPL(NativeFont) void NativeFont::defineMapping(String const &family, StyleMapping const &mapping) { - families.insert(family, mapping); + s_families.insert(family, mapping); } NativeFont::NativeFont(String const &family) : d(new Impl(this)) @@ -78,11 +82,11 @@ NativeFont::NativeFont(NativeFont const &other) : Asset(other), d(new Impl(this) *this = other; } -NativeFont &NativeFont::operator = (NativeFont const &other) +NativeFont &NativeFont::operator=(const NativeFont &other) { d->family = other.d->family; d->style = other.d->style; - d->size = other.d->size; + d->pointSize = other.d->pointSize; d->weight = other.d->weight; d->transform = other.d->transform; d->markNotReady(); @@ -95,9 +99,9 @@ void NativeFont::setFamily(String const &family) d->markNotReady(); } -void NativeFont::setSize(dfloat size) +void NativeFont::setPointSize(float pointSize) { - d->size = size; + d->pointSize = pointSize; d->markNotReady(); } @@ -124,9 +128,9 @@ String NativeFont::family() const return d->family; } -dfloat NativeFont::size() const +float NativeFont::pointSize() const { - return d->size; + return d->pointSize; } NativeFont::Style NativeFont::style() const @@ -147,15 +151,15 @@ NativeFont::Transform NativeFont::transform() const String NativeFont::nativeFontName() const { // Check the defined mappings. - auto found = families.find(d->family); - if (found != families.end()) + auto found = s_families.find(d->family); + if (found != s_families.end()) { - const StyleMapping &map = found->second; + const auto &styleMapping = found->second; const Spec spec(d->style, d->weight); - auto found = map.find(spec); - if (found != map.end()) + auto mapped = styleMapping.find(spec); + if (mapped != styleMapping.end()) { - return found->second; + return mapped->second; } } return d->family; @@ -185,7 +189,7 @@ int NativeFont::lineSpacing() const return nativeFontLineSpacing(); } -Rectanglei NativeFont::measure(String const &text) const +Rectanglei NativeFont::measure(const String &text) const { d->prepare(); @@ -198,7 +202,7 @@ Rectanglei NativeFont::measure(String const &text) const } } - Rectanglei const bounds = nativeFontMeasure(text); + const Rectanglei bounds = nativeFontMeasure(text); // Remember this for later. if (d->measureCache.size() > MAX_CACHE_STRINGS) @@ -217,12 +221,22 @@ int NativeFont::width(String const &text) const return nativeFontWidth(text); } -Image NativeFont::rasterize(String const & text, - Image::Color const &foreground, - Image::Color const &background) const +Image NativeFont::rasterize(const String & text, + const Image::Color &foreground, + const Image::Color &background) const { d->prepare(); return nativeFontRasterize(text, foreground, background); } +void NativeFont::setPixelRatio(float pixelRatio) +{ + pNativeFontPixelRatio.setValue(pixelRatio); +} + +float NativeFont::pixelRatio() +{ + return pNativeFontPixelRatio.value(); +} + } // namespace de diff --git a/doomsday/libs/gui/src/text/sdlnativefont.cpp b/doomsday/libs/gui/src/text/sdlnativefont.cpp index a2049ddcde..9718fad805 100644 --- a/doomsday/libs/gui/src/text/sdlnativefont.cpp +++ b/doomsday/libs/gui/src/text/sdlnativefont.cpp @@ -27,16 +27,16 @@ namespace de { struct FontSpec { String name; // family followed by style - int size; + int pixelSize; bool operator<(const FontSpec &other) const { - const int c = name.compareWithoutCase(other.name); - if (c == 0) + const int cmp = name.compareWithoutCase(other.name); + if (cmp == 0) { - return cmp(size, other.size) < 0; + return pixelSize < other.pixelSize; } - return c < 0; + return cmp < 0; } }; @@ -94,16 +94,9 @@ struct FontCache // thread-local { Map> fonts; // loaded fonts -// void insertFont(TTF_Font *font, int size) -// { -// const String name = fontName(font); -// debug("[SdlNativeFont] inserting font %p '%s' size:%d", font, name.c_str(), size); -// fonts[{name, size}].reset(font); -// } - - TTF_Font *load(const String &name, int size) + TTF_Font *load(const String &name, int pixelSize) { - auto found = fonts.find({name, size}); + auto found = fonts.find({name, pixelSize}); if (found != fonts.end()) { return found->second.get(); @@ -115,19 +108,19 @@ struct FontCache // thread-local return nullptr; } TTF_Font *font = TTF_OpenFontRW( - SDL_RWFromConstMem(data->second.data(), int(data->second.size())), SDL_TRUE, size); + SDL_RWFromConstMem(data->second.data(), int(data->second.size())), SDL_TRUE, pixelSize); DE_ASSERT(font != nullptr); if (!font) { - debug("[SdlNativeFont] failed to open '%s' size:%d", name.c_str(), size); + debug("[SdlNativeFont] failed to open '%s' size:%d", name.c_str(), pixelSize); return nullptr; } - debug("[SdlNativeFont] loaded %p '%s' size:%d", font, name.c_str(), size); - fonts[{name, size}].reset(font); + debug("[SdlNativeFont] loaded %p '%s' size:%d", font, name.c_str(), pixelSize); + fonts[{name, pixelSize}].reset(font); return font; } - TTF_Font *getFont(const String &family, int size, NativeFont::Weight weight, + TTF_Font *getFont(const String &family, int pixelSize, NativeFont::Weight weight, NativeFont::Style style) { String name = family; @@ -140,7 +133,7 @@ struct FontCache // thread-local name += (weight >= NativeFont::Bold ? " Bold" : " Light"); if (style == NativeFont::Italic) name += " Italic"; } - return load(name.c_str(), size); + return load(name.c_str(), pixelSize); } }; @@ -169,7 +162,7 @@ DE_PIMPL(SdlNativeFont) void updateFontAndMetrics() { font = s_fontCache.get().getFont(self().nativeFontName(), - roundi(self().size()), + roundi(self().pointSize() * pixelRatio()), NativeFont::Weight(self().weight()), self().style()); if (font)