summaryrefslogtreecommitdiff
path: root/pango/pangocoretext-fontmap.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-07-04 11:16:05 -0400
committerMatthias Clasen <mclasen@redhat.com>2022-07-04 11:17:21 -0400
commitbcdce34c8ac0adffd589e9fb68b62ff09368bb0f (patch)
tree7b92ba875b22212d15ffb9d9620d517cfa427a1e /pango/pangocoretext-fontmap.c
parentb197cc08b18bc44a3e93f859ca7e61dfe335bbc5 (diff)
downloadpango-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.c460
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: */