diff options
-rw-r--r-- | configure.ac | 22 | ||||
-rw-r--r-- | libass/Makefile.am | 4 | ||||
-rw-r--r-- | libass/ass_coretext.c | 217 | ||||
-rw-r--r-- | libass/ass_coretext.h | 34 | ||||
-rw-r--r-- | libass/ass_fontselect.c | 8 |
5 files changed, 284 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index fce38ef2..6cfd823e 100644 --- a/configure.ac +++ b/configure.ac @@ -151,6 +151,28 @@ PKG_CHECK_MODULES([FONTCONFIG], fontconfig >= 2.4.2, [ ]) fi +if test x$enable_coretext != xno; then +OLDLIBS="$LIBS" +# Linking to CoreText directly only works from Mountain Lion and iOS6. In +# earlier OS releases CoreText was part of the ApplicationServices umbrella +# framework. +LIBS="$LIBS -framework CoreText -framework CoreFoundation -framework CoreGraphics" +AC_MSG_CHECKING([for CORETEXT]) +AC_LINK_IFELSE([ + AC_LANG_PROGRAM( + [[#include <CoreText/CoreText.h>]], + [[CTFontCreateWithFontDescriptor(NULL, 0.0, NULL);]],) + ], [ + AC_DEFINE(CONFIG_CORETEXT, 1, [found CoreText in System library]) + coretext=true + AC_MSG_RESULT([yes]) + ], [ + LIBS="$OLDLIBS" + coretext=false + AC_MSG_RESULT([no]) + ]) +fi + if test x$enable_harfbuzz != xno; then PKG_CHECK_MODULES([HARFBUZZ], harfbuzz >= 0.9.5, [ CFLAGS="$CFLAGS $HARFBUZZ_CFLAGS" diff --git a/libass/Makefile.am b/libass/Makefile.am index b8659e6b..68547682 100644 --- a/libass/Makefile.am +++ b/libass/Makefile.am @@ -26,7 +26,9 @@ libass_la_SOURCES = ass.c ass_cache.c ass_font.c ass_fontselect.c ass_render.c \ ass_library.h ass_types.h ass_utils.h ass_drawing.c \ ass_drawing.h ass_cache_template.h ass_render.h \ ass_parse.c ass_parse.h ass_render_api.c ass_shaper.c \ - ass_shaper.h ass_strtod.c ass_fontconfig.c ass_fontconfig.h + ass_shaper.h ass_strtod.c ass_fontconfig.c ass_fontconfig.h \ + ass_coretext.c ass_coretext.h + libass_la_LDFLAGS = -no-undefined -version-info $(LIBASS_LT_CURRENT):$(LIBASS_LT_REVISION):$(LIBASS_LT_AGE) libass_la_LDFLAGS += -export-symbols $(srcdir)/libass.sym diff --git a/libass/ass_coretext.c b/libass/ass_coretext.c new file mode 100644 index 00000000..f970226d --- /dev/null +++ b/libass/ass_coretext.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com> + * + * This file is part of libass. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#ifdef CONFIG_CORETEXT + +#include <CoreFoundation/CoreFoundation.h> +#include <CoreText/CoreText.h> + +#include "ass_coretext.h" + +static char *cfstr2buf(CFStringRef string) +{ + const char *buf_ptr = CFStringGetCStringPtr(string, kCFStringEncodingUTF8); + if (buf_ptr) { + return strdup(buf_ptr); + } else { + size_t buf_len = CFStringGetLength(string) + 1; + char *buf = calloc(buf_len, sizeof(char)); + CFStringGetCString(string, buf, buf_len, kCFStringEncodingUTF8); + return buf; + } +} + +static void destroy_font(void *priv) +{ + CFCharacterSetRef set = priv; + CFRelease(set); +} + +static int check_glyph(void *priv, uint32_t code) +{ + CFCharacterSetRef set = priv; + + if (!set) + return 1; + + if (code == 0) + return 1; + + return CFCharacterSetIsLongCharacterMember(set, code); +} + +static char *get_font_file(CTFontDescriptorRef fontd) +{ + CFURLRef url = CTFontDescriptorCopyAttribute(fontd, kCTFontURLAttribute); + CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + char *buffer = cfstr2buf(path); + CFRelease(path); + CFRelease(url); + return buffer; +} + +static void get_name(CTFontDescriptorRef fontd, CFStringRef attr, + char **array, int *idx) +{ + + CFStringRef name = CTFontDescriptorCopyAttribute(fontd, attr); + if (name) { + array[*idx] = cfstr2buf(name); + CFRelease(name); + *idx += 1; + } +} + +static void get_trait(CFDictionaryRef traits, CFStringRef attribute, + float *trait) +{ + CFNumberRef cftrait = CFDictionaryGetValue(traits, attribute); + if (!CFNumberGetValue(cftrait, kCFNumberFloatType, trait)) + *trait = 0.0; +} + +static void get_font_traits(CTFontDescriptorRef fontd, + ASS_FontProviderMetaData *meta) +{ + float weight, slant, width; + + CFDictionaryRef traits = + CTFontDescriptorCopyAttribute(fontd, kCTFontTraitsAttribute); + + get_trait(traits, kCTFontWeightTrait, &weight); + get_trait(traits, kCTFontSlantTrait, &slant); + get_trait(traits, kCTFontWidthTrait, &width); + + CFRelease(traits); + + // Printed all of my system fonts (see if'deffed code below). Here is how + // CoreText 'normalized' weights maps to CSS/libass: + + // opentype: 0 100 200 300 400 500 600 700 800 900 + // css: LIGHT REG MED SBOLD BOLD BLACK EXTRABL + // libass: LIGHT MEDIUM BOLD + // coretext: -0.4 0.0 0.23 0.3 0.4 0.62 + + if (weight >= 0.62) + meta->weight = 800; + else if (weight >= 0.4) + meta->weight = 700; + else if (weight >= 0.3) + meta->weight = 600; + else if (weight >= 0.23) + meta->weight = 500; + else if (weight >= -0.4) + meta->weight = 400; + else + meta->weight = 200; + + if (slant > 0.03) + meta->slant = FONT_SLANT_ITALIC; + else + meta->slant = FONT_SLANT_NONE; + + if (width <= -0.2) + meta->width = FONT_WIDTH_CONDENSED; + else if (width >= 0.2) + meta->width = FONT_WIDTH_EXPANDED; + else + meta->width = FONT_WIDTH_NORMAL; + +#if 0 + char *name[1]; + int idx = 0; + get_name(fontd, kCTFontDisplayNameAttribute, name, &idx); + char *file = get_font_file(fontd); + printf( + "Font traits for: %-40s [%-50s] " + "<slant: %f, %03d>, <weight: (%f, %03d)>, <width: %f, %03d>\n", + name[0], file, + slant, meta->slant, weight, meta->weight, width, meta->width); + free(name[0]); + free(file); +#endif +} + +static void scan_fonts(ASS_Library *lib, ASS_FontProvider *provider) +{ + ASS_FontProviderMetaData meta; + char *families[1]; + char *fullnames[2]; + + CTFontCollectionRef coll = CTFontCollectionCreateFromAvailableFonts(NULL); + CFArrayRef fontsd = CTFontCollectionCreateMatchingFontDescriptors(coll); + + for (int i = 0; i < CFArrayGetCount(fontsd); i++) { + CTFontDescriptorRef fontd = CFArrayGetValueAtIndex(fontsd, i); + int index = 0; + + char *path = get_font_file(fontd); + if (strcmp("", path) == 0) { + // skip the font if the URL field in the font descriptor is empty + free(path); + continue; + } + + memset(&meta, 0, sizeof(meta)); + get_font_traits(fontd, &meta); + + get_name(fontd, kCTFontFamilyNameAttribute, families, &meta.n_family); + meta.families = families; + + get_name(fontd, kCTFontDisplayNameAttribute, fullnames, &meta.n_fullname); + get_name(fontd, kCTFontNameAttribute, fullnames, &meta.n_fullname); + meta.fullnames = fullnames; + + CFCharacterSetRef chset = + CTFontDescriptorCopyAttribute(fontd, kCTFontCharacterSetAttribute); + ass_font_provider_add_font(provider, &meta, path, index, (void*)chset); + + for (int j = 0; j < meta.n_family; j++) + free(meta.families[j]); + + for (int j = 0; j < meta.n_fullname; j++) + free(meta.fullnames[j]); + + free(path); + } + + CFRelease(fontsd); + CFRelease(coll); +} + +static ASS_FontProviderFuncs coretext_callbacks = { + NULL, + check_glyph, + destroy_font, + NULL +}; + +ASS_FontProvider * +ass_coretext_add_provider(ASS_Library *lib, ASS_FontSelector *selector) +{ + ASS_FontProvider *provider = + ass_font_provider_new(selector, &coretext_callbacks, NULL); + + scan_fonts(lib, provider); + + return provider; +} + +#endif diff --git a/libass/ass_coretext.h b/libass/ass_coretext.h new file mode 100644 index 00000000..8d969275 --- /dev/null +++ b/libass/ass_coretext.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com> + * + * This file is part of libass. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include "ass_types.h" +#include "ass_fontselect.h" + +#ifndef ASS_CORETEXT_H +#define ASS_CORETEXT_H + +#ifdef CONFIG_CORETEXT + +ASS_FontProvider * +ass_coretext_add_provider(ASS_Library *lib, ASS_FontSelector *selector); + +#endif + +#endif diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index cf1c0888..9ef0acef 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -37,6 +37,7 @@ #include "ass_library.h" #include "ass_fontselect.h" #include "ass_fontconfig.h" +#include "ass_coretext.h" #include "ass_font.h" #define ABS(x) ((x) < 0 ? -(x) : (x)) @@ -803,6 +804,13 @@ ass_fontselect_init(ASS_Library *library, priv->embedded_provider = ass_embedded_fonts_add_provider(library, priv, ftlibrary); +#ifdef CONFIG_CORETEXT + if (fc != 0) { + priv->default_provider = ass_coretext_add_provider(library, priv); + return priv; + } +#endif + #ifdef CONFIG_FONTCONFIG if (fc != 0) priv->default_provider = ass_fontconfig_add_provider(library, |