Add a basic CoreText-based fonts collector backend
This commit is contained in:
parent
f8c3504898
commit
973f0b09fc
3 changed files with 115 additions and 1 deletions
|
@ -59,7 +59,6 @@ src_OBJ := \
|
||||||
$(d)export_framerate.o \
|
$(d)export_framerate.o \
|
||||||
$(d)fft.o \
|
$(d)fft.o \
|
||||||
$(d)font_file_lister.o \
|
$(d)font_file_lister.o \
|
||||||
$(d)font_file_lister_fontconfig.o \
|
|
||||||
$(d)frame_main.o \
|
$(d)frame_main.o \
|
||||||
$(d)gl_text.o \
|
$(d)gl_text.o \
|
||||||
$(d)gl_wrap.o \
|
$(d)gl_wrap.o \
|
||||||
|
@ -119,7 +118,10 @@ src_OBJ := \
|
||||||
$(TOP)lib/libuniversalchardet.a \
|
$(TOP)lib/libuniversalchardet.a \
|
||||||
|
|
||||||
ifeq (yes, $(BUILD_DARWIN))
|
ifeq (yes, $(BUILD_DARWIN))
|
||||||
|
src_OBJ += $(d)font_file_lister_coretext.o
|
||||||
src_OBJ += $(subst .mm,.o,$(wildcard $(d)osx/*.mm))
|
src_OBJ += $(subst .mm,.o,$(wildcard $(d)osx/*.mm))
|
||||||
|
else
|
||||||
|
src_OBJ += $(d)font_file_lister_fontconfig.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
###############
|
###############
|
||||||
|
|
|
@ -63,7 +63,25 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
using FontFileLister = GdiFontFileLister;
|
using FontFileLister = GdiFontFileLister;
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
struct CoreTextFontFileLister {
|
||||||
|
CoreTextFontFileLister(FontCollectorStatusCallback &) {}
|
||||||
|
|
||||||
|
/// @brief Get the path to the font with the given styles
|
||||||
|
/// @param facename Name of font face
|
||||||
|
/// @param bold ASS font weight
|
||||||
|
/// @param italic Italic?
|
||||||
|
/// @param characters Characters in this style
|
||||||
|
/// @return Path to the matching font file(s), or empty if not found
|
||||||
|
CollectionResult GetFontPaths(std::string const& facename, int bold, bool italic, std::vector<int> const& characters);
|
||||||
|
};
|
||||||
|
|
||||||
|
using FontFileLister = CoreTextFontFileLister;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
typedef struct _FcConfig FcConfig;
|
typedef struct _FcConfig FcConfig;
|
||||||
typedef struct _FcFontSet FcFontSet;
|
typedef struct _FcFontSet FcFontSet;
|
||||||
|
|
||||||
|
|
94
src/font_file_lister_coretext.mm
Normal file
94
src/font_file_lister_coretext.mm
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright (c) 2016, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
|
#include "font_file_lister.h"
|
||||||
|
|
||||||
|
#include <AppKit/AppKit.h>
|
||||||
|
#include <CoreText/CoreText.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void process_font(CollectionResult& ret, NSFontDescriptor *font, int bold, bool italic,
|
||||||
|
std::vector<int> const& characters) {
|
||||||
|
// For whatever reason there is no NSFontURLAttribute
|
||||||
|
NSURL *url = [font objectForKey:(__bridge NSString *)kCTFontURLAttribute];
|
||||||
|
if (!url)
|
||||||
|
return;
|
||||||
|
|
||||||
|
NSDictionary *attributes = [font objectForKey:NSFontTraitsAttribute];
|
||||||
|
double weight = [attributes[NSFontWeightTrait] doubleValue];
|
||||||
|
double slant = [attributes[NSFontSlantTrait] doubleValue];
|
||||||
|
|
||||||
|
if (italic != (slant > 0.03))
|
||||||
|
return;
|
||||||
|
if (bold == 0 && weight > 0)
|
||||||
|
return;
|
||||||
|
if (bold == 1 && weight < 0.4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
NSCharacterSet *codepoints = [font objectForKey:NSFontCharacterSetAttribute];
|
||||||
|
for (int chr : characters) {
|
||||||
|
if (![codepoints longCharacterIsMember:chr]) {
|
||||||
|
ret.missing += chr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.paths.push_back(url.absoluteString.UTF8String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectionResult CoreTextFontFileLister::GetFontPaths(std::string const& facename,
|
||||||
|
int bold, bool italic,
|
||||||
|
std::vector<int> const& characters) {
|
||||||
|
CollectionResult ret;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
|
NSString *name = @(facename.c_str() + (facename[0] == '@'));
|
||||||
|
NSArray *attrs = @[
|
||||||
|
[NSFontDescriptor fontDescriptorWithFontAttributes:@{NSFontFamilyAttribute: name}],
|
||||||
|
[NSFontDescriptor fontDescriptorWithFontAttributes:@{NSFontFaceAttribute: name}],
|
||||||
|
[NSFontDescriptor fontDescriptorWithFontAttributes:@{NSFontNameAttribute: name}]
|
||||||
|
];
|
||||||
|
|
||||||
|
auto font_collection = [NSFontCollection fontCollectionWithDescriptors:attrs];
|
||||||
|
for (NSFontDescriptor *desc in font_collection.matchingDescriptors) {
|
||||||
|
process_font(ret, desc, bold, italic, characters);
|
||||||
|
|
||||||
|
// If we didn't get any results, check for non-bold/italic variants
|
||||||
|
// and collect them with a warning
|
||||||
|
if (ret.paths.empty() && bold) {
|
||||||
|
process_font(ret, desc, 0, italic, characters);
|
||||||
|
if (!ret.paths.empty())
|
||||||
|
ret.fake_bold = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret.paths.empty() && italic) {
|
||||||
|
process_font(ret, desc, bold, false, characters);
|
||||||
|
if (!ret.paths.empty())
|
||||||
|
ret.fake_italic = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret.paths.empty() && bold && italic) {
|
||||||
|
process_font(ret, desc, 0, false, characters);
|
||||||
|
if (!ret.paths.empty()) {
|
||||||
|
ret.fake_bold = true;
|
||||||
|
ret.fake_italic = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
Loading…
Reference in a new issue