diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-07-04 11:16:05 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-07-04 11:17:21 -0400 |
commit | bcdce34c8ac0adffd589e9fb68b62ff09368bb0f (patch) | |
tree | 7b92ba875b22212d15ffb9d9620d517cfa427a1e /pango/pangocoretext-fontmap.c | |
parent | b197cc08b18bc44a3e93f859ca7e61dfe335bbc5 (diff) | |
download | pango-bcdce34c8ac0adffd589e9fb68b62ff09368bb0f.tar.gz |
Move the code from pango/ to pango2/
Life is easier if the src path matches the installed
header path prefix, so make them match. Update all
users.
Diffstat (limited to 'pango/pangocoretext-fontmap.c')
-rw-r--r-- | pango/pangocoretext-fontmap.c | 460 |
1 files changed, 0 insertions, 460 deletions
diff --git a/pango/pangocoretext-fontmap.c b/pango/pangocoretext-fontmap.c deleted file mode 100644 index 3b7cdd47..00000000 --- a/pango/pangocoretext-fontmap.c +++ /dev/null @@ -1,460 +0,0 @@ -/* Pango2 - * - * Copyright (C) 2021 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "config.h" -#include <math.h> - -#include <gio/gio.h> - -#include "pangocoretext-fontmap.h" -#include "pango-hbfamily-private.h" -#include "pango-fontmap-private.h" -#include "pango-hbface-private.h" -#include "pango-hbfont-private.h" -#include "pango-context.h" -#include "pango-impl-utils.h" -#include "pango-trace-private.h" - -#include <Carbon/Carbon.h> -#include <hb-ot.h> -#include <hb-coretext.h> - - -/** - * Pango2CoreTextFontMap: - * - * `Pango2CoreTextFontMap` is a subclass of `Pango2FontMap` that uses - * CoreText to populate the fontmap with the available fonts. - */ - - -struct _Pango2CoreTextFontMap -{ - Pango2FontMap parent_instance; -}; - -struct _Pango2CoreTextFontMapClass -{ - Pango2FontMapClass parent_class; -}; - -/* {{{ CoreText utilities */ - -#define ct_weight_min -0.7f -#define ct_weight_max 0.8f - -/* This map is based on empirical data from analyzing a large collection of - * fonts and comparing the opentype value with the value that OSX returns. - * see: https://bugzilla.gnome.org/show_bug.cgi?id=766148 - * FIXME: This need recalibrating, values outside these bounds do occur! - */ - -static struct { - float ct_weight; - Pango2Weight pango2_weight; -} ct_weight_map[] = { - { ct_weight_min, PANGO2_WEIGHT_THIN }, - { -0.5, PANGO2_WEIGHT_ULTRALIGHT }, - { -0.23, PANGO2_WEIGHT_LIGHT }, - { -0.115, PANGO2_WEIGHT_SEMILIGHT }, - { 0.00, PANGO2_WEIGHT_NORMAL }, - { 0.2, PANGO2_WEIGHT_MEDIUM }, - { 0.3, PANGO2_WEIGHT_SEMIBOLD }, - { 0.4, PANGO2_WEIGHT_BOLD }, - { 0.6, PANGO2_WEIGHT_ULTRABOLD }, - { ct_weight_max, PANGO2_WEIGHT_HEAVY } -}; - -static int -lerp (float x, float x1, float x2, int y1, int y2) -{ - float dx = x2 - x1; - int dy = y2 - y1; - return y1 + (dy * (x - x1) + dx / 2) / dx; -} - -static Pango2Weight -ct_font_descriptor_get_weight (CTFontDescriptorRef desc) -{ - CFDictionaryRef dict; - CFNumberRef cf_number; - CGFloat value; - Pango2Weight weight = PANGO2_WEIGHT_NORMAL; - guint i; - - dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute); - cf_number = (CFNumberRef)CFDictionaryGetValue (dict, kCTFontWeightTrait); - - if (cf_number != NULL && CFNumberGetValue (cf_number, kCFNumberCGFloatType, &value)) - { - if (!(value >= ct_weight_min && value <= ct_weight_max)) - { - i = value > ct_weight_max ? G_N_ELEMENTS (ct_weight_map) - 1 : 0; - weight = ct_weight_map[i].ct_weight; - } - else - { - for (i = 1; value > ct_weight_map[i].ct_weight; ++i) - ; - - weight = lerp (value, ct_weight_map[i-1].ct_weight, ct_weight_map[i].ct_weight, - ct_weight_map[i-1].pango2_weight, ct_weight_map[i].pango2_weight); - - } - } - else - weight = PANGO2_WEIGHT_NORMAL; - - CFRelease (dict); - - return weight; -} - -static char * -gchar_from_cf_string (CFStringRef str) -{ - CFIndex len; - char *buffer; - - /* GetLength returns the number of UTF-16 pairs, so this number - * times 2 should definitely gives us enough space for UTF8. - * We add one for the terminating zero. - */ - len = CFStringGetLength (str) * 2 + 1; - buffer = g_new0 (char, len); - CFStringGetCString (str, buffer, len, kCFStringEncodingUTF8); - - return buffer; -} - -static char * -ct_font_descriptor_get_family_name (CTFontDescriptorRef desc, - gboolean may_fail) -{ - CFStringRef cf_str; - char *buffer; - - cf_str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute); - if (!cf_str) - { - int i; - - /* No font family name is set, try to retrieve font name and deduce - * the family name from that instead. - */ - cf_str = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute); - if (!cf_str) - { - if (may_fail) - return NULL; - - /* This font is likely broken, return a default family name ... */ - return g_strdup ("Sans"); - } - - buffer = gchar_from_cf_string (cf_str); - CFRelease (cf_str); - - for (i = 0; i < strlen (buffer); i++) - if (buffer[i] == '-') - break; - - if (i < strlen (buffer)) - { - char *ret; - - ret = g_strndup (buffer, i); - g_free (buffer); - - return ret; - } - else - return buffer; - } - - buffer = gchar_from_cf_string (cf_str); - CFRelease (cf_str); - - return buffer; -} - -static char * -ct_font_descriptor_get_style_name (CTFontDescriptorRef desc) -{ - CFStringRef cf_str; - char *buffer; - - cf_str = CTFontDescriptorCopyAttribute (desc, kCTFontStyleNameAttribute); - if (!cf_str) - return NULL; - - buffer = gchar_from_cf_string (cf_str); - CFRelease (cf_str); - - return buffer; -} - -static CTFontSymbolicTraits -ct_font_descriptor_get_traits (CTFontDescriptorRef desc) -{ - CFDictionaryRef dict; - CFNumberRef cf_number; - SInt64 traits; - - /* This is interesting, the value stored is a CTFontSymbolicTraits which - * is defined as uint32_t. CFNumber does not have an obvious type which - * deals with unsigned values. Upon inspection with CFNumberGetType, - * it turns out this value is stored as SInt64, so we use that to - * obtain the value from the CFNumber. - */ - dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute); - cf_number = (CFNumberRef)CFDictionaryGetValue (dict, kCTFontSymbolicTrait); - if (!CFNumberGetValue (cf_number, kCFNumberSInt64Type, &traits)) - traits = 0; - CFRelease (dict); - - return (CTFontSymbolicTraits)traits; -} - -static gboolean -ct_font_descriptor_is_small_caps (CTFontDescriptorRef desc) -{ - CFIndex i, count; - CFArrayRef array; - CFStringRef str; - gboolean retval = FALSE; - - /* See http://stackoverflow.com/a/4811371 for why this works and an - * explanation of the magic number "3" used below. - */ - array = CTFontDescriptorCopyAttribute (desc, kCTFontFeaturesAttribute); - if (!array) - return FALSE; - - str = CFStringCreateWithCString (NULL, "CTFeatureTypeIdentifier", - kCFStringEncodingASCII); - - count = CFArrayGetCount (array); - for (i = 0; i < count; i++) - { - CFDictionaryRef dict = CFArrayGetValueAtIndex (array, i); - CFNumberRef num; - - num = (CFNumberRef)CFDictionaryGetValue (dict, str); - if (num) - { - int value = 0; - - if (CFNumberGetValue (num, kCFNumberSInt32Type, &value) && - value == 3) - { - /* This font supports small caps. */ - retval = TRUE; - break; - } - } - } - - CFRelease (str); - CFRelease (array); - - return retval; -} - -static gboolean -pango2_core_text_style_name_is_oblique (const char *style_name) -{ - return style_name && strstr (style_name, "Oblique"); -} - -static Pango2FontDescription * -font_description_from_ct_font_descriptor (CTFontDescriptorRef desc) -{ - SInt64 font_traits; - char *family_name; - char *style_name; - Pango2FontDescription *font_desc; - - font_desc = pango2_font_description_new (); - - family_name = ct_font_descriptor_get_family_name (desc, FALSE); - pango2_font_description_set_family (font_desc, family_name); - g_free (family_name); - - pango2_font_description_set_weight (font_desc, ct_font_descriptor_get_weight (desc)); - - font_traits = ct_font_descriptor_get_traits (desc); - style_name = ct_font_descriptor_get_style_name (desc); - - if ((font_traits & kCTFontItalicTrait) == kCTFontItalicTrait) - pango2_font_description_set_style (font_desc, PANGO2_STYLE_ITALIC); - else if (pango2_core_text_style_name_is_oblique (style_name)) - pango2_font_description_set_style (font_desc, PANGO2_STYLE_OBLIQUE); - else - pango2_font_description_set_style (font_desc, PANGO2_STYLE_NORMAL); - - if ((font_traits & kCTFontCondensedTrait) == kCTFontCondensedTrait) - pango2_font_description_set_stretch (font_desc, PANGO2_STRETCH_CONDENSED); - - if (ct_font_descriptor_is_small_caps (desc)) - pango2_font_description_set_variant (font_desc, PANGO2_VARIANT_SMALL_CAPS); - else - pango2_font_description_set_variant (font_desc, PANGO2_VARIANT_NORMAL); - - g_free (style_name); - - return font_desc; -} - -static Pango2HbFace * -face_from_ct_font_descriptor (CTFontDescriptorRef desc) -{ - Pango2HbFace *face; - CTFontRef ctfont; - CGFontRef cgfont; - hb_face_t *hb_face; - char *name; - Pango2FontDescription *description; - - ctfont = CTFontCreateWithFontDescriptor (desc, 0.0, NULL); - cgfont = CTFontCopyGraphicsFont (ctfont, NULL); - - hb_face = hb_coretext_face_create (cgfont); - - CFRelease (cgfont); - CFRelease (ctfont); - - name = ct_font_descriptor_get_style_name (desc); - description = font_description_from_ct_font_descriptor (desc); - pango2_font_description_unset_fields (description, PANGO2_FONT_MASK_VARIANT | - PANGO2_FONT_MASK_SIZE | - PANGO2_FONT_MASK_GRAVITY); - - hb_face_make_immutable (hb_face); - - face = pango2_hb_face_new_from_hb_face (hb_face, -1, name, description); - // FIXME: what about languages? see CTFontCopySupportedLanguages - - pango2_font_description_free (description); - g_free (name); - hb_face_destroy (hb_face); - - return face; -} - -/* }}} */ -/* {{{ Pango2FontMap implementation */ - -static void -pango2_core_text_font_map_populate (Pango2FontMap *map) -{ - CTFontCollectionRef collection; - CFArrayRef ctfaces; - CFIndex count; - - /* Add all system fonts */ - collection = CTFontCollectionCreateFromAvailableFonts (0); - ctfaces = CTFontCollectionCreateMatchingFontDescriptors (collection); - count = CFArrayGetCount (ctfaces); - - for (int i = 0; i < count; i++) - { - CTFontDescriptorRef desc = CFArrayGetValueAtIndex (ctfaces, i); - Pango2HbFace *face = face_from_ct_font_descriptor (desc); - pango2_font_map_add_face (map, PANGO2_FONT_FACE (face)); - } - - /* Add generic aliases */ - struct { - const char *alias_name; - const char *family_name; - } aliases[] = { - { "Monospace", "Courier" }, - { "Sans-serif", "Helvetica" }, - { "Sans", "Helvetica" }, - { "Serif", "Times" }, - { "Cursive", "Apple Chancery" }, - { "Fantasy", "Papyrus", }, - { "System-ui", ".AppleSystemUIFont" }, - { "Emoji", "Apple Color Emoji" } - }; - - for (int i = 0; i < G_N_ELEMENTS (aliases); i++) - { - Pango2FontFamily *family = pango2_font_map_get_family (map, aliases[i].family_name); - - if (family) - { - Pango2GenericFamily *alias_family; - - alias_family = pango2_generic_family_new (aliases[i].alias_name); - pango2_generic_family_add_family (alias_family, family); - pango2_font_map_add_family (map, PANGO2_FONT_FAMILY (alias_family)); - } - } -} - -/* }}} */ -/* {{{ Pango2CoreTextFontMap implementation */ - -G_DEFINE_FINAL_TYPE (Pango2CoreTextFontMap, pango2_core_text_font_map, PANGO2_TYPE_FONT_MAP) - -static void -pango2_core_text_font_map_init (Pango2CoreTextFontMap *self) -{ - pango2_font_map_repopulate (PANGO2_FONT_MAP (self), TRUE); -} - -static void -pango2_core_text_font_map_finalize (GObject *object) -{ - G_OBJECT_CLASS (pango2_core_text_font_map_parent_class)->finalize (object); -} - -static void -pango2_core_text_font_map_class_init (Pango2CoreTextFontMapClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - Pango2FontMapClass *font_map_class = PANGO2_FONT_MAP_CLASS (class); - - object_class->finalize = pango2_core_text_font_map_finalize; - - font_map_class->populate = pango2_core_text_font_map_populate; -} - -/* }}} */ - /* {{{ Public API */ - -/** - * pango2_core_text_font_map_new: - * - * Creates a new `Pango2CoreTextFontMap` object. - * - * Returns: a new `Pango2CoreTextFontMap` - */ -Pango2CoreTextFontMap * -pango2_core_text_font_map_new (void) -{ - return g_object_new (PANGO2_TYPE_CORE_TEXT_FONT_MAP, NULL); -} - -/* }}} */ - -/* vim:set foldmethod=marker expandtab: */ |