Finalized and implemented underlines on OS X.
This commit is contained in:
parent
eb7dfa5cc4
commit
4195bc3b4b
|
@ -302,6 +302,12 @@ static int specsIdentical(struct attr *attr, uiAttributeSpec *spec)
|
||||||
case uiAttributeSize:
|
case uiAttributeSize:
|
||||||
// TODO use a closest match?
|
// TODO use a closest match?
|
||||||
return attr->spec.Double == spec->Double;
|
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 uiAttributeColor:
|
||||||
case uiAttributeBackground:
|
case uiAttributeBackground:
|
||||||
// TODO use a closest match?
|
// TODO use a closest match?
|
||||||
|
|
126
darwin/attrstr.m
126
darwin/attrstr.m
|
@ -1,6 +1,59 @@
|
||||||
// 12 february 2017
|
// 12 february 2017
|
||||||
#import "uipriv_darwin.h"
|
#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
|
// 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 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?
|
// 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)
|
static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data)
|
||||||
{
|
{
|
||||||
struct foreachParams *p = (struct foreachParams *) data;
|
struct foreachParams *p = (struct foreachParams *) data;
|
||||||
CFRange range;
|
CFRange range;
|
||||||
CGColorSpaceRef colorspace;
|
|
||||||
CGColorRef color;
|
CGColorRef color;
|
||||||
CGFloat components[4];
|
|
||||||
size_t ostart, oend;
|
size_t ostart, oend;
|
||||||
backgroundBlock block;
|
backgroundBlock block;
|
||||||
|
int32_t us;
|
||||||
|
CFNumberRef num;
|
||||||
|
|
||||||
ostart = start;
|
ostart = start;
|
||||||
oend = end;
|
oend = end;
|
||||||
|
@ -112,16 +184,7 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case uiAttributeColor:
|
case uiAttributeColor:
|
||||||
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
|
color = mkcolor(spec);
|
||||||
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);
|
|
||||||
CFAttributedStringSetAttribute(p->mas, range, kCTForegroundColorAttributeName, color);
|
CFAttributedStringSetAttribute(p->mas, range, kCTForegroundColorAttributeName, color);
|
||||||
CFRelease(color);
|
CFRelease(color);
|
||||||
break;
|
break;
|
||||||
|
@ -137,6 +200,45 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
|
||||||
else
|
else
|
||||||
CFAttributedStringSetAttribute(p->mas, range, kCTVerticalFormsAttributeName, kCFBooleanFalse);
|
CFAttributedStringSetAttribute(p->mas, range, kCTVerticalFormsAttributeName, kCFBooleanFalse);
|
||||||
break;
|
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
|
// TODO
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -125,6 +125,8 @@ const char *uiInit(uiInitOptions *o)
|
||||||
[realNSApp() setMainMenu:[appDelegate().menuManager makeMenubar]];
|
[realNSApp() setMainMenu:[appDelegate().menuManager makeMenubar]];
|
||||||
|
|
||||||
setupFontPanel();
|
setupFontPanel();
|
||||||
|
|
||||||
|
initUnderlineColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
globalPool = [[NSAutoreleasePool alloc] init];
|
globalPool = [[NSAutoreleasePool alloc] init];
|
||||||
|
@ -140,6 +142,7 @@ void uiUninit(void)
|
||||||
[globalPool release];
|
[globalPool release];
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
uninitUnderlineColors();
|
||||||
[delegate release];
|
[delegate release];
|
||||||
[realNSApp() setDelegate:nil];
|
[realNSApp() setDelegate:nil];
|
||||||
[app release];
|
[app release];
|
||||||
|
|
|
@ -145,5 +145,7 @@ extern CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd);
|
||||||
extern void fontdescFromCTFontDescriptor(CTFontDescriptorRef ctdesc, uiDrawFontDescriptor *uidesc);
|
extern void fontdescFromCTFontDescriptor(CTFontDescriptorRef ctdesc, uiDrawFontDescriptor *uidesc);
|
||||||
|
|
||||||
// attrstr.m
|
// attrstr.m
|
||||||
|
extern void initUnderlineColors(void);
|
||||||
|
extern void uninitUnderlineColors(void);
|
||||||
typedef void (^backgroundBlock)(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y);
|
typedef void (^backgroundBlock)(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y);
|
||||||
extern CFAttributedStringRef attrstrToCoreFoundation(uiDrawTextLayoutParams *p, NSArray **backgroundBlocks);
|
extern CFAttributedStringRef attrstrToCoreFoundation(uiDrawTextLayoutParams *p, NSArray **backgroundBlocks);
|
||||||
|
|
|
@ -98,8 +98,45 @@ static void setupAttributedString(void)
|
||||||
spec.Type = uiAttributeVerticalForms;
|
spec.Type = uiAttributeVerticalForms;
|
||||||
spec.Value = 1;
|
spec.Value = 1;
|
||||||
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
|
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
|
||||||
|
|
||||||
uiAttributedStringAppendUnattributed(attrstr, " (which you can draw rotated for proper vertical text)");
|
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, ", ");
|
uiAttributedStringAppendUnattributed(attrstr, ", ");
|
||||||
|
|
||||||
next = "multiple TODO";
|
next = "multiple TODO";
|
||||||
|
|
|
@ -29,6 +29,7 @@ _UI_ENUM(uiAttribute) {
|
||||||
// TODO kCTStrokeWidthAttributeName/kCTStrokeColorAttributeName? doesn't seem to be present anywhere else?
|
// TODO kCTStrokeWidthAttributeName/kCTStrokeColorAttributeName? doesn't seem to be present anywhere else?
|
||||||
|
|
||||||
uiAttributeUnderline, // enum uiDrawUnderlineStyle
|
uiAttributeUnderline, // enum uiDrawUnderlineStyle
|
||||||
|
// TODO what is the color in the case we don't specify it, black or the text color?
|
||||||
uiAttributeUnderlineColor, // enum uiDrawUnderlineColor
|
uiAttributeUnderlineColor, // enum uiDrawUnderlineColor
|
||||||
|
|
||||||
// TODO kCTSuperscriptAttributeName vs below
|
// TODO kCTSuperscriptAttributeName vs below
|
||||||
|
|
Loading…
Reference in New Issue