And implemented fontvariation.m.

This commit is contained in:
Pietro Gagliardi 2017-11-03 19:52:49 -04:00
parent 72d31285c1
commit 8333063cc0
3 changed files with 147 additions and 1 deletions

View File

@ -1,5 +1,6 @@
// 3 january 2017
#import "uipriv_darwin.h"
#import "fontstyle.h"
// Core Text exposes font style info in two forms:
// - Fonts with a QuickDraw GX font variation (fvar) table, a feature

View File

@ -52,3 +52,10 @@
- (CFStringRef)familyName;
- (CFArrayRef)variationAxes;
@end
// fonttraits.m
extern void processFontTraits(fontStyleData *d, uiDrawFontDescriptor *out);
// fontvariation.m
extern NSDictionary *mkVariationAxisDict(CFArrayRef axes, CFDataRef avarTable);
extern void processFontVariation(fontStyleData *d, NSDictionary *axisDict, uiDrawFontDescriptor *out);

View File

@ -1,5 +1,6 @@
// 2 november 2017
#import "uipriv_darwin.h"
#import "fontstyle.h"
// This is the part of the font style matching and normalization code
// that handles fonts that use the fvar table.
@ -155,7 +156,7 @@ static fixed214 normalizedTo214(fixed1616 val, const fixed1616 *avarMappings, si
return fixed1616ToFixed214(val);
}
fixed1616 *avarExtract(CFDataRef table, size_t index, size_t *n)
static fixed1616 *avarExtract(CFDataRef table, CFIndex index, size_t *n)
{
const UInt8 *b;
size_t off;
@ -180,3 +181,140 @@ fixed1616 *avarExtract(CFDataRef table, size_t index, size_t *n)
}
return entries;
}
staatic BOOL extractAxisDictValue(CFDictionaryRef dict, CFStringRef key, fixed1616 *out)
{
CFNumberRef num;
double v;
num = (CFNumberRef) CFDictionaryGetValue(dict, key);
if (CFNumberGetValue(num, kCFNumberTypeDouble, &v) == false)
return NO;
*out = doubleToFixed1616(v);
return YES;
}
@interface fvarAxis : NSObject {
fixed1616 min;
fixed1616 max;
fixed1616 def;
fixed1616 *avarMappings;
size_t avarCount;
}
- (id)initWithIndex:(CFIndex)i dict:(CFDictionaryRef)dict avarTable:(CFDataRef)table;
- (double)normalize:(double)v;
@end
@implementation fvarAxis
- (id)initWithIndex:(CFIndex)i dict:(CFDictionaryRef)dict avarTable:(CFDataRef)table
{
self = [super init];
if (self) {
self->avarMappings = NULL;
self->avarCount = 0;
if (!extractAxisDictValue(dict, kCTFontVariationAxisMinimumValueKey, &(self->min)))
goto fail;
if (!extractAxisDictValue(dict, kCTFontVariationAxisMaximumValueKey, &(self->max)))
goto fail;
if (!extractAxisDictValue(dict, kCTFontVariationAxisDefaultValueKey, &(self->def)))
goto fail;
if (table != NULL)
self->avarMappings = avarExtract(table, i, &(self->avarCount));
}
return self;
fail:
[self release];
return nil;
}
- (void)dealloc
{
if (self->avarMappings != NULL) {
uiFree(self->avarMappings);
self->avarMappings = NULL;
}
[super dealloc];
}
- (double)normalize:(double)d
{
fixed1616 n;
fixed214 n2;
n = doubleToFixed1616(d);
n = fixed16161Normalize(n, self->min, self->max, self->def);
n2 = normalizedTo214(n, self->avarMappings, self->avarCount);
return fixed214ToDouble(n2);
}
@end
NSDictionary *mkVariationAxisDict(CFArrayRef axes, CFDataRef avarTable)
{
CFDictionaryRef axis;
CFIndex i, n;
NSMutableDictionary *out;
n = CFArrayGetLength(axes);
out = [NSMutableDictionary new];
for (i = 0; i < n; i++) {
CFNumberRef key;
axis = (CFDictionaryRef) CFArrayGetValueAtIndex(axes, i);
key = (CFNumberRef) CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey);
[out setObject:[[fvarAxis alloc] initWithIndex:i dict:axis avarTable:table]
forKey:((NSNumber *) key)];
}
if (table != NULL)
CFRelease(table);
return out;
}
#define fvarAxisKey(n) [NSNumber numberWithUnsignedInteger:k]
static BOOL tryAxis(NSDictionary *axisDict, CFDictionaryRef var, NSNumber *key, double *out)
{
fvarAxis *axis;
CFNumberRef num;
axis = (fvarAxis *) [axisDict objectForKey:key];
if (axis == nil)
return NO;
num = (CFNumberRef) CFDictionaryGetValue(var, (CFNumberRef) key);
if (num == nil)
return NO;
if (CFNumberGetValue(num, kCFNumberTypeDouble, out) == false) {
// TODO
return NO;
}
*out = [axis normalize:*out];
return YES;
}
void processFontVariation(fontStyleData *d, NSDictionary *axisDict, uiDrawFontDescriptor *out)
{
double v;
out->Weight = uiDrawTextWeightNormal;
out->Stretch = uiDrawTextStretchNormal;
var = [d variation];
if (tryAxis(axisDict, var, fvarAxisKey(fvarWeight), &v)) {
// v is now a value between -1 and 1 scaled linearly between discrete points
// we want a linear value between 0 and 1000 with 400 being normal
if (v < 0) {
v += 1;
out->Weight = (uiDrawTextWeight) (v * 400);
} else if (v > 0)
out->Weight += (uiDrawTextWeight) (v * 600);
}
if (tryAxis(axisDict, var, fvarAxisKey(fvarWidth), &v)) {
// likewise, but with stretches, we go from 0 to 8 with 4 being directly between the two, so this is sufficient
v += 1;
out->Stretch = (uiDrawTextStretch) (v * 4);
}
}