From 933b98054f40bb224acda134d7bb77a023bcc57f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 8 Jan 2020 20:07:15 -0500 Subject: devdraw: use consistent mac-* prefix on macOS files We were using osx- and cocoa- but it's not even OS X anymore. --- src/cmd/fontsrv/mac.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 src/cmd/fontsrv/mac.c (limited to 'src/cmd/fontsrv/mac.c') diff --git a/src/cmd/fontsrv/mac.c b/src/cmd/fontsrv/mac.c new file mode 100644 index 00000000..b4dadd90 --- /dev/null +++ b/src/cmd/fontsrv/mac.c @@ -0,0 +1,362 @@ +#include + +#define Point OSXPoint +#define Rect OSXRect +#define Cursor OSXCursor +#include +#undef Rect +#undef Point +#undef Cursor +#undef offsetof +#undef nil + +#include +#include +#include +#include "a.h" + +extern void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar[], const CGGlyph[], size_t); + +// In these fonts, it's too hard to distinguish U+2018 and U+2019, +// so don't map the ASCII quotes there. +// See https://github.com/9fans/plan9port/issues/86 +static char *skipquotemap[] = { + "Courier", + "Osaka", +}; + +int +mapUnicode(char *name, int i) +{ + int j; + + if(0xd800 <= i && i < 0xe000) // surrogate pairs, will crash OS X libraries! + return 0xfffd; + for(j=0; jname); + desc = CTFontDescriptorCreateWithNameAndSize(s, size); + CFRelease(s); + if(desc == nil) + return; + font = CTFontCreateWithFontDescriptor(desc, 0, nil); + CFRelease(desc); + if(font == nil) + return; + + color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); + ctxt = CGBitmapContextCreate(nil, 1, 1, 8, 1, color, kCGImageAlphaNone); + CGColorSpaceRelease(color); + CGContextSetTextPosition(ctxt, 0, 0); + + for(i=0; i r.origin.x) + bbox.origin.x = r.origin.x; + if(bbox.origin.y > r.origin.y) + bbox.origin.y = r.origin.y; + if(bbox.size.width < r.size.width) + bbox.size.width = r.size.width; + if(bbox.size.height < r.size.height) + bbox.size.height = r.size.height; + } + + bbox.size.width -= bbox.origin.x; + bbox.size.height -= bbox.origin.y; + + *height = bbox.size.height + 0.999999; + *ascent = *height - (-bbox.origin.y + 0.999999); + + CGContextRelease(ctxt); + CFRelease(font); +} + +void +load(XFont *f) +{ + int i; + + if(f->loaded) + return; + f->loaded = 1; + + // compute height and ascent for each size on demand + f->loadheight = fontheight; + + // enable all Unicode ranges + for(i=0; irange); i++) { + f->range[i] = 1; + f->nrange++; + } +} + +Memsubfont* +mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias) +{ + CFStringRef s; + CGColorSpaceRef color; + CGContextRef ctxt; + CTFontRef font; + CTFontDescriptorRef desc; + CGRect bbox; + Memimage *m, *mc, *m1; + int x, y, y0; + int i, height, ascent; + Fontchar *fc, *fc0; + Memsubfont *sf; + CGFloat whitef[] = { 1.0, 1.0 }; + CGColorRef white; + + s = c2mac(name); + desc = CTFontDescriptorCreateWithNameAndSize(s, size); + CFRelease(s); + if(desc == nil) + return nil; + font = CTFontCreateWithFontDescriptor(desc, 0, nil); + CFRelease(desc); + if(font == nil) + return nil; + + + bbox = CTFontGetBoundingBox(font); + x = (int)(bbox.size.width*2 + 0.99999999); + + fontheight(f, size, &height, &ascent); + y = height; + y0 = height - ascent; + + m = allocmemimage(Rect(0, 0, x*(hi+1-lo)+1, y+1), GREY8); + if(m == nil) + return nil; + mc = allocmemimage(Rect(0, 0, x+1, y+1), GREY8); + if(mc == nil){ + freememimage(m); + return nil; + } + memfillcolor(m, DBlack); + memfillcolor(mc, DBlack); + fc = malloc((hi+2 - lo) * sizeof fc[0]); + sf = malloc(sizeof *sf); + if(fc == nil || sf == nil) { + freememimage(m); + freememimage(mc); + free(fc); + free(sf); + return nil; + } + fc0 = fc; + + color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); + ctxt = CGBitmapContextCreate(byteaddr(mc, mc->r.min), Dx(mc->r), Dy(mc->r), 8, + mc->width*sizeof(u32int), color, kCGImageAlphaNone); + white = CGColorCreate(color, whitef); + CGColorSpaceRelease(color); + if(ctxt == nil) { + freememimage(m); + freememimage(mc); + free(fc); + free(sf); + return nil; + } + + CGContextSetAllowsAntialiasing(ctxt, antialias); + CGContextSetTextPosition(ctxt, 0, 0); // XXX +#if OSX_VERSION >= 101400 + CGContextSetAllowsFontSmoothing(ctxt, false); +#endif + + x = 0; + for(i=lo; i<=hi; i++, fc++) { + char buf[20]; + CFStringRef str; + CFDictionaryRef attrs; + CFAttributedStringRef attrString; + CTLineRef line; + CGRect r; + CGPoint p1; + CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; + CFTypeRef values[] = { font, white }; + + sprint(buf, "%C", (Rune)mapUnicode(name, i)); + str = c2mac(buf); + + // See https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/CoreText_Programming/LayoutOperations/LayoutOperations.html#//apple_ref/doc/uid/TP40005533-CH12-SW2 + attrs = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, + (const void**)&values, sizeof(keys) / sizeof(keys[0]), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + attrString = CFAttributedStringCreate(kCFAllocatorDefault, str, attrs); + CFRelease(str); + CFRelease(attrs); + + line = CTLineCreateWithAttributedString(attrString); + CGContextSetTextPosition(ctxt, 0, y0); + r = CTLineGetImageBounds(line, ctxt); + memfillcolor(mc, DBlack); + CTLineDraw(line, ctxt); + CFRelease(line); + + fc->x = x; + fc->top = 0; + fc->bottom = Dy(m->r); + +// fprint(2, "printed %#x: %g %g\n", mapUnicode(i), p1.x, p1.y); + p1 = CGContextGetTextPosition(ctxt); + if(p1.x <= 0 || mapUnicode(name, i) == 0xfffd) { + fc->width = 0; + fc->left = 0; + if(i == 0) { + drawpjw(m, fc, x, (int)(bbox.size.width + 0.99999999), y, y - y0); + x += fc->width; + } + continue; + } + + memimagedraw(m, Rect(x, 0, x + p1.x, y), mc, ZP, memopaque, ZP, S); + fc->width = p1.x; + fc->left = 0; + x += p1.x; + } + fc->x = x; + + // round up to 32-bit boundary + // so that in-memory data is same + // layout as in-file data. + if(x == 0) + x = 1; + if(y == 0) + y = 1; + if(antialias) + x += -x & 3; + else + x += -x & 31; + m1 = allocmemimage(Rect(0, 0, x, y), antialias ? GREY8 : GREY1); + memimagedraw(m1, m1->r, m, m->r.min, memopaque, ZP, S); + freememimage(m); + freememimage(mc); + + sf->name = nil; + sf->n = hi+1 - lo; + sf->height = Dy(m1->r); + sf->ascent = Dy(m1->r) - y0; + sf->info = fc0; + sf->bits = m1; + + return sf; +} -- cgit v1.2.3