fontsrv: fix handling of colored glyphs (emoji)

Drawing as white on black to produce a mask only works if
the white on black is the inversion of black on white.
Emoji that force use of specific colors don't respect that.
Draw black on white and invert to mask separately.
This commit is contained in:
Russ Cox 2020-08-15 09:10:54 -04:00
parent 977b25a76a
commit 9843fc0d82

View file

@ -75,6 +75,17 @@ mac2r(CGRect r, int size, int unit)
return rr; return rr;
} }
void
meminvert(Memimage *m)
{
uchar *p, *ep;
p = byteaddr(m, m->r.min);
ep = p + 4*m->width*Dy(m->r);
for(; p < ep; p++)
*p ^= 0xff;
}
void void
loadfonts(void) loadfonts(void)
{ {
@ -223,8 +234,8 @@ mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias)
int i, height, ascent; int i, height, ascent;
Fontchar *fc, *fc0; Fontchar *fc, *fc0;
Memsubfont *sf; Memsubfont *sf;
CGFloat whitef[] = { 1.0, 1.0 }; CGFloat blackf[] = { 0.0, 1.0 };
CGColorRef white; CGColorRef black;
s = c2mac(name); s = c2mac(name);
desc = CTFontDescriptorCreateWithNameAndSize(s, size); desc = CTFontDescriptorCreateWithNameAndSize(s, size);
@ -267,7 +278,7 @@ mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias)
color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
ctxt = CGBitmapContextCreate(byteaddr(mc, mc->r.min), Dx(mc->r), Dy(mc->r), 8, ctxt = CGBitmapContextCreate(byteaddr(mc, mc->r.min), Dx(mc->r), Dy(mc->r), 8,
mc->width*sizeof(u32int), color, kCGImageAlphaNone); mc->width*sizeof(u32int), color, kCGImageAlphaNone);
white = CGColorCreate(color, whitef); black = CGColorCreate(color, blackf);
CGColorSpaceRelease(color); CGColorSpaceRelease(color);
if(ctxt == nil) { if(ctxt == nil) {
freememimage(m); freememimage(m);
@ -293,7 +304,7 @@ mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias)
CGRect r; CGRect r;
CGPoint p1; CGPoint p1;
CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName };
CFTypeRef values[] = { font, white }; CFTypeRef values[] = { font, black };
sprint(buf, "%C", (Rune)mapUnicode(name, i)); sprint(buf, "%C", (Rune)mapUnicode(name, i));
str = c2mac(buf); str = c2mac(buf);
@ -310,7 +321,7 @@ mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias)
line = CTLineCreateWithAttributedString(attrString); line = CTLineCreateWithAttributedString(attrString);
CGContextSetTextPosition(ctxt, 0, y0); CGContextSetTextPosition(ctxt, 0, y0);
r = CTLineGetImageBounds(line, ctxt); r = CTLineGetImageBounds(line, ctxt);
memfillcolor(mc, DBlack); memfillcolor(mc, DWhite);
CTLineDraw(line, ctxt); CTLineDraw(line, ctxt);
CFRelease(line); CFRelease(line);
@ -330,6 +341,7 @@ mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias)
continue; continue;
} }
meminvert(mc);
memimagedraw(m, Rect(x, 0, x + p1.x, y), mc, ZP, memopaque, ZP, S); memimagedraw(m, Rect(x, 0, x + p1.x, y), mc, ZP, memopaque, ZP, S);
fc->width = p1.x; fc->width = p1.x;
fc->left = 0; fc->left = 0;