merge
This commit is contained in:
commit
9b4a2324d3
13 changed files with 1140 additions and 7 deletions
292
src/cmd/fontsrv/osx.c
Normal file
292
src/cmd/fontsrv/osx.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue