Finalized and implemented underlines on OS X.

This commit is contained in:
Pietro Gagliardi 2017-02-14 14:57:56 -05:00
parent eb7dfa5cc4
commit 4195bc3b4b
6 changed files with 164 additions and 13 deletions

View File

@ -302,6 +302,12 @@ static int specsIdentical(struct attr *attr, uiAttributeSpec *spec)
case uiAttributeSize:
// TODO use a closest match?
return attr->spec.Double == spec->Double;
case uiAttributeUnderlineColor:
if (attr->spec.Value != spec->Value)
return 0;
if (attr->spec.Value != uiDrawUnderlineColorCustom)
return 1;
// otherwise fall through
case uiAttributeColor:
case uiAttributeBackground:
// TODO use a closest match?

View File

@ -1,6 +1,59 @@
// 12 february 2017
#import "uipriv_darwin.h"
// this is what AppKit does internally
// WebKit does this too; see https://github.com/adobe/webkit/blob/master/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm
static NSColor *spellingColor = nil;
static NSColor *grammarColor = nil;
static NSColor *auxiliaryColor = nil;
static NSColor *tryColorNamed(NSString *name)
{
NSImage *img;
img = [NSImage imageNamed:name];
if (img == nil)
return nil;
return [NSColor colorWithPatternImage:img];
}
void initUnderlineColors(void)
{
spellingColor = tryColorNamed(@"NSSpellingDot");
if (spellingColor == nil) {
// WebKit says this is needed for "older systems"; not sure how old, but 10.11 AppKit doesn't look for this
spellingColor = tryColorNamed(@"SpellingDot");
if (spellingColor == nil)
spellingColor = [NSColor redColor];
}
[spellingColor retain]; // override autoreleasing
grammarColor = tryColorNamed(@"NSGrammarDot");
if (grammarColor == nil) {
// WebKit says this is needed for "older systems"; not sure how old, but 10.11 AppKit doesn't look for this
grammarColor = tryColorNamed(@"GrammarDot");
if (grammarColor == nil)
grammarColor = [NSColor greenColor];
}
[grammarColor retain]; // override autoreleasing
auxiliaryColor = tryColorNamed(@"NSCorrectionDot");
if (auxiliaryColor == nil) {
// WebKit says this is needed for "older systems"; not sure how old, but 10.11 AppKit doesn't look for this
auxiliaryColor = tryColorNamed(@"CorrectionDot");
if (auxiliaryColor == nil)
auxiliaryColor = [NSColor blueColor];
}
[auxiliaryColor retain]; // override autoreleasing
}
void uninitUnderlineColors(void)
{
[auxiliaryColor release];
[grammarColor release];
[spellingColor release];
}
// unlike the other systems, Core Text rolls family, size, weight, italic, width, AND opentype features into the "font" attribute
// TODO opentype features and AAT fvar table info is lost, so a handful of fonts in the font panel ("Titling" variants of some fonts and Skia and possibly others but those are the examples I know about) cannot be represented by uiDrawFontDescriptor; what *can* we do about this since this info is NOT part of the font on other platforms?
// TODO see if we could use NSAttributedString?
@ -64,15 +117,34 @@ static backgroundBlock mkBackgroundBlock(size_t start, size_t end, double r, dou
});
}
static CGColorRef mkcolor(uiAttributeSpec *spec)
{
CGColorSpaceRef colorspace;
CGColorRef color;
CGFloat components[4];
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
if (colorspace == NULL) {
// TODO
}
components[0] = spec->R;
components[1] = spec->G;
components[2] = spec->B;
components[3] = spec->A;
color = CGColorCreate(colorspace, components);
CFRelease(colorspace);
return color;
}
static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data)
{
struct foreachParams *p = (struct foreachParams *) data;
CFRange range;
CGColorSpaceRef colorspace;
CGColorRef color;
CGFloat components[4];
size_t ostart, oend;
backgroundBlock block;
int32_t us;
CFNumberRef num;
ostart = start;
oend = end;
@ -112,16 +184,7 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
});
break;
case uiAttributeColor:
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
if (colorspace == NULL) {
// TODO
}
components[0] = spec->R;
components[1] = spec->G;
components[2] = spec->B;
components[3] = spec->A;
color = CGColorCreate(colorspace, components);
CFRelease(colorspace);
color = mkcolor(spec);
CFAttributedStringSetAttribute(p->mas, range, kCTForegroundColorAttributeName, color);
CFRelease(color);
break;
@ -137,6 +200,45 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
else
CFAttributedStringSetAttribute(p->mas, range, kCTVerticalFormsAttributeName, kCFBooleanFalse);
break;
case uiAttributeUnderline:
switch (spec->Value) {
case uiDrawUnderlineStyleNone:
us = kCTUnderlineStyleNone;
break;
case uiDrawUnderlineStyleSingle:
us = kCTUnderlineStyleSingle;
break;
case uiDrawUnderlineStyleDouble:
us = kCTUnderlineStyleDouble;
break;
case uiDrawUnderlineStyleSuggestion:
// TODO incorrect if a solid color
us = kCTUnderlineStyleThick;
break;
}
num = CFNumberCreate(NULL, kCFNumberSInt32Type, &us);
CFAttributedStringSetAttribute(p->mas, range, kCTUnderlineStyleAttributeName, num);
CFRelease(num);
break;
case uiAttributeUnderlineColor:
switch (spec->Value) {
case uiDrawUnderlineColorCustom:
color = mkcolor(spec);
break;
case uiDrawUnderlineColorSpelling:
color = [spellingColor CGColor];
break;
case uiDrawUnderlineColorGrammar:
color = [grammarColor CGColor];
break;
case uiDrawUnderlineColorAuxiliary:
color = [auxiliaryColor CGColor];
break;
}
CFAttributedStringSetAttribute(p->mas, range, kCTUnderlineColorAttributeName, color);
if (spec->Value == uiDrawUnderlineColorCustom)
CFRelease(color);
break;
// TODO
}
return 0;

