Blame


1 9b4a2324 2009-07-09 rsc #include <u.h>
2 9b4a2324 2009-07-09 rsc
3 9b4a2324 2009-07-09 rsc #define Point OSXPoint
4 9b4a2324 2009-07-09 rsc #define Rect OSXRect
5 9b4a2324 2009-07-09 rsc #define Cursor OSXCursor
6 9b4a2324 2009-07-09 rsc #include <Carbon/Carbon.h>
7 9b4a2324 2009-07-09 rsc #undef Rect
8 9b4a2324 2009-07-09 rsc #undef Point
9 9b4a2324 2009-07-09 rsc #undef Cursor
10 9b4a2324 2009-07-09 rsc #undef offsetof
11 9b4a2324 2009-07-09 rsc #undef nil
12 9b4a2324 2009-07-09 rsc
13 9b4a2324 2009-07-09 rsc #include <libc.h>
14 9b4a2324 2009-07-09 rsc #include <draw.h>
15 9b4a2324 2009-07-09 rsc #include <memdraw.h>
16 9b4a2324 2009-07-09 rsc #include "a.h"
17 9b4a2324 2009-07-09 rsc
18 9b4a2324 2009-07-09 rsc
19 9b4a2324 2009-07-09 rsc extern void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar[], const CGGlyph[], size_t);
20 9b4a2324 2009-07-09 rsc
21 9b4a2324 2009-07-09 rsc char*
22 9b4a2324 2009-07-09 rsc mac2c(CFStringRef s)
23 9b4a2324 2009-07-09 rsc {
24 9b4a2324 2009-07-09 rsc char *p;
25 9b4a2324 2009-07-09 rsc int n;
26 9b4a2324 2009-07-09 rsc
27 9b4a2324 2009-07-09 rsc n = CFStringGetLength(s)*8;
28 9b4a2324 2009-07-09 rsc p = malloc(n);
29 9b4a2324 2009-07-09 rsc CFStringGetCString(s, p, n, kCFStringEncodingUTF8);
30 9b4a2324 2009-07-09 rsc return p;
31 9b4a2324 2009-07-09 rsc }
32 9b4a2324 2009-07-09 rsc
33 9b4a2324 2009-07-09 rsc CFStringRef
34 9b4a2324 2009-07-09 rsc c2mac(char *p)
35 9b4a2324 2009-07-09 rsc {
36 9b4a2324 2009-07-09 rsc return CFStringCreateWithBytes(nil, (uchar*)p, strlen(p), kCFStringEncodingUTF8, false);
37 9b4a2324 2009-07-09 rsc }
38 9b4a2324 2009-07-09 rsc
39 9b4a2324 2009-07-09 rsc Rectangle
40 9b4a2324 2009-07-09 rsc mac2r(CGRect r, int size, int unit)
41 9b4a2324 2009-07-09 rsc {
42 9b4a2324 2009-07-09 rsc Rectangle rr;
43 9b4a2324 2009-07-09 rsc
44 9b4a2324 2009-07-09 rsc rr.min.x = r.origin.x*size/unit;
45 9b4a2324 2009-07-09 rsc rr.min.y = r.origin.y*size/unit;
46 9b4a2324 2009-07-09 rsc rr.max.x = (r.origin.x+r.size.width)*size/unit + 0.99999999;
47 9b4a2324 2009-07-09 rsc rr.max.y = (r.origin.x+r.size.width)*size/unit + 0.99999999;
48 9b4a2324 2009-07-09 rsc return rr;
49 9b4a2324 2009-07-09 rsc }
50 9b4a2324 2009-07-09 rsc
51 9b4a2324 2009-07-09 rsc void
52 9b4a2324 2009-07-09 rsc loadfonts(void)
53 9b4a2324 2009-07-09 rsc {
54 9b4a2324 2009-07-09 rsc int i, n;
55 9b4a2324 2009-07-09 rsc CTFontCollectionRef allc;
56 9b4a2324 2009-07-09 rsc CFArrayRef array;
57 9b4a2324 2009-07-09 rsc CFStringRef s;
58 9b4a2324 2009-07-09 rsc CTFontDescriptorRef f;
59 9b4a2324 2009-07-09 rsc
60 9b4a2324 2009-07-09 rsc allc = CTFontCollectionCreateFromAvailableFonts(0);
61 9b4a2324 2009-07-09 rsc array = CTFontCollectionCreateMatchingFontDescriptors(allc);
62 9b4a2324 2009-07-09 rsc n = CFArrayGetCount(array);
63 9b4a2324 2009-07-09 rsc xfont = emalloc9p(n*sizeof xfont[0]);
64 9b4a2324 2009-07-09 rsc for(i=0; i<n; i++) {
65 9b4a2324 2009-07-09 rsc f = (void*)CFArrayGetValueAtIndex(array, i);
66 9b4a2324 2009-07-09 rsc if(f == nil)
67 9b4a2324 2009-07-09 rsc continue;
68 9b4a2324 2009-07-09 rsc s = CTFontDescriptorCopyAttribute(f, kCTFontNameAttribute);
69 9b4a2324 2009-07-09 rsc xfont[nxfont].name = mac2c(s);
70 9b4a2324 2009-07-09 rsc CFRelease(s);
71 9b4a2324 2009-07-09 rsc nxfont++;
72 9b4a2324 2009-07-09 rsc }
73 9b4a2324 2009-07-09 rsc }
74 9b4a2324 2009-07-09 rsc
75 9b4a2324 2009-07-09 rsc CGRect
76 9b4a2324 2009-07-09 rsc subfontbbox(CGFontRef font, int lo, int hi)
77 9b4a2324 2009-07-09 rsc {
78 9b4a2324 2009-07-09 rsc int i, first;
79 9b4a2324 2009-07-09 rsc CGRect bbox;
80 9b4a2324 2009-07-09 rsc
81 9b4a2324 2009-07-09 rsc bbox.origin.x = 0;
82 9b4a2324 2009-07-09 rsc bbox.origin.y = 0;
83 9b4a2324 2009-07-09 rsc bbox.size.height = 0;
84 9b4a2324 2009-07-09 rsc bbox.size.width = 0;
85 9b4a2324 2009-07-09 rsc
86 9b4a2324 2009-07-09 rsc first = 1;
87 9b4a2324 2009-07-09 rsc for(i=lo; i<=hi; i++) {
88 9b4a2324 2009-07-09 rsc UniChar u;
89 9b4a2324 2009-07-09 rsc CGGlyph g;
90 9b4a2324 2009-07-09 rsc CGRect r;
91 9b4a2324 2009-07-09 rsc
92 9b4a2324 2009-07-09 rsc u = i;
93 9b4a2324 2009-07-09 rsc CGFontGetGlyphsForUnichars(font, &u, &g, 1);
94 9b4a2324 2009-07-09 rsc if(g == 0 || !CGFontGetGlyphBBoxes(font, &g, 1, &r))
95 9b4a2324 2009-07-09 rsc continue;
96 9b4a2324 2009-07-09 rsc
97 9b4a2324 2009-07-09 rsc r.size.width += r.origin.x;
98 9b4a2324 2009-07-09 rsc r.size.height += r.origin.y;
99 9b4a2324 2009-07-09 rsc if(first) {
100 9b4a2324 2009-07-09 rsc bbox = r;
101 9b4a2324 2009-07-09 rsc first = 0;
102 9b4a2324 2009-07-09 rsc continue;
103 9b4a2324 2009-07-09 rsc }
104 9b4a2324 2009-07-09 rsc if(bbox.origin.x > r.origin.x)
105 9b4a2324 2009-07-09 rsc bbox.origin.x = r.origin.x;
106 9b4a2324 2009-07-09 rsc if(bbox.origin.y > r.origin.y)
107 9b4a2324 2009-07-09 rsc bbox.origin.y = r.origin.y;
108 9b4a2324 2009-07-09 rsc if(bbox.size.width < r.size.width)
109 9b4a2324 2009-07-09 rsc bbox.size.width = r.size.width;
110 9b4a2324 2009-07-09 rsc if(bbox.size.height < r.size.height)
111 9b4a2324 2009-07-09 rsc bbox.size.height = r.size.height;
112 9b4a2324 2009-07-09 rsc }
113 9b4a2324 2009-07-09 rsc
114 9b4a2324 2009-07-09 rsc bbox.size.width -= bbox.origin.x;
115 9b4a2324 2009-07-09 rsc bbox.size.height -= bbox.origin.y;
116 9b4a2324 2009-07-09 rsc return bbox;
117 9b4a2324 2009-07-09 rsc }
118 9b4a2324 2009-07-09 rsc
119 9b4a2324 2009-07-09 rsc void
120 9b4a2324 2009-07-09 rsc load(XFont *f)
121 9b4a2324 2009-07-09 rsc {
122 9b4a2324 2009-07-09 rsc int i, j;
123 9b4a2324 2009-07-09 rsc CGFontRef font;
124 9b4a2324 2009-07-09 rsc CFStringRef s;
125 9b4a2324 2009-07-09 rsc UniChar u[256];
126 9b4a2324 2009-07-09 rsc CGGlyph g[256];
127 9b4a2324 2009-07-09 rsc CGRect bbox;
128 9b4a2324 2009-07-09 rsc
129 9b4a2324 2009-07-09 rsc if(f->loaded)
130 9b4a2324 2009-07-09 rsc return;
131 9b4a2324 2009-07-09 rsc f->loaded = 1;
132 9b4a2324 2009-07-09 rsc s = c2mac(f->name);
133 9b4a2324 2009-07-09 rsc font = CGFontCreateWithFontName(s);
134 9b4a2324 2009-07-09 rsc CFRelease(s);
135 9b4a2324 2009-07-09 rsc if(font == nil)
136 9b4a2324 2009-07-09 rsc return;
137 9b4a2324 2009-07-09 rsc
138 9b4a2324 2009-07-09 rsc // assume bbox gives latin1 is height/ascent for all
139 9b4a2324 2009-07-09 rsc bbox = subfontbbox(font, 0x00, 0xff);
140 9b4a2324 2009-07-09 rsc f->unit = CGFontGetUnitsPerEm(font);
141 9b4a2324 2009-07-09 rsc f->height = bbox.size.height;
142 9b4a2324 2009-07-09 rsc f->originy = bbox.origin.y;
143 9b4a2324 2009-07-09 rsc
144 9b4a2324 2009-07-09 rsc // figure out where the letters are
145 9b4a2324 2009-07-09 rsc for(i=0; i<0xffff; i+=0x100) {
146 9b4a2324 2009-07-09 rsc for(j=0; j<0x100; j++) {
147 9b4a2324 2009-07-09 rsc u[j] = i+j;
148 9b4a2324 2009-07-09 rsc g[j] = 0;
149 9b4a2324 2009-07-09 rsc }
150 9b4a2324 2009-07-09 rsc CGFontGetGlyphsForUnichars(font, u, g, 256);
151 9b4a2324 2009-07-09 rsc for(j=0; j<0x100; j++) {
152 9b4a2324 2009-07-09 rsc if(g[j] != 0) {
153 9b4a2324 2009-07-09 rsc f->range[i>>8] = 1;
154 9b4a2324 2009-07-09 rsc f->nrange++;
155 9b4a2324 2009-07-09 rsc break;
156 9b4a2324 2009-07-09 rsc }
157 9b4a2324 2009-07-09 rsc }
158 9b4a2324 2009-07-09 rsc }
159 9b4a2324 2009-07-09 rsc CFRelease(font);
160 9b4a2324 2009-07-09 rsc }
161 9b4a2324 2009-07-09 rsc
162 9b4a2324 2009-07-09 rsc Memsubfont*
163 9b4a2324 2009-07-09 rsc mksubfont(char *name, int lo, int hi, int size, int antialias)
164 9b4a2324 2009-07-09 rsc {
165 9b4a2324 2009-07-09 rsc CFStringRef s;
166 9b4a2324 2009-07-09 rsc CGColorSpaceRef color;
167 9b4a2324 2009-07-09 rsc CGContextRef ctxt;
168 9b4a2324 2009-07-09 rsc CGFontRef font;
169 9b4a2324 2009-07-09 rsc CGRect bbox;
170 9b4a2324 2009-07-09 rsc Memimage *m, *mc, *m1;
171 9b4a2324 2009-07-09 rsc int x, y, y0;
172 9b4a2324 2009-07-09 rsc int i, unit;
173 9b4a2324 2009-07-09 rsc Fontchar *fc, *fc0;
174 9b4a2324 2009-07-09 rsc Memsubfont *sf;
175 9b4a2324 2009-07-09 rsc
176 9b4a2324 2009-07-09 rsc s = c2mac(name);
177 9b4a2324 2009-07-09 rsc font = CGFontCreateWithFontName(s);
178 9b4a2324 2009-07-09 rsc CFRelease(s);
179 9b4a2324 2009-07-09 rsc if(font == nil)
180 9b4a2324 2009-07-09 rsc return nil;
181 9b4a2324 2009-07-09 rsc bbox = subfontbbox(font, lo, hi);
182 9b4a2324 2009-07-09 rsc unit = CGFontGetUnitsPerEm(font);
183 9b4a2324 2009-07-09 rsc x = (int)(bbox.size.width * size / unit + 0.99999999);
184 9b4a2324 2009-07-09 rsc y = bbox.size.height * size/unit + 0.99999999;
185 9b4a2324 2009-07-09 rsc y0 = (int)(-bbox.origin.y * size/unit + 0.99999999);
186 9b4a2324 2009-07-09 rsc m = allocmemimage(Rect(0, 0, x*(hi+1-lo), y), GREY8);
187 9b4a2324 2009-07-09 rsc if(m == nil)
188 9b4a2324 2009-07-09 rsc return nil;
189 9b4a2324 2009-07-09 rsc mc = allocmemimage(Rect(0, 0, x, y), GREY8);
190 9b4a2324 2009-07-09 rsc if(mc == nil)
191 9b4a2324 2009-07-09 rsc return nil;
192 9b4a2324 2009-07-09 rsc memfillcolor(m, DBlack);
193 9b4a2324 2009-07-09 rsc memfillcolor(mc, DBlack);
194 9b4a2324 2009-07-09 rsc fc = malloc((hi+2 - lo) * sizeof fc[0]);
195 9b4a2324 2009-07-09 rsc sf = malloc(sizeof *sf);
196 9b4a2324 2009-07-09 rsc if(fc == nil || sf == nil) {
197 9b4a2324 2009-07-09 rsc freememimage(m);
198 9b4a2324 2009-07-09 rsc freememimage(mc);
199 9b4a2324 2009-07-09 rsc free(fc);
200 9b4a2324 2009-07-09 rsc free(sf);
201 9b4a2324 2009-07-09 rsc return nil;
202 9b4a2324 2009-07-09 rsc }
203 9b4a2324 2009-07-09 rsc fc0 = fc;
204 9b4a2324 2009-07-09 rsc
205 9b4a2324 2009-07-09 rsc color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
206 9b4a2324 2009-07-09 rsc ctxt = CGBitmapContextCreate(byteaddr(mc, mc->r.min), Dx(mc->r), Dy(mc->r), 8,
207 9b4a2324 2009-07-09 rsc mc->width*sizeof(u32int), color, kCGImageAlphaNone);
208 9b4a2324 2009-07-09 rsc CGColorSpaceRelease(color);
209 9b4a2324 2009-07-09 rsc if(ctxt == nil) {
210 9b4a2324 2009-07-09 rsc freememimage(m);
211 9b4a2324 2009-07-09 rsc freememimage(mc);
212 9b4a2324 2009-07-09 rsc free(fc);
213 9b4a2324 2009-07-09 rsc free(sf);
214 9b4a2324 2009-07-09 rsc return nil;
215 9b4a2324 2009-07-09 rsc }
216 9b4a2324 2009-07-09 rsc
217 9b4a2324 2009-07-09 rsc CGContextSetFont(ctxt, font);
218 9b4a2324 2009-07-09 rsc CGContextSetFontSize(ctxt, size);
219 9b4a2324 2009-07-09 rsc CGContextSetAllowsAntialiasing(ctxt, antialias);
220 9b4a2324 2009-07-09 rsc CGContextSetRGBFillColor(ctxt, 1, 1, 1, 1);
221 9b4a2324 2009-07-09 rsc CGContextSetTextPosition(ctxt, 0, 0); // XXX
222 9b4a2324 2009-07-09 rsc
223 9b4a2324 2009-07-09 rsc x = 0;
224 9b4a2324 2009-07-09 rsc for(i=lo; i<=hi; i++, fc++) {
225 9b4a2324 2009-07-09 rsc UniChar u[2];
226 9b4a2324 2009-07-09 rsc CGGlyph g[2];
227 9b4a2324 2009-07-09 rsc CGRect r[2];
228 9b4a2324 2009-07-09 rsc CGPoint p1;
229 9b4a2324 2009-07-09 rsc int n;
230 9b4a2324 2009-07-09 rsc
231 9b4a2324 2009-07-09 rsc fc->x = x;
232 9b4a2324 2009-07-09 rsc fc->top = 0;
233 9b4a2324 2009-07-09 rsc fc->bottom = Dy(m->r);
234 9b4a2324 2009-07-09 rsc
235 9b4a2324 2009-07-09 rsc n = 0;
236 9b4a2324 2009-07-09 rsc u[n++] = i;
237 9b4a2324 2009-07-09 rsc if(0) // debugging
238 9b4a2324 2009-07-09 rsc u[n++] = '|';
239 9b4a2324 2009-07-09 rsc g[0] = 0;
240 9b4a2324 2009-07-09 rsc CGFontGetGlyphsForUnichars(font, u, g, n);
241 9b4a2324 2009-07-09 rsc if(g[0] == 0 || !CGFontGetGlyphBBoxes(font, g, n, r)) {
242 9b4a2324 2009-07-09 rsc None:
243 9b4a2324 2009-07-09 rsc fc->width = 0;
244 9b4a2324 2009-07-09 rsc if(i == 0) {
245 9b4a2324 2009-07-09 rsc Point p;
246 9b4a2324 2009-07-09 rsc Fontchar *i;
247 9b4a2324 2009-07-09 rsc p = Pt(x, y0);
248 9b4a2324 2009-07-09 rsc // memimagestring(m, p, memwhite, ZP, defont, peterface);
249 9b4a2324 2009-07-09 rsc i = defont->info + 0;
250 9b4a2324 2009-07-09 rsc 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),
251 9b4a2324 2009-07-09 rsc memwhite, ZP, defont->bits, Pt(i->x, i->top), S);
252 9b4a2324 2009-07-09 rsc p.x += i->width;
253 9b4a2324 2009-07-09 rsc fc->left = i->left;
254 9b4a2324 2009-07-09 rsc fc->width = i->width;
255 9b4a2324 2009-07-09 rsc x = p.x;
256 9b4a2324 2009-07-09 rsc }
257 9b4a2324 2009-07-09 rsc continue;
258 9b4a2324 2009-07-09 rsc }
259 9b4a2324 2009-07-09 rsc memfillcolor(mc, DBlack);
260 9b4a2324 2009-07-09 rsc CGContextSetTextPosition(ctxt, 0, y0);
261 9b4a2324 2009-07-09 rsc CGContextShowGlyphs(ctxt, g, n);
262 9b4a2324 2009-07-09 rsc p1 = CGContextGetTextPosition(ctxt);
263 9b4a2324 2009-07-09 rsc if(p1.x <= 0)
264 9b4a2324 2009-07-09 rsc goto None;
265 9b4a2324 2009-07-09 rsc memimagedraw(m, Rect(x, 0, x + p1.x, y), mc, ZP, memopaque, ZP, S);
266 9b4a2324 2009-07-09 rsc fc->width = p1.x;
267 9b4a2324 2009-07-09 rsc fc->left = 0;
268 9b4a2324 2009-07-09 rsc x += p1.x;
269 9b4a2324 2009-07-09 rsc }
270 9b4a2324 2009-07-09 rsc fc->x = x;
271 9b4a2324 2009-07-09 rsc
272 9b4a2324 2009-07-09 rsc // round up to 32-bit boundary
273 9b4a2324 2009-07-09 rsc // so that in-memory data is same
274 9b4a2324 2009-07-09 rsc // layout as in-file data.
275 9b4a2324 2009-07-09 rsc if(antialias)
276 9b4a2324 2009-07-09 rsc x += -x & 3;
277 9b4a2324 2009-07-09 rsc else
278 9b4a2324 2009-07-09 rsc x += -x & 31;
279 9b4a2324 2009-07-09 rsc m1 = allocmemimage(Rect(0, 0, x, y), antialias ? GREY8 : GREY1);
280 9b4a2324 2009-07-09 rsc memimagedraw(m1, m1->r, m, m->r.min, memopaque, ZP, S);
281 9b4a2324 2009-07-09 rsc freememimage(m);
282 9b4a2324 2009-07-09 rsc
283 9b4a2324 2009-07-09 rsc sf->name = nil;
284 9b4a2324 2009-07-09 rsc sf->n = hi+1 - lo;
285 9b4a2324 2009-07-09 rsc sf->height = Dy(m1->r);
286 9b4a2324 2009-07-09 rsc sf->ascent = Dy(m1->r) - y0;
287 9b4a2324 2009-07-09 rsc sf->info = fc0;
288 9b4a2324 2009-07-09 rsc sf->bits = m1;
289 9b4a2324 2009-07-09 rsc
290 9b4a2324 2009-07-09 rsc return sf;
291 9b4a2324 2009-07-09 rsc }
292 9b4a2324 2009-07-09 rsc