diff options
author | Russ Cox <rsc@swtch.com> | 2009-07-08 21:43:14 -0700 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2009-07-08 21:43:14 -0700 |
commit | 9b4a2324d39a8c952c8184249d2b06b9349205a2 (patch) | |
tree | a721c194fb6772ffb668aeb548f9ceaef9f56dce /src/cmd/fontsrv/osx.c | |
parent | 4a18fa68b01bf8121a8660d3f5214e5927763251 (diff) | |
parent | 4a18fa68b01bf8121a8660d3f5214e5927763251 (diff) | |
download | plan9port-9b4a2324d39a8c952c8184249d2b06b9349205a2.tar.gz plan9port-9b4a2324d39a8c952c8184249d2b06b9349205a2.tar.bz2 plan9port-9b4a2324d39a8c952c8184249d2b06b9349205a2.zip |
merge
Diffstat (limited to 'src/cmd/fontsrv/osx.c')
-rw-r--r-- | src/cmd/fontsrv/osx.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/src/cmd/fontsrv/osx.c b/src/cmd/fontsrv/osx.c new file mode 100644 index 00000000..94190d19 --- /dev/null +++ b/src/cmd/fontsrv/osx.c @@ -0,0 +1,292 @@ +#include <u.h> + +#define Point OSXPoint +#define Rect OSXRect +#define Cursor OSXCursor +#include <Carbon/Carbon.h> +#undef Rect +#undef Point +#undef Cursor +#undef offsetof +#undef nil + +#include <libc.h> +#include <draw.h> +#include <memdraw.h> +#include "a.h" + + +extern void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar[], const CGGlyph[], size_t); + +char* +mac2c(CFStringRef s) +{ + char *p; + int n; + + n = CFStringGetLength(s)*8; + p = malloc(n); + CFStringGetCString(s, p, n, kCFStringEncodingUTF8); + return p; +} + +CFStringRef +c2mac(char *p) +{ + return CFStringCreateWithBytes(nil, (uchar*)p, strlen(p), kCFStringEncodingUTF8, false); +} + +Rectangle +mac2r(CGRect r, int size, int unit) +{ + Rectangle rr; + + rr.min.x = r.origin.x*size/unit; + rr.min.y = r.origin.y*size/unit; + rr.max.x = (r.origin.x+r.size.width)*size/unit + 0.99999999; + rr.max.y = (r.origin.x+r.size.width)*size/unit + 0.99999999; + return rr; +} + +void +loadfonts(void) +{ + int i, n; + CTFontCollectionRef allc; + CFArrayRef array; + CFStringRef s; + CTFontDescriptorRef f; + + allc = CTFontCollectionCreateFromAvailableFonts(0); + array = CTFontCollectionCreateMatchingFontDescriptors(allc); + n = CFArrayGetCount(array); + xfont = emalloc9p(n*sizeof xfont[0]); + for(i=0; i<n; i++) { + f = (void*)CFArrayGetValueAtIndex(array, i); + if(f == nil) + continue; + s = CTFontDescriptorCopyAttribute(f, kCTFontNameAttribute); + xfont[nxfont].name = mac2c(s); + CFRelease(s); + nxfont++; + } +} + +CGRect +subfontbbox(CGFontRef font, int lo, int hi) +{ + int i, first; + CGRect bbox; + + bbox.origin.x = 0; + bbox.origin.y = 0; + bbox.size.height = 0; + bbox.size.width = 0; + + first = 1; + for(i=lo; i<=hi; i++) { + UniChar u; + CGGlyph g; + CGRect r; + + u = i; + CGFontGetGlyphsForUnichars(font, &u, &g, 1); + if(g == 0 || !CGFontGetGlyphBBoxes(font, &g, 1, &r)) + continue; + + r.size.width += r.origin.x; + r.size.height += r.origin.y; + if(first) { + bbox = r; + first = 0; + continue; + } + if(bbox.origin.x > 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; + return bbox; +} + +void +load(XFont *f) +{ + int i, j; + CGFontRef font; + CFStringRef s; + UniChar u[256]; + CGGlyph g[256]; + CGRect bbox; + + if(f->loaded) + return; + f->loaded = 1; + s = c2mac(f->name); + font = CGFontCreateWithFontName(s); + CFRelease(s); + if(font == nil) + return; + + // assume bbox gives latin1 is height/ascent for all + bbox = subfontbbox(font, 0x00, 0xff); + f->unit = CGFontGetUnitsPerEm(font); + f->height = bbox.size.height; + f->originy = bbox.origin.y; + + // figure out where the letters are + for(i=0; i<0xffff; i+=0x100) { + for(j=0; j<0x100; j++) { + u[j] = i+j; + g[j] = 0; + } + CGFontGetGlyphsForUnichars(font, u, g, 256); + for(j=0; j<0x100; j++) { + if(g[j] != 0) { + f->range[i>>8] = 1; + f->nrange++; + break; + } + } + } + CFRelease(font); +} + +Memsubfont* +mksubfont(char *name, int lo, int hi, int size, int antialias) +{ + CFStringRef s; + CGColorSpaceRef color; + CGContextRef ctxt; + CGFontRef font; + CGRect bbox; + Memimage *m, *mc, *m1; + int x, y, y0; + int i, unit; + Fontchar *fc, *fc0; + Memsubfont *sf; + + s = c2mac(name); + font = CGFontCreateWithFontName(s); + CFRelease(s); + if(font == nil) + return nil; + bbox = subfontbbox(font, lo, hi); + unit = CGFontGetUnitsPerEm(font); + x = (int)(bbox.size.width * size / unit + 0.99999999); + y = bbox.size.height * size/unit + 0.99999999; + y0 = (int)(-bbox.origin.y * size/unit + 0.99999999); + m = allocmemimage(Rect(0, 0, x*(hi+1-lo), y), GREY8); + if(m == nil) + return nil; + mc = allocmemimage(Rect(0, 0, x, y), GREY8); + if(mc == nil) + 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); + CGColorSpaceRelease(color); + if(ctxt == nil) { + freememimage(m); + freememimage(mc); + free(fc); + free(sf); + return nil; + } + + CGContextSetFont(ctxt, font); + CGContextSetFontSize(ctxt, size); + CGContextSetAllowsAntialiasing(ctxt, antialias); + CGContextSetRGBFillColor(ctxt, 1, 1, 1, 1); + CGContextSetTextPosition(ctxt, 0, 0); // XXX + + x = 0; + for(i=lo; i<=hi; i++, fc++) { + UniChar u[2]; + CGGlyph g[2]; + CGRect r[2]; + CGPoint p1; + int n; + + fc->x = x; + fc->top = 0; + fc->bottom = Dy(m->r); + + n = 0; + u[n++] = i; + if(0) // debugging + u[n++] = '|'; + g[0] = 0; + CGFontGetGlyphsForUnichars(font, u, g, n); + if(g[0] == 0 || !CGFontGetGlyphBBoxes(font, g, n, r)) { + None: + fc->width = 0; + if(i == 0) { + Point p; + Fontchar *i; + p = Pt(x, y0); + // memimagestring(m, p, memwhite, ZP, defont, peterface); + i = defont->info + 0; + memdraw(m, Rect(p.x+i->left, p.y+i->top, p.x+i->left+(i[1].x-i[0].x), p.y+i->bottom), + memwhite, ZP, defont->bits, Pt(i->x, i->top), S); + p.x += i->width; + fc->left = i->left; + fc->width = i->width; + x = p.x; + } + continue; + } + memfillcolor(mc, DBlack); + CGContextSetTextPosition(ctxt, 0, y0); + CGContextShowGlyphs(ctxt, g, n); + p1 = CGContextGetTextPosition(ctxt); + if(p1.x <= 0) + goto None; + 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(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); + + 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; +} + |