View File

@ -125,6 +125,8 @@ const char *uiInit(uiInitOptions *o)
[realNSApp() setMainMenu:[appDelegate().menuManager makeMenubar]];
setupFontPanel();
initUnderlineColors();
}
globalPool = [[NSAutoreleasePool alloc] init];
@ -140,6 +142,7 @@ void uiUninit(void)
[globalPool release];
@autoreleasepool {
uninitUnderlineColors();
[delegate release];
[realNSApp() setDelegate:nil];
[app release];

View File

@ -145,5 +145,7 @@ extern CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd);
extern void fontdescFromCTFontDescriptor(CTFontDescriptorRef ctdesc, uiDrawFontDescriptor *uidesc);
// attrstr.m
extern void initUnderlineColors(void);
extern void uninitUnderlineColors(void);
typedef void (^backgroundBlock)(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y);
extern CFAttributedStringRef attrstrToCoreFoundation(uiDrawTextLayoutParams *p, NSArray **backgroundBlocks);

View File

@ -98,8 +98,45 @@ static void setupAttributedString(void)
spec.Type = uiAttributeVerticalForms;
spec.Value = 1;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, " (which you can draw rotated for proper vertical text)");
uiAttributedStringAppendUnattributed(attrstr, ", ");
next = "multiple";
start = uiAttributedStringLen(attrstr);
end = start + strlen(next);
uiAttributedStringAppendUnattributed(attrstr, next);
spec.Type = uiAttributeUnderline;
spec.Value = uiDrawUnderlineStyleSingle;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, " ");
next = "underlines";
start = uiAttributedStringLen(attrstr);
end = start + strlen(next);
uiAttributedStringAppendUnattributed(attrstr, next);
spec.Type = uiAttributeUnderline;
spec.Value = uiDrawUnderlineStyleDouble;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
spec.Type = uiAttributeUnderlineColor;
spec.Value = uiDrawUnderlineColorCustom;
spec.R = 0.5;
spec.G = 0.0;
spec.B = 1.0;
spec.A = 1.0;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, " (");
next = "including underlines for spelling correction and the like";
start = uiAttributedStringLen(attrstr);
end = start + strlen(next);
uiAttributedStringAppendUnattributed(attrstr, next);
spec.Type = uiAttributeUnderline;
spec.Value = uiDrawUnderlineStyleSuggestion;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
spec.Type = uiAttributeUnderlineColor;
spec.Value = uiDrawUnderlineColorSpelling;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, ")");
uiAttributedStringAppendUnattributed(attrstr, ", ");
next = "multiple TODO";

View File

@ -29,6 +29,7 @@ _UI_ENUM(uiAttribute) {
// TODO kCTStrokeWidthAttributeName/kCTStrokeColorAttributeName? doesn't seem to be present anywhere else?
uiAttributeUnderline, // enum uiDrawUnderlineStyle
// TODO what is the color in the case we don't specify it, black or the text color?
uiAttributeUnderlineColor, // enum uiDrawUnderlineColor
// TODO kCTSuperscriptAttributeName vs below