1 /***********************************************************/
2 /* */
3 /* System dependent graphics (unix, x11) */
4 /* */
5 /***********************************************************/
6
7 #include "unix/guts.h"
8 #include "Image.h"
9
10 #define SORT(a,b) { int swp; if ((a) > (b)) { swp=(a); (a)=(b); (b)=swp; }}
11 #define REVERT(a) (XX-> size. y - (a) - 1)
12 #define SHIFT(a,b) { (a) += XX-> gtransform. x + XX-> btransform. x; \
13 (b) += XX-> gtransform. y + XX-> btransform. y; }
14 #define RANGE(a) { if ((a) < -16383) (a) = -16383; else if ((a) > 16383) a = 16383; }
15 #define RANGE2(a,b) RANGE(a) RANGE(b)
16
17 typedef struct {
18 int default_char1;
19 int default_char2;
20 int offset;
21 XFontStruct *fs;
22 } CharStructABC;
23
24 static void
init_xchar_abc(XFontStruct * fs,CharStructABC * s)25 init_xchar_abc( XFontStruct * fs, CharStructABC * s)
26 {
27 s-> fs = fs;
28 s-> default_char1 = fs-> default_char >> 8;
29 s-> default_char2 = fs-> default_char & 0xff;
30 s-> offset = fs-> max_char_or_byte2 - fs-> min_char_or_byte2 + 1;
31
32 if (
33 s-> default_char2 < fs-> min_char_or_byte2 ||
34 s-> default_char2 > fs-> max_char_or_byte2 ||
35 s-> default_char1 < fs-> min_byte1 ||
36 s-> default_char1 > fs-> max_byte1
37 ) {
38 s-> default_char1 = fs-> min_byte1;
39 s-> default_char2 = fs-> min_char_or_byte2;
40 }
41 }
42
43 static XCharStruct *
xchar_struct(CharStructABC * s,unsigned int codepoint)44 xchar_struct( CharStructABC * s, unsigned int codepoint)
45 {
46 XCharStruct * cs;
47 int i1 = codepoint >> 8;
48 int i2 = codepoint & 0xff;
49 XFontStruct * fs = s-> fs;
50
51 if ( !fs-> per_char)
52 cs = &fs-> min_bounds;
53 else if (
54 i2 < fs-> min_char_or_byte2 ||
55 i2 > fs-> max_char_or_byte2 ||
56 i1 < fs-> min_byte1 ||
57 i1 > fs-> max_byte1
58 )
59 cs = fs-> per_char +
60 (s->default_char1 - fs-> min_byte1) * s->offset +
61 s->default_char2 - fs-> min_char_or_byte2;
62 else
63 cs = fs-> per_char +
64 (i1 - fs-> min_byte1) * s->offset +
65 i2 - fs-> min_char_or_byte2;
66
67 return cs;
68 }
69
70 static int need_swap_bytes = -1;
71 static void
swap_bytes(register uint16_t * area,int len)72 swap_bytes( register uint16_t * area, int len )
73 {
74 if ( need_swap_bytes < 0 ) {
75 XChar2b b = { 0x1, 0x23 };
76 uint16_t a = 0x123, *pb = (uint16_t*) &b;
77 need_swap_bytes = a != *pb;
78 }
79 if ( need_swap_bytes ) while (len-- > 0) {
80 register uint16_t x = *area;
81 *(area++) = (( x & 0xff ) << 8) | (x >> 8);
82 }
83 }
84 #define SWAP_BYTES(area,len) if (need_swap_bytes) swap_bytes(area,len)
85
86
87 static Point
gp_get_text_overhangs(Handle self,const char * text,int len,int flags)88 gp_get_text_overhangs( Handle self, const char *text, int len, int flags)
89 {
90 DEFXX;
91 Point ret;
92 if ( len > 0) {
93 XCharStruct * cs;
94 cs = prima_char_struct( XX-> font-> fs, (void*) text, flags & (toUTF8 | toGlyphs));
95 ret. x = ( cs-> lbearing < 0) ? - cs-> lbearing : 0;
96 text += (len - 1) * ((flags & (toUTF8 | toGlyphs)) ? 2 : 1);
97 cs = prima_char_struct( XX-> font-> fs, (void*) text, flags & (toUTF8 | toGlyphs));
98 ret. y = (( cs-> width - cs-> rbearing) < 0) ? cs-> rbearing - cs-> width : 0;
99 } else
100 ret. x = ret. y = 0;
101 return ret;
102 }
103
104 static int
105 gp_get_text_width( Handle self, const char *text, int len, int flags);
106
107 static Point *
108 gp_get_text_box( Handle self, const char * text, int len, int flags);
109
110 static Bool
gp_text_out_rotated(Handle self,const char * text,uint16_t * advances,int16_t * positions,int x,int y,int len,int flags,Bool * ok_to_not_rotate)111 gp_text_out_rotated(
112 Handle self, const char * text,
113 uint16_t * advances, int16_t * positions,
114 int x, int y, int len, int flags, Bool * ok_to_not_rotate
115 ) {
116 DEFXX;
117 int i;
118 PRotatedFont r;
119 XCharStruct *cs;
120 int px, py = ( XX-> flags. paint_base_line) ? XX-> font-> font. descent : 0;
121 int ax = 0, ay = 0;
122 int psx, psy, dsx, dsy;
123 Fixed rx, ry;
124 Bool wide = flags & toUnicode;
125
126 if ( !prima_update_rotated_fonts( XX-> font,
127 text, len, wide,
128 PDrawable( self)-> font. direction, &r, ok_to_not_rotate
129 ))
130 return false;
131
132 for ( i = 0; i < len; i++) {
133 XChar2b index;
134 int real_ax, real_ay;
135
136 /* acquire actual character index */
137 index. byte1 = wide ? (( XChar2b*) text + i)-> byte1 : 0;
138 index. byte2 = wide ? (( XChar2b*) text + i)-> byte2 : *((unsigned char*)text + i);
139
140 if ( index. byte1 < r-> first1 || index. byte1 >= r-> first1 + r-> height ||
141 index. byte2 < r-> first2 || index. byte2 >= r-> first2 + r-> width) {
142 if ( r-> defaultChar1 < 0 || r-> defaultChar2 < 0) continue;
143 index. byte1 = ( unsigned char) r-> defaultChar1;
144 index. byte2 = ( unsigned char) r-> defaultChar2;
145 }
146
147 /* querying character */
148 if ( r-> map[(index. byte1 - r-> first1) * r-> width + index. byte2 - r-> first2] == NULL)
149 continue;
150 cs = XX-> font-> fs-> per_char ?
151 XX-> font-> fs-> per_char +
152 ( index. byte1 - XX-> font-> fs-> min_byte1) * r-> width +
153 index. byte2 - XX-> font-> fs-> min_char_or_byte2 :
154 &(XX-> font-> fs-> min_bounds);
155
156 /* find reference point in pixmap */
157 px = ( cs-> lbearing < 0) ? -cs-> lbearing : 0;
158 rx. l = px * r-> cos2. l - py * r-> sin2. l + UINT16_PRECISION/2;
159 ry. l = px * r-> sin2. l + py * r-> cos2. l + UINT16_PRECISION/2;
160 psx = rx. i. i - r-> shift. x;
161 psy = ry. i. i - r-> shift. y;
162
163 /* find glyph position */
164 real_ax = ax;
165 real_ay = ay;
166 if ( positions ) {
167 real_ax += positions[i * 2];
168 real_ay += positions[i * 2 + 1];
169 }
170 rx. l = real_ax * r-> cos2. l - real_ay * r-> sin2. l + UINT16_PRECISION/2;
171 ry. l = real_ax * r-> sin2. l + real_ay * r-> cos2. l + UINT16_PRECISION/2;
172 dsx = x + rx. i. i - psx;
173 dsy = REVERT( y + ry. i. i) + psy - r-> dimension. y + 1;
174
175 if ( guts. debug & DEBUG_FONTS) {
176 _debug("shift %d %d\n", r-> shift.x, r-> shift.y);
177 _debug("point ref: %d %d => %d %d. dims: %d %d, [%d %d %d]\n", px, py, psx, psy, r-> dimension.x, r-> dimension.y,
178 cs-> lbearing, cs-> rbearing - cs-> lbearing, cs-> width - cs-> rbearing);
179 _debug("plot ref: %d %d => %d %d\n", ax, ay, rx.i.i, ry.i.i);
180 _debug("at: %d %d ( sz = %d), dest: %d %d\n", x, y, XX-> size.y, dsx, dsy);
181 }
182
183 /* GXandReverse ropNotDestAnd */ /* dest = (!dest) & src */
184 /* GXorReverse ropNotDestOr */ /* dest = (!dest) | src */
185 /* GXequiv ropNotSrcXor */ /* dest ^= !src */
186 /* GXandInverted ropNotSrcAnd */ /* dest &= !src */
187 /* GXorInverted ropNotSrcOr */ /* dest |= !src */
188 /* GXnand ropNotAnd */ /* dest = !(src & dest) */
189 /* GXnor ropNotOr */ /* dest = !(src | dest) */
190 /* GXinvert ropInvert */ /* dest = !dest */
191
192 switch ( XX-> paint_rop) { /* XXX Limited set edition - either expand to full list or find new way to display bitmaps */
193 case ropXorPut:
194 XSetBackground( DISP, XX-> gc, 0);
195 XSetFunction( DISP, XX-> gc, GXxor);
196 break;
197 case ropOrPut:
198 XSetBackground( DISP, XX-> gc, 0);
199 XSetFunction( DISP, XX-> gc, GXor);
200 break;
201 case ropAndPut:
202 XSetBackground( DISP, XX-> gc, 0xffffffff);
203 XSetFunction( DISP, XX-> gc, GXand);
204 break;
205 case ropNotPut:
206 case ropBlackness:
207 XSetForeground( DISP, XX-> gc, 0);
208 XSetBackground( DISP, XX-> gc, 0xffffffff);
209 XSetFunction( DISP, XX-> gc, GXand);
210 break;
211 case ropWhiteness:
212 XSetForeground( DISP, XX-> gc, 0xffffffff);
213 XSetBackground( DISP, XX-> gc, 0);
214 XSetFunction( DISP, XX-> gc, GXor);
215 break;
216 default:
217 XSetForeground( DISP, XX-> gc, 0);
218 XSetBackground( DISP, XX-> gc, 0xffffffff);
219 XSetFunction( DISP, XX-> gc, GXand);
220 }
221 XPutImage( DISP, XX-> gdrawable, XX-> gc,
222 r-> map[(index. byte1 - r-> first1) * r-> width + index. byte2 - r-> first2]-> image,
223 0, 0, dsx, dsy, r-> dimension.x, r-> dimension.y);
224 XCHECKPOINT;
225 switch ( XX-> paint_rop) {
226 case ropAndPut:
227 case ropOrPut:
228 case ropXorPut:
229 case ropBlackness:
230 case ropWhiteness:
231 break;
232 case ropNotPut:
233 XSetForeground( DISP, XX-> gc, XX-> fore. primary);
234 XSetBackground( DISP, XX-> gc, 0xffffffff);
235 XSetFunction( DISP, XX-> gc, GXorInverted);
236 goto DISPLAY;
237 default:
238 XSetForeground( DISP, XX-> gc, XX-> fore. primary);
239 XSetBackground( DISP, XX-> gc, 0);
240 XSetFunction( DISP, XX-> gc, GXor);
241 DISPLAY:
242 XPutImage( DISP, XX-> gdrawable, XX-> gc,
243 r-> map[(index. byte1 - r-> first1) * r-> width + index. byte2 - r-> first2]-> image,
244 0, 0, dsx, dsy, r-> dimension.x, r-> dimension.y);
245 XCHECKPOINT;
246 }
247 ax += advances ? advances[i] : cs-> width;
248 }
249 apc_gp_set_rop( self, XX-> paint_rop);
250 XSetFillStyle( DISP, XX-> gc, FillSolid);
251 XSetForeground( DISP, XX-> gc, XX-> fore. primary);
252 XSetBackground( DISP, XX-> gc, XX-> back. primary);
253 XX-> flags. brush_fore = 1;
254 XX-> flags. brush_back = 1;
255
256 if ( PDrawable( self)-> font. style & (fsUnderlined|fsStruckOut)) {
257 int lw = apc_gp_get_line_width( self);
258 int tw = gp_get_text_width( self, text, len, flags | toAddOverhangs) - 1;
259 int d = XX-> font-> underlinePos;
260 Point ovx = gp_get_text_overhangs( self, text, len, flags);
261 int x1, y1, x2, y2;
262 if ( lw != XX-> font-> underlineThickness)
263 apc_gp_set_line_width( self, XX-> font-> underlineThickness);
264
265 if ( PDrawable( self)-> font. style & fsUnderlined) {
266 ay = d + ( XX-> flags. paint_base_line ? 0 : XX-> font-> font. descent);
267 rx. l = -ovx.x * r-> cos2. l - ay * r-> sin2. l + 0.5;
268 ry. l = -ovx.x * r-> sin2. l + ay * r-> cos2. l + 0.5;
269 x1 = x + rx. i. i;
270 y1 = y + ry. i. i;
271 tw += ovx.y;
272 rx. l = tw * r-> cos2. l - ay * r-> sin2. l + 0.5;
273 ry. l = tw * r-> sin2. l + ay * r-> cos2. l + 0.5;
274 x2 = x + rx. i. i;
275 y2 = y + ry. i. i;
276 XDrawLine( DISP, XX-> gdrawable, XX-> gc, x1, REVERT( y1), x2, REVERT( y2));
277 }
278
279 if ( PDrawable( self)-> font. style & fsStruckOut) {
280 ay = (PDrawable( self)-> font.ascent - PDrawable( self)-> font.internalLeading)/2 +
281 + ( XX-> flags. paint_base_line ? 0 : XX-> font-> font. descent);
282 rx. l = -ovx.x * r-> cos2. l - ay * r-> sin2. l + 0.5;
283 ry. l = -ovx.x * r-> sin2. l + ay * r-> cos2. l + 0.5;
284 x1 = x + rx. i. i;
285 y1 = y + ry. i. i;
286 tw += ovx.y;
287 rx. l = tw * r-> cos2. l - ay * r-> sin2. l + 0.5;
288 ry. l = tw * r-> sin2. l + ay * r-> cos2. l + 0.5;
289 x2 = x + rx. i. i;
290 y2 = y + ry. i. i;
291 XDrawLine( DISP, XX-> gdrawable, XX-> gc, x1, REVERT( y1), x2, REVERT( y2));
292 }
293
294 if ( lw != XX-> font-> underlineThickness)
295 apc_gp_set_line_width( self, lw);
296 }
297 XFLUSH;
298 return true;
299 }
300
301 static void
paint_text_background(Handle self,const char * text,int x,int y,int len,int flags)302 paint_text_background( Handle self, const char * text, int x, int y, int len, int flags)
303 {
304 DEFXX;
305 int i;
306 Point * p;
307 FillPattern fp;
308
309 memcpy( &fp, apc_gp_get_fill_pattern( self), sizeof( FillPattern));
310 p = gp_get_text_box( self, text, len, flags);
311 XSetForeground( DISP, XX-> gc, XX-> back. primary);
312 XX-> flags. brush_back = 0;
313 XX-> flags. brush_fore = 1;
314 XX-> fore. balance = 0;
315 XSetFunction( DISP, XX-> gc, GXcopy);
316 apc_gp_set_fill_pattern( self, fillPatterns[fpSolid]);
317 for ( i = 0; i < 4; i++) {
318 p[i].x += x;
319 p[i].y += y;
320 }
321 i = p[2].x; p[2].x = p[3].x; p[3].x = i;
322 i = p[2].y; p[2].y = p[3].y; p[3].y = i;
323
324 apc_gp_fill_poly( self, 4, p);
325 apc_gp_set_rop( self, XX-> paint_rop);
326 apc_gp_set_color( self, XX-> fore. color);
327 apc_gp_set_fill_pattern( self, fp);
328 free( p);
329 }
330
331 static void
draw_text_underline(Handle self,const char * text,int x,int y,int len,int flags)332 draw_text_underline(Handle self, const char * text, int x, int y, int len, int flags)
333 {
334 DEFXX;
335 int lw = apc_gp_get_line_width( self) + .5;
336 int tw = gp_get_text_width( self, text, len, flags | toAddOverhangs);
337 int d = XX-> font-> underlinePos;
338 Point ovx = gp_get_text_overhangs( self, text, len, flags);
339 if ( lw != XX-> font-> underlineThickness)
340 apc_gp_set_line_width( self, XX-> font-> underlineThickness);
341 if ( PDrawable( self)-> font. style & fsUnderlined)
342 XDrawLine( DISP, XX-> gdrawable, XX-> gc,
343 x - ovx.x, REVERT( y + d), x + tw - 1 + ovx.y, REVERT( y + d));
344 if ( PDrawable( self)-> font. style & fsStruckOut) {
345 int scy = REVERT( y + (XX-> font-> font.ascent - XX-> font-> font.internalLeading)/2);
346 XDrawLine( DISP, XX-> gdrawable, XX-> gc,
347 x - ovx.x, scy, x + tw - 1 + ovx.y, scy);
348 }
349 if ( lw != XX-> font-> underlineThickness)
350 apc_gp_set_line_width( self, lw);
351 }
352
353 static Bool
text_out(Handle self,const char * text,int x,int y,int len,int flags)354 text_out( Handle self, const char * text, int x, int y, int len, int flags)
355 {
356 DEFXX;
357 if ( !XX-> flags. paint_base_line)
358 y += XX-> font-> font. descent;
359
360 XSetFillStyle( DISP, XX-> gc, FillSolid);
361 if ( !XX-> flags. brush_fore) {
362 XSetForeground( DISP, XX-> gc, XX-> fore. primary);
363 XX-> flags. brush_fore = 1;
364 }
365
366 if ( flags & toUTF8)
367 XDrawString16( DISP, XX-> gdrawable, XX-> gc, x, REVERT( y) + 1, (XChar2b*) text, len);
368 else
369 XDrawString( DISP, XX-> gdrawable, XX-> gc, x, REVERT( y) + 1, ( char*) text, len);
370 XCHECKPOINT;
371 return true;
372 }
373
374 static Bool
glyphs_out_with_advances(Handle self,PGlyphsOutRec t,int x,int y)375 glyphs_out_with_advances( Handle self, PGlyphsOutRec t, int x, int y)
376 {
377 DEFXX;
378 int i, run_length, next_x;
379 uint16_t * glyphs, *advances, *run_glyphs;
380 int16_t * positions;
381 CharStructABC s;
382 if ( !XX-> flags. paint_base_line)
383 y += XX-> font-> font. descent;
384
385 XSetFillStyle( DISP, XX-> gc, FillSolid);
386 if ( !XX-> flags. brush_fore) {
387 XSetForeground( DISP, XX-> gc, XX-> fore. primary);
388 XX-> flags. brush_fore = 1;
389 }
390
391 init_xchar_abc(XX->font->fs, &s);
392 y = REVERT(y) + 1;
393 next_x = x;
394 for (
395 i = run_length = 0,
396 glyphs = run_glyphs = t-> glyphs,
397 advances = t-> advances,
398 positions = t->positions;
399 i < t-> len;
400 i++, glyphs++, advances++, positions += 2
401 ) {
402 uint16_t xc = *glyphs;
403 int default_advance;
404
405 SWAP_BYTES(&xc, 1);
406 default_advance = xchar_struct(&s, xc)-> width;
407
408 if (
409 (positions[0] == 0 && positions[1] == 0) &&
410 (default_advance == *advances || i == t->len-1)
411 ) {
412 run_length++;
413 next_x += default_advance;
414 } else {
415 if ( run_length > 0 ) {
416 XDrawString16( DISP, XX-> gdrawable, XX-> gc,
417 x, y, (XChar2b*) run_glyphs, run_length);
418 x = next_x;
419 }
420 XDrawString16( DISP, XX-> gdrawable, XX-> gc,
421 x + positions[0], y - positions[1], (XChar2b*) glyphs, 1);
422 next_x += *advances;
423 run_glyphs = glyphs + 1;
424 run_length = 0;
425 x = next_x;
426 }
427 }
428 if ( run_length > 0 )
429 XDrawString16( DISP, XX-> gdrawable, XX-> gc,
430 x, y, (XChar2b*) run_glyphs, run_length);
431
432 XCHECKPOINT;
433 return true;
434 }
435
436 Bool
apc_gp_text_out(Handle self,const char * text,int x,int y,int len,int flags)437 apc_gp_text_out( Handle self, const char * text, int x, int y, int len, int flags)
438 {
439 Bool ret;
440 DEFXX;
441
442 if ( PObject( self)-> options. optInDrawInfo) return false;
443 if ( !XF_IN_PAINT(XX)) return false;
444
445 if ( len == 0) return true;
446 if ( len > 65535 ) len = 65535;
447 flags &= ~toGlyphs;
448
449 #ifdef USE_XFT
450 if ( XX-> font-> xft)
451 return prima_xft_text_out( self, text, x, y, len, flags);
452 #endif
453
454 if ( flags & toUTF8 )
455 if ( !( text = ( char *) prima_alloc_utf8_to_wchar( text, len))) return false;
456
457 if ( XX-> flags. paint_opaque)
458 paint_text_background( self, text, x, y, len, flags);
459
460 SHIFT(x, y);
461 RANGE2(x,y);
462 if ( PDrawable( self)-> font. direction != 0) {
463 Bool ok_to_not_rotate = false;
464 Bool ret;
465 ret = gp_text_out_rotated( self, text, NULL, NULL, x, y, len, flags, &ok_to_not_rotate);
466 if ( !ok_to_not_rotate) {
467 if ( flags & toUTF8) free(( char *) text);
468 return ret;
469 }
470 }
471
472 ret = text_out(self, text, x, y, len, flags);
473 if ( PDrawable( self)-> font. style & (fsUnderlined|fsStruckOut))
474 draw_text_underline(self, text, x, y, len, flags);
475
476 if ( flags & toUTF8) free(( char *) text);
477 XFLUSH;
478
479 return ret;
480 }
481
482 Bool
apc_gp_glyphs_out(Handle self,PGlyphsOutRec t,int x,int y)483 apc_gp_glyphs_out( Handle self, PGlyphsOutRec t, int x, int y)
484 {
485 Bool ret;
486 DEFXX;
487
488 if ( PObject( self)-> options. optInDrawInfo) return false;
489 if ( !XF_IN_PAINT(XX)) return false;
490
491 if ( t->len == 0) return true;
492 if ( t->len > 65535 ) t->len = 65535;
493
494 #ifdef USE_XFT
495 if ( XX-> font-> xft)
496 return prima_xft_glyphs_out( self, t, x, y);
497 #endif
498
499 SWAP_BYTES(t->glyphs,t->len);
500 if ( XX-> flags. paint_opaque)
501 paint_text_background( self, (const char*) t->glyphs, x, y, t->len, toUnicode);
502
503 SHIFT(x, y);
504 RANGE2(x,y);
505 if ( PDrawable( self)-> font. direction != 0) {
506 Bool ok_to_not_rotate = false;
507 ret = gp_text_out_rotated( self, (const char*) t->glyphs,
508 t->advances, t->positions,
509 x, y, t->len, toUnicode, &ok_to_not_rotate);
510 if ( !ok_to_not_rotate)
511 goto EXIT;
512 }
513
514 ret =
515 t-> advances ?
516 glyphs_out_with_advances(self, t, x, y) :
517 text_out(self, (const char*) t->glyphs, x, y, t->len, toUnicode);
518
519 if ( PDrawable( self)-> font. style & (fsUnderlined|fsStruckOut))
520 draw_text_underline(self, (const char*) t->glyphs, x, y, t->len, toUnicode);
521 XFLUSH;
522
523 EXIT:
524 SWAP_BYTES(t->glyphs,t->len);
525 return ret;
526 }
527
528 Bool
text_shaper_core_text(Handle self,PTextShapeRec r)529 text_shaper_core_text( Handle self, PTextShapeRec r)
530 {
531 int i;
532 uint16_t *glyphs;
533 uint32_t *text;
534
535 for ( i = 0, glyphs = r->glyphs, text = r->text; i < r->len; i++) {
536 uint32_t c = *(text++);
537 if ( c > 0xffff ) c = 0x0;
538 *(glyphs++) = c;
539 }
540 r-> n_glyphs = r->len;
541
542 if ( r-> advances ) {
543 uint16_t *glyphs, *advances;
544 CharStructABC s;
545 init_xchar_abc(X(self)->font->fs, &s);
546 for (
547 i = 0, glyphs = r->glyphs, advances = r->advances;
548 i < r-> len;
549 i++
550 )
551 *(advances++) = xchar_struct(&s, *(glyphs++))-> width;
552 bzero(r->positions, r->len * 2 * sizeof(int16_t));
553 }
554
555 return true;
556 }
557
558 PTextShapeFunc
apc_gp_get_text_shaper(Handle self,int * type)559 apc_gp_get_text_shaper( Handle self, int * type)
560 {
561 #ifdef USE_XFT
562 if ( X(self)-> font && X(self)-> font-> xft) {
563 int t = *type;
564 #ifdef WITH_HARFBUZZ
565 if ( guts. use_harfbuzz && *type == tsFull )
566 return prima_xft_text_shaper_harfbuzz;
567 #endif
568 *type = tsGlyphs;
569 return ( t == tsBytes ) ?
570 prima_xft_text_shaper_bytes :
571 prima_xft_text_shaper_ident;
572 }
573 #endif
574 *type = tsNone;
575 return text_shaper_core_text;
576 }
577
578 PFontABC
prima_xfont2abc(XFontStruct * fs,int firstChar,int lastChar)579 prima_xfont2abc( XFontStruct * fs, int firstChar, int lastChar)
580 {
581 int k, l;
582 CharStructABC s;
583 PFontABC abc = malloc( sizeof( FontABC) * (lastChar - firstChar + 1));
584 init_xchar_abc(fs, &s);
585 for ( k = firstChar, l = 0; k <= lastChar; k++, l++) {
586 XCharStruct * cs = xchar_struct(&s, (unsigned int) k);
587 abc[l]. a = cs-> lbearing;
588 abc[l]. b = cs-> rbearing - cs-> lbearing;
589 abc[l]. c = cs-> width - cs-> rbearing;
590 }
591 return abc;
592 }
593
594 PFontABC
apc_gp_get_font_abc(Handle self,int firstChar,int lastChar,int flags)595 apc_gp_get_font_abc( Handle self, int firstChar, int lastChar, int flags)
596 {
597 PFontABC abc;
598
599 if ( self) {
600 DEFXX;
601 #ifdef USE_XFT
602 if ( XX-> font-> xft)
603 return prima_xft_get_font_abc( self, firstChar, lastChar, flags);
604 #endif
605
606 abc = prima_xfont2abc( XX-> font-> fs, firstChar, lastChar);
607 } else
608 abc = prima_xfont2abc( guts. font_abc_nil_hack, firstChar, lastChar);
609 return abc;
610 }
611
612 PFontABC
prima_xfont2def(Handle self,int first,int last)613 prima_xfont2def( Handle self, int first, int last)
614 {
615 DEFXX;
616 XCharStruct *max;
617 Pixmap pixmap;
618 GC gc;
619 XGCValues gcv;
620 int i, j, k, w, h, ls;
621 PFontABC ret;
622 XImage *xi;
623
624 if ( !( ret = malloc( sizeof(FontABC) * ( last - first + 1 ) )))
625 return NULL;
626 bzero( ret, sizeof(FontABC) * ( last - first + 1 ));
627
628 max = &XX-> font-> fs-> max_bounds;
629 w = max-> width * 3;
630 h = max-> descent + max-> ascent;
631 ls = (( w + 31) / 32) * 4;
632 w = ls * 8;
633 pixmap = XCreatePixmap( DISP, guts. root, w, h, 1);
634 gcv. graphics_exposures = false;
635 gc = XCreateGC( DISP, pixmap, GCGraphicsExposures, &gcv);
636 XSetFont( DISP, gc, XX-> font-> id);
637
638 for ( i = 0; i <= last - first; i++) {
639 XChar2b ch;
640 ch. byte1 = (first + i) / 256;
641 ch. byte2 = (first + i) % 256;
642 XSetForeground( DISP, gc, 0);
643 XFillRectangle( DISP, pixmap, gc, 0, 0, w, h);
644 XSetForeground( DISP, gc, 1);
645 XDrawString16( DISP, pixmap, gc, 10, h - XX->font->font. descent, &ch, 1);
646
647 if (!(xi = XGetImage( DISP, pixmap, 0, 0, w, h, 1, XYPixmap))) {
648 free( ret );
649 ret = NULL;
650 break;
651 }
652 /*
653 for ( j = 0; j < h; j++) {
654 int k, l;
655 for ( k = 0; k < ls; k++) {
656 Byte * p = (Byte*)xi-> data + j * xi-> bytes_per_line + k;
657 printf(".");
658 for ( l = 0; l < 8; l++) {
659 int z = (*p) & ( 1 << l );
660 printf("%s", z ? "*" : " ");
661 }
662 }
663 printf("\n");
664 }
665 */
666 for ( j = 0; j < h; j++) {
667 Byte * p = (Byte*)xi-> data + j * xi-> bytes_per_line;
668 for ( k = 0; k < ls; k++, p++) {
669 if ( *p != 0 ) {
670 ret[i]. c = j;
671 goto FOUND_C;
672 }
673 }
674 }
675 FOUND_C:
676 for ( j = h - 1; j >= 0; j--) {
677 Byte * p = (Byte*)xi-> data + j * xi-> bytes_per_line;
678 for ( k = 0; k < ls; k++, p++) {
679 if ( *p != 0 ) {
680 ret[i]. a = h - j - 1;
681 goto FOUND_A;
682 }
683 }
684 }
685 FOUND_A:
686 if ( ret[i].a != 0 || ret[i].c != 0)
687 ret[i]. b = h - ret[i]. a - ret[i]. c;
688 XDestroyImage( xi);
689 }
690
691 XFreeGC( DISP, gc);
692 XFreePixmap( DISP, pixmap);
693
694 return ret;
695 }
696
697 PFontABC
apc_gp_get_font_def(Handle self,int firstChar,int lastChar,int flags)698 apc_gp_get_font_def( Handle self, int firstChar, int lastChar, int flags)
699 {
700 PFontABC abc;
701 #ifdef USE_XFT
702 DEFXX;
703 if ( XX-> font-> xft)
704 return prima_xft_get_font_def( self, firstChar, lastChar, flags);
705 #endif
706 abc = prima_xfont2def( self, firstChar, lastChar);
707 return abc;
708 }
709
710 static int
gp_get_text_width(Handle self,const char * text,int len,int flags)711 gp_get_text_width( Handle self, const char *text, int len, int flags)
712 {
713 DEFXX;
714 int ret;
715 ret = (flags & toUTF8) ?
716 XTextWidth16( XX-> font-> fs, ( XChar2b *) text, len) :
717 XTextWidth ( XX-> font-> fs, (char*) text, len);
718 if ( flags & toAddOverhangs ) {
719 Point ovx = gp_get_text_overhangs( self, text, len, flags);
720 ret += ovx. x + ovx. y;
721 }
722 return ret;
723 }
724
725 int
apc_gp_get_text_width(Handle self,const char * text,int len,int flags)726 apc_gp_get_text_width( Handle self, const char * text, int len, int flags)
727 {
728 int ret;
729
730 flags &= ~toGlyphs;
731 if ( len > 65535 ) len = 65535;
732
733 #ifdef USE_XFT
734 if ( X(self)-> font-> xft)
735 return prima_xft_get_text_width( X(self)-> font, text, len, flags,
736 X(self)-> xft_map8, NULL);
737 #endif
738
739 if ( flags & toUTF8 )
740 if ( !( text = ( char *) prima_alloc_utf8_to_wchar( text, len))) return 0;
741 ret = gp_get_text_width( self, text, len, flags);
742 if ( flags & toUTF8)
743 free(( char*) text);
744 return ret;
745 }
746
747 int
apc_gp_get_glyphs_width(Handle self,PGlyphsOutRec t)748 apc_gp_get_glyphs_width( Handle self, PGlyphsOutRec t)
749 {
750 int ret;
751 if ( t->len > 65535 ) t->len = 65535;
752
753 #ifdef USE_XFT
754 if ( X(self)-> font-> xft)
755 return prima_xft_get_glyphs_width( X(self)-> font, t, NULL);
756 #endif
757
758 SWAP_BYTES(t->glyphs,t->len);
759 ret = gp_get_text_width( self, (char*) t->glyphs, t->len, toUTF8 );
760 SWAP_BYTES(t->glyphs,t->len);
761 return ret;
762 }
763
764 static Point *
gp_get_text_box(Handle self,const char * text,int len,int flags)765 gp_get_text_box( Handle self, const char * text, int len, int flags)
766 {
767 DEFXX;
768 Point * pt = ( Point *) malloc( sizeof( Point) * 5);
769 int x;
770 Point ovx;
771
772 if ( !pt) return NULL;
773 if ( flags & toGlyphs ) flags &= ~toUTF8;
774
775 x = (flags & toUTF8) ?
776 XTextWidth16( XX-> font-> fs, ( XChar2b*) text, len) :
777 XTextWidth( XX-> font-> fs, (char*)text, len);
778 ovx = gp_get_text_overhangs( self, text, len, flags);
779
780 pt[0].y = pt[2]. y = XX-> font-> font. ascent - 1;
781 pt[1].y = pt[3]. y = - XX-> font-> font. descent;
782 pt[4].y = 0;
783 pt[4].x = x;
784 pt[3].x = pt[2]. x = x + ovx. y;
785 pt[0].x = pt[1]. x = - ovx. x;
786
787 if ( !XX-> flags. paint_base_line) {
788 int i;
789 for ( i = 0; i < 4; i++) pt[i]. y += XX-> font-> font. descent;
790 }
791
792 if ( PDrawable( self)-> font. direction != 0) {
793 int i;
794 double s = sin( PDrawable( self)-> font. direction / 57.29577951);
795 double c = cos( PDrawable( self)-> font. direction / 57.29577951);
796 for ( i = 0; i < 5; i++) {
797 double x = pt[i]. x * c - pt[i]. y * s;
798 double y = pt[i]. x * s + pt[i]. y * c;
799 pt[i]. x = x + (( x > 0) ? 0.5 : -0.5);
800 pt[i]. y = y + (( y > 0) ? 0.5 : -0.5);
801 }
802 }
803
804 return pt;
805 }
806
807 Point *
apc_gp_get_text_box(Handle self,const char * text,int len,int flags)808 apc_gp_get_text_box( Handle self, const char * text, int len, int flags)
809 {
810 Point * ret;
811
812 if ( len > 65535 ) len = 65535;
813
814 #ifdef USE_XFT
815 if ( X(self)-> font-> xft)
816 return prima_xft_get_text_box( self, text, len, flags);
817 #endif
818 if ( flags & toUTF8)
819 if ( !( text = ( char *) prima_alloc_utf8_to_wchar( text, len))) return 0;
820 ret = gp_get_text_box( self, text, len, flags);
821 if ( flags & toUTF8)
822 free(( char*) text);
823 return ret;
824 }
825
826 Point *
apc_gp_get_glyphs_box(Handle self,PGlyphsOutRec t)827 apc_gp_get_glyphs_box( Handle self, PGlyphsOutRec t)
828 {
829 Point * ret;
830 if ( t->len > 65535 ) t->len = 65535;
831 #ifdef USE_XFT
832 if ( X(self)-> font-> xft)
833 return prima_xft_get_glyphs_box( self, t);
834 #endif
835 SWAP_BYTES(t->glyphs,t->len);
836 ret = gp_get_text_box( self, (char*) t->glyphs, t->len, toUTF8);
837 SWAP_BYTES(t->glyphs,t->len);
838 return ret;
839 }
840
841