Started really refactoring attrstr.m by turning uiprivCombinedFontAttr into an actual attribute that CFAttributedString will manage itself; it will store uiAttributes (so we can use uiprivAttributeEqual() instead of duplicating its logic). Later, we will make it convert to CTFontRefs in place.

This commit is contained in:
Pietro Gagliardi 2018-03-04 23:57:18 -05:00
parent 49c3f77d46
commit 9e57c78fb3
1 changed files with 100 additions and 47 deletions

View File

@ -71,72 +71,125 @@ struct foreachParams {
NSMutableArray *backgroundBlocks; NSMutableArray *backgroundBlocks;
}; };
@interface uiprivCombinedFontAttr : NSObject // TODO what if this is NULL?
@property const char *family; static const CFStringRef combinedFontAttrName = CFSTR("libuiCombinedFontAttribute");
@property double size;
@property uiDrawTextWeight weight; enum {
@property uiDrawTextItalic italic; cFamily,
@property uiDrawTextStretch stretch; cSize,
@property const uiOpenTypeFeatures *features; cWeight,
- (id)initWithDefaultFont:(uiDrawFontDescriptor *)defaultFont; cItalic,
- (BOOL)same:(uiprivCombinedFontAttr *)b; cStretch,
- (CTFontRef)toCTFont; cFeatures,
nc,
};
static const int toc[] = {
[uiAttributeFamily] = cFamily,
[uiAttributeSize] = cSize,
[uiAttributeWeight] = cWeight,
[uiAttributeItalic] = cItalic,
[uiAttributeStretch] = cStretch,
[uiAttributeFeatures] = cFeatures,
};
@interface uiprivCombinedFontAttr : NSObject<NSCopying> {
uiAttribute *attrs[nc];
}
- (void)setAttribute:(uiAttribute *)attr;
- (CTFontRef)toCTFontWithDefaultFont:(uiDrawFontDescriptor *)defaultFont;
@end @end
@implementation uiprivCombinedFontAttr @implementation uiprivCombinedFontAttr
- (id)initWithDefaultFont:(uiDrawFontDescriptor *)defaultFont - (id)init
{ {
self = [super init]; self = [super init];
if (self) { if (self)
// TODO define behaviors if defaultFont->Family or any attribute Family is NULL, same with other invalid values memset(self->attrs, 0, nc * sizeof (uiAttribute *));
self.family = defaultFont->Family;
self.size = defaultFont->Size;
self.weight = defaultFont->Weight;
self.italic = defaultFont->Italic;
self.stretch = defaultFont->Stretch;
self.features = NULL;
}
return self; return self;
} }
// TODO deduplicate this with common/attribute.c - (void)dealloc
- (BOOL)same:(uiprivCombinedFontAttr *)b
{ {
// TODO should this be case-insensitive? int i;
if (strcmp(self.family, b.family) != 0)
return NO; for (i = 0; i < nc; i++)
// TODO use a closest match? if (self->attrs[i] != NULL) {
if (self.size != b.size) uiprivAttributeRelease(self->attrs[i]);
return NO; self->attrs[i] = NULL;
if (self.weight != b.weight) }
return NO; [super dealloc];
if (self.italic != b.italic) }
return NO;
if (self.stretch != b.stretch) - (id)copyWithZone:(NSZone *)zone
return NO; {
// this also handles NULL cases uiprivCombinedFontAttr *ret;
if (!uiOpenTypeFeaturesEqual(self.features, b.features)) int i;
ret = [[uiprivCombinedFontAttr allocWithZone:zone] init];
for (i = 0; i < nc; i++)
if (self->attrs[i] != NULL)
ret->attrs[i] = uiprivAttributeRetain(self->attrs[i]);
return ret;
}
- (void)setAttribute:(uiAttribute *)attr
{
int index;
index = toc[uiAttributeGetType(attr)];
if (self->attrs[index] != NULL)
uiprivAttributeRelease(self->attrs[index]);
self->attrs[index] = uiprivAttributeRetain(attr);
}
- (BOOL)isEqual:(id)bb
{
uiprivCombinedFontAttr *b = (uiprivCombinedFontAttr *) bb;
int i;
if (b == nil)
return NO; return NO;
for (i = 0; i < nc; i++) {
if (self->attrs[i] == NULL && b->attrs[i] == NULL)
continue;
if (self->attrs[i] == NULL || b->attrs[i] == NULL)
return NO;
if (!uiprivAttributeEqual(self->attrs[i], b->attrs[i]))
return NO;
}
return YES; return YES;
} }
- (CTFontRef)toCTFont - (NSUInteger)hash
{
// TODO implement this somehow; not quite sure how...
return [super hash];
}
- (CTFontRef)toCTFontWithDefaultFont:(uiDrawFontDescriptor *)defaultFont
{ {
uiDrawFontDescriptor uidesc; uiDrawFontDescriptor uidesc;
CTFontDescriptorRef desc; CTFontDescriptorRef desc;
CTFontRef font; CTFontRef font;
// TODO const-correct uiDrawFontDescriptor or change this function below uidesc = *defaultFont;
uidesc.Family = (char *) (self.family); if (self->attrs[cFamily] != NULL)
uidesc.Size = self.size; // TODO const-correct uiDrawFontDescriptor or change this function below
uidesc.Weight = self.weight; uidesc.Family = (char *) uiAttributeFamily(self->attrs[cFamily]);
uidesc.Italic = self.italic; if (self->attrs[cSize] != NULL)
uidesc.Stretch = self.stretch; uidesc.Size = uiAttributeSize(self->attrs[cSize]);
desc = fontdescToCTFontDescriptor(&uidesc); if (self->attrs[cWeight] != NULL)
if (self.features != NULL) uidesc.Weight = uiAttributeWeight(self->attrs[cWeight]);
desc = uiprivCTFontDescriptorAppendFeatures(desc, self.features); if (self->attrs[cItalic] != NULL)
font = CTFontCreateWithFontDescriptor(desc, self.size, NULL); uidesc.Italic = uiAttributeItalic(self->attrs[cItalic]);
if (self->attrs[cStretch] != NULL)
uidesc.Stretch = uiAttributeStretch(self->attrs[cStretch]);
desc = uiprivDrawFontDescriptorToCTFontDescriptor(&uidesc);
if (self->attrs[cFeatures] != NULL)
desc = uiprivCTFontDescriptorAppendFeatures(desc, uiAttributeFeatures(self->attrs[cFeatures]));
font = CTFontCreateWithFontDescriptor(desc, uidesc.Size, NULL);
CFRelease(desc); // TODO correct? CFRelease(desc); // TODO correct?
return font; return font;
} }